Jump to content
Posted Thu Jun 8, 2017 3:18 PM
Posted Thu Jun 8, 2017 4:38 PM
I'm pretty sure that's the amount of money that Cmart has.
Posted Thu Jun 8, 2017 8:55 PM
Interesting that it's in hexadecimal. Code for a bitmap image?
Posted Thu Jun 8, 2017 9:31 PM
Posted Thu Jun 8, 2017 11:25 PM
Who put my password in WC Baseball.
Posted Fri Jun 9, 2017 3:07 AM
Posted Fri Jun 9, 2017 5:10 AM
Interesting. The first 32 characters look like they might be a CP1610 CPU register dump:
10a0 - R0 - ? 1217 - R1 - ? 5737 - R2 - address 0007 - R3 - ? 5c28 - R4 - index register address 5f5d - R5 - index register address 031d - R6 - stack pointer 5437 - R7 - PC address
From there things are less clear, it could be STIC or PSG register dumps, or perhaps more likely RAM. There is enough screen space to display a further 52 16-bit numbers, or 104 8-bit numbers.
A quick scout around the code at $5437 is not immediately enlightening, at least not to me.
Edit: It occurs to me that if this is the version of WC Baseball being used for the league, DZ-Jay's changes may mean that my looking at the disassembly of the standard version is probably not terribly helpful.
Edited by decle, Fri Jun 9, 2017 5:56 AM.
Posted Mon Jun 12, 2017 8:33 AM
I've always wondered what the WC Baseball crash screen looked like.
I didn't even know there was one!
Posted Wed Jul 12, 2017 4:07 PM
Haven't seen this one before...crash.gif
Not to toot our own horn, but we Intellivisionaries talked a bit about the crash screen in ep7 and posted a screenshot of the crash screen in the show notes for ep8: http://intellivision...e-8-sea-battle/
I was rather intrigued by the fact that the two crash screens submitted by Rick and tacrec are identical. So, with JoeZ's help I have been looking into the World Championship Baseball crashes a bit more. To do this we have focused on the computer vs computer games played at difficulty level 3, like those used in the Intellivision Baseball League.
It looks as though, providing the controller is not touched during play, there might "only" be 65,535 distinct computer vs computer games at a particular speed and difficulty setting. Furthermore, with a bit of jzIntv footling, it is possible to set things up to play any one of these games. It is also possible to work out at the end whether the game crashed, and what the final score was if it didn't. Finally, if jzIntv plays games at its fastest possible speed each lasts less than 5 seconds. Therefore, it is possible to play every single game at a given speed and difficultly level in less than 2 computer days. This compares to more than 2.5 years of continuous play at normal speed.
Well, we have played all 65,535 computer games at skill level 3 and the fastest speed
So, what did we discover?
Here are the numbers:
For those interested in the debug screen itself, it would seem that it is a dump of the System RAM content from address $2f0 upward. The reason that the first bit looks to be a register dump is that this region of memory starts with the program stack. So, we are probably seeing the register state that was pushed onto the stack at a previous VBLANK interrupt. The screen is drawn when the CPU stack grows too large. There are only 26 distinct patterns of data seen on the 1,638 debug screens. The most common screen is this one, which is seen at the end of 632 games.
If you want to see this behaviour for yourself you can use the following jzIntv script files with your vanilla copy of WCB. The script files are used as follows:
jzintv.exe -z1 -r2 -d –script=path\to\commandScript.txt path\to\yourWcBaseballRom.bin
I recommend replacing -r2 with -r0 when watching long games, to make things go as quickly as possible. These scripts have been tested against the new 20170708 stable version of jzIntv. Because of the sensitivity to timing, they almost certainly will not give the same results with other versions and obviously there is no way to use them on real hardware. Here are script files that show:
We can also get some “interesting” information about the games that finish without crashing. For example:
So, there is a small bias toward the Home team winning. Comparing these numbers with the current Intellivision Baseball League season of 52 games we see that the games lasted an average of 9.6 innings. The Home team have won 35 of the games with an average score of 1.69 runs with the Visitors winning the remaining 17 games scoring an average of 1.44 runs. Therefore, the Home teams have been doing rather better than expected this season. Again, it should be noted that two different versions of jzIntv will have been used by tacrec and myself, and this will have a potentially significant bearing on the results.
For the curious, here is a plot of the scores of all the games and their frequency:
And the full set of results:
results.txt 4.59MB 5 downloads
It is possible to play any of these games if you search for and replace the text GAME_NUMBER with the hex value of the game number you want in the following jzIntv script:
template.txt 8.47KB 2 downloads
If you play both of the 8-12 Visitor win games above you may notice they look to be the same. In fact, they are two different games (#0052 and #0104), so what is happening? It would seem that although some games might start with different random number seeds, the way in which the random numbers are generated and used leads to them merging. By the end of the game they have the same seed value, having played the same game. Remember, it is unlikely that WCB will ever need a random number across the full range of 1 to 65,535. Instead it might need a number from 1-10, for example. According to Joe, the way in which the EXEC works is that in this case it will choose a number from 1-16 (16 being the smallest power of 2 greater than 10). If the number selected is between 11 and 16 the EXEC just throws it away and tries again until one is generated in the required range. This approach of skipping over some numbers will make the seeds used tend to a subset of values and the games to merge. This leads to a couple of questions.
Firstly, how many really distinct games are there in the set of 65,535 looked at? Unfortunately, I don’t know, the number of games in each merged set varies and just defining what constitutes an equivalent game is potentially problematic. We can say that there are at least 210 unique games, based on the final scores and number of innings.
Secondly, by seeing the results of merged games are we “missing” other possible game outcomes? Again, I’m not sure. If you look at the way in which the game scripts work, they inject the state of the Intellivision that I captured during the initialisation of a single, real game. Variations in this state might open up other results, for example the 1-5 Mutants win over the Snakes after 11 innings in the Intellivision Baseball League on 04/17 is not found in this data set. If differences in this initial state are important, identifying which bits WCB is sensitive to, and all the valid combinations of the sensitive portion is probably an enormous task. That said, using a couple of different captured states does not appear to change the results, so the fact that this game is missing could also be down to the different version of jzIntv used.
Some of you may be wondering what happened to the 65,536th game. Well, game 0 is never selected or played by the EXEC. This is because, like all random number generators based on Linear Feedback Shift Registers (LFSR), the one in the Intellivision EXEC does not work with the seed value 0. If game 0 was selected, the random number generator would just churn out 0, and at level 3 this leads to a never-ending game:
level3Game0.txt 8.46KB 4 downloads
It is a good job this cannot happen without specifically setting it up. The same 0th game at difficulty level 4 is rather more interesting:
level4Game0.txt 8.46KB 4 downloads
It still results in a never-ending game, with neither side able to score. However, some progress is able to be made, and if you are patient enough you will see that the programmers never intended a game to have more than 99 innings (minimising the jzIntv window speeds things up). Above this value punctuation characters are used for the left inning digit. This punctuation continues through to inning 128, after which the inning value resets to 1.
I think at is about it for this post. Of course, having used our more advanced debugging and computing resources to make the WCB bugs reproducible, the real objective is to try to understand why the crashes occur, and potentially fix them. But, that is for another day.
My sincere thanks to Joe for his insights and jzIntv help, without which this analysis would not have been possible. As always, all feedback is most welcome (and yes Rick, I know this is not a game. By the way, how is the RCA Studio II podcast coming? )
Posted Wed Jul 12, 2017 8:17 PM
Posted Wed Jul 12, 2017 8:22 PM
Wow. Great and interesting breakdown. I didn't know a new version of jzintv existed, so I'll use that for the football league this fall.
The IBL has a real home field advantage! I never noticed that.
It only took 13 games to get 8 runs? It took me 3.5 years to get above 6!
Edited by tacrec, Wed Jul 12, 2017 9:09 PM.
Posted Wed Jul 12, 2017 9:30 PM
Posted Fri Jul 14, 2017 12:04 PM
So you can consistently reproduce the error; that's amazing. I'm not sure what's going on in the script; are you replacing random events with something specific? How does one number change generate an entire consistent game?
When pitting the computer against itself, the computer player's actions are driven entirely by the EXEC's random number generator. Also, I believe some aspects of the game itself are driven by the EXEC's random number generator, whether or not you have computer opponents.
"Random" is a misnomer. It's actually a pseudo-random number generator (PRNG), built from a linear feedback shift register (LFSR). LFSR based PRNGs always produce the same sequence of random bits. A 16-bit LFSR with a maximal period will go through 65,535 states before looping back to the beginning.
The current state of the LFSR is commonly referred to as the seed. You can get a different game by starting the seed at a different value. It will still go through the same overall sequence, but the sequence will start at a different point.
What decle's doing is pretty straightforward: He's setting the seed to a fixed value at the very start of the game. There are 65,535 unique starting values for the 16-bit seed that do anything useful, so that makes for 65,535 unique computer-v-computer games, assuming no other inputs to the process. (The all-0s value behaves very badly.) The "no other inputs" part is important, which is why he stresses not touching the controllers. A larger variety of games is possible if you consider every possible perturbation to the RNG sequence due to outside influences (e.g. us hairless apes banging on controllers).
Here is the exact code for the EXEC's LFSR PRNG. This could have been written much more efficiently, sadly. It's a Fibonacci realization of a 4-tap LFSR. A Galois realization (such as what RAND_FAST uses) would have been more efficient. This guy takes 97 cycles to compute one new random bit, while the RAND_FAST approach (which is just as strong mathematically) takes 12 to 19 cycles/bit.
X_RAND1: PSHR R5 ; 167D MOVR R0, R5 ; 167E BEQ L_17D4 ; 167F PSHR R1 ; 1681 PSHR R2 ; 1682 CLRR R2 ; 1683 MVI G_035E, R0 ; 1684 R0 = seed L_1686: SLL R0, 2 ; 1686 R0 = seed << 2 SLL R0, 2 ; 1687 R0 = seed << 4 MOVR R0, R1 ; 1688 R1 = seed << 4 XOR G_035E, R0 ; 1689 R0 = seed ^ (seed << 4) SWAP R1, 1 ; 168B R1 = (seed << 12) | (seed >> 4) SLL R1, 1 ; 168C R1 = (seed << 13) | ((seed >> 3) & ~1) XORR R1, R0 ; 168D R0 = seed ^ (seed << 4) ^ (seed << 13) ^ ((seed >> 3) & ~1) SLL R1, 2 ; 168E R1 = (seed << 15) | ((seed >> 1) & ~7) XORR R1, R0 ; 168F R0 = seed ^ (seed << 4) ^ (seed << 13) ^ (seed << 15) ^ ((seed >> 3) & ~1) ^ ((seed >> 1) & ~7) ;... so far pretty impressive, right? Now the really depressing part: RLC R0, 1 ; 1690 C = ((seed >> 15) ^ (seed >> 11) ^ (seed >> 2) ^ (seed >> 0)) & 1 MVI G_035E, R0 ; 1691 R0 = seed RLC R0, 1 ; 1693 R0 = (seed << 1) | (((seed >> 15) ^ (seed >> 11) ^ (seed >> 2) ^ (seed >> 0)) & 1) MVO R0, G_035E ; 1694 seed = (seed << 1) | (((seed >> 15) ^ (seed >> 11) ^ (seed >> 2) ^ (seed >> 0)) & 1) ;... yep, all that computation just to generate one stinking bit. SETC ; 1696 RLC R2, 1 ; 1697 DECR R5 ; 1698 BNEQ L_1686 ; 1699
I imagine part of the reason the process is so timing sensitive is that the EXEC pumps the random number generator in its idle loop. A slight change in the amount of idle time will change the exact sequence of random numbers, and thus the evolution of the game.
The recently released jzIntv fixes a long-standing issue where the CPU reacted slightly differently to BUSRQ and INTRQ depending on whether you were single-stepping or running flat out. Also, different audio rate settings could affect the CPU's behavior here. I rewrote a big chunk of jzIntv's CPU <=> STIC interaction to clean that up.
In the process, I also made a few minor optimizations, so that '-r0' mode runs significantly faster, especially when combined with -a0. I also added a jzintv_batch build that has zero connection to SDL and runs fully headless. It runs even faster still with -r0 -a0. Given the magnitude of the change, it's always possible something else ended up slightly off. If you notice anything, please let me know.
Edited by intvnut, Fri Jul 14, 2017 12:11 PM.
Posted Fri Jul 14, 2017 1:11 PM
The code is the answer, and the answer is the code.
0 members, 0 guests, 0 anonymous users