<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/">
	<channel>
		<title><![CDATA[Hack64 - Hacking]]></title>
		<link>https://hack64.net/</link>
		<description><![CDATA[Hack64 - https://hack64.net]]></description>
		<pubDate>Sat, 09 May 2026 09:00:44 +0000</pubDate>
		<generator>MyBB</generator>
		<item>
			<title><![CDATA[After Applying Patch or Changing Textures In A Rom...]]></title>
			<link>https://hack64.net/Thread-After-Applying-Patch-or-Changing-Textures-In-A-Rom</link>
			<pubDate>Wed, 04 Aug 2021 16:33:18 +0000</pubDate>
			<guid isPermaLink="false">https://hack64.net/Thread-After-Applying-Patch-or-Changing-Textures-In-A-Rom</guid>
			<description><![CDATA[it shows me a white screen after the title screen, no save screen...]]></description>
			<content:encoded><![CDATA[it shows me a white screen after the title screen, no save screen...]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[How To Detect SM64 ROM Versions In C]]></title>
			<link>https://hack64.net/Thread-How-To-Detect-SM64-ROM-Versions-In-C</link>
			<pubDate>Sun, 04 Jul 2021 03:04:00 +0000</pubDate>
			<guid isPermaLink="false">https://hack64.net/Thread-How-To-Detect-SM64-ROM-Versions-In-C</guid>
			<description><![CDATA[void check_rom()<br />
{<br />
// Read byte by byte so endian-ness is irrelevant<br />
    fseek(rom, 0, SEEK_SET);<br />
// 59th byte starts region ID<br />
    fseek(rom, 59, SEEK_SET);<br />
    fread(&rom_byte_1, 1, 1, rom);<br />
    fread(&rom_byte_2, 1, 1, rom);<br />
    fread(&rom_byte_3, 1, 1, rom);<br />
    fread(&rom_byte_4, 1, 1, rom);<br />
    <br />
    if(rom_byte_1 == 0x4E && rom_byte_2 == 0x53 && rom_byte_3 == 0x4D && rom_byte_4 == 0x4A) //NSMJ in hex, both OG japan and shindou ROMs contain this<br />
    {<br />
    fseek(rom, 0, SEEK_SET);<br />
// 35th byte starts ER M in OG japan and ERMA in shindou, how convenient. This is because shindou says the game name is SUPERMARIO64, all other versions say SUPER MARIO 64<br />
    fseek(rom, 35, SEEK_SET);<br />
    fread(&rom_byte_1, 1, 1, rom);<br />
    fread(&rom_byte_2, 1, 1, rom);<br />
    fread(&rom_byte_3, 1, 1, rom);<br />
    fread(&rom_byte_4, 1, 1, rom);<br />
        if(rom_byte_1 == 0x45 && rom_byte_2 == 0x52 && rom_byte_3 == 0x20 && rom_byte_4 == 0x4D) //ER M in hex<br />
        {<br />
        printf("Validated ROM as .z64 Japan\n");<br />
        }<br />
        else if(rom_byte_1 == 0x45 && rom_byte_2 == 0x52 && rom_byte_3 == 0x4D && rom_byte_4 == 0x41) //ERMA in hex<br />
        {<br />
        printf("Validated ROM as .z64 Shindou Edition\n");<br />
        }<br />
        else<br />
        {<br />
// Should be impossible<br />
        printf("Error: Can not figure out if this is the original Japan or the Shindou Edition ROM!\n");<br />
        end_input = TRUE;<br />
        }<br />
    }<br />
    else if(rom_byte_1 == 0x4E && rom_byte_2 == 0x53 && rom_byte_3 == 0x4D && rom_byte_4 == 0x45) //NSMJ in hex<br />
    {<br />
    printf("Validated ROM as .z64 USA\n");<br />
    }<br />
    else if(rom_byte_1 == 0x4E && rom_byte_2 == 0x53 && rom_byte_3 == 0x4D && rom_byte_4 == 0x50) //NSME in hex<br />
    {<br />
    printf("Validated ROM as .z64 PAL\n");<br />
    }<br />
    else<br />
    {<br />
    fseek(rom, 0, SEEK_SET);<br />
    fread(&rom_byte_1, 1, 1, rom);<br />
    fread(&rom_byte_2, 1, 1, rom);<br />
    fread(&rom_byte_3, 1, 1, rom);<br />
    fread(&rom_byte_4, 1, 1, rom);<br />
        if(rom_byte_1 == 0x37 && rom_byte_2 == 0x80 && rom_byte_3 == 0x40 && rom_byte_4 == 0x12) // First 4 bytes of a little endian sm64 rom which is NOT supported<br />
        {<br />
        printf("This is a little-endian, .n64 format SM64 ROM file. SM64GSW requires a big-endian, .z64 format SM64 ROM file.\n");<br />
        end_input = TRUE;<br />
        }<br />
        else<br />
        {<br />
        printf("Error: This does not appear to be a valid SM64 ROM!\n");<br />
        end_input = TRUE;<br />
        }<br />
    }<br />
}<br />
<br />
This is a little snippet of the SM64GSW v1.4 I'm working on, and I thought this could be useful to others. The above code was figured out by myself using a hex editor on various .z64 (A.K.A Big-Endian PROPER file format ROMs). This is 3-BSD licensed as SM64GSW is 3-BSD licensed (but does not include this code yet) <a href="https://github.com/alex-free/sm64gsw" target="_blank" rel="noopener" class="mycode_url">https://github.com/alex-free/sm64gsw</a> . Of course simple file markers are not copyrightable so feel free to use them in other software, no matter the license <img src="https://hack64.net/images/smilies/smile.png" alt="Smile" title="Smile" class="smilie smilie_1" />]]></description>
			<content:encoded><![CDATA[void check_rom()<br />
{<br />
// Read byte by byte so endian-ness is irrelevant<br />
    fseek(rom, 0, SEEK_SET);<br />
// 59th byte starts region ID<br />
    fseek(rom, 59, SEEK_SET);<br />
    fread(&rom_byte_1, 1, 1, rom);<br />
    fread(&rom_byte_2, 1, 1, rom);<br />
    fread(&rom_byte_3, 1, 1, rom);<br />
    fread(&rom_byte_4, 1, 1, rom);<br />
    <br />
    if(rom_byte_1 == 0x4E && rom_byte_2 == 0x53 && rom_byte_3 == 0x4D && rom_byte_4 == 0x4A) //NSMJ in hex, both OG japan and shindou ROMs contain this<br />
    {<br />
    fseek(rom, 0, SEEK_SET);<br />
// 35th byte starts ER M in OG japan and ERMA in shindou, how convenient. This is because shindou says the game name is SUPERMARIO64, all other versions say SUPER MARIO 64<br />
    fseek(rom, 35, SEEK_SET);<br />
    fread(&rom_byte_1, 1, 1, rom);<br />
    fread(&rom_byte_2, 1, 1, rom);<br />
    fread(&rom_byte_3, 1, 1, rom);<br />
    fread(&rom_byte_4, 1, 1, rom);<br />
        if(rom_byte_1 == 0x45 && rom_byte_2 == 0x52 && rom_byte_3 == 0x20 && rom_byte_4 == 0x4D) //ER M in hex<br />
        {<br />
        printf("Validated ROM as .z64 Japan\n");<br />
        }<br />
        else if(rom_byte_1 == 0x45 && rom_byte_2 == 0x52 && rom_byte_3 == 0x4D && rom_byte_4 == 0x41) //ERMA in hex<br />
        {<br />
        printf("Validated ROM as .z64 Shindou Edition\n");<br />
        }<br />
        else<br />
        {<br />
// Should be impossible<br />
        printf("Error: Can not figure out if this is the original Japan or the Shindou Edition ROM!\n");<br />
        end_input = TRUE;<br />
        }<br />
    }<br />
    else if(rom_byte_1 == 0x4E && rom_byte_2 == 0x53 && rom_byte_3 == 0x4D && rom_byte_4 == 0x45) //NSMJ in hex<br />
    {<br />
    printf("Validated ROM as .z64 USA\n");<br />
    }<br />
    else if(rom_byte_1 == 0x4E && rom_byte_2 == 0x53 && rom_byte_3 == 0x4D && rom_byte_4 == 0x50) //NSME in hex<br />
    {<br />
    printf("Validated ROM as .z64 PAL\n");<br />
    }<br />
    else<br />
    {<br />
    fseek(rom, 0, SEEK_SET);<br />
    fread(&rom_byte_1, 1, 1, rom);<br />
    fread(&rom_byte_2, 1, 1, rom);<br />
    fread(&rom_byte_3, 1, 1, rom);<br />
    fread(&rom_byte_4, 1, 1, rom);<br />
        if(rom_byte_1 == 0x37 && rom_byte_2 == 0x80 && rom_byte_3 == 0x40 && rom_byte_4 == 0x12) // First 4 bytes of a little endian sm64 rom which is NOT supported<br />
        {<br />
        printf("This is a little-endian, .n64 format SM64 ROM file. SM64GSW requires a big-endian, .z64 format SM64 ROM file.\n");<br />
        end_input = TRUE;<br />
        }<br />
        else<br />
        {<br />
        printf("Error: This does not appear to be a valid SM64 ROM!\n");<br />
        end_input = TRUE;<br />
        }<br />
    }<br />
}<br />
<br />
This is a little snippet of the SM64GSW v1.4 I'm working on, and I thought this could be useful to others. The above code was figured out by myself using a hex editor on various .z64 (A.K.A Big-Endian PROPER file format ROMs). This is 3-BSD licensed as SM64GSW is 3-BSD licensed (but does not include this code yet) <a href="https://github.com/alex-free/sm64gsw" target="_blank" rel="noopener" class="mycode_url">https://github.com/alex-free/sm64gsw</a> . Of course simple file markers are not copyrightable so feel free to use them in other software, no matter the license <img src="https://hack64.net/images/smilies/smile.png" alt="Smile" title="Smile" class="smilie smilie_1" />]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Web-based N64 ROM byteswapper (.n64/.v64 to .z64)]]></title>
			<link>https://hack64.net/Thread-Web-based-N64-ROM-byteswapper-n64-v64-to-z64</link>
			<pubDate>Mon, 24 Feb 2020 01:06:11 +0000</pubDate>
			<guid isPermaLink="false">https://hack64.net/Thread-Web-based-N64-ROM-byteswapper-n64-v64-to-z64</guid>
			<description><![CDATA[Here's a web-based tool for converting malignant .n64/.v64-formatted ROMs to .z64:<br />
<br />
<a href="https://hack64.net/tools/swapper.php" target="_blank" rel="noopener" class="mycode_url">https://hack64.net/tools/swapper.php</a>]]></description>
			<content:encoded><![CDATA[Here's a web-based tool for converting malignant .n64/.v64-formatted ROMs to .z64:<br />
<br />
<a href="https://hack64.net/tools/swapper.php" target="_blank" rel="noopener" class="mycode_url">https://hack64.net/tools/swapper.php</a>]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[ExoQuant - A color reduction library that can be used for CI textures]]></title>
			<link>https://hack64.net/Thread-ExoQuant-A-color-reduction-library-that-can-be-used-for-CI-textures</link>
			<pubDate>Sat, 13 Apr 2019 04:22:32 +0000</pubDate>
			<guid isPermaLink="false">https://hack64.net/Thread-ExoQuant-A-color-reduction-library-that-can-be-used-for-CI-textures</guid>
			<description><![CDATA[ExoQuant is a MIT licensed C library written by Dennis Ranke that can be used to reduce the number of colors in an image, which is useful for creating CI textures. I have also written ports to C#, Javascript, VB.NET, and Python that should give the same results as the original C version.<br />
<br />
ExoQuant v0.7 (C/C++): <a href="https://github.com/exoticorn/exoquant" target="_blank" rel="noopener" class="mycode_url">https://github.com/exoticorn/exoquant</a><br />
ExoQuantSharp (C#): <a href="https://github.com/DavidSM64/ExoQuantSharp" target="_blank" rel="noopener" class="mycode_url">https://github.com/DavidSM64/ExoQuantSharp</a><br />
ExoQuantJS (Javascript): <a href="https://github.com/DavidSM64/ExoQuantJS" target="_blank" rel="noopener" class="mycode_url">https://github.com/DavidSM64/ExoQuantJS</a><br />
ExoQuantVB (Visual Basic .NET): <a href="https://github.com/DavidSM64/ExoQuantVB" target="_blank" rel="noopener" class="mycode_url">https://github.com/DavidSM64/ExoQuantVB</a><br />
ExoQuantPY (Python): <a href="https://github.com/DavidSM64/ExoQuantPY" target="_blank" rel="noopener" class="mycode_url">https://github.com/DavidSM64/ExoQuantPY</a><br />
<br />
<span style="font-size: x-large;" class="mycode_size">Converting RGBA32 data to CI data + palette:</span><br />
<br />
<div class="spoiler">
		<div class="thead"><button class="button float_right" onclick="javascript: if(parentNode.parentNode.getElementsByTagName('div')[2].style.display == 'block'){ parentNode.parentNode.getElementsByTagName('div')[2].style.display = 'none'; this.innerHTML='Show Content'; } else { parentNode.parentNode.getElementsByTagName('div')[2].style.display = 'block'; this.innerHTML='Hide Content'; }">Show Content</button>C<div style="clear: both;"></div></div>
		<div class="trow1" style="display: none;">
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>/**<br />
* width = Width of the Texture.<br />
* height = Height of the Texture.<br />
* ciBitDepth = Should either be 4 for CI4, or 8 for CI8<br />
* numOfColors = Size of the color palette.<br />
* rgba32Data = input RGBA32 data<br />
* ciData = output CI data<br />
* rgba16Palette = output palette for CI data<br />
*/<br />
void ConvertRGBA32ToCI(int width, int height, int ciBitDepth, int numOfColors, unsigned char *rgba32Data, unsigned char **ciData, unsigned char **rgba16Palette)<br />
{<br />
   if (ciBitDepth == 8) // CI8<br />
   {<br />
       if (numOfColors &gt; 256)<br />
           numOfColors = 256;<br />
   }<br />
   else // CI4<br />
   {<br />
       if (numOfColors &gt; 16)<br />
           numOfColors = 16;<br />
   }<br />
<br />
   int ci_len = width * height;<br />
   <br />
   unsigned char* ci8Data = malloc(ci_len); // Output CI8 data buffer.<br />
   unsigned char* rgba32Palette = malloc(numOfColors * 4); // palette buffer.<br />
<br />
   // Use ExoQuant to reduce the number of colors.<br />
   exq_data *pExq = exq_init();<br />
   exq_feed(pExq, rgba32Data, ci_len);<br />
   exq_quantize_hq(pExq, numOfColors);<br />
   exq_get_palette(pExq, rgba32Palette, numOfColors);<br />
   exq_map_image_ordered(pExq, width, height, rgba32Data, ci8Data);<br />
   exq_free(pExq);<br />
   <br />
   *rgba16Palette = malloc(numOfColors * 2);<br />
<br />
   // Convert RGBA32 palette to a RGBA16 palette<br />
   for (int i = 0; i &lt; numOfColors; i++)<br />
   {<br />
       unsigned char red = (rgba32Palette[i * 4 + 0] / 8) &amp; 0x1F;<br />
       unsigned char green = (rgba32Palette[i * 4 + 1] / 8) &amp; 0x1F;<br />
       unsigned char blue = (rgba32Palette[i * 4 + 2] / 8) &amp; 0x1F;<br />
       unsigned char alpha = rgba32Palette[i * 4 + 3] &gt; 0 ? 1 : 0; // 1 bit alpha<br />
<br />
       (*rgba16Palette)[i * 2 + 0] = (red &lt;&lt; 3) | (green &gt;&gt; 2);<br />
       (*rgba16Palette)[i * 2 + 1] = ((green &amp; 3) &lt;&lt; 6) | (blue &lt;&lt; 1) | alpha;<br />
   }<br />
<br />
<br />
   if (ciBitDepth == 4)<br />
   {<br />
       ci_len /= 2;<br />
       <br />
       *ciData = malloc(ci_len);<br />
       for (int i = 0; i &lt; ci_len; i++)<br />
       {<br />
           (*ciData)[i] = (ci8Data[i * 2 + 0] &lt;&lt; 4) | ci8Data[i * 2 + 1];<br />
       }<br />
   }<br />
   else<br />
   {<br />
       *ciData = malloc(ci_len);<br />
       for(int i = 0; i &lt; ci_len; i++)<br />
       {<br />
           (*ciData)[i] = ci8Data[i];<br />
       }<br />
   }<br />
   <br />
   free(ci8Data);<br />
   free(rgba32Palette);<br />
}</code></div></div></div>
	</div>
<div class="spoiler">
		<div class="thead"><button class="button float_right" onclick="javascript: if(parentNode.parentNode.getElementsByTagName('div')[2].style.display == 'block'){ parentNode.parentNode.getElementsByTagName('div')[2].style.display = 'none'; this.innerHTML='Show Content'; } else { parentNode.parentNode.getElementsByTagName('div')[2].style.display = 'block'; this.innerHTML='Hide Content'; }">Show Content</button>C++<div style="clear: both;"></div></div>
		<div class="trow1" style="display: none;">
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>/**<br />
* width = Width of the Texture.<br />
* height = Height of the Texture.<br />
* ciBitDepth = Should either be 4 for CI4, or 8 for CI8<br />
* numOfColors = Size of the color palette.<br />
* rgba32Data = input RGBA32 data<br />
* ciData = output CI data<br />
* rgba16Palette = output palette for CI data<br />
*/<br />
void ConvertRGBA32ToCI(int width, int height, int ciBitDepth, int numOfColors, std::vector&lt;unsigned char&gt; &amp;rgba32Data, std::vector&lt;unsigned char&gt; &amp;ciData, std::vector&lt;unsigned char&gt; &amp;rgba16Palette)<br />
{<br />
    if (ciBitDepth != 4 &amp;&amp; ciBitDepth != 8)<br />
        throw std::invalid_argument("Invalid CI type! ciBitDepth should either be 4 or 8.");<br />
<br />
    if (ciBitDepth == 8) // CI8<br />
    {<br />
        if (numOfColors &gt; 256)<br />
            numOfColors = 256;<br />
    }<br />
    else // CI4<br />
    {<br />
        if (numOfColors &gt; 16)<br />
            numOfColors = 16;<br />
    }<br />
<br />
    std::vector&lt;unsigned char&gt; ci8Data(rgba32Data.size() / 4); // Output CI8 data buffer.<br />
    std::vector&lt;unsigned char&gt; rgba32Palette(numOfColors * 4); // palette buffer.<br />
<br />
    // Use ExoQuant to reduce the number of colors.<br />
    exq_data *pExq = exq_init();<br />
    exq_feed(pExq, (unsigned char*)&amp;rgba32Data[0], width * height);<br />
    exq_quantize_hq(pExq, numOfColors);<br />
    exq_get_palette(pExq, (unsigned char*)&amp;rgba32Palette[0], numOfColors);<br />
    exq_map_image_ordered(pExq, width, height, (unsigned char*)&amp;rgba32Data[0], (unsigned char*)&amp;ci8Data[0]);<br />
    exq_free(pExq);<br />
    <br />
    rgba16Palette.resize(numOfColors * 2);<br />
<br />
    // Convert RGBA32 palette to a RGBA16 palette<br />
    for (int i = 0; i &lt; numOfColors; i++)<br />
    {<br />
        unsigned char red = (rgba32Palette[i * 4 + 0] / 8) &amp; 0x1F;<br />
        unsigned char green = (rgba32Palette[i * 4 + 1] / 8) &amp; 0x1F;<br />
        unsigned char blue = (rgba32Palette[i * 4 + 2] / 8) &amp; 0x1F;<br />
        unsigned char alpha = rgba32Palette[i * 4 + 3] &gt; 0 ? 1 : 0; // 1 bit alpha<br />
<br />
        rgba16Palette[i * 2 + 0] = (red &lt;&lt; 3) | (green &gt;&gt; 2);<br />
        rgba16Palette[i * 2 + 1] = ((green &amp; 3) &lt;&lt; 6) | (blue &lt;&lt; 1) | alpha;<br />
    }<br />
<br />
    if (ciBitDepth == 4)<br />
    {<br />
        // Convert CI8 image to CI4 image<br />
        ciData.resize(ci8Data.size() / 2);<br />
        for (int i = 0; i &lt; ciData.size(); i++)<br />
        {<br />
            ciData[i] = (ci8Data[i * 2 + 0] &lt;&lt; 4) | ci8Data[i * 2 + 1];<br />
        }<br />
    }<br />
    else<br />
    {<br />
        ciData.resize(ci8Data.size());<br />
        for(int i = 0; i &lt; ci8Data.size(); i++)<br />
        {<br />
            ciData[i] = ci8Data[i];<br />
        }<br />
    }<br />
}</code></div></div></div>
	</div>
<div class="spoiler">
		<div class="thead"><button class="button float_right" onclick="javascript: if(parentNode.parentNode.getElementsByTagName('div')[2].style.display == 'block'){ parentNode.parentNode.getElementsByTagName('div')[2].style.display = 'none'; this.innerHTML='Show Content'; } else { parentNode.parentNode.getElementsByTagName('div')[2].style.display = 'block'; this.innerHTML='Hide Content'; }">Show Content</button>C#<div style="clear: both;"></div></div>
		<div class="trow1" style="display: none;">
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>/**<br />
* width = Width of the Texture.<br />
* height = Height of the Texture.<br />
* ciBitDepth = Should either be 4 for CI4, or 8 for CI8<br />
* numOfColors = Size of the color palette.<br />
* rgba32Data = input RGBA32 data<br />
* out ciData = output CI data<br />
* out rgba16Palette = output palette for CI data<br />
*/<br />
void ConvertRGBA32ToCI(int width, int height, int ciBitDepth, int numOfColors, byte[] rgba32Data, out byte[] ciData, out byte[] rgba16Palette)<br />
{<br />
    if (ciBitDepth != 4 &amp;&amp; ciBitDepth != 8)<br />
        throw new Exception("Invalid CI type: CI" + ciBitDepth);<br />
<br />
    if (ciBitDepth == 8) // CI8<br />
    {<br />
        if (numOfColors &gt; 256)<br />
            numOfColors = 256;<br />
    }<br />
    else // CI4<br />
    {<br />
        if (numOfColors &gt; 16)<br />
            numOfColors = 16;<br />
    }<br />
<br />
    // Use ExoQuant to reduce the number of colors.<br />
    ExoQuant exq = new ExoQuant();<br />
    exq.Feed(rgba32Data);<br />
    exq.QuantizeHq(numOfColors);<br />
    exq.GetPalette(out byte[] rgba32Palette, numOfColors);<br />
    exq.MapImageOrdered(width, height, rgba32Data, out byte[] ci8Data);<br />
<br />
    rgba16Palette = new byte[numOfColors * 2];<br />
<br />
    // Convert RGBA32 palette to a RGBA16 palette<br />
    for (int i = 0; i &lt; numOfColors; i++)<br />
    {<br />
        byte red = (byte)((rgba32Palette[i * 4 + 0] / 8) &amp; 0x1F);<br />
        byte green = (byte)((rgba32Palette[i * 4 + 1] / 8) &amp; 0x1F);<br />
        byte blue = (byte)((rgba32Palette[i * 4 + 2] / 8) &amp; 0x1F);<br />
        byte alpha = (byte)(rgba32Palette[i * 4 + 3] &gt; 0 ? 1 : 0); // 1 bit alpha<br />
<br />
        rgba16Palette[i * 2 + 0] = (byte)((red &lt;&lt; 3) | (green &gt;&gt; 2));<br />
        rgba16Palette[i * 2 + 1] = (byte)(((green &amp; 3) &lt;&lt; 6) | (blue &lt;&lt; 1) | alpha);<br />
    }<br />
<br />
    if (ciBitDepth == 4)<br />
    {<br />
        // Convert CI8 image to CI4 image<br />
        ciData = new byte[rgba32Data.Length / 8];<br />
        for (int i = 0; i &lt; ciData.Length; i++)<br />
        {<br />
            ciData[i] = (byte)((ci8Data[i * 2 + 0] &lt;&lt; 4) | ci8Data[i * 2 + 1]);<br />
        }<br />
    }<br />
    else<br />
        ciData = ci8Data;<br />
}</code></div></div></div>
	</div>
<br />
<span style="font-size: x-large;" class="mycode_size">Comparing RGBA16 to CI4:</span><br />
<br />
A benefit of using CI4 is that it uses up much less data in a ROM compared to RGBA16. Not all textures should be converted to CI4 though. If a texture relies on having lots of different hues, then it will not translate to CI4 well.<br />
<br />
The level backgrounds in SM64 are pretty good CI4 candidates, since they generally theme around one or two colors.<br />
<br />
<span style="font-size: large;" class="mycode_size"><img src="https://i.imgur.com/JCanpLB.png" alt="[Image: JCanpLB.png]" class="mycode_img" /></span><br />
<br />
However, the castle paintings are bad CI4 candidates since they use a lot of different colors.<br />
<br />
<span style="font-size: large;" class="mycode_size"><img src="https://i.imgur.com/TUYOxQT.png" alt="[Image: TUYOxQT.png]" class="mycode_img" /></span>]]></description>
			<content:encoded><![CDATA[ExoQuant is a MIT licensed C library written by Dennis Ranke that can be used to reduce the number of colors in an image, which is useful for creating CI textures. I have also written ports to C#, Javascript, VB.NET, and Python that should give the same results as the original C version.<br />
<br />
ExoQuant v0.7 (C/C++): <a href="https://github.com/exoticorn/exoquant" target="_blank" rel="noopener" class="mycode_url">https://github.com/exoticorn/exoquant</a><br />
ExoQuantSharp (C#): <a href="https://github.com/DavidSM64/ExoQuantSharp" target="_blank" rel="noopener" class="mycode_url">https://github.com/DavidSM64/ExoQuantSharp</a><br />
ExoQuantJS (Javascript): <a href="https://github.com/DavidSM64/ExoQuantJS" target="_blank" rel="noopener" class="mycode_url">https://github.com/DavidSM64/ExoQuantJS</a><br />
ExoQuantVB (Visual Basic .NET): <a href="https://github.com/DavidSM64/ExoQuantVB" target="_blank" rel="noopener" class="mycode_url">https://github.com/DavidSM64/ExoQuantVB</a><br />
ExoQuantPY (Python): <a href="https://github.com/DavidSM64/ExoQuantPY" target="_blank" rel="noopener" class="mycode_url">https://github.com/DavidSM64/ExoQuantPY</a><br />
<br />
<span style="font-size: x-large;" class="mycode_size">Converting RGBA32 data to CI data + palette:</span><br />
<br />
<div class="spoiler">
		<div class="thead"><button class="button float_right" onclick="javascript: if(parentNode.parentNode.getElementsByTagName('div')[2].style.display == 'block'){ parentNode.parentNode.getElementsByTagName('div')[2].style.display = 'none'; this.innerHTML='Show Content'; } else { parentNode.parentNode.getElementsByTagName('div')[2].style.display = 'block'; this.innerHTML='Hide Content'; }">Show Content</button>C<div style="clear: both;"></div></div>
		<div class="trow1" style="display: none;">
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>/**<br />
* width = Width of the Texture.<br />
* height = Height of the Texture.<br />
* ciBitDepth = Should either be 4 for CI4, or 8 for CI8<br />
* numOfColors = Size of the color palette.<br />
* rgba32Data = input RGBA32 data<br />
* ciData = output CI data<br />
* rgba16Palette = output palette for CI data<br />
*/<br />
void ConvertRGBA32ToCI(int width, int height, int ciBitDepth, int numOfColors, unsigned char *rgba32Data, unsigned char **ciData, unsigned char **rgba16Palette)<br />
{<br />
   if (ciBitDepth == 8) // CI8<br />
   {<br />
       if (numOfColors &gt; 256)<br />
           numOfColors = 256;<br />
   }<br />
   else // CI4<br />
   {<br />
       if (numOfColors &gt; 16)<br />
           numOfColors = 16;<br />
   }<br />
<br />
   int ci_len = width * height;<br />
   <br />
   unsigned char* ci8Data = malloc(ci_len); // Output CI8 data buffer.<br />
   unsigned char* rgba32Palette = malloc(numOfColors * 4); // palette buffer.<br />
<br />
   // Use ExoQuant to reduce the number of colors.<br />
   exq_data *pExq = exq_init();<br />
   exq_feed(pExq, rgba32Data, ci_len);<br />
   exq_quantize_hq(pExq, numOfColors);<br />
   exq_get_palette(pExq, rgba32Palette, numOfColors);<br />
   exq_map_image_ordered(pExq, width, height, rgba32Data, ci8Data);<br />
   exq_free(pExq);<br />
   <br />
   *rgba16Palette = malloc(numOfColors * 2);<br />
<br />
   // Convert RGBA32 palette to a RGBA16 palette<br />
   for (int i = 0; i &lt; numOfColors; i++)<br />
   {<br />
       unsigned char red = (rgba32Palette[i * 4 + 0] / 8) &amp; 0x1F;<br />
       unsigned char green = (rgba32Palette[i * 4 + 1] / 8) &amp; 0x1F;<br />
       unsigned char blue = (rgba32Palette[i * 4 + 2] / 8) &amp; 0x1F;<br />
       unsigned char alpha = rgba32Palette[i * 4 + 3] &gt; 0 ? 1 : 0; // 1 bit alpha<br />
<br />
       (*rgba16Palette)[i * 2 + 0] = (red &lt;&lt; 3) | (green &gt;&gt; 2);<br />
       (*rgba16Palette)[i * 2 + 1] = ((green &amp; 3) &lt;&lt; 6) | (blue &lt;&lt; 1) | alpha;<br />
   }<br />
<br />
<br />
   if (ciBitDepth == 4)<br />
   {<br />
       ci_len /= 2;<br />
       <br />
       *ciData = malloc(ci_len);<br />
       for (int i = 0; i &lt; ci_len; i++)<br />
       {<br />
           (*ciData)[i] = (ci8Data[i * 2 + 0] &lt;&lt; 4) | ci8Data[i * 2 + 1];<br />
       }<br />
   }<br />
   else<br />
   {<br />
       *ciData = malloc(ci_len);<br />
       for(int i = 0; i &lt; ci_len; i++)<br />
       {<br />
           (*ciData)[i] = ci8Data[i];<br />
       }<br />
   }<br />
   <br />
   free(ci8Data);<br />
   free(rgba32Palette);<br />
}</code></div></div></div>
	</div>
<div class="spoiler">
		<div class="thead"><button class="button float_right" onclick="javascript: if(parentNode.parentNode.getElementsByTagName('div')[2].style.display == 'block'){ parentNode.parentNode.getElementsByTagName('div')[2].style.display = 'none'; this.innerHTML='Show Content'; } else { parentNode.parentNode.getElementsByTagName('div')[2].style.display = 'block'; this.innerHTML='Hide Content'; }">Show Content</button>C++<div style="clear: both;"></div></div>
		<div class="trow1" style="display: none;">
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>/**<br />
* width = Width of the Texture.<br />
* height = Height of the Texture.<br />
* ciBitDepth = Should either be 4 for CI4, or 8 for CI8<br />
* numOfColors = Size of the color palette.<br />
* rgba32Data = input RGBA32 data<br />
* ciData = output CI data<br />
* rgba16Palette = output palette for CI data<br />
*/<br />
void ConvertRGBA32ToCI(int width, int height, int ciBitDepth, int numOfColors, std::vector&lt;unsigned char&gt; &amp;rgba32Data, std::vector&lt;unsigned char&gt; &amp;ciData, std::vector&lt;unsigned char&gt; &amp;rgba16Palette)<br />
{<br />
    if (ciBitDepth != 4 &amp;&amp; ciBitDepth != 8)<br />
        throw std::invalid_argument("Invalid CI type! ciBitDepth should either be 4 or 8.");<br />
<br />
    if (ciBitDepth == 8) // CI8<br />
    {<br />
        if (numOfColors &gt; 256)<br />
            numOfColors = 256;<br />
    }<br />
    else // CI4<br />
    {<br />
        if (numOfColors &gt; 16)<br />
            numOfColors = 16;<br />
    }<br />
<br />
    std::vector&lt;unsigned char&gt; ci8Data(rgba32Data.size() / 4); // Output CI8 data buffer.<br />
    std::vector&lt;unsigned char&gt; rgba32Palette(numOfColors * 4); // palette buffer.<br />
<br />
    // Use ExoQuant to reduce the number of colors.<br />
    exq_data *pExq = exq_init();<br />
    exq_feed(pExq, (unsigned char*)&amp;rgba32Data[0], width * height);<br />
    exq_quantize_hq(pExq, numOfColors);<br />
    exq_get_palette(pExq, (unsigned char*)&amp;rgba32Palette[0], numOfColors);<br />
    exq_map_image_ordered(pExq, width, height, (unsigned char*)&amp;rgba32Data[0], (unsigned char*)&amp;ci8Data[0]);<br />
    exq_free(pExq);<br />
    <br />
    rgba16Palette.resize(numOfColors * 2);<br />
<br />
    // Convert RGBA32 palette to a RGBA16 palette<br />
    for (int i = 0; i &lt; numOfColors; i++)<br />
    {<br />
        unsigned char red = (rgba32Palette[i * 4 + 0] / 8) &amp; 0x1F;<br />
        unsigned char green = (rgba32Palette[i * 4 + 1] / 8) &amp; 0x1F;<br />
        unsigned char blue = (rgba32Palette[i * 4 + 2] / 8) &amp; 0x1F;<br />
        unsigned char alpha = rgba32Palette[i * 4 + 3] &gt; 0 ? 1 : 0; // 1 bit alpha<br />
<br />
        rgba16Palette[i * 2 + 0] = (red &lt;&lt; 3) | (green &gt;&gt; 2);<br />
        rgba16Palette[i * 2 + 1] = ((green &amp; 3) &lt;&lt; 6) | (blue &lt;&lt; 1) | alpha;<br />
    }<br />
<br />
    if (ciBitDepth == 4)<br />
    {<br />
        // Convert CI8 image to CI4 image<br />
        ciData.resize(ci8Data.size() / 2);<br />
        for (int i = 0; i &lt; ciData.size(); i++)<br />
        {<br />
            ciData[i] = (ci8Data[i * 2 + 0] &lt;&lt; 4) | ci8Data[i * 2 + 1];<br />
        }<br />
    }<br />
    else<br />
    {<br />
        ciData.resize(ci8Data.size());<br />
        for(int i = 0; i &lt; ci8Data.size(); i++)<br />
        {<br />
            ciData[i] = ci8Data[i];<br />
        }<br />
    }<br />
}</code></div></div></div>
	</div>
<div class="spoiler">
		<div class="thead"><button class="button float_right" onclick="javascript: if(parentNode.parentNode.getElementsByTagName('div')[2].style.display == 'block'){ parentNode.parentNode.getElementsByTagName('div')[2].style.display = 'none'; this.innerHTML='Show Content'; } else { parentNode.parentNode.getElementsByTagName('div')[2].style.display = 'block'; this.innerHTML='Hide Content'; }">Show Content</button>C#<div style="clear: both;"></div></div>
		<div class="trow1" style="display: none;">
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>/**<br />
* width = Width of the Texture.<br />
* height = Height of the Texture.<br />
* ciBitDepth = Should either be 4 for CI4, or 8 for CI8<br />
* numOfColors = Size of the color palette.<br />
* rgba32Data = input RGBA32 data<br />
* out ciData = output CI data<br />
* out rgba16Palette = output palette for CI data<br />
*/<br />
void ConvertRGBA32ToCI(int width, int height, int ciBitDepth, int numOfColors, byte[] rgba32Data, out byte[] ciData, out byte[] rgba16Palette)<br />
{<br />
    if (ciBitDepth != 4 &amp;&amp; ciBitDepth != 8)<br />
        throw new Exception("Invalid CI type: CI" + ciBitDepth);<br />
<br />
    if (ciBitDepth == 8) // CI8<br />
    {<br />
        if (numOfColors &gt; 256)<br />
            numOfColors = 256;<br />
    }<br />
    else // CI4<br />
    {<br />
        if (numOfColors &gt; 16)<br />
            numOfColors = 16;<br />
    }<br />
<br />
    // Use ExoQuant to reduce the number of colors.<br />
    ExoQuant exq = new ExoQuant();<br />
    exq.Feed(rgba32Data);<br />
    exq.QuantizeHq(numOfColors);<br />
    exq.GetPalette(out byte[] rgba32Palette, numOfColors);<br />
    exq.MapImageOrdered(width, height, rgba32Data, out byte[] ci8Data);<br />
<br />
    rgba16Palette = new byte[numOfColors * 2];<br />
<br />
    // Convert RGBA32 palette to a RGBA16 palette<br />
    for (int i = 0; i &lt; numOfColors; i++)<br />
    {<br />
        byte red = (byte)((rgba32Palette[i * 4 + 0] / 8) &amp; 0x1F);<br />
        byte green = (byte)((rgba32Palette[i * 4 + 1] / 8) &amp; 0x1F);<br />
        byte blue = (byte)((rgba32Palette[i * 4 + 2] / 8) &amp; 0x1F);<br />
        byte alpha = (byte)(rgba32Palette[i * 4 + 3] &gt; 0 ? 1 : 0); // 1 bit alpha<br />
<br />
        rgba16Palette[i * 2 + 0] = (byte)((red &lt;&lt; 3) | (green &gt;&gt; 2));<br />
        rgba16Palette[i * 2 + 1] = (byte)(((green &amp; 3) &lt;&lt; 6) | (blue &lt;&lt; 1) | alpha);<br />
    }<br />
<br />
    if (ciBitDepth == 4)<br />
    {<br />
        // Convert CI8 image to CI4 image<br />
        ciData = new byte[rgba32Data.Length / 8];<br />
        for (int i = 0; i &lt; ciData.Length; i++)<br />
        {<br />
            ciData[i] = (byte)((ci8Data[i * 2 + 0] &lt;&lt; 4) | ci8Data[i * 2 + 1]);<br />
        }<br />
    }<br />
    else<br />
        ciData = ci8Data;<br />
}</code></div></div></div>
	</div>
<br />
<span style="font-size: x-large;" class="mycode_size">Comparing RGBA16 to CI4:</span><br />
<br />
A benefit of using CI4 is that it uses up much less data in a ROM compared to RGBA16. Not all textures should be converted to CI4 though. If a texture relies on having lots of different hues, then it will not translate to CI4 well.<br />
<br />
The level backgrounds in SM64 are pretty good CI4 candidates, since they generally theme around one or two colors.<br />
<br />
<span style="font-size: large;" class="mycode_size"><img src="https://i.imgur.com/JCanpLB.png" alt="[Image: JCanpLB.png]" class="mycode_img" /></span><br />
<br />
However, the castle paintings are bad CI4 candidates since they use a lot of different colors.<br />
<br />
<span style="font-size: large;" class="mycode_size"><img src="https://i.imgur.com/TUYOxQT.png" alt="[Image: TUYOxQT.png]" class="mycode_img" /></span>]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Virtual Pro-Wrestling 2 freem Edition]]></title>
			<link>https://hack64.net/Thread-Virtual-Pro-Wrestling-2-freem-Edition</link>
			<pubDate>Tue, 05 Feb 2019 22:42:22 +0000</pubDate>
			<guid isPermaLink="false">https://hack64.net/Thread-Virtual-Pro-Wrestling-2-freem-Edition</guid>
			<description><![CDATA[<span style="font-weight: bold;" class="mycode_b"><img src="http://vpw.ajworld.net/vpw2freem/media/vpw2fe_logo.png" alt="[Image: vpw2fe_logo.png]" class="mycode_img" /><br />
<br />
<a href="http://vpw.ajworld.net/vpw2freem/" target="_blank" rel="noopener" class="mycode_url">Official website</a></span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">Virtual Pro-Wrestling 2 freem Edition</span> is a hack of AKI Corporation's Virtual Pro-Wrestling 2 on the Nintendo 64. The hack replaces various default VPW2 wrestlers with other wrestlers, most of whom have been in other AKI wrestling games. Unlike most other AKI wrestling game modding projects, the changes in VPW2 freem Edition are made by editing the ROM, meaning the resulting hack can be played on real hardware.<br />
<br />
A quick rundown of what's been changed:<ul class="mycode_list">
</li>
<li>Replaced various wrestlers with wrestlers from other AKI wrestling games.<br />
</li>
<li>Replaced a small amount of wrestlers with new wrestlers (who haven't been in an AKI game before).<br />
</li>
<li>The game starts out fully unlocked; nothing is hidden.<br />
</li>
<li>Increased amount of points available for changing offensive and defensive parameters.<br />
</li>
<li>A bunch of graphical changes. This includes the user interface, as well as some arenas.<br />
</li></ul>
The first preview version was released on January 28, 2019. Expect future updates to fix issues and add other content that wasn't ready in time for the preview release.]]></description>
			<content:encoded><![CDATA[<span style="font-weight: bold;" class="mycode_b"><img src="http://vpw.ajworld.net/vpw2freem/media/vpw2fe_logo.png" alt="[Image: vpw2fe_logo.png]" class="mycode_img" /><br />
<br />
<a href="http://vpw.ajworld.net/vpw2freem/" target="_blank" rel="noopener" class="mycode_url">Official website</a></span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">Virtual Pro-Wrestling 2 freem Edition</span> is a hack of AKI Corporation's Virtual Pro-Wrestling 2 on the Nintendo 64. The hack replaces various default VPW2 wrestlers with other wrestlers, most of whom have been in other AKI wrestling games. Unlike most other AKI wrestling game modding projects, the changes in VPW2 freem Edition are made by editing the ROM, meaning the resulting hack can be played on real hardware.<br />
<br />
A quick rundown of what's been changed:<ul class="mycode_list">
</li>
<li>Replaced various wrestlers with wrestlers from other AKI wrestling games.<br />
</li>
<li>Replaced a small amount of wrestlers with new wrestlers (who haven't been in an AKI game before).<br />
</li>
<li>The game starts out fully unlocked; nothing is hidden.<br />
</li>
<li>Increased amount of points available for changing offensive and defensive parameters.<br />
</li>
<li>A bunch of graphical changes. This includes the user interface, as well as some arenas.<br />
</li></ul>
The first preview version was released on January 28, 2019. Expect future updates to fix issues and add other content that wasn't ready in time for the preview release.]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Fast3D Microcodes]]></title>
			<link>https://hack64.net/Thread-Fast3D-Microcodes</link>
			<pubDate>Sun, 18 Nov 2018 04:26:01 +0000</pubDate>
			<guid isPermaLink="false">https://hack64.net/Thread-Fast3D-Microcodes</guid>
			<description><![CDATA[I've been busy the past couple of days going through some N64 roms and extracting the Fast3D microcode from them, and now I'm here to share them with you all. I'm also sharing a couple basic tools that I wrote to dump some of the microcodes, and disassemble the .bin files into readable assembly code.<br />
<br />
<span style="display: inline-block;margin-bottom: 8px;"><span style="font-weight: bold;" class="mycode_b"><span style="font-size: medium;" class="mycode_size">Download</span></span></span><!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://hack64.net/images/attachtypes/zip.png" title="ZIP File" border="0" alt=".zip" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=35" target="_blank" title="">N64 graphics microcode dumps (Nov 17th 2018).zip</a> (Size: 183.25 KB / Downloads: 1277)
<!-- end: postbit_attachments_attachment --><br />
<br />
<div class="spoiler">
		<div class="thead"><button class="button float_right" onclick="javascript: if(parentNode.parentNode.getElementsByTagName('div')[2].style.display == 'block'){ parentNode.parentNode.getElementsByTagName('div')[2].style.display = 'none'; this.innerHTML='Show Content'; } else { parentNode.parentNode.getElementsByTagName('div')[2].style.display = 'block'; this.innerHTML='Hide Content'; }">Show Content</button>List of games and their microcodes that I have so far<div style="clear: both;"></div></div>
		<div class="trow1" style="display: none;">
<code class="codeblock" style="max-height: none; display:block;background-color:#111111">007 - GoldenEye<br />
- gspFast3DNoN.fifo(2.0G)<br />
<br />
Banjo-Kazooie<br />
- gspF3DEX.fifo(1.21)<br />
- gspL3DEX.fifo(1.21)<br />
<br />
Banjo-Tooie<br />
- gspF3DEX2.fifo(2.08)<br />
- gspF3DEX2NoN.fifo(2.08)<br />
- gspL3DEX2.fifo(2.08)<br />
<br />
Conker's Bad Fur Day*<br />
- gspF3DConkerN64.fifo<br />
- gspF3DConkerN64NoN.fifo<br />
- gspF3DConkerN64NoN.fifo(ext)<br />
- gspF3DEX2.fifo<br />
- gspF3DEX2NoN.fifo<br />
- gspF3DEX2BS.fifo<br />
- gspF3DEX2BSNoN.fifo<br />
- gspF3DEX2BG.fifo<br />
- gspF3DEX2BGNoN.fifo<br />
- gspF3DEX2BGBS.fifo<br />
- gspF3DEX2BGBSNoN.fifo<br />
<br />
* Note: "gspF3DConkerN64" was a name I made up, as the signature for the microcode is just "Conker N64 - Rare Ltd". It seems like it is a modified version of gspFast3D, but I'm not 100% sure on that. The "gspF3DConkerN64NoN.fifo(ext)" microcode is nearly identical to "gspF3DConkerN64NoN.fifo", except that 6 lines of assembly code were added. I currently have no idea of what those extra lines do.<br />
<br />
Diddy Kong Racing**<br />
- gspF3DDKR<br />
- gspF3DDKR.dram<br />
- gspF3DDKR.fifo<br />
<br />
** Note: "F3DDKR" is the name given to the microcode by Mupen64. It looks like a modified version of gspFast3D.<br />
<br />
Doraemon - Nobita to 3tsu no Seireiseki<br />
- gspFast3D<br />
- gspFast3D.dram<br />
- gspFast3D.fifo<br />
- gspFast3DNoN<br />
- gspFast3DNoN.dram<br />
- gspFast3DNoN.fifo<br />
<br />
Gex 64: Enter the Gecko<br />
- gspF3DEX.fifo(1.23)<br />
<br />
Mario Kart 64<br />
- gspF3DEX.fifo(0.95)<br />
- gspF3DLX.fifo(0.95)<br />
<br />
Super Mario 64<br />
- gspFast3D.fifo(2.0D)<br />
<br />
Super Mario 64 (Shindou Edition)<br />
- gspFast3D.fifo(2.0H)<br />
<br />
Super Smash Bros<br />
- gspF3DEX2.fifo(2.04H)<br />
<br />
The Legend of Zelda: Ocarina of Time<br />
- F3DZEXNoN.fifo(2.06H)<br />
- S2DEX.fifo(2.05)<br />
<br />
The Legend of Zelda: Majora's Mask<br />
- F3DZEXNoN.fifo(2.08I)<br />
- S2DEX.fifo(2.08)<br />
</code><br />
</div>
	</div>
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b"><span style="font-size: medium;" class="mycode_size">How do I use these .bin files with an OSTask structure?</span></span><br />
<br />
It is straight forward. The <span style="font-weight: bold;" class="mycode_b">.code.bin</span> file is the microcode that gets pointed to by <span style="font-weight: bold;" class="mycode_b">t.ucode</span>, while the <span style="font-weight: bold;" class="mycode_b">.data.bin</span> file is the data that gets pointed to by <span style="font-weight: bold;" class="mycode_b">t.ucode_data</span>. I've also included the boot microcode from every game in their respective folders in the microcode dump. I'm not sure if they are actually needed or not, but if you do need them they are pointed to by <span style="font-weight: bold;" class="mycode_b">t.ucode_boot</span>.<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b"><span style="font-size: medium;" class="mycode_size">Dumping Fast3D microcodes from N64 games</span></span><br />
<br />
The way that I got most of these microcodes is by using shygoo's Javascript API in the latest version Project64 <a href="https://github.com/project64/project64" target="_blank" rel="noopener" class="mycode_url">(You will have to compile Project64 from the github repo)</a>. It is not perfect, but it should be able to get you at-least some Fast3D microcodes from most of the N64 games. Some of microcodes are harder to get than others. For example: I had to dump all 11 of Conker's Fast3D microcodes manually, since only 2 of them are loaded into RAM.<br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://hack64.net/images/attachtypes/zip.png" title="ZIP File" border="0" alt=".zip" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=36" target="_blank" title="">DumpMicrocode.js.zip</a> (Size: 4.75 KB / Downloads: 1018)
<!-- end: postbit_attachments_attachment --><br />
<br />
This script will look for microcode signatures or RSP overlay tables in RAM to find the location of the data section of all the Fast3D microcodes in the ROM. Once I find the data section, I can then look for an OSTask structure. The OSTask structure will tell me where the main code lies within memory. Once you find the location of one fast3d microcode, then you can easily find the rest. This is because, for most N64 games, the Fast3D microcodes are contiguous in memory. For example: if you find the first microcode at address 0x80010000 and the size of the microcode is 0x1408 bytes, then you can expect the next Fast3D microcode to be at the address 0x80011410 (Both the microcode and data have to be 16-byte aligned for some reason).<br />
<br />
To calculate the size of the microcode, you will need to find the overlay table entries in the .data section of the Fast3D microcode. For the Fast3D / F3DEX microcodes, the overlay table is simply at the beginning of the data section and are all contiguous (Usually has 5 entries). F3DEX2 works differently, and has the overlay entries near the bottom of the data section. They can be in different places depending on the exact microcode. Do note that the entries are 4-byte aligned.<br />
<br />
<img src="https://i.imgur.com/MQXRzd0.png" alt="[Image: MQXRzd0.png]" class="mycode_img" /><br />
<br />
<img src="https://i.imgur.com/I6KYIC9.png" alt="[Image: I6KYIC9.png]" class="mycode_img" /><br />
<br />
The overlay table is used to dynamically overwrite code in IMEM, which means that most of the fast3d microcodes are actually bigger than 4KB. Each entry in the overlay table is 8 bytes long. The first 4 bytes tell you the source offset from the start of the microcode section in RDRAM. The following 2 bytes tell you the size of the section (minus 1). The last two bytes tells you the destination offset in IMEM where the code will be copied to.<br />
<br />
To get the size of the microcode from the overlay entries you just simply calculate <span style="font-weight: bold;" class="mycode_b">RDRAM_Offset + Size + 1</span> for each entry, and the largest value out of all the entries will be your total microcode size. For example, the total size for the SM64 microcode is: <span style="font-weight: bold;" class="mycode_b">0x000013A0 + 0x0067 + 1 = 0x1408</span>.<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b"><span style="font-size: medium;" class="mycode_size">Disassembling the microcode into RSP assembly</span></span><br />
<br />
I'm sure there are plenty of free and open source MIPS R4300 disassemblers out there, but I wanted to write my own to get a better understanding of the vector registers and opcodes. <br />
<br />
You will need to look at the overlay table entries in the .data section to be able to correctly view the RSP assembly, otherwise the branch opcodes will not be correct. You need to set "RAM address" as the IMEM destination offset (prefixed with 0400), and set "Length" as the size + 1. Once the code has been disassembled, you can just simply select all the text with Ctrl-A and then copy-paste the assembly code into your favorite text editor.<br />
<br />
<span style="font-weight: bold;" class="mycode_b"><span style="font-size: medium;" class="mycode_size">Download: </span></span><a href="https://github.com/DavidSM64/David-s-N64-RSP-Disassembler/releases" target="_blank" rel="noopener" class="mycode_url">https://github.com/DavidSM64/David-s-N64...r/releases</a><br />
<span style="font-weight: bold;" class="mycode_b"><span style="font-size: medium;" class="mycode_size">Source: </span></span><a href="https://github.com/DavidSM64/David-s-N64-RSP-Disassembler" target="_blank" rel="noopener" class="mycode_url">https://github.com/DavidSM64/David-s-N64...sassembler</a><br />
<br />
<img src="https://i.imgur.com/4bYPf8l.png" alt="[Image: 4bYPf8l.png]" class="mycode_img" />]]></description>
			<content:encoded><![CDATA[I've been busy the past couple of days going through some N64 roms and extracting the Fast3D microcode from them, and now I'm here to share them with you all. I'm also sharing a couple basic tools that I wrote to dump some of the microcodes, and disassemble the .bin files into readable assembly code.<br />
<br />
<span style="display: inline-block;margin-bottom: 8px;"><span style="font-weight: bold;" class="mycode_b"><span style="font-size: medium;" class="mycode_size">Download</span></span></span><!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://hack64.net/images/attachtypes/zip.png" title="ZIP File" border="0" alt=".zip" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=35" target="_blank" title="">N64 graphics microcode dumps (Nov 17th 2018).zip</a> (Size: 183.25 KB / Downloads: 1277)
<!-- end: postbit_attachments_attachment --><br />
<br />
<div class="spoiler">
		<div class="thead"><button class="button float_right" onclick="javascript: if(parentNode.parentNode.getElementsByTagName('div')[2].style.display == 'block'){ parentNode.parentNode.getElementsByTagName('div')[2].style.display = 'none'; this.innerHTML='Show Content'; } else { parentNode.parentNode.getElementsByTagName('div')[2].style.display = 'block'; this.innerHTML='Hide Content'; }">Show Content</button>List of games and their microcodes that I have so far<div style="clear: both;"></div></div>
		<div class="trow1" style="display: none;">
<code class="codeblock" style="max-height: none; display:block;background-color:#111111">007 - GoldenEye<br />
- gspFast3DNoN.fifo(2.0G)<br />
<br />
Banjo-Kazooie<br />
- gspF3DEX.fifo(1.21)<br />
- gspL3DEX.fifo(1.21)<br />
<br />
Banjo-Tooie<br />
- gspF3DEX2.fifo(2.08)<br />
- gspF3DEX2NoN.fifo(2.08)<br />
- gspL3DEX2.fifo(2.08)<br />
<br />
Conker's Bad Fur Day*<br />
- gspF3DConkerN64.fifo<br />
- gspF3DConkerN64NoN.fifo<br />
- gspF3DConkerN64NoN.fifo(ext)<br />
- gspF3DEX2.fifo<br />
- gspF3DEX2NoN.fifo<br />
- gspF3DEX2BS.fifo<br />
- gspF3DEX2BSNoN.fifo<br />
- gspF3DEX2BG.fifo<br />
- gspF3DEX2BGNoN.fifo<br />
- gspF3DEX2BGBS.fifo<br />
- gspF3DEX2BGBSNoN.fifo<br />
<br />
* Note: "gspF3DConkerN64" was a name I made up, as the signature for the microcode is just "Conker N64 - Rare Ltd". It seems like it is a modified version of gspFast3D, but I'm not 100% sure on that. The "gspF3DConkerN64NoN.fifo(ext)" microcode is nearly identical to "gspF3DConkerN64NoN.fifo", except that 6 lines of assembly code were added. I currently have no idea of what those extra lines do.<br />
<br />
Diddy Kong Racing**<br />
- gspF3DDKR<br />
- gspF3DDKR.dram<br />
- gspF3DDKR.fifo<br />
<br />
** Note: "F3DDKR" is the name given to the microcode by Mupen64. It looks like a modified version of gspFast3D.<br />
<br />
Doraemon - Nobita to 3tsu no Seireiseki<br />
- gspFast3D<br />
- gspFast3D.dram<br />
- gspFast3D.fifo<br />
- gspFast3DNoN<br />
- gspFast3DNoN.dram<br />
- gspFast3DNoN.fifo<br />
<br />
Gex 64: Enter the Gecko<br />
- gspF3DEX.fifo(1.23)<br />
<br />
Mario Kart 64<br />
- gspF3DEX.fifo(0.95)<br />
- gspF3DLX.fifo(0.95)<br />
<br />
Super Mario 64<br />
- gspFast3D.fifo(2.0D)<br />
<br />
Super Mario 64 (Shindou Edition)<br />
- gspFast3D.fifo(2.0H)<br />
<br />
Super Smash Bros<br />
- gspF3DEX2.fifo(2.04H)<br />
<br />
The Legend of Zelda: Ocarina of Time<br />
- F3DZEXNoN.fifo(2.06H)<br />
- S2DEX.fifo(2.05)<br />
<br />
The Legend of Zelda: Majora's Mask<br />
- F3DZEXNoN.fifo(2.08I)<br />
- S2DEX.fifo(2.08)<br />
</code><br />
</div>
	</div>
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b"><span style="font-size: medium;" class="mycode_size">How do I use these .bin files with an OSTask structure?</span></span><br />
<br />
It is straight forward. The <span style="font-weight: bold;" class="mycode_b">.code.bin</span> file is the microcode that gets pointed to by <span style="font-weight: bold;" class="mycode_b">t.ucode</span>, while the <span style="font-weight: bold;" class="mycode_b">.data.bin</span> file is the data that gets pointed to by <span style="font-weight: bold;" class="mycode_b">t.ucode_data</span>. I've also included the boot microcode from every game in their respective folders in the microcode dump. I'm not sure if they are actually needed or not, but if you do need them they are pointed to by <span style="font-weight: bold;" class="mycode_b">t.ucode_boot</span>.<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b"><span style="font-size: medium;" class="mycode_size">Dumping Fast3D microcodes from N64 games</span></span><br />
<br />
The way that I got most of these microcodes is by using shygoo's Javascript API in the latest version Project64 <a href="https://github.com/project64/project64" target="_blank" rel="noopener" class="mycode_url">(You will have to compile Project64 from the github repo)</a>. It is not perfect, but it should be able to get you at-least some Fast3D microcodes from most of the N64 games. Some of microcodes are harder to get than others. For example: I had to dump all 11 of Conker's Fast3D microcodes manually, since only 2 of them are loaded into RAM.<br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://hack64.net/images/attachtypes/zip.png" title="ZIP File" border="0" alt=".zip" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=36" target="_blank" title="">DumpMicrocode.js.zip</a> (Size: 4.75 KB / Downloads: 1018)
<!-- end: postbit_attachments_attachment --><br />
<br />
This script will look for microcode signatures or RSP overlay tables in RAM to find the location of the data section of all the Fast3D microcodes in the ROM. Once I find the data section, I can then look for an OSTask structure. The OSTask structure will tell me where the main code lies within memory. Once you find the location of one fast3d microcode, then you can easily find the rest. This is because, for most N64 games, the Fast3D microcodes are contiguous in memory. For example: if you find the first microcode at address 0x80010000 and the size of the microcode is 0x1408 bytes, then you can expect the next Fast3D microcode to be at the address 0x80011410 (Both the microcode and data have to be 16-byte aligned for some reason).<br />
<br />
To calculate the size of the microcode, you will need to find the overlay table entries in the .data section of the Fast3D microcode. For the Fast3D / F3DEX microcodes, the overlay table is simply at the beginning of the data section and are all contiguous (Usually has 5 entries). F3DEX2 works differently, and has the overlay entries near the bottom of the data section. They can be in different places depending on the exact microcode. Do note that the entries are 4-byte aligned.<br />
<br />
<img src="https://i.imgur.com/MQXRzd0.png" alt="[Image: MQXRzd0.png]" class="mycode_img" /><br />
<br />
<img src="https://i.imgur.com/I6KYIC9.png" alt="[Image: I6KYIC9.png]" class="mycode_img" /><br />
<br />
The overlay table is used to dynamically overwrite code in IMEM, which means that most of the fast3d microcodes are actually bigger than 4KB. Each entry in the overlay table is 8 bytes long. The first 4 bytes tell you the source offset from the start of the microcode section in RDRAM. The following 2 bytes tell you the size of the section (minus 1). The last two bytes tells you the destination offset in IMEM where the code will be copied to.<br />
<br />
To get the size of the microcode from the overlay entries you just simply calculate <span style="font-weight: bold;" class="mycode_b">RDRAM_Offset + Size + 1</span> for each entry, and the largest value out of all the entries will be your total microcode size. For example, the total size for the SM64 microcode is: <span style="font-weight: bold;" class="mycode_b">0x000013A0 + 0x0067 + 1 = 0x1408</span>.<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b"><span style="font-size: medium;" class="mycode_size">Disassembling the microcode into RSP assembly</span></span><br />
<br />
I'm sure there are plenty of free and open source MIPS R4300 disassemblers out there, but I wanted to write my own to get a better understanding of the vector registers and opcodes. <br />
<br />
You will need to look at the overlay table entries in the .data section to be able to correctly view the RSP assembly, otherwise the branch opcodes will not be correct. You need to set "RAM address" as the IMEM destination offset (prefixed with 0400), and set "Length" as the size + 1. Once the code has been disassembled, you can just simply select all the text with Ctrl-A and then copy-paste the assembly code into your favorite text editor.<br />
<br />
<span style="font-weight: bold;" class="mycode_b"><span style="font-size: medium;" class="mycode_size">Download: </span></span><a href="https://github.com/DavidSM64/David-s-N64-RSP-Disassembler/releases" target="_blank" rel="noopener" class="mycode_url">https://github.com/DavidSM64/David-s-N64...r/releases</a><br />
<span style="font-weight: bold;" class="mycode_b"><span style="font-size: medium;" class="mycode_size">Source: </span></span><a href="https://github.com/DavidSM64/David-s-N64-RSP-Disassembler" target="_blank" rel="noopener" class="mycode_url">https://github.com/DavidSM64/David-s-N64...sassembler</a><br />
<br />
<img src="https://i.imgur.com/4bYPf8l.png" alt="[Image: 4bYPf8l.png]" class="mycode_img" />]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Flashcart Test Requests]]></title>
			<link>https://hack64.net/Thread-Flashcart-Test-Requests</link>
			<pubDate>Wed, 22 Aug 2018 18:10:50 +0000</pubDate>
			<guid isPermaLink="false">https://hack64.net/Thread-Flashcart-Test-Requests</guid>
			<description><![CDATA[If you have romhack patches or homebrew you would like to have tested on hardware, you may post them here. Before submitting, please test on an accurate emulator setup (For N64 testing try <a href="https://github.com/tj90241/cen64/releases">CEN64</a> or the <a href="https://github.com/ata4/angrylion-rdp-plus/releases">angrylion graphics plugin</a>).<br />
<br />
Testers: Please include the name and version of the flashcart used for testing. Screencaps of gameplay are also appreciated.]]></description>
			<content:encoded><![CDATA[If you have romhack patches or homebrew you would like to have tested on hardware, you may post them here. Before submitting, please test on an accurate emulator setup (For N64 testing try <a href="https://github.com/tj90241/cen64/releases">CEN64</a> or the <a href="https://github.com/ata4/angrylion-rdp-plus/releases">angrylion graphics plugin</a>).<br />
<br />
Testers: Please include the name and version of the flashcart used for testing. Screencaps of gameplay are also appreciated.]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Web-based ROM patcher (APS, BPS, IPS, MOD/Star Rod, PPF, UPS, VCDiff/xdelta)]]></title>
			<link>https://hack64.net/Thread-Web-based-ROM-patcher-APS-BPS-IPS-MOD-Star-Rod-PPF-UPS-VCDiff-xdelta</link>
			<pubDate>Mon, 06 Aug 2018 18:42:35 +0000</pubDate>
			<guid isPermaLink="false">https://hack64.net/Thread-Web-based-ROM-patcher-APS-BPS-IPS-MOD-Star-Rod-PPF-UPS-VCDiff-xdelta</guid>
			<description><![CDATA[Here's a web-based ROM patcher I made as an offshoot of the work-in-progress site downloads section<br />
<br />
<a href="https://hack64.net/tools/patcher.php" target="_blank" rel="noopener" class="mycode_url">https://hack64.net/tools/patcher.php</a><br />
<br />
Currently supported patch formats:<br />
<ul style="padding-left:20px;">
<li>APS<br />
<li>BPS<br />
<li>IPS<br />
<li>MOD (Star Rod)<br />
<li>PPF<br />
<li>UPS<br />
<li>VCDiff (xdelta)<br />
</ul>
<br />
Todo:<br />
<ul style="padding-left:20px;">
<li>VCDiff secondary compression support<br />
<li>Patch creation (maybe)<br />
</ul>
<br />
If you happen to encounter any bugs please report them here.]]></description>
			<content:encoded><![CDATA[Here's a web-based ROM patcher I made as an offshoot of the work-in-progress site downloads section<br />
<br />
<a href="https://hack64.net/tools/patcher.php" target="_blank" rel="noopener" class="mycode_url">https://hack64.net/tools/patcher.php</a><br />
<br />
Currently supported patch formats:<br />
<ul style="padding-left:20px;">
<li>APS<br />
<li>BPS<br />
<li>IPS<br />
<li>MOD (Star Rod)<br />
<li>PPF<br />
<li>UPS<br />
<li>VCDiff (xdelta)<br />
</ul>
<br />
Todo:<br />
<ul style="padding-left:20px;">
<li>VCDiff secondary compression support<br />
<li>Patch creation (maybe)<br />
</ul>
<br />
If you happen to encounter any bugs please report them here.]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[N64 YUV2RGB Library (C, C++, C#, VB.NET)]]></title>
			<link>https://hack64.net/Thread-N64-YUV2RGB-Library-C-C-C-VB-NET</link>
			<pubDate>Sat, 14 Jul 2018 18:08:33 +0000</pubDate>
			<guid isPermaLink="false">https://hack64.net/Thread-N64-YUV2RGB-Library-C-C-C-VB-NET</guid>
			<description><![CDATA[This is a simple multi-language library that can be used to convert between YUV16 and RGB data. <span style="font-weight: bold;" class="mycode_b">Note:</span> This library only converts binary data. It does not convert bitmap images like PNG, JPEG, or BMP to YUV16 data, although you could easily decode those into RGB data and then convert to YUV16 using this library.<br />
<br />
You can see more details and the source code on the GitHub page: <a href="https://github.com/DavidSM64/N64-YUV2RGB-Library" target="_blank" rel="noopener" class="mycode_url">https://github.com/DavidSM64/N64-YUV2RGB-Library</a><br />
<br />
<span style="font-weight: bold;" class="mycode_b"><span style="font-size: large;" class="mycode_size">Functions</span></span><br />
<ul class="mycode_list">
</li>
<li><span style="font-weight: bold;" class="mycode_b">YUV2RGB</span>: Decodes a YUV value into a RGB value<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">RGB2YUV</span>: Encodes 2 RGB pixels into 1 UYVY pair<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">decodeArray_YUVtoRGB</span>: Decodes an array of YUV data (UYVY pairs) into an RGB data array.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">decodeArray_YUVtoRGBA</span>: Decodes an array of YUV data (UYVY pairs) into an RGBA data array.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">encodeArray_YUVfromRGB</span>: Encodes an array of RGB data into an YUV (UYVY pairs) data array.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">encodeArray_YUVfromRGBA</span>: Encodes an array of RGBA data into an YUV (UYVY pairs) data array.<br />
</li></ul>
]]></description>
			<content:encoded><![CDATA[This is a simple multi-language library that can be used to convert between YUV16 and RGB data. <span style="font-weight: bold;" class="mycode_b">Note:</span> This library only converts binary data. It does not convert bitmap images like PNG, JPEG, or BMP to YUV16 data, although you could easily decode those into RGB data and then convert to YUV16 using this library.<br />
<br />
You can see more details and the source code on the GitHub page: <a href="https://github.com/DavidSM64/N64-YUV2RGB-Library" target="_blank" rel="noopener" class="mycode_url">https://github.com/DavidSM64/N64-YUV2RGB-Library</a><br />
<br />
<span style="font-weight: bold;" class="mycode_b"><span style="font-size: large;" class="mycode_size">Functions</span></span><br />
<ul class="mycode_list">
</li>
<li><span style="font-weight: bold;" class="mycode_b">YUV2RGB</span>: Decodes a YUV value into a RGB value<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">RGB2YUV</span>: Encodes 2 RGB pixels into 1 UYVY pair<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">decodeArray_YUVtoRGB</span>: Decodes an array of YUV data (UYVY pairs) into an RGB data array.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">decodeArray_YUVtoRGBA</span>: Decodes an array of YUV data (UYVY pairs) into an RGBA data array.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">encodeArray_YUVfromRGB</span>: Encodes an array of RGB data into an YUV (UYVY pairs) data array.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">encodeArray_YUVfromRGBA</span>: Encodes an array of RGBA data into an YUV (UYVY pairs) data array.<br />
</li></ul>
]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[N64 ROM Assembly Editor]]></title>
			<link>https://hack64.net/Thread-N64-ROM-Assembly-Editor</link>
			<pubDate>Thu, 22 Mar 2018 16:35:11 +0000</pubDate>
			<guid isPermaLink="false">https://hack64.net/Thread-N64-ROM-Assembly-Editor</guid>
			<description><![CDATA[Hello! I've been doing some work on the assembly editor since last post, so there are a few more features. Anyone using it prior to this post will need to use "Re-map jumps" in the tools menu to apply a few minor changes to their jumps.data file.<br />
<br />
It's core features are:<ul class="mycode_list">
</li>
<li>Game offset mode: Jumps/branches/addresses and navigation will be treated with the appropriate memory region offset<br />
</li>
<li>Memory region calculation: Main and Boot regions automatically calculated and supports additional memory regions<br />
</li>
<li>Hex/Binary mode<br />
</li>
<li>Assembly search engine: Search particular phrases to locate some code<br />
</li>
<li>Highlighting for jumps/branches and selected register<br />
</li>
<li>Highlighting for Load/Store instructions which can be determined to target the same memory address<br />
</li>
<li>Text boxes containing original assembly, hacked assembly and comments/notes which are constantly aligned<br />
</li>
<li>Easy address translation from memory editor to emulator<br />
</li>
<li>Checksum calculation (should work for most games)<br />
</li>
<li>CRC bypass (works for some games)<br />
</li>
<li>Jump/branch mapping which allows highlighting of "branch/jump targets" and "jumps to function" lookup<br />
</li>
<li>Changeable colour scheme<br />
</li>
<li>Hacking notes are always output to a negotiable text document in order of address they are aligned with<br />
</li>
<li>Generate a script from a script template to apply to a batch of addresses for use in other programs<br />
</li>
<li>Float/Double <--> Hex translation<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Cutting</span> instructions which have branches pointing to them will cause all branches within the function to be modified when you paste so that the branches point to the new paste location<br />
</li>
<li>Modifying the SP frame push or pop (ADDIU SP, SP &#36;####) will cause all read and write instructions within the function which use SP as the base address to be offset by the same amount<br />
</li>
<li>Function optimiser (more info below)<br />
</li>
<li>Generate a runtime patch script for PJ64d (patches all changes made during session while in disassembly view)<br />
*comes with a server script you can run with PJ64d, which makes patching a little quicker.<br />
</li></ul>
<br />
It's currently functional spaghetti source code. If you would like to give it a whirl and you're on linux or mac, you will need a Python 3.5 or 3.6 interpreter, also need to install Python's "tkinter" and "keyboard" modules. If you're on Windows, there is a download link to a snapshot of my Python environment, the disassembler and a batch file to run it through python.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">(For Operating Systems other than Windows)</span><br />
If you haven't dabbled in python before, you likely won't have the interpreter on your machine. I'd suggest Anaconda (a Python virtual environment manager) as when you make an environment, you can specify "Anaconda" at the end of the command when creating a virtual environment in the command prompt, and it will create the python installation with a whole heap of commonly used modules, including tkinter. Anaconda might chew up to 1gb of data to install, as a forewarning.<br />
<span style="font-weight: bold;" class="mycode_b">After an update I have made, you will now also be required to install the keyboard module.</span><br />
This is only because it doesn't come with Anaconda. Installing keyboard is easy, the instructions can be found here <a href="https://pypi.python.org/pypi/keyboard/" target="_blank" rel="noopener" class="mycode_url">https://pypi.python.org/pypi/keyboard/</a><br />
<br />
Anaconda for OSX: <a href="https://docs.conda.io/projects/conda/en/latest/user-guide/install/macos.html" target="_blank" rel="noopener" class="mycode_url">https://docs.conda.io/projects/conda/en/...macos.html</a><br />
Anaconda for Linux: <a href="https://docs.conda.io/projects/conda/en/latest/user-guide/install/linux.html" target="_blank" rel="noopener" class="mycode_url">https://docs.conda.io/projects/conda/en/...linux.html</a><br />
*Don't choose miniconda, from what I understand, you can get stuck in "dependency hell" while trying to obtain tkinter, which is not a place you want to be in<br />
<br />
<span style="font-size: medium;" class="mycode_size">Source on Git: <a href="https://github.com/mitchasdf/N64-Rom-Disassembler" target="_blank" rel="noopener" class="mycode_url">https://github.com/mitchasdf/N64-Rom-Disassembler</a><br />
Download for Windows** (includes python, tkinter and keyboard): </span><a href="https://drive.google.com/file/d/173KICgiUUkVWsCRSnMPw8yG5UvhXT-qk/view?usp=sharing" target="_blank" rel="noopener" class="mycode_url"><span style="font-size: medium;" class="mycode_size">https://drive.google.com/file/d/173KICgiUUkVWsCRSnMPw8yG5UvhXT-qk/view?usp=sharing</span></a><br />
<br />
<span style="font-weight: bold;" class="mycode_b"><span style="font-size: small;" class="mycode_size">**You may need to disable any ad or popup blockers or add the page to the blocker's exclusion list. If you don't, you will get "failed to start action" and http errors, or the page will simply hang on loading when attempting to download. The download button is located at the top-right of the page.</span></span><br />
<br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Usage</span></span><br />
<br />
In the main window, there are 4 tall text boxes. Respectively, they represent: Addresses, base file, hack file, hacking notes/comments.<br />
<br />
When you open a rom initially, you can choose "start new" in the file menu to select the base file and then the name and location for the hack file. If you already have a hack file you wish to open, you can "open existing" and then associate it with the base file in the 2nd file navigation window.<br />
<br />
They might feel like normal text boxes, but they have heavily modified behaviour so as to keep the code and comments aligned. You can copy/paste or backspace multiple lines of code or comments and it will be safe.<br />
<br />
The text boxes are bound with a few hotkeys which make life a bit easier. I'll list them all here:<ul class="mycode_list">
</li>
<li>Return: Move to end of next line<br />
</li>
<li>Shift+Return: Move to end of previous line<br />
</li>
<li>Shift+Backspace or Shift+Delete: Remove line of code<br />
</li>
<li>Ctrl+B: Insert branch template (BEQ R0, R0, &#36;)<br />
</li>
<li>Ctrl+R: Restore line of code, or selection of lines of code<br />
</li>
<li>Ctrl+Shift+R: Restore whole function<br />
</li>
<li>Ctrl+F: Follow jump or branch<br />
</li>
<li>Ctrl+G: Find all J or JAL which target any address inside the current function<br />
</li>
<li>Ctrl+O: Optimise the current function<br />
</li>
<li>Ctrl+P: Create a patch file for PJ64d to run during emulation<br />
</li>
<li>Ctrl+Comma (< key): Undo<br />
</li>
<li>Ctrl+Fullstop (> key): Redo<br />
</li></ul>
<br />
The rest of the hotkeys which don't affect the text boxes can be found scattered in the Menu.<br />
<br />
Extra text box behaviours:<ul class="mycode_list">
</li>
<li>NOP will be automatically removed when typing on that line<br />
</li>
<li>Blank lines will be replaced with and treated as NOP<br />
</li>
<li>Multi-line selections will be extended to the bounds of the start and end lines you select when you attempt to action the selection<br />
</li>
<li>Hack text box will always input as upper case letters<br />
</li></ul>
<br />
For address translation from memory editor RAM to emulator RAM, you may use an option to set the memory editor offset for the current game, and from there you can either type in addresses manually, or, if you leave the input text box blank and just click the translate button, it will try to convert your clipboard contents instead.<br />
<br />
The comments navigator has a "filter" option to search for comments with particular phrases. It will filter out any comment that doesn't contain each word you type in, separated by spaces. You can see an example of that in the comments navigator image below.<br />
<br />
If you group your addresses by adding hashtags (#group name) to the end of their comments, you can then add those groups to the batch with the click of a button in the script generator window.<br />
<br />
To use additional memory region offsets, its as simple as setting the parameters using the option in the options menu, then all jumps to that region will appear with the offset applied. All additional jumps made to that region will be encoded accordingly. Setting memory regions has no affect on the layout or placement of the code, only how it appears. The addresses list on the left side of the main window (and addresses in all other windows) will also have the offset applied during game offset mode.<br />
Every navigation task which shifts your view will only have the region offset applied to your input during game offset mode.<br />
<br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Function optimisation</span></span><br />
<br />
There are several tasks that can be done to grant yourself a few NOPs in a function in order to have room for your own logic.<br />
<br />
For the sake of this explanation, I'll refer to registers T0 through T9 and AT as scratch registers. <br />
<br />
I'll refer a couple of times to "sections", which consist of areas within the function, broken up by any instruction that is targeted by a branch or returned to from a linked jumped. These are locations where any scratch register's contents can <span style="font-weight: bold;" class="mycode_b">no longer</span> safely be assumed.<br />
<br />
The current optimisation tasks that are performed when pressing Ctrl+O are:<ul class="mycode_list">
</li>
<li>Excess pointers declared using a scratch register or the SP will be removed and all pointers using the removed register will be pointed to the original pointer. This can only be done within each "section".<br />
</li>
<li>JALs which target a function that only contain 1 or 2 instructions other than JR RA will be replaced with said instructions, so as to "merge" those 2 "sections" either side of the JAL and possibly remove more redundant pointers.<br />
</li>
<li>Branches which target the next non-NOP instruction will be removed, as there is no point in it being there.<br />
</li>
<li>Branch delay slots which are filled with NOP will be substituted with the next available non-NOP instruction, only if the instruction <span style="font-weight: bold;" class="mycode_b">writes </span>to either a scratch register or a float register. This grants 1 extra NOP per eligible branch.<br />
</li>
<li>..<br />
</li>
<li>Not an optimisation task, but something to keep in mind: All float comparison instructions (C.#.#) and their branch functions (BC1#) require at least 1 other instruction (a NOP will suffice) in between them. This is because for all float comparison instructions, there is an additional delay on writing the result to the FP register, which is what the float branches read from to conditionally jump. If there is nothing separating the float comparison and the float branch, it will take the contents of FP prior to the float compare, resulting in not errors, but strange behaviours.<br />
</li></ul>
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Screenshots</span></span><br />
<br />
<span style="font-weight: bold;" class="mycode_b"><span style="font-size: medium;" class="mycode_size">Main window</span></span><br />
<a href="https://ibb.co/gLgkqH"><img src="https://preview.ibb.co/fvo9Hx/main_window.png" alt="main_window" border="0"></a><br />
<br />
<span style="font-weight: bold;" class="mycode_b"><span style="font-size: medium;" class="mycode_size">Comments window</span></span><br />
<a href="https://ibb.co/f1yWVH"><img src="https://preview.ibb.co/dMf0Pc/comments_window.png" alt="comments_window" border="0"></a><br />
<br />
<span style="font-weight: bold;" class="mycode_b"><span style="font-size: medium;" class="mycode_size">Jumps window</span></span><br />
<a href="https://ibb.co/cztbxx"><img src="https://preview.ibb.co/kpYLPc/jumps_window.png" alt="jumps_window" border="0"></a>]]></description>
			<content:encoded><![CDATA[Hello! I've been doing some work on the assembly editor since last post, so there are a few more features. Anyone using it prior to this post will need to use "Re-map jumps" in the tools menu to apply a few minor changes to their jumps.data file.<br />
<br />
It's core features are:<ul class="mycode_list">
</li>
<li>Game offset mode: Jumps/branches/addresses and navigation will be treated with the appropriate memory region offset<br />
</li>
<li>Memory region calculation: Main and Boot regions automatically calculated and supports additional memory regions<br />
</li>
<li>Hex/Binary mode<br />
</li>
<li>Assembly search engine: Search particular phrases to locate some code<br />
</li>
<li>Highlighting for jumps/branches and selected register<br />
</li>
<li>Highlighting for Load/Store instructions which can be determined to target the same memory address<br />
</li>
<li>Text boxes containing original assembly, hacked assembly and comments/notes which are constantly aligned<br />
</li>
<li>Easy address translation from memory editor to emulator<br />
</li>
<li>Checksum calculation (should work for most games)<br />
</li>
<li>CRC bypass (works for some games)<br />
</li>
<li>Jump/branch mapping which allows highlighting of "branch/jump targets" and "jumps to function" lookup<br />
</li>
<li>Changeable colour scheme<br />
</li>
<li>Hacking notes are always output to a negotiable text document in order of address they are aligned with<br />
</li>
<li>Generate a script from a script template to apply to a batch of addresses for use in other programs<br />
</li>
<li>Float/Double <--> Hex translation<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Cutting</span> instructions which have branches pointing to them will cause all branches within the function to be modified when you paste so that the branches point to the new paste location<br />
</li>
<li>Modifying the SP frame push or pop (ADDIU SP, SP &#36;####) will cause all read and write instructions within the function which use SP as the base address to be offset by the same amount<br />
</li>
<li>Function optimiser (more info below)<br />
</li>
<li>Generate a runtime patch script for PJ64d (patches all changes made during session while in disassembly view)<br />
*comes with a server script you can run with PJ64d, which makes patching a little quicker.<br />
</li></ul>
<br />
It's currently functional spaghetti source code. If you would like to give it a whirl and you're on linux or mac, you will need a Python 3.5 or 3.6 interpreter, also need to install Python's "tkinter" and "keyboard" modules. If you're on Windows, there is a download link to a snapshot of my Python environment, the disassembler and a batch file to run it through python.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">(For Operating Systems other than Windows)</span><br />
If you haven't dabbled in python before, you likely won't have the interpreter on your machine. I'd suggest Anaconda (a Python virtual environment manager) as when you make an environment, you can specify "Anaconda" at the end of the command when creating a virtual environment in the command prompt, and it will create the python installation with a whole heap of commonly used modules, including tkinter. Anaconda might chew up to 1gb of data to install, as a forewarning.<br />
<span style="font-weight: bold;" class="mycode_b">After an update I have made, you will now also be required to install the keyboard module.</span><br />
This is only because it doesn't come with Anaconda. Installing keyboard is easy, the instructions can be found here <a href="https://pypi.python.org/pypi/keyboard/" target="_blank" rel="noopener" class="mycode_url">https://pypi.python.org/pypi/keyboard/</a><br />
<br />
Anaconda for OSX: <a href="https://docs.conda.io/projects/conda/en/latest/user-guide/install/macos.html" target="_blank" rel="noopener" class="mycode_url">https://docs.conda.io/projects/conda/en/...macos.html</a><br />
Anaconda for Linux: <a href="https://docs.conda.io/projects/conda/en/latest/user-guide/install/linux.html" target="_blank" rel="noopener" class="mycode_url">https://docs.conda.io/projects/conda/en/...linux.html</a><br />
*Don't choose miniconda, from what I understand, you can get stuck in "dependency hell" while trying to obtain tkinter, which is not a place you want to be in<br />
<br />
<span style="font-size: medium;" class="mycode_size">Source on Git: <a href="https://github.com/mitchasdf/N64-Rom-Disassembler" target="_blank" rel="noopener" class="mycode_url">https://github.com/mitchasdf/N64-Rom-Disassembler</a><br />
Download for Windows** (includes python, tkinter and keyboard): </span><a href="https://drive.google.com/file/d/173KICgiUUkVWsCRSnMPw8yG5UvhXT-qk/view?usp=sharing" target="_blank" rel="noopener" class="mycode_url"><span style="font-size: medium;" class="mycode_size">https://drive.google.com/file/d/173KICgiUUkVWsCRSnMPw8yG5UvhXT-qk/view?usp=sharing</span></a><br />
<br />
<span style="font-weight: bold;" class="mycode_b"><span style="font-size: small;" class="mycode_size">**You may need to disable any ad or popup blockers or add the page to the blocker's exclusion list. If you don't, you will get "failed to start action" and http errors, or the page will simply hang on loading when attempting to download. The download button is located at the top-right of the page.</span></span><br />
<br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Usage</span></span><br />
<br />
In the main window, there are 4 tall text boxes. Respectively, they represent: Addresses, base file, hack file, hacking notes/comments.<br />
<br />
When you open a rom initially, you can choose "start new" in the file menu to select the base file and then the name and location for the hack file. If you already have a hack file you wish to open, you can "open existing" and then associate it with the base file in the 2nd file navigation window.<br />
<br />
They might feel like normal text boxes, but they have heavily modified behaviour so as to keep the code and comments aligned. You can copy/paste or backspace multiple lines of code or comments and it will be safe.<br />
<br />
The text boxes are bound with a few hotkeys which make life a bit easier. I'll list them all here:<ul class="mycode_list">
</li>
<li>Return: Move to end of next line<br />
</li>
<li>Shift+Return: Move to end of previous line<br />
</li>
<li>Shift+Backspace or Shift+Delete: Remove line of code<br />
</li>
<li>Ctrl+B: Insert branch template (BEQ R0, R0, &#36;)<br />
</li>
<li>Ctrl+R: Restore line of code, or selection of lines of code<br />
</li>
<li>Ctrl+Shift+R: Restore whole function<br />
</li>
<li>Ctrl+F: Follow jump or branch<br />
</li>
<li>Ctrl+G: Find all J or JAL which target any address inside the current function<br />
</li>
<li>Ctrl+O: Optimise the current function<br />
</li>
<li>Ctrl+P: Create a patch file for PJ64d to run during emulation<br />
</li>
<li>Ctrl+Comma (< key): Undo<br />
</li>
<li>Ctrl+Fullstop (> key): Redo<br />
</li></ul>
<br />
The rest of the hotkeys which don't affect the text boxes can be found scattered in the Menu.<br />
<br />
Extra text box behaviours:<ul class="mycode_list">
</li>
<li>NOP will be automatically removed when typing on that line<br />
</li>
<li>Blank lines will be replaced with and treated as NOP<br />
</li>
<li>Multi-line selections will be extended to the bounds of the start and end lines you select when you attempt to action the selection<br />
</li>
<li>Hack text box will always input as upper case letters<br />
</li></ul>
<br />
For address translation from memory editor RAM to emulator RAM, you may use an option to set the memory editor offset for the current game, and from there you can either type in addresses manually, or, if you leave the input text box blank and just click the translate button, it will try to convert your clipboard contents instead.<br />
<br />
The comments navigator has a "filter" option to search for comments with particular phrases. It will filter out any comment that doesn't contain each word you type in, separated by spaces. You can see an example of that in the comments navigator image below.<br />
<br />
If you group your addresses by adding hashtags (#group name) to the end of their comments, you can then add those groups to the batch with the click of a button in the script generator window.<br />
<br />
To use additional memory region offsets, its as simple as setting the parameters using the option in the options menu, then all jumps to that region will appear with the offset applied. All additional jumps made to that region will be encoded accordingly. Setting memory regions has no affect on the layout or placement of the code, only how it appears. The addresses list on the left side of the main window (and addresses in all other windows) will also have the offset applied during game offset mode.<br />
Every navigation task which shifts your view will only have the region offset applied to your input during game offset mode.<br />
<br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Function optimisation</span></span><br />
<br />
There are several tasks that can be done to grant yourself a few NOPs in a function in order to have room for your own logic.<br />
<br />
For the sake of this explanation, I'll refer to registers T0 through T9 and AT as scratch registers. <br />
<br />
I'll refer a couple of times to "sections", which consist of areas within the function, broken up by any instruction that is targeted by a branch or returned to from a linked jumped. These are locations where any scratch register's contents can <span style="font-weight: bold;" class="mycode_b">no longer</span> safely be assumed.<br />
<br />
The current optimisation tasks that are performed when pressing Ctrl+O are:<ul class="mycode_list">
</li>
<li>Excess pointers declared using a scratch register or the SP will be removed and all pointers using the removed register will be pointed to the original pointer. This can only be done within each "section".<br />
</li>
<li>JALs which target a function that only contain 1 or 2 instructions other than JR RA will be replaced with said instructions, so as to "merge" those 2 "sections" either side of the JAL and possibly remove more redundant pointers.<br />
</li>
<li>Branches which target the next non-NOP instruction will be removed, as there is no point in it being there.<br />
</li>
<li>Branch delay slots which are filled with NOP will be substituted with the next available non-NOP instruction, only if the instruction <span style="font-weight: bold;" class="mycode_b">writes </span>to either a scratch register or a float register. This grants 1 extra NOP per eligible branch.<br />
</li>
<li>..<br />
</li>
<li>Not an optimisation task, but something to keep in mind: All float comparison instructions (C.#.#) and their branch functions (BC1#) require at least 1 other instruction (a NOP will suffice) in between them. This is because for all float comparison instructions, there is an additional delay on writing the result to the FP register, which is what the float branches read from to conditionally jump. If there is nothing separating the float comparison and the float branch, it will take the contents of FP prior to the float compare, resulting in not errors, but strange behaviours.<br />
</li></ul>
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Screenshots</span></span><br />
<br />
<span style="font-weight: bold;" class="mycode_b"><span style="font-size: medium;" class="mycode_size">Main window</span></span><br />
<a href="https://ibb.co/gLgkqH"><img src="https://preview.ibb.co/fvo9Hx/main_window.png" alt="main_window" border="0"></a><br />
<br />
<span style="font-weight: bold;" class="mycode_b"><span style="font-size: medium;" class="mycode_size">Comments window</span></span><br />
<a href="https://ibb.co/f1yWVH"><img src="https://preview.ibb.co/dMf0Pc/comments_window.png" alt="comments_window" border="0"></a><br />
<br />
<span style="font-weight: bold;" class="mycode_b"><span style="font-size: medium;" class="mycode_size">Jumps window</span></span><br />
<a href="https://ibb.co/cztbxx"><img src="https://preview.ibb.co/kpYLPc/jumps_window.png" alt="jumps_window" border="0"></a>]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[n64sym - N64 SDK symbol identification tool]]></title>
			<link>https://hack64.net/Thread-n64sym-N64-SDK-symbol-identification-tool</link>
			<pubDate>Thu, 15 Mar 2018 20:00:34 +0000</pubDate>
			<guid isPermaLink="false">https://hack64.net/Thread-n64sym-N64-SDK-symbol-identification-tool</guid>
			<description><![CDATA[This tool can be used to identify common N64 symbols/functions in games by searching ROM/RAM dumps for code in the SDK's libraries.<br />
<br />
Download: <a href="https://github.com/shygoo/n64sym/releases" target="_blank" rel="noopener" class="mycode_url">https://github.com/shygoo/n64sym/releases</a><br />
Source: <a href="https://github.com/shygoo/n64sym" target="_blank" rel="noopener" class="mycode_url">https://github.com/shygoo/n64sym</a><br />
<br />
<b>Usage</b><br />
<br />
<span style="font-family: consolas;" class="mycode_font">n64sym &lt;binary path&gt; [options]</span><br />
<br />
<b>Options</b><span style="font-family: consolas;" class="mycode_font"><br />
-s                        scan for symbols from the built-in signature file<br />
-l &lt;sig/lib/obj path(s)&gt;  scan for symbols from signature/object/library file(s)<br />
-f &lt;output format&gt;        set the output format (pj64, nemu, armips, n64split, default)<br />
-o &lt;output path&gt;          set the output path<br />
-h &lt;headersize&gt;           set the header size  (default: 0x80000000)<br />
-t                        scan thoroughly<br />
-v                        enable verbose logging</span><br />
<br />
Example:<span style="font-family: consolas;" class="mycode_font"><br />
> n64sym dumps/paper_mario.bin -s<br />
80069840 __osPfsRWInode<br />
80069090 osPfsNumFiles<br />
80069190 osPfsInitPak<br />
80069388 pfsinitpak_o_0050<br />
80069460 osPfsRepairId<br />
800694C0 __osPfsGetStatus<br />
...</span>]]></description>
			<content:encoded><![CDATA[This tool can be used to identify common N64 symbols/functions in games by searching ROM/RAM dumps for code in the SDK's libraries.<br />
<br />
Download: <a href="https://github.com/shygoo/n64sym/releases" target="_blank" rel="noopener" class="mycode_url">https://github.com/shygoo/n64sym/releases</a><br />
Source: <a href="https://github.com/shygoo/n64sym" target="_blank" rel="noopener" class="mycode_url">https://github.com/shygoo/n64sym</a><br />
<br />
<b>Usage</b><br />
<br />
<span style="font-family: consolas;" class="mycode_font">n64sym &lt;binary path&gt; [options]</span><br />
<br />
<b>Options</b><span style="font-family: consolas;" class="mycode_font"><br />
-s                        scan for symbols from the built-in signature file<br />
-l &lt;sig/lib/obj path(s)&gt;  scan for symbols from signature/object/library file(s)<br />
-f &lt;output format&gt;        set the output format (pj64, nemu, armips, n64split, default)<br />
-o &lt;output path&gt;          set the output path<br />
-h &lt;headersize&gt;           set the header size  (default: 0x80000000)<br />
-t                        scan thoroughly<br />
-v                        enable verbose logging</span><br />
<br />
Example:<span style="font-family: consolas;" class="mycode_font"><br />
> n64sym dumps/paper_mario.bin -s<br />
80069840 __osPfsRWInode<br />
80069090 osPfsNumFiles<br />
80069190 osPfsInitPak<br />
80069388 pfsinitpak_o_0050<br />
80069460 osPfsRepairId<br />
800694C0 __osPfsGetStatus<br />
...</span>]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Project64 Debugger]]></title>
			<link>https://hack64.net/Thread-Project64-Debugger</link>
			<pubDate>Sat, 10 Mar 2018 12:03:00 +0000</pubDate>
			<guid isPermaLink="false">https://hack64.net/Thread-Project64-Debugger</guid>
			<description><![CDATA[Project64 debugger<br />
<br />
Manual: <a href="https://hack64.net/docs/pj64d/" target="_blank" rel="noopener" class="mycode_url">https://hack64.net/docs/pj64d/</a><br />
Javascript API documentation: <a href="https://hack64.net/docs/pj64d/apidoc.php" target="_blank" rel="noopener" class="mycode_url">https://hack64.net/docs/pj64d/apidoc.php</a><br />
Project64 repo: <a href="https://github.com/project64/project64" target="_blank" rel="noopener" class="mycode_url">https://github.com/project64/project64</a><br />
Download development builds: <a href="https://www.pj64-emu.com/nightly-builds" target="_blank" rel="noopener" class="mycode_url">https://www.pj64-emu.com/nightly-builds</a><br />
<br />
<span style="font-weight: bold;" class="mycode_b">Video demos</span><br />
<a href="https://www.youtube.com/watch?v=PC0Tlz6oiN0" target="_blank" rel="noopener" class="mycode_url">Javascript CPU event hooking example</a><br />
<a href="https://www.youtube.com/watch?v=vG24uvidU_Y" target="_blank" rel="noopener" class="mycode_url">Javascript socket example</a><br />
<a href="https://www.youtube.com/watch?v=UgHuGIKO9hs" target="_blank" rel="noopener" class="mycode_url">Debugging example</a><br />
<br />
If you have any bug reports, questions or suggestions, feel free to post them!<br />
<br />
<a href="https://skelux.net/showthread.php?tid=549" target="_blank" rel="noopener" class="mycode_url">Old thread archive</a><br />
<br />
<img src="http://i.imgur.com/KJhd94F.png" alt="[Image: KJhd94F.png]" class="mycode_img" />]]></description>
			<content:encoded><![CDATA[Project64 debugger<br />
<br />
Manual: <a href="https://hack64.net/docs/pj64d/" target="_blank" rel="noopener" class="mycode_url">https://hack64.net/docs/pj64d/</a><br />
Javascript API documentation: <a href="https://hack64.net/docs/pj64d/apidoc.php" target="_blank" rel="noopener" class="mycode_url">https://hack64.net/docs/pj64d/apidoc.php</a><br />
Project64 repo: <a href="https://github.com/project64/project64" target="_blank" rel="noopener" class="mycode_url">https://github.com/project64/project64</a><br />
Download development builds: <a href="https://www.pj64-emu.com/nightly-builds" target="_blank" rel="noopener" class="mycode_url">https://www.pj64-emu.com/nightly-builds</a><br />
<br />
<span style="font-weight: bold;" class="mycode_b">Video demos</span><br />
<a href="https://www.youtube.com/watch?v=PC0Tlz6oiN0" target="_blank" rel="noopener" class="mycode_url">Javascript CPU event hooking example</a><br />
<a href="https://www.youtube.com/watch?v=vG24uvidU_Y" target="_blank" rel="noopener" class="mycode_url">Javascript socket example</a><br />
<a href="https://www.youtube.com/watch?v=UgHuGIKO9hs" target="_blank" rel="noopener" class="mycode_url">Debugging example</a><br />
<br />
If you have any bug reports, questions or suggestions, feel free to post them!<br />
<br />
<a href="https://skelux.net/showthread.php?tid=549" target="_blank" rel="noopener" class="mycode_url">Old thread archive</a><br />
<br />
<img src="http://i.imgur.com/KJhd94F.png" alt="[Image: KJhd94F.png]" class="mycode_img" />]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Simple Armips GUI v1.3.2]]></title>
			<link>https://hack64.net/Thread-Simple-Armips-GUI-v1-3-2</link>
			<pubDate>Fri, 09 Mar 2018 13:48:37 +0000</pubDate>
			<guid isPermaLink="false">https://hack64.net/Thread-Simple-Armips-GUI-v1-3-2</guid>
			<description><![CDATA[<img src="https://i.imgur.com/MJlGyYW.png" alt="[Image: MJlGyYW.png]" class="mycode_img" /><br />
<br />
This is a simple front-end GUI for <span style="text-decoration: underline;" class="mycode_u"><a href="https://github.com/Kingcom/armips" target="_blank" rel="noopener" class="mycode_url">Kingcom's Armips program</a></span>. This is useful for people who don't want to include the ".Open / .Close / .n64" in all of their Armips source files. This also includes the n64crc program, which will automatically update the ROM's checksum when you import a source file if the profile is set on "N64" or "N64 RSP". If you have ever used Tarek's CajeASM GUI, then this should be very familiar to you.<br />
<br />
This program also includes 7 basic ASM examples for SM64 in the "<span style="font-family: Courier New;" class="mycode_font">/data/examples/N64/Super Mario 64"</span> folder. There are 2 different versions of the examples, one that is just assembly code and the other which uses the SM64 Macro Library (sm64mlib). See the bottom part of this post for more information.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">[Download & Source]</span> <span style="text-decoration: underline;" class="mycode_u"><a href="https://github.com/DavidSM64/SimpleArmipsGui/releases/tag/1.3.2" target="_blank" rel="noopener" class="mycode_url">https://github.com/DavidSM64/SimpleArmip.../tag/1.3.2</a></span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">Note:</span> You will need the 32-bit Visual Studio 2015 redistributable to run armips. If you don't have it, then you can download it here: <a href="https://www.microsoft.com/en-US/download/details.aspx?id=48145" target="_blank" rel="noopener" class="mycode_url">https://www.microsoft.com/en-US/download...x?id=48145</a>. Make sure to select "vc_redist.x86.exe".<br />
<br />
If you want to know more about how to use armips itself, then I highly suggest looking at <span style="text-decoration: underline;" class="mycode_u"><a href="https://github.com/Kingcom/armips/blob/master/Readme.md" target="_blank" rel="noopener" class="mycode_url">the readme page on Kingcom's Github</a></span>.<br />
<br />
<div class="spoiler">
		<div class="thead"><button class="button float_right" onclick="javascript: if(parentNode.parentNode.getElementsByTagName('div')[2].style.display == 'block'){ parentNode.parentNode.getElementsByTagName('div')[2].style.display = 'none'; this.innerHTML='Show Content'; } else { parentNode.parentNode.getElementsByTagName('div')[2].style.display = 'block'; this.innerHTML='Hide Content'; }">Show Content</button>Changelog<div style="clear: both;"></div></div>
		<div class="trow1" style="display: none;"><span style="font-weight: bold;" class="mycode_b">Version 1.3.2</span><br />
* Updated to latest version of armips (v0.10.0-48-g7aa5cba)<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Version 1.3.1</span><br />
* Fixed a bug with additional arguments not being concatted correctly. You should no longer have to add a space at the beginning.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Version 1.3</span><br />
* Restructured File paths<br />
* Added profiles for each of the different 10 architectures that armips supports.<br />
* Updated to the latest armips build (v0.9-107-gc19500c)<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Version 1.2<br />
</span>* You can now convert your assembly code to a SM64 Editor tweak in the new XML patch window.<br />
* You can now manage the executable programs that get run when the "Assemble!" button is pressed. You can even run programs before Armips does.<br />
* Moved the "Armips Readme" button to the main window.<br />
* Added a checkbox in the settings window to enable/disable the "File assembled successfully to ROM." message after a successful assemble.<br />
* Updated to latest armips build (v0.9-96-ge2610fe)<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Version 1.1<br />
</span>* Added armips.exe updater, which was created by shygoo<br />
* Added a button to take you to armips' readme file<br />
* Slightly changed layout of settings menu<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Version 1.0.4<br />
</span>* Updated to latest armips build (v0.9-85-g0cf6fdc)<br />
* Updated sm64mlib to version 0.2<br />
- Added new macros: .f3d_vertex, .f3d_dw, .f3d_loadTLUT, .CI4_palette<br />
- Fixed up a lot of macros from levelscripts.asm, geoscripts.asm, and fast3dscripts.asm that were broken.<span style="font-weight: bold;" class="mycode_b"><br />
<br />
Version 1.0.3</span><br />
* Updated armips.exe to latest build (v0.9-75-gc39eb76)<br />
* Removed .asciiz macro in sm64mlib, because .asciiz is now natively in armips.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Version 1.0.2</span><br />
* Added 2 new ASM examples.<br />
* Updated sm64mlib to v0.1 (Minor changes to sm64functions.asm file)<br />
* More armips psuedo instructions in examples and sm64mlib functions.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Version 1.0.1</span><br />
* Added a new checkbox in the settings menu, which makes it so that the file-path of the ASM file is the root directory. This is enabled by default<br />
* Fixed a bug where file-paths with spaces causes imports to fail<br />
* Switch over to using n64crc.exe instead of chksum64.exe, due to chksum64 creating invalid checksums with some N64 games.</div>
	</div>
<br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">How to use the program:</span></span><br />
<ol type="1" class="mycode_list">
</li>
<li>Load up the ROM file<br />
</li>
<li>Load up the Assembly source file<br />
</li>
<li>Press the Assemble button.<br />
</li>
<li>If the import fails, then fix the source code according to what the error console says and go back to step 2<br />
</li></ol>
<br />
<div class="spoiler">
		<div class="thead"><button class="button float_right" onclick="javascript: if(parentNode.parentNode.getElementsByTagName('div')[2].style.display == 'block'){ parentNode.parentNode.getElementsByTagName('div')[2].style.display = 'none'; this.innerHTML='Show Content'; } else { parentNode.parentNode.getElementsByTagName('div')[2].style.display = 'block'; this.innerHTML='Hide Content'; }">Show Content</button>How does the gui work with armips.exe?<div style="clear: both;"></div></div>
		<div class="trow1" style="display: none;">When the "Assemble!" button is pressed, the program will go through all the executables and run them in order. (see: "Managing Executables")<br />
<br />
When the armips program is reached, it will create a temporary assembly file that will include the specified ASM file the user includes, along with any libraries that are enabled in the settings menu. The labels <span style="font-weight: bold;" class="mycode_b">SAG_IMPORTPATH</span> and <span style="font-weight: bold;" class="mycode_b">SAG_FILEPOS</span> are created to represent the variables that go into the ".Open" directive<br />
<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>// This is temp.asm<br />
SAG_FILEPOS equ 0x0<br />
SAG_IMPORTPATH equ "C:/Path/To/Rom/File"<br />
.Open SAG_IMPORTPATH, SAG_FILEPOS<br />
<br />
// Set armips to N64 mode<br />
.n64<br />
<br />
// Include any libraries the user specified in the settings menu<br />
.include "C:/Path/To/Library/Include/File"<br />
<br />
.include "C:/Path/To/Asm/File"<br />
.Close</code></div></div></div>
	</div>
<br />
<span style="font-weight: bold;" class="mycode_b"><span style="font-size: medium;" class="mycode_size">Settings:</span></span><br />
<br />
<span style="font-weight: bold;" class="mycode_b"><span style="font-size: medium;" class="mycode_size"><img src="https://i.imgur.com/2NwlWGi.png" alt="[Image: 2NwlWGi.png]" class="mycode_img" /></span></span><br />
<br />
Pressing the red gear icon in the top-left corner of the main window will open the settings menu. This menu will allow you to change some options like the RAM address that will be used when opening the file. This is where you can also enable/disable libraries to use with your assembly code. Right now only the SM64 Macro Library (aka: sm64mlib) will be included. If anyone else has some useful libraries, then let me know so I can include them in future releases. You can find the libraries under a profile's libs folder (<span style="font-family: Courier New;" class="mycode_font">/data/profiles/*/libs/</span>) folder.<br />
<ul class="mycode_list">
</li>
<li>[Pre-Lib ASM] - Edit armips code that will be processed BEFORE libraries have been loaded<br />
</li>
<li>[Post-Lib ASM] - Edit armips code that will be processed AFTER libraries have been loaded<br />
</li>
<li>[Update armips.exe] - Looks up the latest build of the armips.exe program and gives you the option to download if available.<br />
</li>
<li>[Manage executables] - Manage all of the programs that will be run in order when you click the "Assemble!" button.<br />
</li></ul>
<br />
<div class="spoiler">
		<div class="thead"><button class="button float_right" onclick="javascript: if(parentNode.parentNode.getElementsByTagName('div')[2].style.display == 'block'){ parentNode.parentNode.getElementsByTagName('div')[2].style.display = 'none'; this.innerHTML='Show Content'; } else { parentNode.parentNode.getElementsByTagName('div')[2].style.display = 'block'; this.innerHTML='Hide Content'; }">Show Content</button>Managing Executables<div style="clear: both;"></div></div>
		<div class="trow1" style="display: none;"><span style="font-weight: bold;" class="mycode_b"><span style="font-size: medium;" class="mycode_size"><img src="https://i.imgur.com/ODxNkiv.png" alt="[Image: ODxNkiv.png]" class="mycode_img" /></span></span><br />
<br />
In this window you can manage which programs will be run after you click the "Assemble!" button. <br />
<ul class="mycode_list">
</li>
<li>Disable or enable a process by using the checkbox on the right side<br />
</li>
<li>You can change the order by using the up/down arrows on the right side<br />
</li>
<li>Add a new reference using the "Add Executable" button on the top left.<br />
</li>
<li>Pressing the "Edit" button will allow you to change the program or delete the reference.<br />
</li>
<li>There are 5 special labels that you can use in the arguments line:<ul class="mycode_list">
</li>
<li><span style="font-weight: bold;" class="mycode_b">&#36;{ROM_FILE_PATH}</span> is the path to the ROM file.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">&#36;{ROM_FILE_SIZE}</span> will output the size (in bytes) of the ROM file as a plain integer.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">&#36;{ASM_FILE_PATH}</span> is the path to the ASM file.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">&#36;{FILE_RAM_ADDRESS}</span> is the file RAM address specified in the settings window outputted as a hex integer.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">&#36;{ARMIPS_ADDITIONAL_ARGUMENTS}</span> is the line of text the user enters in the "Additional Arguments" window.<br />
</li></ul>
</li></ul>
</div>
	</div>
<br />
<div class="spoiler">
		<div class="thead"><button class="button float_right" onclick="javascript: if(parentNode.parentNode.getElementsByTagName('div')[2].style.display == 'block'){ parentNode.parentNode.getElementsByTagName('div')[2].style.display = 'none'; this.innerHTML='Show Content'; } else { parentNode.parentNode.getElementsByTagName('div')[2].style.display = 'block'; this.innerHTML='Hide Content'; }">Show Content</button>Creating SM64 Editor Tweaks<div style="clear: both;"></div></div>
		<div class="trow1" style="display: none;"><img src="https://i.imgur.com/4a8Dshi.png" alt="[Image: 4a8Dshi.png]" class="mycode_img" /><br />
<br />
To convert your assembly code into a SM64 Editor Tweak, you only need to do the following:<br />
<ol type="1" class="mycode_list">
</li>
<li>Load a ROM file and the ASM file you wish to make into a tweak.<br />
</li>
<li>Click the "XML" button at the top-left corner of the window.<br />
</li>
<li>In the XML Patch window, select the "SM64 Editor Tweak" profile on the right side.<br />
</li>
<li>Type your description of the tweak inside the textbox.<br />
</li>
<li>Press the "Make XML patch" button on the top left of the window.<br />
</li>
<li>Navigate to the Tweaks folder for the SM64 Editor (/SM64 Editor/Data/Tweaks/)<br />
</li>
<li>Save the file, and it should now appear within the Tweak manager in the SM64 Editor.<br />
</li></ol>
</div>
	</div>
<br />
<span style="font-weight: bold;" class="mycode_b"><span style="font-size: medium;" class="mycode_size">SM64 Macro Library (v0.2):</span></span><br />
<br />
sm64mlib was made to be a replacement for the <a href="http://origami64.net/showthread.php?tid=359" target="_blank" rel="noopener" class="mycode_url">defined SM64 functions file I made for CajeASM</a>. The SM64 Macro Library adds a lot of custom macros to make programming much simpler. Compare the two source files below. They both do the exact same thing, but the sm64mlib version uses fewer lines of code. Please look through the <span style="font-family: Courier New;" class="mycode_font">.asm</span> files in the /<span style="font-family: Courier New;" class="mycode_font">data/profiles/N64/libs/sm64mlib</span> folder to see how the macros work.<br />
<br />
<div class="spoiler">
		<div class="thead"><button class="button float_right" onclick="javascript: if(parentNode.parentNode.getElementsByTagName('div')[2].style.display == 'block'){ parentNode.parentNode.getElementsByTagName('div')[2].style.display = 'none'; this.innerHTML='Show Content'; } else { parentNode.parentNode.getElementsByTagName('div')[2].style.display = 'block'; this.innerHTML='Hide Content'; }">Show Content</button>Hello World ASM example (Armips 0.9+)<div style="clear: both;"></div></div>
		<div class="trow1" style="display: none;">// [ARMIPS 0.9+] "Hello World" Example by Davideesk<br />
<br />
.defineLabel func_printXY, 0x802D66C0<br />
<br />
.orga 0x861C0 ; Set ROM address<br />
.area 0x90 ; Set data import limit to 0x90 bytes<br />
addiu sp, sp, -0x18<br />
sw ra, 0x14 (sp)<br />
<br />
la a2, 0x802CB250 ; Pointer to "Hello World" text<br />
li a0, 0x60 ; x position<br />
jal func_printXY ; call printXY function<br />
li a1, 0x20 ; y position<br />
<br />
lw ra, 0x14 (sp)<br />
jr ra<br />
addiu sp, sp, 0x18<br />
.endarea<br />
<br />
.orga 0x86250 ; 0x802CB250<br />
.asciiz "Hello World"</div>
	</div>
<div class="spoiler">
		<div class="thead"><button class="button float_right" onclick="javascript: if(parentNode.parentNode.getElementsByTagName('div')[2].style.display == 'block'){ parentNode.parentNode.getElementsByTagName('div')[2].style.display = 'none'; this.innerHTML='Show Content'; } else { parentNode.parentNode.getElementsByTagName('div')[2].style.display = 'block'; this.innerHTML='Hide Content'; }">Show Content</button>Hello World ASM example (Armips 0.9+ w/ SM64 Macro Library)<div style="clear: both;"></div></div>
		<div class="trow1" style="display: none;">// [ARMIPS 0.9 w/ SM64 Macro Library] "Hello World" Example by Davideesk<br />
<br />
.orga 0x861C0 ; Set ROM address<br />
.area 0x90 ; Set data import limit to 0x90 bytes<br />
addiu sp, sp, -0x18<br />
sw ra, 0x14 (sp)<br />
<br />
// Prints "Hello World" at the screen pos (0x60, 0x20)<br />
.f_printXY 0x60, 0x20, 0x802CB250<br />
<br />
lw ra, 0x14 (sp)<br />
jr ra<br />
addiu sp, sp, 0x18<br />
.endarea<br />
<br />
.orga 0x86250 ; 0x802CB250<br />
.asciiz "Hello World"</div>
	</div>]]></description>
			<content:encoded><![CDATA[<img src="https://i.imgur.com/MJlGyYW.png" alt="[Image: MJlGyYW.png]" class="mycode_img" /><br />
<br />
This is a simple front-end GUI for <span style="text-decoration: underline;" class="mycode_u"><a href="https://github.com/Kingcom/armips" target="_blank" rel="noopener" class="mycode_url">Kingcom's Armips program</a></span>. This is useful for people who don't want to include the ".Open / .Close / .n64" in all of their Armips source files. This also includes the n64crc program, which will automatically update the ROM's checksum when you import a source file if the profile is set on "N64" or "N64 RSP". If you have ever used Tarek's CajeASM GUI, then this should be very familiar to you.<br />
<br />
This program also includes 7 basic ASM examples for SM64 in the "<span style="font-family: Courier New;" class="mycode_font">/data/examples/N64/Super Mario 64"</span> folder. There are 2 different versions of the examples, one that is just assembly code and the other which uses the SM64 Macro Library (sm64mlib). See the bottom part of this post for more information.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">[Download & Source]</span> <span style="text-decoration: underline;" class="mycode_u"><a href="https://github.com/DavidSM64/SimpleArmipsGui/releases/tag/1.3.2" target="_blank" rel="noopener" class="mycode_url">https://github.com/DavidSM64/SimpleArmip.../tag/1.3.2</a></span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">Note:</span> You will need the 32-bit Visual Studio 2015 redistributable to run armips. If you don't have it, then you can download it here: <a href="https://www.microsoft.com/en-US/download/details.aspx?id=48145" target="_blank" rel="noopener" class="mycode_url">https://www.microsoft.com/en-US/download...x?id=48145</a>. Make sure to select "vc_redist.x86.exe".<br />
<br />
If you want to know more about how to use armips itself, then I highly suggest looking at <span style="text-decoration: underline;" class="mycode_u"><a href="https://github.com/Kingcom/armips/blob/master/Readme.md" target="_blank" rel="noopener" class="mycode_url">the readme page on Kingcom's Github</a></span>.<br />
<br />
<div class="spoiler">
		<div class="thead"><button class="button float_right" onclick="javascript: if(parentNode.parentNode.getElementsByTagName('div')[2].style.display == 'block'){ parentNode.parentNode.getElementsByTagName('div')[2].style.display = 'none'; this.innerHTML='Show Content'; } else { parentNode.parentNode.getElementsByTagName('div')[2].style.display = 'block'; this.innerHTML='Hide Content'; }">Show Content</button>Changelog<div style="clear: both;"></div></div>
		<div class="trow1" style="display: none;"><span style="font-weight: bold;" class="mycode_b">Version 1.3.2</span><br />
* Updated to latest version of armips (v0.10.0-48-g7aa5cba)<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Version 1.3.1</span><br />
* Fixed a bug with additional arguments not being concatted correctly. You should no longer have to add a space at the beginning.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Version 1.3</span><br />
* Restructured File paths<br />
* Added profiles for each of the different 10 architectures that armips supports.<br />
* Updated to the latest armips build (v0.9-107-gc19500c)<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Version 1.2<br />
</span>* You can now convert your assembly code to a SM64 Editor tweak in the new XML patch window.<br />
* You can now manage the executable programs that get run when the "Assemble!" button is pressed. You can even run programs before Armips does.<br />
* Moved the "Armips Readme" button to the main window.<br />
* Added a checkbox in the settings window to enable/disable the "File assembled successfully to ROM." message after a successful assemble.<br />
* Updated to latest armips build (v0.9-96-ge2610fe)<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Version 1.1<br />
</span>* Added armips.exe updater, which was created by shygoo<br />
* Added a button to take you to armips' readme file<br />
* Slightly changed layout of settings menu<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Version 1.0.4<br />
</span>* Updated to latest armips build (v0.9-85-g0cf6fdc)<br />
* Updated sm64mlib to version 0.2<br />
- Added new macros: .f3d_vertex, .f3d_dw, .f3d_loadTLUT, .CI4_palette<br />
- Fixed up a lot of macros from levelscripts.asm, geoscripts.asm, and fast3dscripts.asm that were broken.<span style="font-weight: bold;" class="mycode_b"><br />
<br />
Version 1.0.3</span><br />
* Updated armips.exe to latest build (v0.9-75-gc39eb76)<br />
* Removed .asciiz macro in sm64mlib, because .asciiz is now natively in armips.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Version 1.0.2</span><br />
* Added 2 new ASM examples.<br />
* Updated sm64mlib to v0.1 (Minor changes to sm64functions.asm file)<br />
* More armips psuedo instructions in examples and sm64mlib functions.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Version 1.0.1</span><br />
* Added a new checkbox in the settings menu, which makes it so that the file-path of the ASM file is the root directory. This is enabled by default<br />
* Fixed a bug where file-paths with spaces causes imports to fail<br />
* Switch over to using n64crc.exe instead of chksum64.exe, due to chksum64 creating invalid checksums with some N64 games.</div>
	</div>
<br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">How to use the program:</span></span><br />
<ol type="1" class="mycode_list">
</li>
<li>Load up the ROM file<br />
</li>
<li>Load up the Assembly source file<br />
</li>
<li>Press the Assemble button.<br />
</li>
<li>If the import fails, then fix the source code according to what the error console says and go back to step 2<br />
</li></ol>
<br />
<div class="spoiler">
		<div class="thead"><button class="button float_right" onclick="javascript: if(parentNode.parentNode.getElementsByTagName('div')[2].style.display == 'block'){ parentNode.parentNode.getElementsByTagName('div')[2].style.display = 'none'; this.innerHTML='Show Content'; } else { parentNode.parentNode.getElementsByTagName('div')[2].style.display = 'block'; this.innerHTML='Hide Content'; }">Show Content</button>How does the gui work with armips.exe?<div style="clear: both;"></div></div>
		<div class="trow1" style="display: none;">When the "Assemble!" button is pressed, the program will go through all the executables and run them in order. (see: "Managing Executables")<br />
<br />
When the armips program is reached, it will create a temporary assembly file that will include the specified ASM file the user includes, along with any libraries that are enabled in the settings menu. The labels <span style="font-weight: bold;" class="mycode_b">SAG_IMPORTPATH</span> and <span style="font-weight: bold;" class="mycode_b">SAG_FILEPOS</span> are created to represent the variables that go into the ".Open" directive<br />
<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>// This is temp.asm<br />
SAG_FILEPOS equ 0x0<br />
SAG_IMPORTPATH equ "C:/Path/To/Rom/File"<br />
.Open SAG_IMPORTPATH, SAG_FILEPOS<br />
<br />
// Set armips to N64 mode<br />
.n64<br />
<br />
// Include any libraries the user specified in the settings menu<br />
.include "C:/Path/To/Library/Include/File"<br />
<br />
.include "C:/Path/To/Asm/File"<br />
.Close</code></div></div></div>
	</div>
<br />
<span style="font-weight: bold;" class="mycode_b"><span style="font-size: medium;" class="mycode_size">Settings:</span></span><br />
<br />
<span style="font-weight: bold;" class="mycode_b"><span style="font-size: medium;" class="mycode_size"><img src="https://i.imgur.com/2NwlWGi.png" alt="[Image: 2NwlWGi.png]" class="mycode_img" /></span></span><br />
<br />
Pressing the red gear icon in the top-left corner of the main window will open the settings menu. This menu will allow you to change some options like the RAM address that will be used when opening the file. This is where you can also enable/disable libraries to use with your assembly code. Right now only the SM64 Macro Library (aka: sm64mlib) will be included. If anyone else has some useful libraries, then let me know so I can include them in future releases. You can find the libraries under a profile's libs folder (<span style="font-family: Courier New;" class="mycode_font">/data/profiles/*/libs/</span>) folder.<br />
<ul class="mycode_list">
</li>
<li>[Pre-Lib ASM] - Edit armips code that will be processed BEFORE libraries have been loaded<br />
</li>
<li>[Post-Lib ASM] - Edit armips code that will be processed AFTER libraries have been loaded<br />
</li>
<li>[Update armips.exe] - Looks up the latest build of the armips.exe program and gives you the option to download if available.<br />
</li>
<li>[Manage executables] - Manage all of the programs that will be run in order when you click the "Assemble!" button.<br />
</li></ul>
<br />
<div class="spoiler">
		<div class="thead"><button class="button float_right" onclick="javascript: if(parentNode.parentNode.getElementsByTagName('div')[2].style.display == 'block'){ parentNode.parentNode.getElementsByTagName('div')[2].style.display = 'none'; this.innerHTML='Show Content'; } else { parentNode.parentNode.getElementsByTagName('div')[2].style.display = 'block'; this.innerHTML='Hide Content'; }">Show Content</button>Managing Executables<div style="clear: both;"></div></div>
		<div class="trow1" style="display: none;"><span style="font-weight: bold;" class="mycode_b"><span style="font-size: medium;" class="mycode_size"><img src="https://i.imgur.com/ODxNkiv.png" alt="[Image: ODxNkiv.png]" class="mycode_img" /></span></span><br />
<br />
In this window you can manage which programs will be run after you click the "Assemble!" button. <br />
<ul class="mycode_list">
</li>
<li>Disable or enable a process by using the checkbox on the right side<br />
</li>
<li>You can change the order by using the up/down arrows on the right side<br />
</li>
<li>Add a new reference using the "Add Executable" button on the top left.<br />
</li>
<li>Pressing the "Edit" button will allow you to change the program or delete the reference.<br />
</li>
<li>There are 5 special labels that you can use in the arguments line:<ul class="mycode_list">
</li>
<li><span style="font-weight: bold;" class="mycode_b">&#36;{ROM_FILE_PATH}</span> is the path to the ROM file.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">&#36;{ROM_FILE_SIZE}</span> will output the size (in bytes) of the ROM file as a plain integer.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">&#36;{ASM_FILE_PATH}</span> is the path to the ASM file.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">&#36;{FILE_RAM_ADDRESS}</span> is the file RAM address specified in the settings window outputted as a hex integer.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">&#36;{ARMIPS_ADDITIONAL_ARGUMENTS}</span> is the line of text the user enters in the "Additional Arguments" window.<br />
</li></ul>
</li></ul>
</div>
	</div>
<br />
<div class="spoiler">
		<div class="thead"><button class="button float_right" onclick="javascript: if(parentNode.parentNode.getElementsByTagName('div')[2].style.display == 'block'){ parentNode.parentNode.getElementsByTagName('div')[2].style.display = 'none'; this.innerHTML='Show Content'; } else { parentNode.parentNode.getElementsByTagName('div')[2].style.display = 'block'; this.innerHTML='Hide Content'; }">Show Content</button>Creating SM64 Editor Tweaks<div style="clear: both;"></div></div>
		<div class="trow1" style="display: none;"><img src="https://i.imgur.com/4a8Dshi.png" alt="[Image: 4a8Dshi.png]" class="mycode_img" /><br />
<br />
To convert your assembly code into a SM64 Editor Tweak, you only need to do the following:<br />
<ol type="1" class="mycode_list">
</li>
<li>Load a ROM file and the ASM file you wish to make into a tweak.<br />
</li>
<li>Click the "XML" button at the top-left corner of the window.<br />
</li>
<li>In the XML Patch window, select the "SM64 Editor Tweak" profile on the right side.<br />
</li>
<li>Type your description of the tweak inside the textbox.<br />
</li>
<li>Press the "Make XML patch" button on the top left of the window.<br />
</li>
<li>Navigate to the Tweaks folder for the SM64 Editor (/SM64 Editor/Data/Tweaks/)<br />
</li>
<li>Save the file, and it should now appear within the Tweak manager in the SM64 Editor.<br />
</li></ol>
</div>
	</div>
<br />
<span style="font-weight: bold;" class="mycode_b"><span style="font-size: medium;" class="mycode_size">SM64 Macro Library (v0.2):</span></span><br />
<br />
sm64mlib was made to be a replacement for the <a href="http://origami64.net/showthread.php?tid=359" target="_blank" rel="noopener" class="mycode_url">defined SM64 functions file I made for CajeASM</a>. The SM64 Macro Library adds a lot of custom macros to make programming much simpler. Compare the two source files below. They both do the exact same thing, but the sm64mlib version uses fewer lines of code. Please look through the <span style="font-family: Courier New;" class="mycode_font">.asm</span> files in the /<span style="font-family: Courier New;" class="mycode_font">data/profiles/N64/libs/sm64mlib</span> folder to see how the macros work.<br />
<br />
<div class="spoiler">
		<div class="thead"><button class="button float_right" onclick="javascript: if(parentNode.parentNode.getElementsByTagName('div')[2].style.display == 'block'){ parentNode.parentNode.getElementsByTagName('div')[2].style.display = 'none'; this.innerHTML='Show Content'; } else { parentNode.parentNode.getElementsByTagName('div')[2].style.display = 'block'; this.innerHTML='Hide Content'; }">Show Content</button>Hello World ASM example (Armips 0.9+)<div style="clear: both;"></div></div>
		<div class="trow1" style="display: none;">// [ARMIPS 0.9+] "Hello World" Example by Davideesk<br />
<br />
.defineLabel func_printXY, 0x802D66C0<br />
<br />
.orga 0x861C0 ; Set ROM address<br />
.area 0x90 ; Set data import limit to 0x90 bytes<br />
addiu sp, sp, -0x18<br />
sw ra, 0x14 (sp)<br />
<br />
la a2, 0x802CB250 ; Pointer to "Hello World" text<br />
li a0, 0x60 ; x position<br />
jal func_printXY ; call printXY function<br />
li a1, 0x20 ; y position<br />
<br />
lw ra, 0x14 (sp)<br />
jr ra<br />
addiu sp, sp, 0x18<br />
.endarea<br />
<br />
.orga 0x86250 ; 0x802CB250<br />
.asciiz "Hello World"</div>
	</div>
<div class="spoiler">
		<div class="thead"><button class="button float_right" onclick="javascript: if(parentNode.parentNode.getElementsByTagName('div')[2].style.display == 'block'){ parentNode.parentNode.getElementsByTagName('div')[2].style.display = 'none'; this.innerHTML='Show Content'; } else { parentNode.parentNode.getElementsByTagName('div')[2].style.display = 'block'; this.innerHTML='Hide Content'; }">Show Content</button>Hello World ASM example (Armips 0.9+ w/ SM64 Macro Library)<div style="clear: both;"></div></div>
		<div class="trow1" style="display: none;">// [ARMIPS 0.9 w/ SM64 Macro Library] "Hello World" Example by Davideesk<br />
<br />
.orga 0x861C0 ; Set ROM address<br />
.area 0x90 ; Set data import limit to 0x90 bytes<br />
addiu sp, sp, -0x18<br />
sw ra, 0x14 (sp)<br />
<br />
// Prints "Hello World" at the screen pos (0x60, 0x20)<br />
.f_printXY 0x60, 0x20, 0x802CB250<br />
<br />
lw ra, 0x14 (sp)<br />
jr ra<br />
addiu sp, sp, 0x18<br />
.endarea<br />
<br />
.orga 0x86250 ; 0x802CB250<br />
.asciiz "Hello World"</div>
	</div>]]></content:encoded>
		</item>
	</channel>
</rss>