From edc9db1e25c9a62c40a98a032350a122cc17b222 Mon Sep 17 00:00:00 2001 From: Alexey 'Cluster' Avdyukhin Date: Mon, 18 Apr 2016 03:08:29 +0300 Subject: First commit --- dumper.c | 899 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 899 insertions(+) create mode 100644 dumper.c (limited to 'dumper.c') diff --git a/dumper.c b/dumper.c new file mode 100644 index 0000000..b327c10 --- /dev/null +++ b/dumper.c @@ -0,0 +1,899 @@ +/* Famicom Dumper/Programmer + * + * Copyright notice for this file: + * Copyright (C) 2016 Cluster + * http://clusterrr.com + * clusterrr@clusterrr.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "defines.h" +#include +#include +#include +#include +#include +#include "usart.h" +#include "comm.h" +#include "jtag.h" + +#define LED_RED_ON PORTB |= (1<<7) +#define LED_RED_OFF PORTB &= ~(1<<7) +#define LED_GREEN_ON PORTB |= (1<<6) +#define LED_GREEN_OFF PORTB &= ~(1<<6) +#define ROMSEL_HI PORTF |= (1<<1) +#define ROMSEL_LOW PORTF &= ~(1<<1) +#define PHI2_HI PORTF |= (1<<0) +#define PHI2_LOW PORTF &= ~(1<<0) +#define MODE_READ { PORTD = 0xFF; DDRD = 0; } +#define MODE_WRITE DDRD = 0xFF +#define PRG_READ PORTF |= (1<<7) +#define PRG_WRITE PORTF &= ~(1<<7) +#define CHR_READ_HI PORTF |= (1<<5) +#define CHR_READ_LOW PORTF &= ~(1<<5) +#define CHR_WRITE_HI PORTF |= (1<<2) +#define CHR_WRITE_LOW PORTF &= ~(1<<2) + +static void (*jump_to_bootloader)(void) = 0xF800; + +ISR(USART0_RX_vect) +{ + unsigned char b; + while (UCSR0A & (1<>8; + + PORTA = l; + PORTC = h; + + // PPU /A13 + if ((address >> 13) & 1) + PORTF &= ~(1<<4); + else + PORTF |= 1<<4; +} + +static void set_romsel(unsigned int address) +{ + if (address & 0x8000) + { + ROMSEL_LOW; + } else { + ROMSEL_HI; + } +} + +static unsigned char read_prg_byte(unsigned int address) +{ + MODE_READ; + PRG_READ; + set_address(address); + PHI2_HI; + set_romsel(address); + _delay_us(1); + return PIND; +} + +static unsigned char read_chr_byte(unsigned int address) +{ + MODE_READ; + PHI2_HI; + ROMSEL_HI; + set_address(address); + CHR_READ_LOW; + + _delay_us(1); + + uint8_t result = PIND; + + CHR_READ_HI; + return result; +} + +static unsigned char read_coolboy_byte(unsigned int address) +{ + MODE_READ; + PRG_READ; + set_address(address); + PHI2_HI; + ROMSEL_LOW; + PORTB |= 1< 0) + { + comm_send_byte(read_prg_byte(address)); + len--; + address++; + } + set_address(0); + PHI2_HI; + ROMSEL_HI; + LED_GREEN_OFF; +} + +static void read_chr_send(unsigned int address, unsigned int len) +{ + LED_GREEN_ON; + comm_start(COMMAND_CHR_READ_RESULT, len); + while (len > 0) + { + comm_send_byte(read_chr_byte(address)); + len--; + address++; + } + set_address(0); + PHI2_HI; + ROMSEL_HI; + LED_GREEN_OFF; +} + +static void read_coolboy_send(unsigned int address, unsigned int len) +{ + LED_GREEN_ON; + PORTB |= 1< 0) + { + comm_send_byte(read_coolboy_byte(address)); + len--; + address++; + } + set_address(0); + ROMSEL_HI; + PORTB |= 1< 0) + { + write_prg_byte(address, *data); + address++; + len--; + data++; + } + //_delay_ms(1); + LED_RED_OFF; +} + +static void write_chr(unsigned int address, unsigned int len, uint8_t* data) +{ + LED_RED_ON; + while (len > 0) + { + write_chr_byte(address, *data); + address++; + len--; + data++; + } + //_delay_ms(1); + LED_RED_OFF; +} + +static void write_prg_flash_command(unsigned int address, uint8_t data) +{ + write_prg_byte(address | 0x8000, data); +} + +static void write_coolboy_flash_command(unsigned int address, uint8_t data) +{ + PORTB |= 1< 0) + { + if (!write_prg_flash_byte(address, *data)) + { + ok = 0; + break; + } + address++; + len--; + data++; + } + LED_RED_OFF; + return ok; +} + +static int write_coolboy(unsigned int address, unsigned int len, uint8_t* data) +{ + LED_RED_ON; + PORTB |= 1< 0) + { + + //uint8_t count = len > 16 ? 16 : len; + uint8_t count = 0; + uint8_t* d = data; + unsigned int a = address; + unsigned int address_base = a & 0xFFE0; + while (len > 0 && ((a & 0xFFE0) == address_base)) + { + if (*d != 0xFF) count++; + a++; + len--; + d++; + } + + if (count) + { + //write_prg_flash_command(0x0000, 0xF0); + write_coolboy_flash_command(0x0AAA, 0xAA); + write_coolboy_flash_command(0x0555, 0x55); + write_coolboy_flash_command(0x0000, 0x25); + write_coolboy_flash_command(0x0000, count-1); + + while (count > 0) + { + if (*data != 0xFF) + { + write_coolboy_flash_command(address, *data); + count--; + } + address++; + data++; + } + + write_coolboy_flash_command(0x0000, 0x29); + _delay_us(10); + + long int timeout = 0; + uint8_t res, last_res = 0; + while (timeout < 100000) + { + res = read_coolboy_byte((address-1) | 0x8000); + ROMSEL_HI; + if (res == last_res && last_res == *(data-1)) break; + last_res = res; + _delay_us(10); + timeout++; + } + if (timeout >= 100000) + { + ok = 0; + break; + } + } + + address = a; + data = d; + } + ROMSEL_HI; + jtag_shutdown(); + LED_RED_OFF; + return ok; +} + +static int write_coolgirl(unsigned int address, unsigned int len, uint8_t* data) +{ + LED_RED_ON; + ROMSEL_HI; + uint8_t ok = 1; + while (len > 0) + { + + //uint8_t count = len > 16 ? 16 : len; + uint8_t count = 0; + uint8_t* d = data; + unsigned int a = address; + unsigned int address_base = a & 0xFFE0; + while (len > 0 && ((a & 0xFFE0) == address_base)) + { + if (*d != 0xFF) count++; + a++; + len--; + d++; + } + + if (count) + { + //write_prg_flash_command(0x0000, 0xF0); + write_prg_flash_command(0x0AAA, 0xAA); + write_prg_flash_command(0x0555, 0x55); + write_prg_flash_command(0x0000, 0x25); + write_prg_flash_command(0x0000, count-1); + + while (count > 0) + { + if (*data != 0xFF) + { + write_prg_flash_command(address, *data); + count--; + } + address++; + data++; + } + + write_prg_flash_command(0x0000, 0x29); + _delay_us(10); + + long int timeout = 0; + uint8_t res, last_res = 0; + while (timeout < 100000) + { + res = read_prg_byte((address-1) | 0x8000); + ROMSEL_HI; + if (res == last_res && last_res == *(data-1)) break; + last_res = res; + _delay_us(10); + timeout++; + } + if (timeout >= 100000) + { + ok = 0; + break; + } + } + + address = a; + data = d; + } + ROMSEL_HI; + LED_RED_OFF; + return ok; +} + +static int write_chr_flash(unsigned int address, unsigned int len, uint8_t* data) +{ + LED_RED_ON; + if (address >= 0x8000) address -= 0x8000; + int ok = 1; + while (len > 0) + { + if (!write_chr_flash_byte(address, *data)) + { + ok = 0; + break; + } + address++; + len--; + data++; + } + LED_RED_OFF; + return ok; +} + +void get_mirroring() +{ + comm_start(COMMAND_MIRRORING_RESULT, 4); + LED_GREEN_ON; + set_address(0); + _delay_us(1); + comm_send_byte((PINE >> 2) & 1); + set_address(1<<10); + _delay_us(1); + comm_send_byte((PINE >> 2) & 1); + set_address(1<<11); + _delay_us(1); + comm_send_byte((PINE >> 2) & 1); + set_address((1<<10) | (1<<11)); + _delay_us(1); + comm_send_byte((PINE >> 2) & 1); + set_address(0); +} + +static void init_ports() +{ + DDRB |= (1 << 6) | (1 << 7); // LEDS + DDRF = 0b10110111; // CPU R/W, IRQ, PPU /RD, PPU /A13, CIRAM /CE, PPU /WR, /ROMSEL, PHI2 + PORTF = 0b11111111; // CPU R/W, IRQ, PPU /RD, PPU /A13, CIRAM /CE, PPU /WR, /ROMSEL, PHI2 + DDRE &= ~(1<<2); // CIRAM A10 + PORTE |= 1<<2; // CIRAM A10 + MODE_READ; + set_address(0); + DDRA = 0xFF; // Address low + DDRC = 0xFF; // Address high +} + +static void reset_phi2() +{ + LED_RED_ON; + LED_GREEN_ON; + PHI2_LOW; + ROMSEL_HI; + _delay_ms(1000); + PHI2_HI; + LED_RED_OFF; + LED_GREEN_OFF; +} + +int main (void) +{ + sei(); + USART_init(); + init_ports(); + jtag_shutdown(); + + LED_RED_OFF; + LED_GREEN_OFF; + + comm_init(); + comm_start(COMMAND_PRG_STARTED, 0); + + uint16_t address; + uint16_t length; + + unsigned long int t = 0; + char led_down = 0; + int led_bright = 0; + + while (1) + { + TCCR1A |= (1<= 10000) + { + if (!led_down) + { + led_bright++; + if (led_bright >= 110) led_down = 1; + } else { + led_bright--; + if (!led_bright) led_down = 0; + } + if (led_bright >= 100) OCR1B = led_bright - 100; + if (led_down) + { + int led_bright2 = 110-led_bright; + if (led_bright2 <= 20) + { + if (led_bright2 > 10) led_bright2 = 20 - led_bright2; + OCR1C = led_bright2*2; + } + } + t = 0; + } + + if (comm_recv_done) + { + comm_recv_done = 0; + t = led_down = led_bright = 0; + TCCR1A = OCR1B = OCR1C = 0; + + switch (comm_recv_command) + { + case COMMAND_PRG_INIT: + comm_start(COMMAND_PRG_STARTED, 0); + break; + + case COMMAND_PRG_READ_REQUEST: + address = recv_buffer[0] | ((uint16_t)recv_buffer[1]<<8); + length = recv_buffer[2] | ((uint16_t)recv_buffer[3]<<8); + read_prg_send(address, length); + break; + + case COMMAND_PRG_WRITE_REQUEST: + address = recv_buffer[0] | ((uint16_t)recv_buffer[1]<<8); + length = recv_buffer[2] | ((uint16_t)recv_buffer[3]<<8); + write_prg(address, length, (uint8_t*)&recv_buffer[4]); + comm_start(COMMAND_PRG_WRITE_DONE, 0); + break; + + case COMMAND_COOLBOY_READ_REQUEST: + address = recv_buffer[0] | ((uint16_t)recv_buffer[1]<<8); + length = recv_buffer[2] | ((uint16_t)recv_buffer[3]<<8); + read_coolboy_send(address, length); + break; + + case COMMAND_PHI2_INIT: + phi2_init(); + comm_start(COMMAND_PHI2_INIT_DONE, 0); + break; + + case COMMAND_RESET: + reset_phi2(); + comm_start(COMMAND_RESET_ACK, 0); + break; + + case COMMAND_PRG_FLASH_ERASE_REQUEST: + if (erase_prg_flash()) + comm_start(COMMAND_PRG_WRITE_DONE, 0); + break; + + case COMMAND_PRG_FLASH_WRITE_REQUEST: + address = recv_buffer[0] | ((uint16_t)recv_buffer[1]<<8); + length = recv_buffer[2] | ((uint16_t)recv_buffer[3]<<8); + if (write_prg_flash(address, length, (uint8_t*)&recv_buffer[4])) + comm_start(COMMAND_PRG_WRITE_DONE, 0); + break; + + case COMMAND_COOLBOY_ERASE_REQUEST: + if (erase_coolboy_sector()) + comm_start(COMMAND_PRG_WRITE_DONE, 0); + break; + + case COMMAND_COOLBOY_WRITE_REQUEST: + address = recv_buffer[0] | ((uint16_t)recv_buffer[1]<<8); + length = recv_buffer[2] | ((uint16_t)recv_buffer[3]<<8); + if (write_coolboy(address, length, (uint8_t*)&recv_buffer[4])) + comm_start(COMMAND_PRG_WRITE_DONE, 0); + break; + + case COMMAND_COOLGIRL_ERASE_SECTOR_REQUEST: + if (erase_coolgirl_sector()) + comm_start(COMMAND_PRG_WRITE_DONE, 0); + break; + + case COMMAND_COOLGIRL_WRITE_REQUEST: + address = recv_buffer[0] | ((uint16_t)recv_buffer[1]<<8); + length = recv_buffer[2] | ((uint16_t)recv_buffer[3]<<8); + if (write_coolgirl(address, length, (uint8_t*)&recv_buffer[4])) + comm_start(COMMAND_PRG_WRITE_DONE, 0); + break; + + case COMMAND_CHR_INIT: + comm_start(COMMAND_CHR_STARTED, 0); + break; + + case COMMAND_CHR_READ_REQUEST: + address = recv_buffer[0] | ((uint16_t)recv_buffer[1]<<8); + length = recv_buffer[2] | ((uint16_t)recv_buffer[3]<<8); + read_chr_send(address, length); + break; + + case COMMAND_CHR_WRITE_REQUEST: + address = recv_buffer[0] | ((uint16_t)recv_buffer[1]<<8); + length = recv_buffer[2] | ((uint16_t)recv_buffer[3]<<8); + write_chr(address, length, (uint8_t*)&recv_buffer[4]); + comm_start(COMMAND_CHR_WRITE_DONE, 0); + break; + + case COMMAND_MIRRORING_REQUEST: + get_mirroring(); + break; + + /* + case COMMAND_EPROM_PREPARE: + write_eprom_prepare(); + break; + + case COMMAND_CHR_EPROM_WRITE_REQUEST: + address = recv_buffer[0] | ((uint16_t)recv_buffer[1]<<8); + length = recv_buffer[2] | ((uint16_t)recv_buffer[3]<<8); + write_eprom(address, length, (uint8_t*)&recv_buffer[4]); + comm_start(COMMAND_CHR_WRITE_DONE, 0); + break; + */ + + case COMMAND_CHR_FLASH_ERASE_REQUEST: + if (erase_chr_flash()) + comm_start(COMMAND_CHR_WRITE_DONE, 0); + break; + + case COMMAND_CHR_FLASH_WRITE_REQUEST: + address = recv_buffer[0] | ((uint16_t)recv_buffer[1]<<8); + length = recv_buffer[2] | ((uint16_t)recv_buffer[3]<<8); + if (write_chr_flash(address, length, (uint8_t*)&recv_buffer[4])) + comm_start(COMMAND_CHR_WRITE_DONE, 0); + break; + + case COMMAND_JTAG_SETUP: + jtag_setup(); + comm_start(COMMAND_JTAG_RESULT, 1); + comm_send_byte(1); + break; + + case COMMAND_JTAG_SHUTDOWN: + jtag_shutdown(); + comm_start(COMMAND_JTAG_RESULT, 1); + comm_send_byte(1); + break; + + case COMMAND_JTAG_EXECUTE: + address = recv_buffer[0] | ((uint16_t)recv_buffer[1]<<8); + comm_start(COMMAND_JTAG_RESULT, 1); + LED_RED_ON; + comm_send_byte(jtag_execute(address, (uint8_t*) &recv_buffer[2])); + LED_RED_OFF; + break; + case COMMAND_BOOTLOADER: + cli(); + MCUCSR = 0; + jump_to_bootloader(); + } + } + } +} -- cgit v1.2.3