Robopanda Hacks and mods

281 posts / 0 new
Last post
Anonymous's picture
Robopanda Hacks and mods

Has any one found any robopanda hacks?

i've thought of changing the LEDs in its eyes.

How about installing an IR sensor in one of the eyes??

I've just thought about these, i'm too afraid of breaking my little panda.

Nocturnal's picture

There is already an IR sensor in the eye, if you look close at his... left (I think) eye when he is off, you should be able to see it.

Nocturnal's picture

Why would they?

Nocturnal's picture

I think they said IR Vision, which is different.

Rudolph's picture

An IR receiver isn't IR vision. Vision requires an emitter and a receiver (at least one of each) to "bounce" the signal off an object and get that signal back. The quicker the IR signal sent by the emitter is received back, the closer the object in question is in proximity. A little bit of math can tell the robot a semi accurate distance measurement, if the software has been set up to do that.

Perhaps Panda's receiver is in preperation for the impending programmable remote?

milw's picture

That's my guess too. has anyone tried shooting panda with any of the remotes?

Nocturnal's picture

Oh, it also has a IR emitter in the other eye.

Rudolph's picture

Perhaps they're in place for a future firmware upgrade to give your Panda the ability to Tivo Animal Planet.

I can't bring myself to spend the money on the Panda to find out the answers to these wonderments. Maybe if my kid showed any interest in it at all I would... 

sevik's picture

If someone interested in RoboPanda reverse engineering/hacking - check out

There is work in progress, but some results already achieved :))

milw's picture

Wow, that's very impressive Sevik! Do you have any videos of him saying something new? And would you consider posting a picture of your dev board and emulator cartridge in this thread? It will take a long time for me to read and truly understand all that you've figured out, but definitely a very nice job!

Nocturnal's picture

Sevik is not quite that far along yet. Exactly how the audio is formated is still in question.

sevik's picture

This is not such an easy task :)

But we are moving :)

Hope to get attention of some more than 3 capable persons to this task... :)

About audio - I hope that some of codecs (only 2 seen in stock cartridges ) can be uncompressed PCM :))

milw's picture

sevik said:
...Hope to get attention of some more than 3 capable persons to this task... :) ...

Are you working on this with other people, and are you asking for more people to help? It sounds like Nocturnal is already working with you perhaps?

sevik's picture

For now only me and Nocturnal really involved in this task.

And I'll be glad to see some more :))

More technical discussion takes place at Unofficial Robosapien Hacks and Mods Forum

Peter Redmer
Peter Redmer's picture

Thanks for sharing your project, Sevik. We'd love to hear more updates on how the project is going, and don't be afraid to discuss it here too :) There are lots of people here who would really enjoy seeing it.

Keep us posted and have fun. Pete

milw's picture

Are you looking for any skills in particular that you and Nocturnal don't already have covered? I have a Robopanda to hand, and would love to hear him sing Stairway to Heaven instead of 'lets have an adventure'!

sevik's picture

:)) You can try to guess audioencoding methods :))

For now we need to decode many bytecodes and guess and check effects of many 29XX commands.

For decoding bytecodes small tracer like first nocturnal's version is really enought (there are need to trace first 30-40 accesses) and small spi flash based cardemu needed (minimal valid cartridge image can be put in 100-200 bytes).

I have big tracer and cartridge emulator, so any tasks with big amount of needed tracing/large cartridge contents can be accomplished.

There are always need in better tools :)) I have decoder and emu, but no real assembler.

milw's picture

So from this bit of your web documentation:
Audio data chunk format:

* int32 - length
* int8 - codec (07 or 09)
* int8 - something (always 128)
* 32 or 48 byte chunks of data
* int16 - something (always FFFF)
* int16 - checksum?

Looking in Nocturnal's cartridge image for patterns of x07 0F nn(32 or 48x) FF FF,
should hit a whole series of audio chunks, correct?

Nocturnal's picture

Or you can go here and here, I wrote a program to dump the records out a while back.

Its been a while, but I'm pretty certain I dropped the record structure (except the details recorded in the name, which is probably recordnum-type-checksum), and just kept the data.

milw's picture

Ah, thanks Nocturnal. Do you know if those are the equivalent of the cartridge_dump *.aud files from Sevik's emu_log archive? Also I gather the data is little-endian, correct?

Nocturnal's picture

They are not quite the same, the *.aud files include the record structure as well as the data, mine are just the data. We also seem to be disagreeing on the total number of items.

sevik's picture

there are list of pointers to start of audio data chunks at start of cartridge (starting at 0005 offset, 3 byte for pointer up to @PEND string, So there are no need for guessing for number of items and its location. And yes, *.aud files - it's exactly this audio chunks.

play bytecode reads start of chunk from this table (see emu logs)

there are at least 2 codecs supported, and when by mistake I putted another value player worked too, but used yet another (not 32 or 48) frame size.

I plan to find all accepted codecs values but this task is lower in list - after decoding of most used bytecodes, assembler in cartridge builder and stack support in emu :))

sevik's picture

*.aud files has all record structure, except for 4 bytes with length.

at least codec value is integral part of data, and can't be dropped :))

Looking at traces I found that player always (for 7 codec at least, I have not waited to end of song) reads 356 bytes more than really present in audio data...

may be It's player fifo prefetch. It matches initial read size of 254+140 bytes - 32 byte frame - 6 bytes of header(length + codec + 0x128). I think tailer really not supposed to be read by player.

Need to check this values for 9 codec.

sevik's picture

about different number of chunks in our decompilations:

