I've separately looked up and found that the R.O.B. hooks up the pins on the microcontroller as:
[R0]&8 - LED
[R0]&4 - arm limit switch
[R0]&2 - base limit switch
[R0]&1 - photosensor
[R1]&3 - H-bridge inputs to up/down motor
[R1]&C - H-bridge inputs to claw motor
[R2]&3 - H-bridge inputs to rotation motor
(edit: The SM590 here appears to be clocked by a 455kHz ceramic resonator, so theoretically it should be operating at 114kips)
Has anyone tried reverse-engineering the firmware? I wrote my own terrible disassembler, but I find this CPU to be sufficiently minimalist to be hard to understand what's going on.
So a custom Nintendo 8-bit microcontroller, and the 3 Sharp chips are driver chips for the 3 motors. Found pinout here.
I'm no good with figuring out the microcontroller, but I've actually been working on a write-up of ROB's behaviour in as much detail as possible, so it could be used when you need to look up such things on the wiki. In case you want to make ROB simulation to your emulator or if you want to make a repro ROB for example. I was gonna make some approximate timing measurements of each of ROB's actions, so that it can be faithfully simulated to the point that the ROB games can be played as they are designed to. But I ran into some inconsistencies that I don't think are intended behaviour. Specifically when I move a gyro above another gyro spinning on one of the trays, it sometimes touches the gyro on the tray which adds friction to the spinning gyro, decreasing its spin time, and sometimes it knocks the spinning gyro down. I don't know if it's due to my ROB's age (he appears to be in very good shape) or if it's a problem with the ROB design from the start. Robot Gyro uses the double up and down movements specifically to be able to move above gyroes I believe.
There is also a disassembler in no$nes (works when just loading rfccpu10.bin, then use utility/disassemble to file). Dunno which disassembler qualifies as more terrible.
Hmmm, there seem to be two unknown opcodes in the rob binary (45h and 53h).
PS. I think it does rather go as 4bit microcontroller, not an 8bit one.
(This is actually the reason I started trying to decipher the firmware, but...)
I was still using NO$NES 1.0 and wondering why it didn't work.
I mean, other than yours using Z80-like mnemonics, and my disassembler using their terrible ones, they're pretty comparable.
One of the bits I really don't understand is:
Code: Select all
a01F: LAX D ; A <- 0xD a04F: ADX 1 ; A += 0x1, skip if carry a067: TR a04F ; PL <- 0x4F
The SM590 datasheet says that 53h is the movsk A,[HL-] that you guessed it would be.Hmmm, there seem to be two unknown opcodes in the rob binary (45h and 53h).
I agree about the 45h instruction, however.
Yes, a short delay... but why do you say that nothing branches? I think "TR a04F" is short for "do TerRible branch to a04F".
So the delay loop increments A thrice... from Dh to Eh, Fh, 0h. Maybe colt can explain that branching stuff better than me : )
The whole function looks unused though... I can't see a call opcode going that... although it does end with a retsk opcode... btw. what is that? return and skip?? Or idea: Could it be an interrupt handler, then retsk might mean something like return from irq.
I am having the feeling that the 100h-byte banks (or 80h-byte banks) are swapped around. The entrypoint at address 000h should never reach a ret opcode (which it does currently do), instead it should probably contain call's to other functions. Also, the whole dump might contain corrupted bits - I guess that wasn't really verfied yet.
What is that SM590 datasheet? Is that better than Sharp SM5K1..SM5K7 datasheets?
As far as I remember SM5K1..SM5K7 were a bit newer than what was used in the CIC chips.
Because I misunderstood it. I have the worst time getting conditions of skip instructions backwards.
"transfer". There's a certain logic to their mnemonics, but they're still not good.I think "TR a04F" is short for "do TerRible branch to a04F".
Like TRansfer and TAX Test if A equals X where x=this immediate value but oh wait there's also an x register...
What? There's a bunch. (The addresses I'm using are the raw polynominal counter)The whole function looks unused though... I can't see a call opcode going that...
Code: Select all
a05F: LBLX 0 ; BL <- 0x0 a06F: RTA ; A <- sfr[BL] ; reg0 a077: TC ; skip if carry a07B: TR a061 ; PL <- 0x61 [...] a061: TBA 2 ; skip if A & (1<<2) (arm limit switch) a030: TR a01D ; PL <- 0x1D a058: TR a01F ; PL <- 0x1F
I agree it's awfully wacky.return and skip??
Not on the SM590. It does have an utterly weird behavior with two different entry points, although I believe it's unused here:Or idea: Could it be an interrupt handler, then retsk might mean something like return from irq.
On a rising edge of ACL (=reset), the polynomial counter starts at 000h. If the micro uses the CCTRL (4Bh) instruction, it'll resume execution at 080h once R22 is high (pin 15, tied high in the R.O.B.).
I have no idea. They're all documented in the same copy of the 1990 Sharp microcontroller databook I found on bitsavers:What is that SM590 datasheet? Is that better than Sharp SM5K1..SM5K7 datasheets?
Nothing other than the SM590 series has few enough pins, or comes in DIP.
Anyways, the page with the SM590/SM591/SM595 opcodes on pdf page 43 is the only one that does match up (there are several similar chips on the later pages, but they all have only 80h-BFh for short jumps, and use C0h-CFh for something else).
However, there are two different instruction sets (known from the CIC disassemblies).
Older CICs and ROB are apparently using SM590/SM591/SM595 instruction set.
Newer CIC's have "not A" opcode elsewhere, and "set/clr C" opcodes swapped, I haven't found a datasheet for that, maybe it was released after the "1990" book.
What I have implemented & documented is for the Newer CIC's, and based on segher's research. Comparing that with SM590/SM591/SM595, there are several differences:
Code: Select all
44 not A ;XXX unlike other that uses 54? 45 cmpsk A,[HL] ;skip if A=RAM[HL] 54 testsk C ;skip if C=1 ;XXX or NOT A on other version? 48/49 swapped set/clr C ;XXX depending on version 47 out [L],[HL] ;uh, weird, using L as src AND dst 4B standby ;uh, does what? standby vect at 080h? 30+0 mov A,n ;and skip any further mov A,N's !!! 56 mov A,L 71 addsk (as guessed) 50 inc H increment H=H+1 51 dec H decrement H=H-1 52 incsk L increment L=L+1, skip if result>0Fh ;\XXX without 53 decsk L decrement L=L-1, skip if result<00h ;/ A=[HL] !?
For example, opcode 52h/53h are probably never reading A=[HL] even on newer CICs (although, the CIC's are always using them after writing [HL]=A, so it wouldn't matter if they do readback A=[HL] or not).
Opcode 54h is "NOT A" in newer CICs and apparently "TESTSK C" in older CICs... knowing that... I was wrong about saying that the delay code isn't executed.
PS. return and skip is just doing what it should (return, and then skip one opcode at return address). That opcode is used that way in CIC code. It does allow to create functions that conditionally skip one opcode after executing the function.
All the 10 known commands always seems to work as they should (unlike in my earlier attempt to control ROB years ago), but none of the newly discovered command slots in the protocol appears to have any affect (I even tried them with the LED off to see if any of them would light the LED up but none of them did). When flashing the command 0000 multiple times I got ROB to perform the RESET command, this got my hopes up at first, but it seems it's just because my program allows sending commands with little delay between, so the wrong command was interpreted when mashing the button.
The test mode works by flashing the screen (or a small window like in the games) alternatively green and black every frame, like stated in Nocash' everynes document. This is done without the preceding 000101 sequence since it is used to adjust ROB's head to the TV screen, so it just blinks the LED whenever the eyes are directed at the flashing window, and stops blinking whenever they aren't. Previously we thought the LED command (1001) was the same as the test mode, but they are separate and the LED command turns on the LED permanently, and doesn't do any toggling of the LED (it's used when exiting the test mode by pressing SELECT in the games, but not in my program's version of the test mode).
Making this I discovered an error in the wiki though. "Up half step" and "Up full step" appears to have been mixed up. 0101 should be full step.
I'm attaching my program to this post in case anyone else want to test it, or to check if I made any mistakes.
Disassembling that code is really a bit difficult. It's less than 500 instructions, but even simple things like setting RAM[12h]=3 are spread across several instructions for loading 1,2,3 into 4bit registers (or re-using old register settings from previous instructions). And yeah, the opcode skip feature is also adding some extra difficulty/clumsiness, especially when "skipping a jump that skips another jump which would skip the following opcodes".
I've looked at the sm590dump.txt file:
Code: Select all
SM590 dumping 9/12/2019 Sean Riddle 1 R00 is bit 0 2 R01 is bit 1 3 R02 is bit 2 4 R03 is bit 3 5 R33/CL2 1K pull-up 6 CL1 200kHz 7 ACL 1K pull-up 8 GND gnd 9 R10 is bit 4 10 R11 is bit 5 11 R12 is bit 6 12 R13 is bit 7 13 R20 1K pull-up 14 R21 1K pull-up 15 R22 1K pull-up 16 VCC vcc Power up the chip, start the clock, lower ACL, then lower R21, then lower R20 and the ROM data should be output on R13:10 and R03:00. If not, tie ACL, R21 and R20 high and try again. The data will repeat in 508-byte groups, every 2032 CL1 clocks. SM591 and SM595 might require changing fields somehow to get all data. The dumped data starts at a random location. Long runs of 00s might indicate the end of the dump. The page and PC are zeroed during ACL, so counting CL1 clocks after ACL goes low will likely allow locating the start of the dump.
Now I am wondering if that is also working with normal CIC chips? Especially the 3195/3196/3197/3198 ones (the 6113 and later SNES chip might work a bit different).
As far as I know the decapped 3195/3196/3197/3198 chips did have 768 bytes of ROM (although using only 512 bytes of it, plus 256 bytes in an unused second "field"). That makes me wonder if the ROB chip does have that unused bytes, too.
The above txt says that it's still unknown how to get the test mode wiring to dump the extra ROM field.
I saw that the wiki says that it takes 13 to 14 vsyncs to send a command. I'm not sure what's meant by that, my program uses exactly 13 bits per command with 1 frame per bit sequentially. Command number 16 doesn't really flash the screen much since it stays on green for the last 8 frames, I guess this could be a reason it isn't used, but I don't know.
Also the wiki says that the test pattern is an endless stream of 25 or 30 Hz flashes. My program (and both games I believe) just changes the palette to black every even frame and green every odd frame. I think that would be a series of bits 010101010101... at 60 Hz. Unlike when flashing the commands, in test mode the whole palette isn't changed to green or the text message "PUSH SELECT KEY" wouldn't be readable at all, the text and window border gets color $26 (they do get black at even frames though). Since it's only used to adjust the head, I guess flashing a dialogue window smaller than the screen is a safe way to ensure ROB is looking somewhere in the middle of the screen. Then flashing the whole screen during the game to ensure he always receives the commands (although this can't be guaranteed, he may be knocked out of sight due to motor vibration as I've learned the hard way).
Your default background color is black. In a game that was bright by default, for the commands where the last bit was 1, reportedly an extra padding bit of dark must be added.
That's the same thing.Also the wiki says that the test pattern is an endless stream of 25 or 30 Hz flashes. My program (and both games I believe) just changes the palette to black every even frame and green every odd frame. I think that would be a series of bits 010101010101... at 60 Hz.
The guide on adafruit says that the receiver in the R.O.B. requires the flashes, instead of constant illumination (in other words, the firmware looks for light, then a lack of light, for each bit time that comes in, not just a 60bps 13-bit message)