So I knew nothing about how to look into a game's data to find specific things. I remember years ago wondering about how to find the information on players in the Genesis version of RBI 3 that I grew up with as a kid. Thankfully I was able to pick up and teach myself at least some basic things about digging into a hex editor, thanks to a variety of things. I'd like to share my story! It's taught me some basic ROM inspection and got me interested in data science.
The player attributes of the NES RBI games are pretty consistent for batters and hitters. The manuals provided with those games do also show the rosters of every team, but not any of the info as presented on Dee-Nee (Power, Contact, etc.) except for Speed and in a different measurement. I looked up ancient posts by Nightwulf, some of which are over 22 years old, and also got a .txt file of the NES RBI 3 player stats which I've reattached here (credit to him btw!).
But man, I never looked into hex editing/viewing before! I was kinda stumped and didn't know where to start. My initial impression is that RBI 3 Genesis has the same attributes as NES but I wanted some confirmation about this. But I had one lead: RBI 4, RBI '93, and RBI '94 have a 'View Teams' mode that lets you see rosters and their attributes...but not in the way Dee-Nee displays them. For example, Power is given a value from 10 to 94 and Contact is rated with a higher number for a better hitting ability as opposed to a lower number that Dee-Nee shows it.
And then I had a bigger lead: RBI 4 made a mistake with their View Teams page! If you check out the pitching speeds, the numbers are given hex values instead of decimal values. With this crucial bit in mind, I had a silly idea. I usually play ROMs on Bizhawk which happens to have a built in Hex Editor/Viewer. So I dumped the ROM hex and looked for a pattern, in the example of say Bob Milacki, looking for $9B $AB $BD next to each in the code using a Ctrl + F. Bingo! I found it, and Bizhawk has a handy feature as well to display ASCII text on the right. Bingo! I found Milacki in offsets $0FC0C0 and $0FC0D0. I had to still make sense of what each of these bytes do though! I brought up a hex-to-decimal convertor and found that the hex translates to:
SL $9B = 155
ME $AB = 171
FA $BD = 189
Hey, these look like pitching speeds! Everything started to make sense and I looked up a lot of Nightwulf's early posts on this forum to get an idea of how to read this data. Since I got this lead in RBI 4 and through pitcher data, I'll start by showing what I found.
Beginning with RBI 4:
Batter and pitcher data are stored separately. I found pitchers starting at offset $0FC0C0 with Bob Milacki. This makes sense as Baltimore is the first team in the data. Using Milacki as an example, I found all of the bytes related to him:
42 7E 4D 69 6C 61 63 6B 69 20 01 91 50 9B AB BD 84 30 00 00
RBI 4 gives room for 10 characters in a player name.
42 7E 4D 69 6C 61 63 6B 69 20 spell out B.Milacki as well as one blank space. That means after that, I have these bytes to concern myself with:
01 91 50 9B AB BD 84 30 00 00
Surprisingly, reading up on Nightwulf's old posts analyzing attributes of players on RBI 1 and 3 on the NES proved remarkably accurate for this Genesis game and shows me that Tengen iterated on their code over time. From this I was able to eventually deduce the following:
*The first two bytes are the pitcher's ERA. Combine them together to get the ERA. $0191 converts to 401 in decimal. Just stick a decimal point between 4 and 0 and you have Bob's ERA as shown on the stat screen: 4.01.
*The third byte is the pitcher's drop ability (D) and their pitching hand combined. Drop ability is accurate on the View Teams page and shows 5. The first bit, $5 is literally 5. The second bit is $0 which determines that he is right-handed.
*I already found out that $9B $AB $BD are the pitching speeds. They translate to 155 slow speed, 171 medium speed, and 189 fast speed.
*The seventh byte combines the pitcher's L/R curve ability. Bob has a 8 Right curve and a 4 Left curve as shown by the bits. The View Teams page shows this as strong side (S) and weak side (W) curve, so in Bob's case, strong is right curve, weak is left curve. The position of the two bits is relative to the pitching hand. Right-handers have the strong-hand curve on the first bit and weak-hand curve on the second. This is reversed for lefties.
*The eighth byte is the pitcher's stamina. $30 translates to 48, which is a typical starter's stamina in most RBI games. Stamina has always worked the same way in the entire classic series, including 4: one pitch deducts 1 stamina, a fastball or a changeup deducts 2.
*The ninth byte is the player's skin color. All Genesis RBI games display a batter/pitcher's skin color (except when fielding) unlike the NES games. If the player is white, this byte is $00, otherwise if the player is black it's $01.
*The tenth byte seems to be padding and is $00, I can't figure out if it does anything.
For batting, I had to largely rely on Nightwulf's analysis of how RBI stats were stored in the NES games and do a bit of deduction. The View Teams page does not display attributes in any way like Dee-Nee shows them. Fortunately the hex still lines up (for the most part) like the old games do. At this point I was getting the hang of using Bizhawk's Hex Editor to find things and fortunately, the batter data is right above the pitching data, starting at offset $0F7FD0 with Mike Devereaux of the Baltimore Orioles:
44 65 76 65 72 65 61 75 78 20 20 95 13 14 03 36 88 40
As before, 10 bytes are set aside for the player name:
44 65 76 65 72 65 61 75 78 20
Batters have eight bytes after that:
20 95 13 14 03 36 88 40
*The second byte is actually the batting average. Convert the hex to decimal and then ADD 111 and stick a decimal point at the start: $95 = 149. 149 + 111 = .260
*The third byte are the home runs the batter had. $13 = 19.
*The fourth byte is contact. $14 = 20. I made assumptions on this one. RBI 2-onward largely (but not always) assigned attributes relative to the player's stats. In RBI 3 NES, looking at the attributes .txt provided by Nightwulf, batters that hit .260 usually have a contact anywhere from 20-22 which lines up here. I have no idea how the game determines its CON rating of 70, only that HIGHER is better rather than lower.
*The fifth and sixth bytes combine to get the Power rating. $0336 = 822. I have no idea how this aligns with the View Teams PWR number of 49.
*The seventh byte is the batter's Speed. $88 = 136. View Teams gives a SPeed rating of 12. This lines up with how the RBI 2 and 3 manuals display speed. No batter in RBI 4 is slower than 122 (5 in View Teams) and no batter is faster than 152 (20 in View Teams)
That said, I have a few mysteries for batters in RBI 4: I don't know what the first and eighth bytes do, and I don't know what the 'C' attribute in View Teams is meant to be. It's either D or L.
S in View Teams is stance: RBI 4, '93, and '94 have different batting stances: F is 'Fast', which is what speedy players have, R is regular, and P is Power for strong hitters. I also am not completely sure what determines whether a batter is right/left/switch, and what determines a batter's position.
This was awesome, I mostly figured out RBI 4 stats! I also hate RBI 4. So I took this knowledge and worked backwards to RBI 3 on the Genesis. There is no View Teams in RBI 3, but the code is largely organized in a similar fashion.
So I went back to Genesis RBI 3 and started to look into confirming if the player data in that game matches up with the NES version. This time I had the luxury of Nightwulf's rbi3.txt to compare stats against. I started with pitching data for RBI 3. It seems to start at offset $052240. For this example, I'll actually use Rick Sutcliffe from the '84 Cubs. Note that Nightwulf grabbed data from a bad dump of NES RBI 3 that corrupted the '84 Cubs batters, but fortuantely not the pitchers.
At offsets $0548E0 and $548F0:
53 75 74 63 6C 69 66 66 80 24 AD B9 D4 95 30 00 72 8C
Player names have an 8 character limit in Genesis RBI 3, same as the NES:
53 75 74 63 6C 69 66 66
After that, you get ten bytes of data:
80 24 AD B9 D4 95 30 00 72 8C
*The first byte is the pitcher's drop ability and their pitching hand. Rick's Drop of 8 matches with the 8 Snk of the .txt. He's also right-handed.
*I don't know what the second byte does. While I might guess it's the ERA, $24 = 36 and I don't know how I can get to Rick's 2.69 ERA from there.
*The third, fourth, and fifth bytes are his slow, medium, and fast pitching speeds respectively. This gives a slow speed of 173, medium of 185, and fast of 212. All of these match with Nightwulf's text.
*The sixth byte combines his right/left curve ability. Right-handers have their dominant-side curve on the first bit and weak-side on the second, flipped for lefties. Rick has a 9 Right curve and a 5 Left curve, same as NES.
*The seventh byte is stamina. $30 = 48, same as NES and generally the same for most starters.
*The eighth byte is skin color. Rick is white, so this is $00. Black players are $01
*The ninth and tenth bytes line up with the Unknown values that Nightwulf found from NES. $72 is 114 and $8C is 140 which are the same as in the NES. Still don't know what they do.
Batters in RBI 3 are a little weirder to figure out. I took a lot of time and pattern-searching to fill in some missing blanks. I'll use Tony Gywnn from the 1984 Padres as an example:
At offsets $051A60 and $051A70
47 77 79 6E 6E 20 20 20 21 F0 05 02 02 FD 90 80 80
Eight characters for the name as usual:
47 77 79 6E 6E 20 20 20
Then you have eight bytes after that:
21 F0 05 02 02 FD 90 80
*The first byte combines the batter's skin color with what direction they bat. $2 is a black player, and $1 is a lefty. Interestingly, if you have a switch hitter, things are different. The first bit for a white switch hitter is $8, for a black switch hitter it's $A. All switch hitters have $0 afterward, same as right-handed hitters. This is consistent with the game as by default, switch hitters start right-handed unless you Time Out and switch their position.
*The second byte is the hitter's batting average. Convert the hex to decimal, ADD 111, and stick a decimal point at the start to get the number. $F0 = 240. 240 + 111 = .351, Tony's batting average.
*The third byte are the hitter's home run total. Simple hex to decimal here. $05 = 5.
*The fourth byte is the batter's contact rating. $02 = 2. This matches Tony's contact in NES RBI 3.
*Combine the fifth and sixth bytes to get the power rating. $02FD = 765 power, same as NES.
*Seventh byte is speed. $90 = 144 also the same as NES.
*The eighth byte seems to be the batter's fielding position. I can get some consistency on this, but I need to work it out a little. $80 is used for Right Fielders.
While I haven't started compiling stats, I feel like I don't need to do this since it appears to me that Genesis RBI 3 has the same player stats as NES RBI 3 (assuming a good dump of the NES ROM that doesn't have corrupted stats). Such as I suspect it's a copy-paste that it even carries the same errors such as '88 Red Sox Roger Clemens being misspelled as 'Clemmens'!
This is really cool! I'm glad I got myself into looking into ROMs for the first time. I have a few things I want to try to investigate somehow, but I'll need to learn much more:
*Does the pinch-hit Power boost still apply in Genesis 3 (does it in NES for that matter)? Does it in any other Genesis entry?
*I noticed in the RAM that the game keeps track of what a player's position is supposed to be and what position they CURRENTLY are in. The RBI 3 (and I think 2) manuals warn that if you put a player in a position they don't play in normally, they are more likely to have errors. I need to find out what determines this in Genesis 3 and if this actually works in NES 3. Teams are otherwise supposed to have a universal error rate - does mismatching a player's position affect the team's universal error rate?
This is super-cool stuff! I don't think anyone's tried mucking with the non-NES releases before, so you're in (mostly) uncharted territory here. I can shed a little light on a couple of things you found...
Quote from: chicobo329 on 09/01/25, 08:55:18 AMThe manuals provided with those games do also show the rosters of every team, but not any of the info as presented on Dee-Nee (Power, Contact, etc.) except for Speed and in a different measurement.
The speed in the manual actually DOES map to in-game speed ratings. The manual provides a number that's on roughly a 1-20 scale, and I figured out (because as a kid I'd memorized Sandberg's rating from the manual in both RBI 2 and RBI 3) that the mapping is 132 game speed = 10 manual speed, with each increment in the manual being worth 2 rating points. '90 Sandberg is 138 in the game, 13 in the book; '89 Sandberg is 132 in the game, 10 in the book. No one has an odd speed rating.
FWIW, while the manual didn't have contact and power ratings, the ratings were tied a lot more tightly to the players' stats, so the correlation is a lot stronger than it was in the original.
Quote from: chicobo329 on 09/01/25, 08:56:31 AM*I don't know what the second byte does. While I might guess it's the ERA, $24 = 36 and I don't know how I can get to Rick's 2.69 ERA from there.
This also probably lines up with the NES version, because its handling of ERA was really weird:
Quote from: nightwulf on 07/01/04, 11:13:41 AMOk, it took a while, but I finally came to a conclusion. The pitcher ERAs in RBI 3 make NO FUCKING SENSE AT ALL. I had to load the game in the debugger and trace ERA "conversion" step-by-step. Eventually two different lookup tables are used, and I can't find any mathematical reasoning behind either one. That'll make an interesting stumbling block if anyone decides to write an editor for the game. Converting from the value stored in the ROM to the displayed ERA is simple enough once you see how it's done; going back from an arbitrary ERA value will be ... interesting at best.
My guess is that this was done as a space-saving measure - they likely didn't want to use more than a single byte for each player but didn't want to limit the ratings to a 2.56 span (in the original, they just let the integer overflow so guys with ERAs over 3.56 ended up looking better). The lookup table takes up the extra space for the table itself but then you can have a wider range and still only a byte per pitcher.
Quote from: chicobo329 on 09/01/25, 09:03:26 AMThis is really cool! I'm glad I got myself into looking into ROMs for the first time. I have a few things I want to try to investigate somehow, but I'll need to learn much more:
*Does the pinch-hit Power boost still apply in Genesis 3 (does it in NES for that matter)? Does it in any other Genesis entry?
*I noticed in the RAM that the game keeps track of what a player's position is supposed to be and what position they CURRENTLY are in. The RBI 3 (and I think 2) manuals warn that if you put a player in a position they don't play in normally, they are more likely to have errors. I need to find out what determines this in Genesis 3 and if this actually works in NES 3. Teams are otherwise supposed to have a universal error rate - does mismatching a player's position affect the team's universal error rate?
I am also really curious what you come up with here. I don't know whether we ever actually determined whether RBI 2/3 have the PH bonus. With the ability to edit lineups, that'd be a really big deal strategically, particularly in an AL game - start your five worst hitters and replace them the first time through the lineup with guys who you want to get the PH boost.
I've also always wondered about the error thing. I use to love playing with the NL All-Stars, but they had bad offensive catchers, so I'd just decide that Andre Dawson was playing catcher and have no one in the lineup with a C position. I never noticed an effect but also catchers barely ever field batted balls, so if it was position-specific the catcher would be the easiest place to get away with it.
Quote from: BeefMaster on 09/02/25, 09:46:09 AMI am also really curious what you come up with here. I don't know whether we ever actually determined whether RBI 2/3 have the PH bonus. With the ability to edit lineups, that'd be a really big deal strategically, particularly in an AL game - start your five worst hitters and replace them the first time through the lineup with guys who you want to get the PH boost.
I can confirm this for the NES games at least. The pinch hit bonus of 64 power still applies in RBI 2 and RBI 3 on the first at-bat.
I didn't know where to look for this but searching through the forums, I found a 23-year old post by Gantry about RBI 1 pinch hitting:
Quote from: Gantry on 12/19/02, 10:23:48 AMA lot of screwing around in nesticle/Ultraedit (windows) and FCE/ghex (linux). For this one, it was all about Nesticle's dump-RAM feature. A batter gets up, pause the game, and dump the ram. Open up ultraedit and check 0x600h - 0x630h. I completly discovered this one by accident, noticed Hendrick's hitting stats weren't matching up...
Surprisingly (or perhaps not that much) the same RAM offsets on the NES apply to RBI 2 and 3. In this example, I have Ron Kittle starting the game for the 1990 Orioles and immediately paused. He has 813 power normally ($032D). If I peek specifically into RAM offsets $0620 and $0630, I get Kittle's power rating, but in reverse ($2D03). I then reset the game so that Steve Finley starts as usual and sub in Ron Kittle and look at the same offsets to get $6D03. Flipped and converted, this is 877 power which is consistent with the 64 power pinch hit bonus. When he went back to bat, the same offsets showed $2D03, reverting back to his 813 power.
Quote from: BeefMaster on 09/02/25, 09:46:09 AMI am also really curious what you come up with here. I don't know whether we ever actually determined whether RBI 2/3 have the PH bonus. With the ability to edit lineups, that'd be a really big deal strategically, particularly in an AL game - start your five worst hitters and replace them the first time through the lineup with guys who you want to get the PH boost.
As for Genesis RBI 3, the RAM is much larger on the Genesis of course. It looks like Tengen used that to just copy the entire roster data for both teams. For pitchers at least, these update in the RAM as needed. For instance, a pitcher's stamina will start to actually decrease live in the RAM after every pitch. But then, if I pinch-hit Ron Kittle in place of Steven Finley, his $032D power does NOT update. So at least on the surface, Genesis RBI 3 doesn't have the pinch-hit bonus. But I also don't really know what to make sense of elsewhere in the RAM anyway. I cannot find Ron Kittle's power rating of $032D anywhere other than the roster data in the RAM.
I see some suspicious stuff around offsets $0600-$0660 (the sixth byte at $0620 constantly cycles from $9A-$9D even when the game is paused. These bytes constantly fluctuate whenever I swing the bat or move the batter, but I think these are just for graphical animations. There's a couple other places in RAM that have constantly moving bytes, but none of them really have anything resembling the current batter's power rating.
Incidentally, Genesis RBI 3 is a lot more specific about bench player positions than it displays and depending on if the error rate changes (which I still need to figure out), it could mean you'd end up mismatching player positions unintentionally. Looking back at the '90 Orioles again, I highlighted the last byte of every player which determines player position (ignore the $FF at the top). I was able to deduce the following values for each position:
Catcher = $01
First Base = $02
Second Base = $04
Third Base = $08
Shortstop = $10
Left Field = $20
Center Field = $40
Right Field = $80
Designated Hitter = $FE (this is only shown in the RAM as a current position and is never a player's default position. In theory you can safely make any batter a Designated Hitter.)
That's great, but the bench players don't specify their exact positions! The data definitely does, but visually to the player it's either OF or IF. Catchers are an exception of course, since it's obvious:
Tim Hulett - IF ($08 Third Base)
David Segui - IF ($02 First Base)
Bob Melvin - C ($01 Catcher)
Brady Anderson - OF ($20 Left Field)
Ron Kittle - OF ($20 Left Field)
A quick skim of the other bench players shows that IF bench players are more specific and generally seems to match up with what they actually played as. For example, Mark Lemke is listed as IF on the '90 Braves bench, but internally, his position is $04 which is Second Base (the position he played). Andres Thomas, also IF on the Braves' bench, is $10 which is Shortstop - the position he actually played on.
But every benched outfielder on every team is $20, Left Field and it's contrary to several of these players' actual positions. For example, Dwight Evans on the 1990 Red Sox is OF on the bench and thus $20/Left Field, but he was a Right Fielder. It's possible the game doesn't seem to care about outfielder accuracy so much? I suppose not every outfielder ever stood in just one part of the outfield their whole careers. But this might have ramifications with how Genesis RBI 3 checks for error rates, if I can ever figure that out.
This is incredible stuff! I make a new entry to the FAQ after a decade plus and link here
I'm not 100% confident that the pinch-hit bonus doesn't apply to Genesis RBI 3, even though the player stats in the RAM aren't updating. But in order to fully understand everything, I need to figure out how Genesis RBI 3 calculates hits in the first place. Based on my suspicions earlier and fiddling with frame advance/rewind/save states, I found the offsets that seem to at least handle the ball positions. The screenshot below is the moment Steve Finley registers a hit against a pitch from Chuck Finley (no relation).
The primary offsets I found are $05F0-0670, note that this is all in the 68K Genesis RAM. So far I've at least deduced a few things about stuff in the middle...
*At offset $0620 - 7th and 8th bytes are the ball position. It ranges from $009x-$01Ax. A pitch down the middle seems to be $0111. A strike is called if the ball is anywhere between $010A-$012A by the time the ball is caught.
*At offset $0630 - 8th and 16th bytes seem to be pitcher position. Leftmost is $0C, rightmost is $25 (this shifts slightly when the pitcher is spitting chewing tobacco/throwing pitches)
*At offset $0640 - This seems to be the batter position. The 10th byte is the vertical position of the batter and the 16th byte is the horizontal position. There are other bytes around these offsets that are slightly before and after the horizontal position of the batter but they just seem to be for animations (the batters will adjust their feet/hands/bat)
Vertical position ranges from $F0 (up)-$10 (down) and horizontal position ranges from $2A (left)-$3D (right) for a lefty. For right-handed hitters, horizontal ranges from $E3 (left)-$F6 (right).
Genesis RBI 3 allows you to properly bunt unlike NES by pressing C which will keep you in that position until you press C again. When you lay down a bunt, your horizontal position is pushed forward by 7. For example a right-handed batter laying down a bunt as close to the plate as possible is at $FD instead of $F6. But also, the hitbox for bunting is shorter than a regular swing.
As an example, I started with these same Finleys and tried to see what ball positions will register the bunt. I moved Steve all the way up ($F0). The ball position needs to be between $0112-$0124 to register the bunt. Meanwhile, I was able to get a foul tip by making contact with a regular swing with the ball at $010E, which a bunt wouldn't reach.
I should note that exactly one frame before the screen transitions to the field (which is when I took this screenshot), the first seven bytes of offset $0600 will clear and the first four bytes of offset $05F0 will change a bit. The second attachment (just the RAM contents alone with highlighted bytes) show what was there before they were cleared. I still really don't have much clue over how to figure out where power and hit index are calculated, but figuring out the positions of things is at least a good step towards this.
I should also note, Steve Finley's Power is 750 ($02EE) but I don't see this anywhere else in the RAM other than where the team rosters are copied (in Steve's case, offset $0240).
Quote from: chicobo329 on 09/05/25, 12:38:25 PM*At offset $0620 - 7th and 8th bytes are the ball position. It ranges from $009x-$01Ax. A pitch down the middle seems to be $0111. A strike is called if the ball is anywhere between $010A-$012A by the time the ball is caught.
Interesting that it appears that the ball/strike call is based on where the ball is caught, regardless of the trajectory it came in on (I also don't know how it'd track that, since a pitch can curve in flight). I guess I KIND OF assumed that but was not really sure - pitches that barely catch the corner I usually think of as strikes.
Nightwulf had figured out the points on the bat at which the contact penalty was applied, but I don't know if he ever figured out trajectory, if that's something you're also looking into.
Quote from: BeefMaster on 09/05/25, 01:56:06 PMInteresting that it appears that the ball/strike call is based on where the ball is caught, regardless of the trajectory it came in on (I also don't know how it'd track that, since a pitch can curve in flight). I guess I KIND OF assumed that but was not really sure - pitches that barely catch the corner I usually think of as strikes.
Nightwulf had figured out the points on the bat at which the contact penalty was applied, but I don't know if he ever figured out trajectory, if that's something you're also looking into.
https://www.youtube.com/watch?v=8hE-U9KcRnk
I put up a quick video showing through frame advance that at least on the surface, it's tracking the position of the ball the entire time of the pitch and as soon as the ball is caught by the catcher, the determination is made. The first pitch was at $0109, a ball. When I rewound a bit and altered the trajectory, I got it caught at $010C, a strike. I guess you can see as I'm advancing frames how the ball position is changing as I muck with its direction. The two bytes next to those interest me and I wonder if it's the vertical ball position as these numbers consistently tick down until they reach the catcher and tick back up and stop at once the ball is thrown back to the pitcher.
As far as ball trajectory, that's not my primary objective although I'm sure I can eventually go down that direction. For now, I'm trying to see where in all these highlighted offsets is the batter's power and how else a pinch-hit bonus could be determined since it's clearly not reading the player stats the same way as the NES.
Quote from: Gantry on 09/02/25, 04:09:46 PMThis is incredible stuff! I make a new entry to the FAQ after a decade plus and link here
https://dee-nee.com/rbi/faq.shtml#RBI3
FAQ has been updated