Arduino gameboy cart reader software, using https://github.com/insidegadgets/GBCartRead
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

144 lines
3.4 KiB

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <locale.h>
#include <libserialport.h>
#include <sys/time.h>
#ifdef __GNUC__
#define A_UNUSED __attribute__((unused))
#else
#define A_UNUSED
#endif
struct sp_port *serial_guess_port(void)
{
struct sp_port **ports;
if (sp_list_ports(&ports) != SP_OK || ports[0] == NULL) {
puts("No serial devices detected");
return NULL;
}
if (ports[1] != NULL) {
puts("Please select a port");
return NULL;
}
return ports[0];
}
char *program_name;
void serial_error(char *message)
{
char *error = sp_last_error_message();
fprintf(stderr, "%s: %s: %s\n", program_name, message, error);
sp_free_error_message(error);
}
int main(int argc, char *argv[])
{
program_name = argv[0];
setlocale(LC_ALL, "");
long save = 0;
if (argc > 1) {
save = strtol(argv[1], NULL, 0);
}
struct sp_port *port;
if (!(port = serial_guess_port())) return 1;
puts(sp_get_port_name(port));
if (sp_open(port, SP_MODE_READ_WRITE) != SP_OK ||
sp_set_baudrate(port, 2000000) != SP_OK ||
sp_set_flowcontrol(port, SP_FLOWCONTROL_NONE) != SP_OK) {
serial_error("Failed to open port");
return 1;
}
usleep(100000LL);
sp_flush(port, SP_BUF_BOTH);
fputs("Waiting for device... ", stdout);
fflush(stdout);
for (;;) {
char c = 0;
sp_blocking_write(port, &c, 1, 0);
if (sp_blocking_read(port, &c, 1, 1000) == 1) {
if (c == 0) {
puts("ROM OK!");
} else {
puts("ROM ERROR");
}
break;
}
}
char command = 1;
uint32_t address = 0x147;
uint32_t size = 3;
sp_blocking_write(port, &command, 1, 0);
sp_blocking_write(port, &address, 4, 0);
sp_blocking_write(port, &size, 4, 0);
sp_blocking_read(port, &command, 1, 0);
if (command != 0) {
puts("An error has occurred");
return 1;
}
char cart_type = 0;
sp_blocking_read(port, &cart_type, 1, 0);
printf("Cart type: %02X\n", cart_type);
char rom_size = 0;
sp_blocking_read(port, &rom_size, 1, 0);
printf("Rom size: %02X\n", rom_size);
char ram_size = 0;
sp_blocking_read(port, &ram_size, 1, 0);
printf("Ram size: %02X\n", ram_size);
command = save ? 3 : 2;
address = 0;
if (!save) {
size = 0x8000 << rom_size;
} else {
size = save;
}
sp_blocking_write(port, &command, 1, 0);
sp_blocking_write(port, &address, 4, 0);
sp_blocking_write(port, &size, 4, 0);
sp_blocking_read(port, &command, 1, 0);
if (command != 0) {
puts("An error has occurred");
return 1;
}
struct timeval begin, end;
gettimeofday(&begin, NULL);
FILE *file = fopen("out.bin", "w");
for (unsigned x = 0; x < size; x += 0x200) {
char c[0x200];
sp_blocking_read(port, &c, 0x200, 0);
if (!save) {
printf("\r%02X:%04X", x / 0x4000, x % 0x4000);
} else {
printf("\r%02X:%04X", x / 0x2000, x % 0x2000);
}
fflush(stdout);
fwrite(&c, 0x200, 1, file);
}
putchar('\n');
fclose(file);
gettimeofday(&end, NULL);
double dt = (double)end.tv_sec - begin.tv_sec + ((double)end.tv_usec - begin.tv_usec) / 1000000;
printf("Average speed: %f KB/s\n", size / 1000 / dt);
}