void btLePacketEncode(uint8_t* packet, uint8_t len, uint8_t chan){ //length is of packet, including crc. pre-populate crc in packet with initial crc value! uint8_t i, dataLen = len - 3; btLeCrc(packet, dataLen, packet + dataLen); for(i = 0; i < 3; i++, dataLen++) packet[dataLen] = swapbits(packet[dataLen]); btLeWhiten(packet, len, btLeWhitenStart(chan)); for(i = 0; i < len; i++) packet[i] = swapbits(packet[i]); }
int pce_swap (st_ucon64_nfo_t *rominfo) { char src_name[FILENAME_MAX], dest_name[FILENAME_MAX]; unsigned char *rom_buffer; int size = ucon64.file_size - rominfo->backup_header_len; if ((rom_buffer = (unsigned char *) malloc (size)) == NULL) { fprintf (stderr, ucon64_msg[ROM_BUFFER_ERROR], size); return -1; } strcpy (src_name, ucon64.fname); strcpy (dest_name, ucon64.fname); ucon64_file_handler (dest_name, src_name, 0); if (rominfo->backup_header_len) // copy header (if present) fcopy (src_name, 0, rominfo->backup_header_len, dest_name, "wb"); ucon64_fread (rom_buffer, rominfo->backup_header_len, size, src_name); swapbits (rom_buffer, size); ucon64_fwrite (rom_buffer, rominfo->backup_header_len, size, dest_name, rominfo->backup_header_len ? "ab" : "wb"); free (rom_buffer); printf (ucon64_msg[WROTE], dest_name); remove_temp_file (); return 0; }
// header format is specified in src/backup/ffe.h int pce_msg (st_ucon64_nfo_t *rominfo) { char src_name[FILENAME_MAX], dest_name[FILENAME_MAX]; unsigned char *rom_buffer = NULL; st_msg_header_t header; int size = ucon64.file_size - rominfo->backup_header_len; if (rominfo->interleaved) if ((rom_buffer = (unsigned char *) malloc (size)) == NULL) { fprintf (stderr, ucon64_msg[ROM_BUFFER_ERROR], size); return -1; } memset (&header, 0, MSG_HEADER_LEN); header.size = (unsigned char) (size / 8192); header.emulation = size == 3 * MBIT ? 1 : 0; header.id1 = 0xaa; header.id2 = 0xbb; header.type = 2; strcpy (src_name, ucon64.fname); strcpy (dest_name, ucon64.fname); set_suffix (dest_name, ".msg"); ucon64_file_handler (dest_name, src_name, 0); ucon64_fwrite (&header, 0, MSG_HEADER_LEN, dest_name, "wb"); if (rominfo->interleaved) { // Magic Super Griffin files should not be "interleaved" ucon64_fread (rom_buffer, rominfo->backup_header_len, size, src_name); swapbits (rom_buffer, size); ucon64_fwrite (rom_buffer, MSG_HEADER_LEN, size, dest_name, "ab"); free (rom_buffer); } else fcopy (src_name, rominfo->backup_header_len, size, dest_name, "ab"); printf (ucon64_msg[WROTE], dest_name); remove_temp_file (); return 0; }
// see src/backup/mgd.h for the file naming scheme int pce_mgd (st_ucon64_nfo_t *rominfo) { char src_name[FILENAME_MAX], dest_name[FILENAME_MAX]; unsigned char *rom_buffer = NULL; int size = ucon64.file_size - rominfo->backup_header_len; if (!rominfo->interleaved) if ((rom_buffer = (unsigned char *) malloc (size)) == NULL) { fprintf (stderr, ucon64_msg[ROM_BUFFER_ERROR], size); return -1; } strcpy (src_name, ucon64.fname); mgd_make_name (ucon64.fname, UCON64_PCE, size, dest_name); ucon64_file_handler (dest_name, src_name, OF_FORCE_BASENAME); // bit-swapping images for the MGD2 only makes sense for owners of a TG-16 // (American version of the PCE) if (!rominfo->interleaved) { ucon64_fread (rom_buffer, rominfo->backup_header_len, size, src_name); swapbits (rom_buffer, size); ucon64_fwrite (rom_buffer, 0, size, dest_name, "wb"); free (rom_buffer); } else fcopy (src_name, rominfo->backup_header_len, size, dest_name, "wb"); printf (ucon64_msg[WROTE], dest_name); remove_temp_file (); mgd_write_index_file ((char *) basename2 (dest_name), 1); return 0; }
static void check_bitmap(void) { uint8_t bits[SFS_BLOCKSIZE], *found, *tofree, tmp; uint32_t alloccount=0, freecount=0, i, j; int bchanged; for (i=0; i<bitblocks; i++) { diskread(bits, SFS_MAP_LOCATION+i); swapbits(bits); found = bitmapdata + i*SFS_BLOCKSIZE; tofree = tofreedata + i*SFS_BLOCKSIZE; bchanged = 0; for (j=0; j<SFS_BLOCKSIZE; j++) { /* we shouldn't have blocks marked both ways */ assert((found[j] & tofree[j])==0); if (bits[j]==found[j]) { continue; } if (bits[j]==(found[j] | tofree[j])) { bits[j] = found[j]; bchanged = 1; continue; } /* free the ones we're freeing */ bits[j] &= ~tofree[j]; /* are we short any? */ if ((bits[j] & found[j]) != found[j]) { tmp = found[j] & ~bits[j]; alloccount += countbits(tmp); if (tmp != 0) { reportbits(i, j, tmp, "free"); } } /* do we have any extra? */ if ((bits[j] & found[j]) != bits[j]) { tmp = bits[j] & ~found[j]; freecount += countbits(tmp); if (tmp != 0) { reportbits(i, j, tmp, "allocated"); } } bits[j] = found[j]; bchanged = 1; } if (bchanged) { swapbits(bits); diskwrite(bits, SFS_MAP_LOCATION+i); } } if (alloccount > 0) { warnx("%lu blocks erroneously shown free in bitmap (fixed)", (unsigned long) alloccount); setbadness(EXIT_RECOV); } if (freecount > 0) { warnx("%lu blocks erroneously shown used in bitmap (fixed)", (unsigned long) freecount); setbadness(EXIT_RECOV); } }
static inline uint8_t btLeWhitenStart(uint8_t chan){ //the value we actually use is what BT'd use left shifted one...makes our life easier return swapbits(chan) | 2; }
void APP_Run(void) { static const uint8_t chRf[] = {2, 26,80}; static const uint8_t chLe[] = {37,38,39}; uint8_t i, L, ch = 0; uint8_t buf[32]; nrf_cmd(0x20, 0x12); //on, no crc, int on RX/TX done nrf_cmd(0x21, 0x00); //no auto-acknowledge nrf_cmd(0x22, 0x00); //no RX nrf_cmd(0x23, 0x02); //5-byte address nrf_cmd(0x24, 0x00); //no auto-retransmit nrf_cmd(0x26, 0x06); //1MBps at 0dBm nrf_cmd(0x27, 0x3E); //clear various flags nrf_cmd(0x3C, 0x00); //no dynamic payloads nrf_cmd(0x3D, 0x00); //no features nrf_cmd(0x31, 32); //always RX 32 bytes nrf_cmd(0x22, 0x01); //RX on pipe 0 buf[0] = 0x30; //set addresses buf[1] = swapbits(0x8E); buf[2] = swapbits(0x89); buf[3] = swapbits(0xBE); buf[4] = swapbits(0xD6); #if 0 nrf_manybytes(buf, 5); #else RF1_WriteRegisterData(RF1_TX_ADDR, &buf[1], 4); #endif buf[0] = 0x2A; #if 0 nrf_manybytes(buf, 5); #else RF1_WriteRegisterData(RF1_RX_ADDR_P0, &buf[1], 4); #endif while(1) { L = 0; buf[L++] = 0x40; //PDU type, given address is random buf[L++] = 11; //17 bytes of payload buf[L++] = MY_MAC_0; buf[L++] = MY_MAC_1; buf[L++] = MY_MAC_2; buf[L++] = MY_MAC_3; buf[L++] = MY_MAC_4; buf[L++] = MY_MAC_5; buf[L++] = 2; //flags (LE-only, limited discovery mode) buf[L++] = 0x01; buf[L++] = 0x05; buf[L++] = 7; buf[L++] = 0x08; buf[L++] = 'n'; buf[L++] = 'R'; buf[L++] = 'F'; buf[L++] = ' '; buf[L++] = 'L'; buf[L++] = 'E'; buf[L++] = 0x55; //CRC start value: 0x555555 buf[L++] = 0x55; buf[L++] = 0x55; if(++ch == sizeof(chRf)) { /* channel hopping */ ch = 0; } //nrf_cmd(0x25, chRf[ch]); (void)RF1_SetChannel(chRf[ch]); //nrf_cmd(0x27, 0x6E); //clear flags RF1_WriteRegister(RF1_STATUS, RF1_STATUS_RX_DR|RF1_STATUS_TX_DS|RF1_STATUS_RX_P_NO_RX_FIFO_EMPTY); /* clear flags */ btLePacketEncode(buf, L, chLe[ch]); //nrf_simplebyte(0xE2); //Clear RX Fifo RF1_Write(RF1_FLUSH_RX); /* flush old data */ //nrf_simplebyte(0xE1); //Clear TX Fifo //RF1_Write(RF1_FLUSH_TX); /* flush old data */ /* done in RF1_TxPayload() */ RF1_TxPayload(buf, L); #if 0 cbi(PORTB, PIN_nCS); spi_byte(0xA0); for(i = 0 ; i < L ; i++) { spi_byte(buf[i]); } sbi(PORTB, PIN_nCS); nrf_cmd(0x20, 0x12); //tx on sbi(PORTB, PIN_CE); //do tx delay_ms(10); cbi(PORTB, PIN_CE); (in preparation of switching to RX quickly); #endif LED1_Neg(); WAIT1_Waitms(10); } /* for */ }
int pce_init (st_ucon64_nfo_t *rominfo) { int result = -1, size, swapped, x; unsigned char *rom_buffer; st_pce_data_t *info, key; x = ucon64.file_size % (16 * 1024); rominfo->backup_header_len = UCON64_ISSET (ucon64.backup_header_len) ? ucon64.backup_header_len : (ucon64.file_size > x ? x : 0); size = ucon64.file_size - rominfo->backup_header_len; if ((rom_buffer = (unsigned char *) malloc (size)) == NULL) { fprintf (stderr, ucon64_msg[ROM_BUFFER_ERROR], size); return -1; } ucon64_fread (rom_buffer, rominfo->backup_header_len, size, ucon64.fname); if (pce_check (rom_buffer, size) == 1) result = 0; swapped = -1; /* 29 40 f0 => unhacked 29 40 80 => U.S.A. -> Jap hack 94 02 0f => bit-swapped and unhacked 94 02 01 => bit-swapped and hacked According to Cowering 2 or 3 games don't use these opcodes to check if a Japanese game is running on an American console. If they are present then it is in the first 500 (or so) bytes. The check for "A..Z" is a fix for Puzznic (J). The check for "HESM" a fix for: Fire Pro Wrestling - 2nd Bout Sounds Fire Pro Wrestling 3 - Legend Bout Sounds */ x = size > 32768 ? 32768 : size; if ((memmem2 (rom_buffer, x, "\x94\x02\x0f", 3, 0) || memmem2 (rom_buffer, x, "\x94\x02\x01", 3, 0)) && memmem2 (rom_buffer, x, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 26, 0) == 0 && memcmp (rom_buffer, "HESM", 4)) swapped = 1; if (UCON64_ISSET (ucon64.interleaved)) swapped = ucon64.interleaved; if ((result == -1 && swapped != 0) || swapped == 1) { // don't swap the bits if -nint is specified if (!UCON64_ISSET (ucon64.do_not_calc_crc) || swapped == 1) ucon64.fcrc32 = crc32 (0, rom_buffer, size); swapbits (rom_buffer, size); if (pce_check (rom_buffer, size) == 1) { swapped = 1; result = 0; } if (swapped != 1) { ucon64.crc32 = ucon64.fcrc32; ucon64.fcrc32 = 0; } } if (swapped != -1) rominfo->interleaved = swapped; if (ucon64.console == UCON64_PCE) result = 0; rominfo->header_start = PCE_HEADER_START; rominfo->header_len = PCE_HEADER_LEN; rominfo->console_usage = pce_usage[0].help; rominfo->backup_usage = rominfo->backup_header_len ? msg_usage[0].help : mgd_usage[0].help; if (!UCON64_ISSET (ucon64.do_not_calc_crc) && result == 0) { if (!ucon64.crc32) ucon64.crc32 = crc32 (0, rom_buffer, size); // additional info key.crc32 = ucon64.crc32; info = (st_pce_data_t *) bsearch (&key, pce_data, sizeof pce_data / sizeof (st_pce_data_t), sizeof (st_pce_data_t), pce_compare); if (info) { if (info->maker) rominfo->maker = NULL_TO_UNKNOWN_S (pce_maker[MIN (info->maker, PCE_MAKER_MAX - 1)]); if (info->serial) if (info->serial[0]) { strcat (rominfo->misc, "\nSerial: "); strcat (rominfo->misc, info->serial); } if (info->date) { int day = info->date / 10000, month = (info->date % 10000) / 100, year = info->date % 100; char date[80]; date[0] = 0; if (day) sprintf (date, "\nDate: %d/%d/19%d", day, month, year); else if (month) sprintf (date, "\nDate: %d/19%d", month, year); else if (year) sprintf (date, "\nDate: 19%d", year); strcat (rominfo->misc, date); } if (info->comment) if (info->comment[0]) { strcat (rominfo->misc, "\nComment: "); strcat (rominfo->misc, info->comment); } } } free (rom_buffer); return result; }
void main (void) { static const uint8_t chRf[] = {2, 26,80}; static const uint8_t chLe[] = {37,38,39}; uint8_t i, L, ch = 0; // initialize buffer with set tx address command // address 8E 89 BE D6 bit-reversed // static rather than local saves 18 bytes static uint8_t buf[32]; //= {0x30, 0x6B, 0x7D, 0x91, 0x71}; SPI_init(); nrf_cmd(0x20, 0x12); //on, no crc, int on RX/TX done _delay_ms(2); // Tpd2stby //nrf_cmd(0x22, 0x00); //no RX nrf_cmd(0x21, 0x00); //no auto-acknowledge //nrf_cmd(0x22, 0x01); //RX on pipe 0 nrf_cmd(0x23, 0x02); //4-byte address nrf_cmd(0x24, 0x00); //no auto-retransmit //nrf_cmd(0x26, 0x06); //1MBps at 0dBm nrf_cmd(0x26, 0x00); //1MBps at -18dBm //nrf_cmd(0x27, 0x3E); //clear various flags //nrf_cmd(0x31, 32); //always RX 32 bytes buf[0] = 0x30; //set tx address buf[1] = swapbits(0x8E); buf[2] = swapbits(0x89); buf[3] = swapbits(0xBE); buf[4] = swapbits(0xD6); nrf_manybytes(buf, 5); //buf[0] = 0x2A; // rx address P0 //nrf_manybytes(buf, 5); while(1){ if(++ch == sizeof(chRf)){ ch = 0; sbi(NRF_PORT, DEBUG_PIN); _delay_ms(109); // wait between advertisements cbi(NRF_PORT, DEBUG_PIN); } L = 0; buf[L++] = 0x02; //PDU type, given address is random buf[L++] = 11; //11 + 6 = 17 bytes of payload buf[L++] = MY_MAC_0; buf[L++] = MY_MAC_1; buf[L++] = MY_MAC_2; buf[L++] = MY_MAC_3; buf[L++] = MY_MAC_4; buf[L++] = MY_MAC_5; buf[L++] = 2; //flags (LE-only, limited discovery mode) buf[L++] = 0x01; buf[L++] = 0x05; buf[L++] = 7; buf[L++] = 0x08; buf[L++] = 'n'; buf[L++] = 'R'; buf[L++] = 'F'; buf[L++] = ' '; buf[L++] = 'L'; buf[L++] = 'E'; buf[L++] = 0x55; //CRC start value: 0x555555 buf[L++] = 0x55; buf[L++] = 0x55; btLePacketEncode(buf, L, chLe[ch]); nrf_cmd(0x25, chRf[ch]); nrf_cmd(0x27, 0x6E); //clear flags //nrf_simplebyte(0xE2); //Clear RX Fifo //nrf_simplebyte(0xE1); //Clear TX Fifo cbi(NRF_PORT, PIN_nCS); spi_byte(0xA0); for(i = 0 ; i < L ; i++) spi_byte(buf[i]); sbi(NRF_PORT, PIN_nCS); //nrf_cmd(0x20, 0x12); //tx on // no CE pulse required when CE tied high sbi(NRF_PORT, PIN_CE); //do tx _delay_us(15); cbi(NRF_PORT, PIN_CE); // only delay for debugging - i.e. check IRQ trigger //_delay_ms(1); // let tx finish } }