The porting of the NESBot Play the 'Tool Assisted Speedrun' videos on the real machine(NES). original (with Arduino): http://www.instructables.com/id/NESBot-Arduino-Powered-Robot-beating-Super-Mario-/ Almost same as the original, it need generated Key-input data by emulator with Lua script. See the original instructables' documents to know how to generate data file. BOM: mbed x1 NES x1 NES controller x1 4021(shift registor) x1
main.cpp@0:19e971e75a74, 2012-01-07 (annotated)
- Committer:
- kshoji
- Date:
- Sat Jan 07 06:23:54 2012 +0000
- Revision:
- 0:19e971e75a74
The porting of the NESBot
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
kshoji | 0:19e971e75a74 | 1 | #include "mbed.h" |
kshoji | 0:19e971e75a74 | 2 | |
kshoji | 0:19e971e75a74 | 3 | // - The porting of the NESBot |
kshoji | 0:19e971e75a74 | 4 | // original : http://www.instructables.com/id/NESBot-Arduino-Powered-Robot-beating-Super-Mario-/ |
kshoji | 0:19e971e75a74 | 5 | // |
kshoji | 0:19e971e75a74 | 6 | // ported by Kaoru Shoji : http://mbed.org/users/kshoji |
kshoji | 0:19e971e75a74 | 7 | // |
kshoji | 0:19e971e75a74 | 8 | // - Connections: |
kshoji | 0:19e971e75a74 | 9 | // a NES, a mbed and a 4021 (shift register) needed. |
kshoji | 0:19e971e75a74 | 10 | // |
kshoji | 0:19e971e75a74 | 11 | // for example) AV-FAMICOM(JPY) connector pinout |
kshoji | 0:19e971e75a74 | 12 | // 1 LATCH (PL, P/S) -> mbed's 9 pin |
kshoji | 0:19e971e75a74 | 13 | // 2 CLOCK -> 4021's 10 pin |
kshoji | 0:19e971e75a74 | 14 | // 3 VCC -> 4021's 16 pin |
kshoji | 0:19e971e75a74 | 15 | // 4 GND -> mbed's GND & 4021's 8 pin |
kshoji | 0:19e971e75a74 | 16 | // 5 DATA -> 4021's 3 pin |
kshoji | 0:19e971e75a74 | 17 | // |
kshoji | 0:19e971e75a74 | 18 | // - Note: |
kshoji | 0:19e971e75a74 | 19 | // The mbed's VCC must be supplied from USB cable. |
kshoji | 0:19e971e75a74 | 20 | // If mbed's VCC is supplied from NES VCC, the LATCH signal detection may be failed. |
kshoji | 0:19e971e75a74 | 21 | // |
kshoji | 0:19e971e75a74 | 22 | // - How to use: |
kshoji | 0:19e971e75a74 | 23 | // 0. Prepare the replay data with FCEUX and Lua script. (Lua script can be downloaded from instructables). |
kshoji | 0:19e971e75a74 | 24 | // The data file needs to be placed into mbed's LocalFileSystem(on the root directory). |
kshoji | 0:19e971e75a74 | 25 | // 1. NES power turn off. |
kshoji | 0:19e971e75a74 | 26 | // 2. connect mbed to NES, and USB power. |
kshoji | 0:19e971e75a74 | 27 | // 3. NES power turn on. |
kshoji | 0:19e971e75a74 | 28 | |
kshoji | 0:19e971e75a74 | 29 | InterruptIn latchInterrupt(p9); // LATCH signal in |
kshoji | 0:19e971e75a74 | 30 | |
kshoji | 0:19e971e75a74 | 31 | DigitalOut R(p10); // -> 4021's p1(7) |
kshoji | 0:19e971e75a74 | 32 | DigitalOut L(p11); // -> 4021's p2(6) |
kshoji | 0:19e971e75a74 | 33 | DigitalOut D(p12); // -> 4021's p3(5) |
kshoji | 0:19e971e75a74 | 34 | DigitalOut U(p13); // -> 4021's p4(4) |
kshoji | 0:19e971e75a74 | 35 | DigitalOut T(p14); // -> 4021's p5(13) |
kshoji | 0:19e971e75a74 | 36 | DigitalOut S(p15); // -> 4021's p6(14) |
kshoji | 0:19e971e75a74 | 37 | DigitalOut B(p16); // -> 4021's p7(15) |
kshoji | 0:19e971e75a74 | 38 | DigitalOut A(p17); // -> 4021's p8(1) |
kshoji | 0:19e971e75a74 | 39 | |
kshoji | 0:19e971e75a74 | 40 | // status LEDs |
kshoji | 0:19e971e75a74 | 41 | DigitalOut led1(LED1); |
kshoji | 0:19e971e75a74 | 42 | DigitalOut led2(LED2); |
kshoji | 0:19e971e75a74 | 43 | DigitalOut led3(LED3); |
kshoji | 0:19e971e75a74 | 44 | DigitalOut led4(LED4); |
kshoji | 0:19e971e75a74 | 45 | |
kshoji | 0:19e971e75a74 | 46 | LocalFileSystem local("mbed"); |
kshoji | 0:19e971e75a74 | 47 | |
kshoji | 0:19e971e75a74 | 48 | // Large buffer may cause time rag when file loading. |
kshoji | 0:19e971e75a74 | 49 | #define BUFFER_LENGTH (128) |
kshoji | 0:19e971e75a74 | 50 | |
kshoji | 0:19e971e75a74 | 51 | unsigned char controllerData[BUFFER_LENGTH]; |
kshoji | 0:19e971e75a74 | 52 | int controllerDataPosition = 0; |
kshoji | 0:19e971e75a74 | 53 | |
kshoji | 0:19e971e75a74 | 54 | FILE *fp; |
kshoji | 0:19e971e75a74 | 55 | long fileLength = 0; |
kshoji | 0:19e971e75a74 | 56 | long filePosition = 0; |
kshoji | 0:19e971e75a74 | 57 | |
kshoji | 0:19e971e75a74 | 58 | volatile bool finished = false; |
kshoji | 0:19e971e75a74 | 59 | |
kshoji | 0:19e971e75a74 | 60 | void writeButtons() { |
kshoji | 0:19e971e75a74 | 61 | unsigned char state = ~controllerData[controllerDataPosition]; |
kshoji | 0:19e971e75a74 | 62 | |
kshoji | 0:19e971e75a74 | 63 | // output to shift register |
kshoji | 0:19e971e75a74 | 64 | R = state & 0x80; |
kshoji | 0:19e971e75a74 | 65 | L = state & 0x40; |
kshoji | 0:19e971e75a74 | 66 | D = state & 0x20; |
kshoji | 0:19e971e75a74 | 67 | U = state & 0x10; |
kshoji | 0:19e971e75a74 | 68 | T = state & 0x08; |
kshoji | 0:19e971e75a74 | 69 | S = state & 0x04; |
kshoji | 0:19e971e75a74 | 70 | B = state & 0x02; |
kshoji | 0:19e971e75a74 | 71 | A = state & 0x01; |
kshoji | 0:19e971e75a74 | 72 | } |
kshoji | 0:19e971e75a74 | 73 | |
kshoji | 0:19e971e75a74 | 74 | void showLEDs() { |
kshoji | 0:19e971e75a74 | 75 | led1 = !U | !D; |
kshoji | 0:19e971e75a74 | 76 | led2 = !L | !R; |
kshoji | 0:19e971e75a74 | 77 | led3 = !A; |
kshoji | 0:19e971e75a74 | 78 | led4 = !B; |
kshoji | 0:19e971e75a74 | 79 | } |
kshoji | 0:19e971e75a74 | 80 | |
kshoji | 0:19e971e75a74 | 81 | void trigger() { |
kshoji | 0:19e971e75a74 | 82 | // when P/S Control signal falled(Serial mode) |
kshoji | 0:19e971e75a74 | 83 | // read the controller state |
kshoji | 0:19e971e75a74 | 84 | writeButtons(); |
kshoji | 0:19e971e75a74 | 85 | showLEDs(); |
kshoji | 0:19e971e75a74 | 86 | |
kshoji | 0:19e971e75a74 | 87 | filePosition++; |
kshoji | 0:19e971e75a74 | 88 | if (filePosition >= fileLength) { |
kshoji | 0:19e971e75a74 | 89 | latchInterrupt.fall(0); |
kshoji | 0:19e971e75a74 | 90 | finished = true; |
kshoji | 0:19e971e75a74 | 91 | return; |
kshoji | 0:19e971e75a74 | 92 | } |
kshoji | 0:19e971e75a74 | 93 | |
kshoji | 0:19e971e75a74 | 94 | controllerDataPosition++; |
kshoji | 0:19e971e75a74 | 95 | if (controllerDataPosition >= BUFFER_LENGTH) { |
kshoji | 0:19e971e75a74 | 96 | fread(controllerData, 1, BUFFER_LENGTH, fp); |
kshoji | 0:19e971e75a74 | 97 | controllerDataPosition = 0; |
kshoji | 0:19e971e75a74 | 98 | } |
kshoji | 0:19e971e75a74 | 99 | } |
kshoji | 0:19e971e75a74 | 100 | |
kshoji | 0:19e971e75a74 | 101 | int main() { |
kshoji | 0:19e971e75a74 | 102 | // TODO replace your filename |
kshoji | 0:19e971e75a74 | 103 | fp = fopen("/mbed/tas.txt", "rb"); |
kshoji | 0:19e971e75a74 | 104 | controllerDataPosition = 0; |
kshoji | 0:19e971e75a74 | 105 | |
kshoji | 0:19e971e75a74 | 106 | fseek(fp, 0L, SEEK_END); |
kshoji | 0:19e971e75a74 | 107 | fileLength = ftell(fp); |
kshoji | 0:19e971e75a74 | 108 | fseek(fp, 0L, SEEK_SET); |
kshoji | 0:19e971e75a74 | 109 | |
kshoji | 0:19e971e75a74 | 110 | fread(controllerData, 1, BUFFER_LENGTH, fp); |
kshoji | 0:19e971e75a74 | 111 | writeButtons(); |
kshoji | 0:19e971e75a74 | 112 | |
kshoji | 0:19e971e75a74 | 113 | latchInterrupt.mode(PullNone); |
kshoji | 0:19e971e75a74 | 114 | latchInterrupt.fall(&trigger); |
kshoji | 0:19e971e75a74 | 115 | |
kshoji | 0:19e971e75a74 | 116 | while(!finished); |
kshoji | 0:19e971e75a74 | 117 | fclose(fp); |
kshoji | 0:19e971e75a74 | 118 | } |