I dumped chunks based on index in begining of cartridge - and some chunks listed there more than 1 time (9 and 10 for example).

The same situation with mover scripts exists - there are many aliases for some scripts.

Nocturnal's picture

Codec value is meta data about the data, and it is preserved in my file naming scheme. So yes, it can be dropped from the data.

The way I read out the records was in sequence, using the record length to find the start of the next record, and continuing until I reached a record with a length of zero.

So assuming you dumped out the records using the index to find the start of a record, and then the record size for the amount of data, did you check for duplicate addresses?

Nocturnal's picture

Damn it! I hate it when someone replies while I am replying, but I guess its my fault for taking so damn long to write a reply.

sevik's picture


I dont like encoding metadata in filenames too :))


sevik's picture

Updated emulator with stack operations, first 139ms of training trace simulated successfully, including spi_reads with computed (not looked up in logs) addresses :))

Cycles with 0EXX commands successfully emulated too.

    7.359 00E8EC [SPI]   2: A1 01
    7.519 00E796 [CPU] 0063CB: call 00A1 // stack: [73CC]
    7.519 00E796 [SPI]   4: 95 C0 02 00
    7.903 002142 [CPU] 0000A1: extend // stack: [0000,73CC]
    7.903 002144 [CPU] 0000A2: pop @0A // @A = 0000, stack: [73CC]
    7.903 002146 [CPU] 0000A3: set $0, #00 // $0 = 00
    7.903 002148 [CPU] 0000A4: push $0 // stack: [0000,73CC]
    7.903 00214A [CPU] 0000A5: cmp #24 // 0000 == 24?, stack: [73CC]
    7.903 00214C [CPU] 0000A6: rjump_f0 0000B2
    7.903 00214E [CPU] 0000A7: rjump 0000AB
    7.903 002142 [SPI]  14: 02 29 0A 24 00 A8 00 2D 24 0E 0B F0 03 E0
    8.276 002156 [CPU] 0000AB: push @0A // stack: [0000,73CC]
    8.276 002158 [CPU] 0000AC: push $0 // stack: [0000,0000,73CC]
    8.276 00215A [CPU] 0000AD: pop2 @0A // @A,@B = 0000,0000, stack: [73CC]
    8.276 00215C [CPU] 0000AE: push #0000 // stack: [0000,73CC]
    8.276 00215E [CPU] 0000AF: push $0 // stack: [0000,0000,73CC]
    8.276 002160 [CPU] 0000B0: pop2 @2E // @2E,@2F = 0000,0000, stack: [73CC]
    8.276 002162 [CPU] 0000B1: rjump 0000A8
    8.276 002156 [SPI]  14: 0A 20 00 2D 0A 25 00 00 00 2D 2E 25 F7 E7
    8.484 002150 [CPU] 0000A8: inc $0 // $0 = 0001, stack: [0000,73CC]
    8.484 002152 [CPU] 0000A9: drop // stack: [73CC]
    8.484 002154 [CPU] 0000AA: rjump 0000A4
    8.484 002150 [SPI]   6: C0 2E 7E 29 FA E7
    8.752 002148 [CPU] 0000A4: push $0 // stack: [0001,73CC]
    8.752 00214A [CPU] 0000A5: cmp #24 // 0001 == 24?, stack: [73CC]
    8.752 00214C [CPU] 0000A6: rjump_f0 0000B2
    8.752 00214E [CPU] 0000A7: rjump 0000AB
    8.752 002148 [SPI]   8: 00 2D 24 0E 0B F0 03 E0
    9.133 002156 [CPU] 0000AB: push @0A // stack: [0000,73CC]
    9.133 002158 [CPU] 0000AC: push $0 // stack: [0001,0000,73CC]


   39.572 00215E [CPU] 0000AF: push $0 // stack: [0023,0000,73CC]
   39.572 002160 [CPU] 0000B0: pop2 @2E // @2E,@2F = 0023,0000, stack: [73CC]
   39.572 002162 [CPU] 0000B1: rjump 0000A8
   39.572 002156 [SPI]  14: 0A 20 00 2D 0A 25 00 00 00 2D 2E 25 F7 E7
   39.782 002150 [CPU] 0000A8: inc $0 // $0 = 0024, stack: [0023,73CC]
   39.782 002152 [CPU] 0000A9: drop // stack: [73CC]
   39.782 002154 [CPU] 0000AA: rjump 0000A4
   39.782 002150 [SPI]   6: C0 2E 7E 29 FA E7
   39.988 002148 [CPU] 0000A4: push $0 // stack: [0024,73CC]
   39.988 00214A [CPU] 0000A5: cmp #24 // 0024 == 24?, stack: [73CC]
   39.988 00214C [CPU] 0000A6: rjump_f0 0000B2
   39.988 002148 [SPI]   6: 00 2D 24 0E 0B F0
   40.110 002164 [SPI]   2: 78 29
   40.110 002164 [CPU] 0000B2: return // stack: []
   40.301 00E79A [CPU] 0063CD: call 05E7 // stack: [73CE]
   40.301 00E798 [SPI]   6: 02 00 DB C5 02 00
   40.481 002BCE [CPU] 0005E7: call 055E // stack: [15E8,73CE]
   40.481 002BCE [SPI]   4: 52 C5 02 00
   40.779 002ABC [CPU] 00055E: set $0, #00 // $0 = 00
   40.779 002ABE [CPU] 00055F: push $0 // stack: [0000,15E8,73CE]
   40.779 002AC0 [CPU] 000560: cmp #14 // 0000 == 14?, stack: [15E8,73CE]