tags:

views:

152

answers:

5

Hey guy,

I'm writing a NES emulator in C/C++ for Mac OS (I've already written one, so I know the basics). Since many hardware registers are mapped to memory locations, I was wondering if there was some syscall I could use to map an address to the result of a function: when it would be accessed, the function would be called. (I'm pretty sure I can't, but hey, it's worth asking.)

Here is what I'd like to do:

int getStatusRegisterValue()
{
    return 0xCAFEBABE;
}

// obviously, more parameters than just this would be involved I suppose
int* statusRegister = syscall_to_map_function_to_address(getStatusRegisterValue);

// from here on, doing (*statusRegister) should call getStatusRegisterValue and
// return its value
*statusRegister == 0xCAFEBABE;

This project is going to be my try at LLVM, and my goal is to recompile the ROM to LLVM bytecode. That's why it would be convenient if the simple memory access could trigger the function (just like on real NES hardware). The two other obvious possibilities to solve my problem are to either cache the register values and store them in actual memory, or call a function from the recompiled code to map the memory locations to whatever they really are.

Thanks!

A: 

In C++ you can overload the * and -> operators for user-defined classes. Would this allow you to achieve what you want?

Oli Charlesworth
That's a good idea, but the execution engine's going to need the feature at a much lower level than C++. I'm going to try to recompile the ROM to LLVM bytecode, and that's why it would be simpler if the sole memory access could execute the function.
zneak
+1  A: 

This almost sounds just like normal function pointers:

typedef int(*function_type)(void);

function_type = &getStatusRegisterValue; // store
int i = function_type(); // call

Different syntax, same idea?

GMan
Not exactly: a NES has several memory locations that access hardware registers instead of an actual RAM address, and I'm trying to mimic this behavior. I'm not going to make the function calls myself (hence it's not a syntax problem): this project is a excuse to use LLVM, so I'll try to recompile the ROM to LLVM bytecode. If I can get my program's address space to behave like a NES's address space, I *think* I would have less things to worry about. There are, of course, obvious alternatives, like using a function to map the locations to whatever they really need to do.
zneak
+1  A: 

This can't be done in C (or C++, but let's just stick to C for simplicity).

You can "emulate" (ha) this effect with operator overloading and functors with explicit addressing, but it won't be the real thing. There are too many assumptions that must be made about the target function to do this normally.

1) You assume it always returns the same value.

Actually, that's about it. Still though, it's a big assumption to make!

Clark Gaebel
Actually, I don't want to assume it always returns the same value. That would be stupid: I don't need to compute the result of a function each time a memory location is accessed if I can just place it there and let it be instead. The equality in the example is just an example of what it'd do. Other than that, obviously, it assumes all sorts of thing for the sake of brevity, but I can imagine a design that would be more flexible.
zneak
A: 

You can't trigger functions to be executed on memory access unless you use memory breakpoints (which is really just for debugging, if available on the system).

This is also independent from the programming language, your question is rather aimed at modern computer platforms in general.

Patrick Daryll Glandien
I specified programming languages simply because if there was a solution, people posting it would know which language to use.
zneak
+3  A: 

Maybe you could try installing a SEGV handler and checking the faulting address there. As I don't use Mac OS I can't help you more.

ninjalj
That *could* be a good idea. However, it needs to be contiguous with other good addresses, so that probably won't do it.
zneak
You mean NES registers are in the same page as real memory? Or that you would emulate some registers using plain old variables? If you don't mind poor performance for everything else on the same page, this should work.
ninjalj
It seems you'd fault on any access in the range $2000 - $5FFF. Sure, that would be slow for expansion ROM access, but that wasn't fast in the first place.
MSalters
No, you're right. The IO register pages mirror themselves continually, so there's no good address inside them except the registers. I won't do it because it's much more expensive that what I'd have wanted, but you still get the good answer.
zneak