Mass performance improvements through data profiling.

Found a bug? Please report it, but remember to follow the bug reporting guidelines.
Missing a sane feature? Let us know!
But please do NOT request ports to other systems.

Moderator: ZSNES Mods

Post Reply
tcaudilllg

Mass performance improvements through data profiling.

Post by tcaudilllg »

For several years I have sought to counter the claim SPC files must be recorded, not ripped, from SNES ROM files. Because the DSP can accept instruction from any point within ROM, the argument has been made that it is impossible to delineate sound data from other data. I no longer believe this to be true.

A code profiling routine could search an entire ROM for instructions that refer to specific hardware components, like the tile tables, the sound DSP, the SuperFX chip, the C4, etc. and with the understanding that those hardware components can only work with specific forms of data (e.g. sound, video), recognize all of the data that will be needed at any point in the game by any one hardware component. Searching the ROM instruction memory for DSP hardware references, a code profiler could index every bit of information on the ROM that will be used for sound into memory ahead of time, and, at the whim of the user, filter all of the sound memory when the ROM is loaded, precluding the need for the sound to be filtered at runtime by the CPU. Every time a filter is activated or deactivated by the user, whether it be a resampler, a Gaussian interpolation, or a HQ2x vectorizer, the profiler respective to the effected hardware could be run again, to update the hardware's data-in-wating as it lied in memory.

With data profiling precalculation, runtime CPU resources may be devoted anew to the act of emulation, as opposed to improving the apparent quality of the presentation. I understand that a code profiler would be a long, hard project to implement, but if it were done just once, I imagine that it could scale to the source of any emulated hardware and thereby increase indefinitely all emulation performance. I will work to design an algorithm for the profiler, if that will be helpful.
Joe Camacho
Devil's Advocate
Posts: 2293
Joined: Mon Aug 02, 2004 7:51 pm
Location: Hmo. Son.

Re: Mass performance improvements through data profiling.

Post by Joe Camacho »

lordgalbalan wrote:I will work to design an algorithm for the profiler, if that will be helpful.
Well, if you think that you can do it, start working on it, I think the developers will appreciate any help given. Thanks for the help. There are people here that can help you, sadly I know next to nothin about this stuff. :oops:
*Sometimes I edit my posts just to correct mistakes.
Nightcrawler
Romhacking God
Posts: 922
Joined: Wed Jul 28, 2004 11:27 pm
Contact:

Post by Nightcrawler »

I don't think that's going to work. Give me a specific example of how you would 'profile' code for the SPC or anything for that matter?

You'd have to look for opcodes that signify loading SPC data or something like that. What happens when say text or graphics data happens to have the same sequence of bytes? What then? There are many things in a ROM besides code and there is no way to seperate what is code and what is data.

