Language…
8 users online: autisticsceptile1993, Batata Douce, DasFueller, DPBOX, Dzing, eltiolavara9, matthwsan, RZRider - Guests: 273 - Bots: 285
Users: 64,795 (2,377 active)
Latest user: mathew

Convert between SNES and PC w/o Lunar Address?

I need to write a function in C# that converts between SNES and PC Hexadecimal Addresses. I guess that alone explains why I can't use Lunar Address for this. P/Invoking Lunar Compress.dll is also not acceptable because I want this software to run on platforms other than Windows (using Mono).

So I need to know the differences between the two addressing formats. I don't have a clue where to look, so I thought I would ask here.

Any help would be appreciated.
Your layout has been removed.
This is my C++ codes for converting between SNES and PC format:


int snespc(unsigned int addrlo, unsigned int addrhi, unsigned int bank)
{
return (addrlo&255)+(256*(addrhi&255))+(32768*bank)+header-32256;//65536-32256=33280
}

int pcsneslo(int addr)
{
return (addr&255);
}

int pcsneshi(int addr)
{
return (((addr+header)/256)&127)+128;
}

int pcsnesbank(int addr)
{
//return (addrlo&255)+(256*(addrhi&255))+(32768*bank)+header-32256;//65536-32256=33280
return ((addr+header)/32768)&255;
}

It converts between SNES LoROM and PC. I think it works in C#, if not, it's propably easy to convert.
<blm> zsnes users are the flatearthers of emulation
Originally posted by Alcaro
Code
int pcsneshi(int addr)
{
return (((addr+header)/256)&127)+128;
}
int pcsnesbank(int addr)
{
//return (addrlo&255)+(256*(addrhi&255))+(32768*bank)+header-32256;//65536-32256=33280
return ((addr+header)/32768)&255;
}

Error: "header" is undefined...

I'm assuming you mean that header is 512 if the ROM has a header, and 0 if the ROM doesn't have a header?

so...
Code
int pcsneshi(int addr, bool header)
{
return (((addr+((int) header * 512)))/256)&127)+128;
}
int pcsnesbank(int addr, bool header)
{
return ((addr+((int) header * 512))/32768)&255;
}


right???
Your layout has been removed.
Actually, header is 0 in a headered ROM and -512 in an unheadered.
It's defined outside of any functions, so it doesn't need to be passed to the functions, but your method does propably work too.
<blm> zsnes users are the flatearthers of emulation
Just to clarify...
Code
int pcsneshi(int addr, bool header)
{
return (((addr+((int) (!header) * -512)))/256)&127)+128;
}
int pcsnesbank(int addr, bool header)
{
return ((addr+((int) (!header) * -512))/32768)&255;
}

Right?
Your layout has been removed.
Originally posted by FyarBall
Just to clarify...
Code
int pcsneshi(int addr, bool header)
{
return (((addr+((int) (!header) * -512)))/256)&127)+128;
}
int pcsnesbank(int addr, bool header)
{
return ((addr+((int) (!header) * -512))/32768)&255;
}

Right?

I doubt that the pcsneshi function will even compile...there seems to be more )'s than ('s. Also, the ((int) (!header) * -512) looks preety weird...there's a double negation there.
I think it should be
Code
int pcsneshi(int addr, bool header)
{
	return (((addr-(((int) header)*512))/256)&127)+128;
}

I think the pcsnesbank function should be
Code
int pcsnesbank(int addr, bool header)
{
	return ((addr-(((int) header)*512))/32768)&255;
}

Actually, I haven't tried the pcsnes functions, I just tried to reverse engineer the snespc function.

Edit: I made a program to test them, and found that the pcsneshi and pcsnesbank functions are preety much wrong. Here's fixed versions of the four functions that takes a header argument:
Code
int snespc(unsigned int addrlo, unsigned int addrhi, unsigned int bank, bool header)
{
 return (addrlo&255)+(256*(addrhi&255))+(32768*bank)-((header)?0:512)-32256;
}

int pcsneslo(int addr, bool header)
{
	return (addr&255);
}

int pcsneshi(int addr, bool header)
{
	return (((addr-((header)?512:0))/256)&127)+128;
}

