Okay,
as you may know PSX has a MIPS R3000 runing above 30 MHz whereas PSP has a MIPS Allegrex runing above 300 hz. If we can run 90% native code in PSP after translating addresses and emulate the rest, I think we could have a very efficient emulator.
I was wondering whether some people here would be interested with such a project. I would need some help about PSX hardware and software programming.
Emulation of GPU, SPU, CDR would come in second time when the R3000 executer would be a success.
Reading some PSX docs at Hitmen's homesite should help me, but if I could find some source about a PSX emulator, it would help me to progress and avoid some caveats.
Two possibilities :
1) have a translator or rather a static recompilator. This is acceptable only if PSX programs don't abuse self-modified code. Has some people knowlegde if it is a common case ?
2) have a dynamic recompiler.
This project should be written from the scratch.
The part where I suck very much is about the PSX hardware emulation (GPU, SPU, GPE, CDR, etc.), so any document or source or help would be welcomed.
Regards.
PSX translator/emulator for PSP
i dont want to stop you if you're doing this just to learn, but there already is a psx emulator out, and the official one is coming out also. just curious about why you'd wanna do it *shrug*
these should be all you need other than a bit of know-how (course, after you read them you'll have that too, right? :))
http://dev.paradogs.com/
these should be all you need other than a bit of know-how (course, after you read them you'll have that too, right? :))
http://dev.paradogs.com/
Your idea is indeed the most efficient way to emulate the PSX on the PSP and would offer at minimum equal framerates on the PSP.
From what I know Sony's "PoPs" uses some sort of static recompilation or "static translation" aswell. They "translate" existing software once, then run that on the PSP in a new boot profile with a small "mini-PSX core" to run the translated code (and probably do the PSX to PSP hw device mapping).
As noted by razorrifh, you might just want to contribute to the existing PSX emulator rather then coding a new one (once it's GPLv2 licensed sources are finally released).
Otherwise I think your interest is driven by the pure fun of it, just implementing such a "translator" and see it work most likely is.
;)
From what I know Sony's "PoPs" uses some sort of static recompilation or "static translation" aswell. They "translate" existing software once, then run that on the PSP in a new boot profile with a small "mini-PSX core" to run the translated code (and probably do the PSX to PSP hw device mapping).
As noted by razorrifh, you might just want to contribute to the existing PSX emulator rather then coding a new one (once it's GPLv2 licensed sources are finally released).
Otherwise I think your interest is driven by the pure fun of it, just implementing such a "translator" and see it work most likely is.
;)
well, are you speaking about this mysterious PS1P of which no one except for Wraggster can try ?razorrifh wrote:i dont want to stop you if you're doing this just to learn, but there already is a psx emulator out, and the official one is coming out also. just curious about why you'd wanna do it *shrug*
these should be all you need other than a bit of know-how (course, after you read them you'll have that too, right? :))
http://dev.paradogs.com/
Ok, let me tell more about. I'm coding a dynarec :PSP250 wrote:Your idea is indeed the most efficient way to emulate the PSX on the PSP and would offer at minimum equal framerates on the PSP.
From what I know Sony's "PoPs" uses some sort of static recompilation or "static translation" aswell. They "translate" existing software once, then run that on the PSP in a new boot profile with a small "mini-PSX core" to run the translated code (and probably do the PSX to PSP hw device mapping).
As noted by razorrifh, you might just want to contribute to the existing PSX emulator rather then coding a new one (once it's GPLv2 licensed sources are finally released).
Otherwise I think your interest is driven by the pure fun of it, just implementing such a "translator" and see it work most likely is.
;)
1) first, i was thinking about a static translator but i ran against some issues which are too complicated to be solved automaticaly : self-modified code, indirect jump or call by a register set during run-time and not compile-time, etc. The problem comes from the lack of meta-data (data which are provided in code-time but discarded in compile-time - size of an array of functions pointers for instance). My opinion is there is no real way to make a static translator which would translate all the stuff without any "exterior" (that is a human developper) help.
2) dynamic translator : that may be partly possible using a constant/copy propagation optimisation which could help you to determine what memory you are accessing and so translate this one in a direct access for once. PCSX x86 dynarec does it. Direct jump or call can be also translated once. However, dynamic translator doesn't work well with self-modified code. However, functions like memset or memcpy being used invariably in RAM or scratchpad are a pain in ass (translator should be able to provide a specific translation of those functions for each memory type).
Ok, I'm working on a dynamic recompiler.
1st stage : an interpreter-like dynarec. Each instruction are translated so long as you don't encounter an indirect jump or call. You can branch everywhere because each instruction has its mapping and has an independent code. Slowest process but you can handle self-modified code by invalidating a map entry at each memory writing on code address (should be optional). Execution is per instruction : this is why it is interpreter-like. Only to be considered as a fall-through or to step on each instruction.
2nd stage : still an interpreter-like dynarec but instructions are gathered in an execution block so far as you don't encounter a branch or jump or break point. Execution is per block but you can branch everywhere as in 1st stage.
3rd stage : use a constant/copy propagation optimisation (CCPO) for direct translation of address (memory access or branch or jump or exit point). Good way to make "PSX to PSP hw device mapping" once.
1st stage and 2nd stage are in good progress. I was able to translate successfully branching or jumping addresses (without CCPO) but decide to postpone it to 3rd stage.
If some people here is working on a PSX emulator on PSP and would like for me to test my dynarec work to his/her work, he/she can contact me.
Otherwise, I would probably need to make a PSP port of PCSX (the only one to be a true GPLed code with source released along) so any help would be welcome :-/.
hlide wrote:1) first, i was thinking about a static translator but i ran against some issues which are too complicated to be solved automaticaly : self-modified code, indirect jump or call by a register set during run-time and not compile-time, etc. ...
Self-modifing code is the biggest obstacle for any of the attempts. The question is how many apps/games on the PSX really make use of it and if there are ways to overcome this while still using the initial ideas. I remember there are next-gen emulators which successfully use this idea, have to look up on that in detail, thus it should be possible.hlide wrote:2) dynamic translator : that may be partly possible using a constant/copy propagation optimisation which could help you to determine what memory you are accessing and so translate this one in a direct access for once. PCSX x86 dynarec does it. Direct jump or call can be also translated once. However, dynamic translator doesn't work well with self-modified code. However, functions like memset or memcpy being used invariably in RAM or scratchpad are a pain in ass (translator should be able to provide a specific translation of those functions for each memory type).
My idea was that you constantly attempt to gather "blocks" of code which can be directly executed on the PSP and switch into interpreter mode for those you can't. A non-translated cache/accessability-API would help for self modifing code (Which would only run in interpreter mode). If that logic works in theory, you might be able to revert to the statc translation idea for those "blocks" and bundle the interpreter with the translation.
However you seem to be already very practical with the implementations so I can't say I am right on all this practically, at least it might help or provide ideas (before I checked on all PSX specs to take all options into account). :)
I assume your "stages" of the dynarec engine you are creating targets to switch from 3 down to 1 depending on the context code?
well, 2nd stage could handle self-modified code that way :
Consider there is map between a PSX address and a PSP call address containing an entry point in a dynarec block (not necessarly at the begining of the block !).
Everytime I write a word at PSX address A (sb/bu/w - yeah this is a slow process so it should only be an option), i check the mapping of this address to dynarec block entry point :
- zero, well this is a pure data memory, nothing special to do
- non zero, the previous word at address A is an instruction ! patch the instruction with a simple return like "jr $ra; add $v0, $a0, 0" and zero out the map entry.
Everytime I encounter a jump or call at address A, it would encounter the two instructions "jr $ra; addu $v0, $a0, 0" which return to the dispatcher (the function which decide to execute a dynarec bloc or to recompile a dynarec block). The dispatcher gets the next PC to execute (here unchanged) and would get a zero mapping so it would recompile starting from PC.
Just for your information.
in 1st stage, each instruction has an autonomous dynarec chunk per instruction terminating with "jr $ra; addu $v0, $a0, 0". So this way the dispatcher executes dynarec per instruction.
in 2nd stage, each instruction has still an autonomous dynarec chunk per instruction but terminating with "addu $a0, $a0, 4" so that the dispatcher executes dynarec per block.
NOTE : $a0 = PC during dynarec execution, $v0 = return PC to dispatcher
EDIT: well, if it works, I suppose 1st stage should be irrelevant
Consider there is map between a PSX address and a PSP call address containing an entry point in a dynarec block (not necessarly at the begining of the block !).
Everytime I write a word at PSX address A (sb/bu/w - yeah this is a slow process so it should only be an option), i check the mapping of this address to dynarec block entry point :
- zero, well this is a pure data memory, nothing special to do
- non zero, the previous word at address A is an instruction ! patch the instruction with a simple return like "jr $ra; add $v0, $a0, 0" and zero out the map entry.
Everytime I encounter a jump or call at address A, it would encounter the two instructions "jr $ra; addu $v0, $a0, 0" which return to the dispatcher (the function which decide to execute a dynarec bloc or to recompile a dynarec block). The dispatcher gets the next PC to execute (here unchanged) and would get a zero mapping so it would recompile starting from PC.
Just for your information.
in 1st stage, each instruction has an autonomous dynarec chunk per instruction terminating with "jr $ra; addu $v0, $a0, 0". So this way the dispatcher executes dynarec per instruction.
in 2nd stage, each instruction has still an autonomous dynarec chunk per instruction but terminating with "addu $a0, $a0, 4" so that the dispatcher executes dynarec per block.
NOTE : $a0 = PC during dynarec execution, $v0 = return PC to dispatcher
EDIT: well, if it works, I suppose 1st stage should be irrelevant