I doubt you would ever be able to get it to accurrately detect ALL instances of SPC loading in a ROM correctly.
[url=http://transcorp.romhacking.net]TransCorp[/url] - Home of the Dual Orb 2, Cho Mahou Tairyku Wozz, and Emerald Dragon SFC/SNES translations.
[url=http://www.romhacking.net]ROMhacking.net[/url] - The central hub of the ROM hacking community.
tcaudilllg

Post by tcaudilllg »

You would have to start at the beginning of the code segment, and use a decision-free emulation algorithm to trace through every segment of the code, following all break instructions only once and without respect to the conditions of the break. In so doing, it would be possible to traverse every single line of executable code in ROM.

The sound DSP uses specific register numbers. At every offset whereat the registers numbers for the DSP were loaded in code, conditional breaks in the vicinity of the offset would be valid. Memory copy routines would function normally, and the sound data destined for the DSP could instead be redirected to RAM until it is called for by the full emulator.
Nightcrawler
Romhacking God
Posts: 922
Joined: Wed Jul 28, 2004 11:27 pm
Contact:

Post by Nightcrawler »

Ok.. so you're going through code and then when you hit a branch you execute all code on BOTH possible branch locations?

Assuming you now do go through every line of code, I still see a problem.
Take this scenario:

You have ONE sound routine for the entire game. You just feed it different offsets to where your SPU data is stored.

By your technique, you would hit this routine to load up the DSP registers for the first song and that's it.

In the real game, this routine is hit MANY times with different offsets each time new data is loaded. You will not be able to rip more than one song from the ROM.

I just can't see how this idea can ever work. Even if you now say you will emulate the game to hit the routine more than once, you have no way to simulate controller input etc.. to meet conditions necessary for the next song to be loaded.
[url=http://transcorp.romhacking.net]TransCorp[/url] - Home of the Dual Orb 2, Cho Mahou Tairyku Wozz, and Emerald Dragon SFC/SNES translations.
[url=http://www.romhacking.net]ROMhacking.net[/url] - The central hub of the ROM hacking community.
tcaudilllg

Post by tcaudilllg »

Nightcrawler wrote:In the real game, this routine is hit MANY times with different offsets each time new data is loaded. You will not be able to rip more than one song from the ROM.
The controller input is irrelevant. Controller input may only be analyzed by branching, you know this. ;) Even interrupt invocation involves momentary branching. If you examine the entire code tree, then you come across every used offset in the course thereof. It is impossible to use a value in code that has not been explicitly declared at some point therein, unless that value is received from an external source, like loading a register with either 1 or 2 depending on which button is pressed. Even then, its case must be dealt with in code. ...To reinforce my point, I will present a case study of this algorithm as it would function on the NES 6502 CPU/sound chip.

...By the way, I've been studying the Japanese alphabet a bit, and I think I've got a slight handle on Romanji/Katakana/Hirogana. If my fledgling experience with the Japanese language can be of help, then I gladly offer my services.
michael flatley
Rookie
Posts: 42
Joined: Wed Aug 18, 2004 10:15 pm

Post by michael flatley »

Wouldn't all possible code branches represent some huge tree with more nodes than there are atoms in the universe?
Nightcrawler
Romhacking God
Posts: 922
Joined: Wed Jul 28, 2004 11:27 pm
Contact:

Post by Nightcrawler »

lordgalbalan wrote:
Nightcrawler wrote:In the real game, this routine is hit MANY times with different offsets each time new data is loaded. You will not be able to rip more than one song from the ROM.
The controller input is irrelevant. Controller input may only be analyzed by branching, you know this. ;) Even interrupt invocation involves momentary branching. If you examine the entire code tree, then you come across every used offset in the course thereof. It is impossible to use a value in code that has not been explicitly declared at some point therein, unless that value is received from an external source, like loading a register with either 1 or 2 depending on which button is pressed. Even then, its case must be dealt with in code. ...To reinforce my point, I will present a case study of this algorithm as it would function on the NES 6502 CPU/sound chip.
Right.. controller input is analyzed by branching. I wasn't thinking along those lines. Controller input was not a good example. I was trying to think of a type of thing that would only happen by actually running the game that can't really be handled by just analyzing the code.

How about this scenario; Would you have a problem with loops?

You've got a loop, it's being executed say 100 times. The only branch instruction just checks to see if the loop has been executed 100 times. Now.. during each iteration of the loop, a running sum is generated in some way. After the loop is finished, that running sum becomes an offset for sound data.

There is no way you would arrive at this offset by simply analyzing all code and branches. Since there NO condition which checks this running sum, the ONLY way to arrive at the offset would be to run through the loop.

How would you handle something like that? That's the only specific case I can think of off the top of my head, but I think there would be other cases where an offset is generated and there is NO branch instruction or condition that checks it.
...By the way, I've been studying the Japanese alphabet a bit, and I think I've got a slight handle on Romanji/Katakana/Hirogana. If my fledgling experience with the Japanese language can be of help, then I gladly offer my services.
I appreciate the offer, but unfortunately to be useful on the translating side of things, you need to be quite fluent in Japanese. I actually also have a translator for most of my projects right now which is rare these days.

On the hacking side of things though, I could probably use extra help if your skills were decent in that area.
[url=http://transcorp.romhacking.net]TransCorp[/url] - Home of the Dual Orb 2, Cho Mahou Tairyku Wozz, and Emerald Dragon SFC/SNES translations.
[url=http://www.romhacking.net]ROMhacking.net[/url] - The central hub of the ROM hacking community.
tcaudilllg

Post by tcaudilllg »

You've got a loop, it's being executed say 100 times. The only branch instruction just checks to see if the loop has been executed 100 times. Now.. during each iteration of the loop, a running sum is generated in some way. After the loop is finished, that running sum becomes an offset for sound data.

There is no way you would arrive at this offset by simply analyzing all code and branches. Since there NO condition which checks this running sum, the ONLY way to arrive at the offset would be to run through the loop.

How would you handle something like that? That's the only specific case I can think of off the top of my head, but I think there would be other cases where an offset is generated and there is NO branch instruction or condition that checks it.
Hmm... I see the scenario, but is there even such a routine in existence? It seems kinda useless for something as straightforward as data storage. Anyway, let's consider this in 6502 native code, to get some insight.

Code: Select all

; Load 100 (64 hex) into the X index register.
; Clear the accumulator.

LDX #$64
LDA 0

Test:

; Decerement the X register

  DEX

; Increment the accumulator

  INA

; Is the X register at 0? If not, repeat the loop.

  BNE Test

; Load the byte at the address pointed to by the accumulator into Y

LDY [A]
I think that does the job. I see what you mean though. Definitely, the issue is far more complex than it at first appears. What if the accumulator is itself dependent on a previous loop? ...In any case, it is possible to determine that there is no escape from the loop in this instance except to pursue it in its entirety, so this loop could be determined as a necessity to execute. ...Isn't that a fully effective solution? I think so... not when you look at it just for quick critique, it doesn't seem like it is. But when you examine the limitations under which the possible critique could actually transpire, I think that this conclusion covers all of the bases.
On the hacking side of things though, I could probably use extra help if your skills were decent in that area.
Sure thing! :)
Nightcrawler
Romhacking God
Posts: 922
Joined: Wed Jul 28, 2004 11:27 pm
Contact:

Post by Nightcrawler »

lordgalbalan wrote:
You've got a loop, it's being executed say 100 times. The only branch instruction just checks to see if the loop has been executed 100 times. Now.. during each iteration of the loop, a running sum is generated in some way. After the loop is finished, that running sum becomes an offset for sound data.

There is no way you would arrive at this offset by simply analyzing all code and branches. Since there NO condition which checks this running sum, the ONLY way to arrive at the offset would be to run through the loop.

How would you handle something like that? That's the only specific case I can think of off the top of my head, but I think there would be other cases where an offset is generated and there is NO branch instruction or condition that checks it.
Hmm... I see the scenario, but is there even such a routine in existence? It seems kinda useless for something as straightforward as data storage.
Sure, there are plenty of routines that calculate offsets based on loops in simalar way. The most common reason for doing this is to find something in a lookup table. You can have a table of offsets to be loaded and in fact, most games do.
Anyway, let's consider this in 6502 native code, to get some insight.

Code: Select all

; Load 100 (64 hex) into the X index register.
; Clear the accumulator.

LDX #$64
LDA 0

Test:

; Decerement the X register

  DEX

; Increment the accumulator

  INA

; Is the X register at 0? If not, repeat the loop.

  BNE Test

; Load the byte at the address pointed to by the accumulator into Y

LDY [A]
I think that does the job. I see what you mean though. Definitely, the issue is far more complex than it at first appears. What if the accumulator is itself dependent on a previous loop? ...In any case, it is possible to determine that there is no escape from the loop in this instance except to pursue it in its entirety, so this loop could be determined as a necessity to execute. ...Isn't that a fully effective solution? I think so... not when you look at it just for quick critique, it doesn't seem like it is. But when you examine the limitations under which the possible critique could actually transpire, I think that this conclusion covers all of the bases.
Yeah, that routine is a basic example of what I was trying to say.
Yes, the accumlator entering a loop is often times already initialized by some other routine or loop. Ok, you say it's possible to determin e which loops are and are not necessary to execute? That's a pretty bold statement. What if the loop before this loop that generated the accumlator value was one of the loops that wasn't necessary to execute?

Take this case also.. the result of this loop points to an offset in a lookup table of offsets to the song data. What I mean by this is you have a table of 10 offsets for each of your 10 songs. Even if you do exectute, the loop, you won't get all 10 offsets. You'd have to know there was a table involved and read ALL offsets of the table.

I think you're opening up a huge can of worms that isn't going to a managable program.

Loop accumulator starting values can be based on the previous 3 loops or the past several routines that are not in any particular order.

You're going toh ave to keep track of mammoth amounts of information and branch points.

I'm surprised that absolutely no one else on this board has any input to this conversation. I'd like to hear some opinions of other knowledgable people on this topic.
On the hacking side of things though, I could probably use extra help if your skills were decent in that area.
Sure thing! :)[/quote]

Send me an e-mail with a summary of your skills. What you know, and what you have done in terms of romhacking. I need to assess your ability so I know what kind of tasks I could give you.
[url=http://transcorp.romhacking.net]TransCorp[/url] - Home of the Dual Orb 2, Cho Mahou Tairyku Wozz, and Emerald Dragon SFC/SNES translations.
[url=http://www.romhacking.net]ROMhacking.net[/url] - The central hub of the ROM hacking community.
illegal eagle
Savestate Pimp
Posts: 129
Joined: Thu Jul 29, 2004 2:15 pm
Contact:

Post by illegal eagle »

Nightcrawler wrote:I'm surprised that absolutely no one else on this board has any input to this conversation.
You already said it:
Nightcrawler wrote:I think you're opening up a huge can of worms that isn't going to be a managable program.

Edit: fixed.
Last edited by illegal eagle on Fri Sep 17, 2004 5:49 pm, edited 1 time in total.
"Other people can give you more suggestions as I just lost all my motivation to respond further to this post."
[i] - Nightcrawler[/i]

[url=http://www.geocities.com/illegal_eagle_2003/]vSNES v2.00[/url]: My SNES savestate viewer.
Nightcrawler
Romhacking God
Posts: 922
Joined: Wed Jul 28, 2004 11:27 pm
Contact:

Post by Nightcrawler »

You have an uncanny ability to quote me when I either misspell words, skip words, or made some other mistake!

How do you do it man? I don't make them that often, but you find them.
[url=http://transcorp.romhacking.net]TransCorp[/url] - Home of the Dual Orb 2, Cho Mahou Tairyku Wozz, and Emerald Dragon SFC/SNES translations.
[url=http://www.romhacking.net]ROMhacking.net[/url] - The central hub of the ROM hacking community.
illegal eagle
Savestate Pimp
Posts: 129
Joined: Thu Jul 29, 2004 2:15 pm
Contact:

Post by illegal eagle »

I didn't notice it, again. Happens when you're knowing what the writer's saying, and jump over sentence parts.
Maybe your spell checking is disabled when you post thoughtful stuff. :wink:
"Other people can give you more suggestions as I just lost all my motivation to respond further to this post."
[i] - Nightcrawler[/i]

[url=http://www.geocities.com/illegal_eagle_2003/]vSNES v2.00[/url]: My SNES savestate viewer.
Post Reply