aboutsummaryrefslogtreecommitdiffhomepage
path: root/Cart_Reader/POKEMINI.ino
blob: d004cb0e8562b9c338ffdb764fb809af308f0902 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
//******************************************
// POKEMON MINI MODULE
//******************************************
#ifdef enable_POKE
// Pokemon Mini
// Cartridge Pinout
// 32P 0.5mm pitch
// NOTE:  Console SMD connector - 33P 1.0mm pitch
//
//    TOP ROW                BOTTOM ROW
//             +----------+
// VCC (3.3V) -| B1       |
//             |       A1 |- VCC (3.3V)
//        A20 -| B2       |
//             |       A2 |- A9/A19
//     A8/A18 -| B3       |
//             |       A3 |- A7/A17
//     A6/A16 -| B4       |
//             |       A4 |- A5/A15
//     A4/A14 -| B5       |
//             |       A5 |- A3/A13
//     A2/A12 -| B6       |
//             |       A6 |- A1/A11
//     A0/A10 -| B7       |
//             |       A7 |- VCC (3.3V)
//       HALE -| B8       |
//             |       -- |
//       LALE -| B9       |
//             |       A8 |- GND
//         D0 -| B10      |
//             |       A9 |- D1
//         D2 -| B11      |
//             |      A10 |- D3
//         D4 -| B12      |
//             |      A11 |- D5
//         D6 -| B13      |
//             |      A12 |- D7
//         OE -| B14      |
//             |      A13 |- IRQ
//         WE -| B15      |
//             |      A14 |- CS
//     CARD_N -| B16      |
//             |      A15 |- GND
//        GND -| B17      |
//             +----------+
//
//                                           TOP
//      +----------------------------------------------------------------------------+
//      | B17  B16  B15  B14  B13  B12  B11  B10  B9  B8  B7  B6  B5  B4  B3  B2  B1 |
// LEFT |                                                                            | RIGHT
//      |    A15  A14  A13  A12  A11  A10  A9  A8  ---  A7  A6  A5  A4  A3  A2  A1   |
//      +----------------------------------------------------------------------------+
//                                          BOTTOM

// CONTROL PINS:
// HALE(PH0) - SNES RESET
// CS(PH3)   - SNES /CS
// LALE(PH4) - SNES /IRQ
// WE(PH5)   - SNES /WR
// OE(PH6)   - SNES /RD

// NOTE:  SET VOLTAGE TO 3.3V

//******************************************
//  Defines
//******************************************
#define HALE_ENABLE PORTH |= (1 << 0)  // LATCH HIGH ADDRESS
#define HALE_DISABLE PORTH &= ~(1 << 0)
#define LALE_ENABLE PORTH |= (1 << 4)  // LATCH LOW ADDRESS
#define LALE_DISABLE PORTH &= ~(1 << 4)
#define CS_ENABLE PORTH |= (1 << 3)  // CHIP SELECT
#define CS_DISABLE PORTH &= ~(1 << 3)
#define WE_ENABLE PORTH |= (1 << 5)  // WRITE ENABLE
#define WE_DISABLE PORTH &= ~(1 << 5)
#define OE_ENABLE PORTH |= (1 << 6)  // OUTPUT ENABLE
#define OE_DISABLE PORTH &= ~(1 << 6)

//******************************************
//  Menu
//******************************************
// Base Menu
static const char pokeMenuItem1[] PROGMEM = "Read ROM";
static const char* const menuOptionsPOKE[] PROGMEM = { pokeMenuItem1, string_reset2 };

void pokeMenu() {
  convertPgm(menuOptionsPOKE, 2);
  uint8_t mainMenu = question_box(F("POKEMON MINI MENU"), menuOptions, 2, 0);

  switch (mainMenu) {
    case 0:
      // Read ROM
      sd.chdir("/");
      readROM_POKE();
      sd.chdir("/");
      break;

    case 1:
      // reset
      resetArduino();
      break;
  }
}