int pcsnesbank(int addr, bool header)
{
	return ((addr-((header)?512:0))/32768)&255;
}

(Can't belive we both forgot about the ternary ?: operator...)
<blm> zsnes users are the flatearthers of emulation
Thanks! I converted it to JavaScript (removed the type declarations and prepend "function" before the function declarations) to play around with it, and it works great both ways. I also did some research, and played around with Lunar Address, and found that HiROM addressing is actually much less complicated than LoROM:

LoROM -> ROM data occupies only the upper half of banks 00 to 6F. Banks 70-7F are reserved by the SNES, banks 80-EF are mirrors of banks 00-6F, and banks F0-FF take on where banks 00-6f left off.

HiROM -> ROM data occupies banks C0-FF fully and completely. This means all you have to worry about when doing conversion is offsetting the PC address "bank" (or highest byte) by C0. The rest of the address stays the same.

So in C syntax style...

Code
int snespchirom(unsigned int addrlo, unsigned int addrhi, unsigned int bank, bool header)
{
 return (addrlo&255)+(256*(addrhi&255))+(65536*((bank&255)-192))+((header)?512:0);
}

int pcsneslohirom(int addr, bool header)
{
	return (addr&255);
}

int pcsneshihirom(int addr, bool header)
{
	return ((addr-((header)?512:0))/256)&255;
}

int pcsnesbankhirom(int addr, bool header)
{
	return (((addr-((header)?512:0))/65536)&255)+192;
}

I used your code as a base, so I hope you don't mind.

These functions work for HiROM. I guess I may as well post again once I make functions for ExHiROM and ExLoROM, so if anyone else is hunting for data and stumbles across this thread, they will find what they need.
Your layout has been removed.
Yes, change my functions as you like. ExLoROM and ExHiROM stuff will be useful for my...secret project. However, I don't think HiROM will be useful for me.
(Also, my lorom codes only works properly for the first 6F banks, but I didn't think that compatibility with 70-FF will be of any use in my project, so I didn't add it. Actually, I didn't even try so high bank numbers.)
<blm> zsnes users are the flatearthers of emulation
Originally posted by Alcaro
(Also, my lorom codes only works properly for the first 6F banks, but I didn't think that compatibility with 70-FF will be of any use in my project, so I didn't add it. Actually, I didn't even try so high bank numbers.)

I've fixed that already :) when I get home I will post the code.

EDIT:
Code
int snespc_lorom(unsigned int addrlo, unsigned int addrhi, unsigned int bank, bool header) 
{ 
  if(((bank&240)==112) || ((addrhi&128) != 128)){
    //Invalid SNES LoROM address!
    /* The first check looks to see if the bank is 7x
       The second check looks to see if the address is in the bottom half of the bank */
    return false;
  }
  return (addrlo&255)+(256*(addrhi&255))+(32768*(bank&127))-((header)?0:512)-32256;
}

int pcsneslo_lorom(int addr, bool header) 
{
	if((header && (addr < 512)) || (addr >= (4194304 + ((header)?512:0)))){
	  //PC Address out of LoROM addressing range!
          /* the first check looks to see if the PC address is IN the header
             the second checks to see if the PC address is too big for LoROM addressing to handle */
          return false;
	}
	return (addr&255);
}
int pcsneshi_lorom(int addr, bool header)
{
        if((header && (addr < 512)) || (addr >= (4194304 + ((header)?512:0)))){
          //PC Address out of LoROM addressing range!
          return false;
        }
	return (((addr-((header)?512:0))/256)&127)+128;
}

int pcsnesbank_lorom(int addr, bool header) 
{
        if((header && (addr < 512)) || (addr >= (4194304 + ((header)?512:0)))){
          //PC Address out of LoROM addressing range!
          return false;
        }
        if(addr >= (3670016 + ((header)?512:0))){
          return (((addr-((header)?512:0))/32768)&255)|128;
        }
	return ((addr-((header)?512:0))/32768)&255;
}


Compiled it and works fine.

EDIT2
ExLoROM and ExHiROM are done. I'm testing it thoroughly before I release the code formally.
Your layout has been removed.