//******************************************
//  SETUP
//******************************************
void setup_POKE() {
  // Request 3.3V
  setVoltage(VOLTS_SET_3V3);

  // Set Address Pins to Output
  // Pokemon Mini uses A0-A9 (DUAL A10-A19) + A20 (CONNECT TO SNES A10) [A11-A23 UNUSED]
  //A0-A7
  DDRF = 0xFF;
  //A8-A15
  DDRK = 0xFF;
  //A16-A23
  DDRL = 0xFF;

  // Set Control Pins to Output
  //       LALE(PH0)   ---(PH1)  CS(PH3)    HALE(PH4)  WE(PH5)    OE(PH6)
  DDRH |= (1 << 0) | (1 << 1) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6);

  // Set TIME(PJ0) to Output (UNUSED)
  DDRJ |= (1 << 0);

  // Set Pins (D0-D7) to Input
  DDRC = 0x00;

  // Setting Control Pins to LOW (DISABLE)
  //       LALE(PH0)    CS(PH3)     HALE(PH4)   WE(PH5)     OE(PH6)
  PORTH &= ~(1 << 0) & ~(1 << 3) & ~(1 << 4) & ~(1 << 5) & ~(1 << 6);

  // SET CS HIGH
  PORTH |= (1 << 3);  // CS HIGH (ENABLE)

  // Set Unused Data Pins (PA0-PA7) to Output
  DDRA = 0xFF;

  // Set Unused Pins HIGH
  PORTA = 0xFF;
  PORTH |= (1 << 1);  // CPUCLK(PH1)
  PORTL = 0xFF;       // A16-A23
  PORTJ |= (1 << 0);  // TIME(PJ0)

  strcpy(romName, "POKEMINI");

  mode = mode_POKE;
}

//******************************************
// READ DATA
//******************************************
uint8_t readData_POKE(uint32_t addr) {
  // Address Lines A0-A20 = 1MB (ALL ROMS ARE 512K)
  // 100000 = 1 0000 0000 0000 0000 0000 = 100 0000 0000|00 0000 0000

  // High Address A10-A20
  PORTF = (addr >> 10) & 0xFF;  // A10-A17
  PORTK = (addr >> 18) & 0x07;  // A18-A20
  HALE_ENABLE;                  // LATCH HIGH ADDRESS
  NOP;
  NOP;
  HALE_DISABLE;

  // Low Address A0-A9
  PORTF = addr & 0xFF;         // A0-A7
  PORTK = (addr >> 8) & 0x03;  // A8-A9
  LALE_ENABLE;                 // LATCH LOW ADDRESS
  NOP;
  NOP;

  // Read Enable
  OE_ENABLE;  // OE HIGH
  NOP;
  NOP;
  NOP;
  NOP;
  NOP;

  // Data
  uint8_t ret = PINC;

  // Read Disable
  OE_DISABLE;  // OE LOW
  NOP;
  NOP;
  NOP;
  NOP;

  LALE_DISABLE;

  return ret;
}

//******************************************
// WRITE DATA
//******************************************
void writeData_POKE(uint32_t addr, uint8_t data) {
  // High Address A10-A20
  PORTF = (addr >> 10) & 0xFF;  // A10-A17
  PORTK = (addr >> 18) & 0x07;  // A18-A20
  HALE_ENABLE;                  // LATCH HIGH ADDRESS
  NOP;
  NOP;
  HALE_DISABLE;

  // Low Address A0-A9
  PORTF = addr & 0xFF;         // A0-A7
  PORTK = (addr >> 8) & 0x03;  // A8-A9
  LALE_ENABLE;                 // LATCH LOW ADDRESS

  // Set Data to Output
  DDRC = 0xFF;
  PORTC = data;

  // Write Enable
  WE_ENABLE;  // WE HIGH
  NOP;
  NOP;
  NOP;
  NOP;
  NOP;

  // Write Disable
  WE_DISABLE;  // OE LOW
  NOP;
  NOP;
  NOP;
  NOP;

  LALE_DISABLE;

  // Reset Data to Input
  DDRC = 0x00;
}

//******************************************
// READ ROM
//******************************************

void readROM_POKE() {
  strcpy(fileName, romName);
  strcat(fileName, ".min");

  // create a new folder for storing rom file
  EEPROM_readAnything(0, foldern);
  sprintf(folder, "POKE/ROM/%d", foldern);
  sd.mkdir(folder, true);
  sd.chdir(folder);

  display_Clear();
  print_STR(saving_to_STR, 0);
  print_Msg(folder);
  println_Msg(F("/..."));
  display_Update();

  // open file on sdcard
  if (!myFile.open(fileName, O_RDWR | O_CREAT))
    print_FatalError(sd_error_STR);

  // write new folder number back to EEPROM
  foldern++;
  EEPROM_writeAnything(0, foldern);

  // read rom
  uint32_t progress = 0;
  draw_progressbar(0, 0x80000);
  for (uint32_t addr = 0; addr < 0x80000; addr += 512) {  // 512K
    for (int w = 0; w < 512; w++) {
      uint8_t temp = readData_POKE(addr + w);
      sdBuffer[w] = temp;
    }
    myFile.write(sdBuffer, 512);
    progress += 512;
    draw_progressbar(progress, 0x80000);
  }
  myFile.close();

  // compare dump CRC with db values
  compareCRC("pkmn.txt", 0, 1, 0);
  println_Msg(F(""));

  // Prints string out of the common strings array either with or without newline
  print_STR(press_button_STR, 1);
  display_Update();
  wait();
}
#endif