#include "dump.h" /* Desc:Dump cart memory into buffer's data array * Pre: buffer elements must be updated to designate how/where to dump * buffer's cur_byte must be cleared or set to where to start dumping * Post:page dumped from cart memory to buffer. * Rtn: SUCCESS or ERROR# depending on if there were errors. */ uint8_t dump_buff( buffer *buff ) { uint8_t addrH = buff->page_num; //A15:8 while accessing page uint8_t bank; //warn uint8_t addrX; //A23:16 while accessing page //TODO use mapper to set mapper controlled address bits //use mem_type to set addrH/X as needed for dump loop //also use to get read function pointer switch ( buff->mem_type ) { case NESCPU_4KB: //mapper lower nibble specifies NES CPU A12-15 if (buff->mapper > 0x0F) { //mapper can only be 4bits (0-15) return ERR_BUFF_PART_NUM_RANGE; } addrH |= (buff->mapper << 4); // 8 << 12 = shift by 4 buff->cur_byte = nes_cpu_page_rd_poll( buff->data, addrH, buff->id, //id contains MSb of page when <256B buffer buff->last_idx, ~FALSE ); break; case NESPPU_1KB: //mapper bits 2-5 specifies NES PPU A10-13 if (buff->mapper & 0xC3) { //make sure bits 7, 6, 1, & 0 aren't set //mapper can only have bits 2-5 set return ERR_BUFF_PART_NUM_RANGE; } addrH |= buff->mapper; // PPU A10-13 get set based on mapper buff->cur_byte = nes_ppu_page_rd_poll( buff->data, addrH, buff->id, buff->last_idx, ~FALSE ); break; case NESCPU_PAGE: //mapper byte specifies CPU A15-8 addrH |= buff->mapper; buff->cur_byte = nes_cpu_page_rd_poll( buff->data, addrH, buff->id, //id contains MSb of page when <256B buffer buff->last_idx, ~FALSE ); break; case NESPPU_PAGE: //mapper byte specifies PPU A13-8 if (buff->mapper & 0xC0) { //make sure bits 7, 6 aren't set //mapper can only have bits 5-0 set return ERR_BUFF_PART_NUM_RANGE; } addrH |= buff->mapper; // PPU A10-13 get set based on mapper buff->cur_byte = nes_ppu_page_rd_poll( buff->data, addrH, buff->id, buff->last_idx, ~FALSE ); break; case SNESROM_PAGE: //ROMSEL is always taken low //mapper byte specifies SNES CPU A15-8 addrH |= (buff->mapper); //no shift needed buff->cur_byte = snes_rom_page_rd_poll( buff->data, addrH, buff->id, //id contains MSb of page when <256B buffer buff->last_idx, ~FALSE ); break; case PRGROM: addrH |= 0x80; //$8000 if (buff->mapper == MMC1) { //write bank value to bank table //page_num shift by 6 bits A15 >> A9(1) bank = (buff->page_num)>>6; bank &= 0x0F; //only 4 bits in PRG //LSb doesn't matter in 32KB mode mmc1_wr(0x8000, 0x10, 1); //write bank to PRG-ROM bank register mmc1_wr(0xE000, bank, 0); //write bank to PRG-ROM bank register //TODO SXROM/SUROM require writting PRG-ROM MSb of address to CHR registers } if (buff->mapper == UxROM) { //addrH &= 0b1011 1111 A14 must always be low addrH &= 0xBF; //write bank value to bank table //page_num shift by 6 bits A14 >> A8(0) bank = (buff->page_num)>>6; //Nomolos bank table @ CC84 //nes_cpu_wr( (0xCC84+bank), bank ); //Owlia bank table @ CC84 //nes_cpu_wr( (0xE473+bank), bank ); //Rushnattack //nes_cpu_wr( (0x8000+bank), bank ); //twindragons //nes_cpu_wr( (0xC000+bank), bank ); //h1 //nes_cpu_wr( (0xFFC0+bank), bank ); //AFB nes_cpu_wr( (0xFD69+bank), bank ); buff->cur_byte = nes_cpu_page_rd_poll( buff->data, addrH, buff->id, //id contains MSb of page when <256B buffer buff->last_idx, ~FALSE ); break; } //if (buff->mapper == MMC3) { // THIS IS HANDLED from the host side using NESCPU_4KB //} if (buff->mapper == MAP30) { //addrH &= 0b1011 1111 A14 must always be low addrH &= 0xBF; //write bank value to bank table //page_num shift by 6 bits A14 >> A8(0) bank = (buff->page_num)>>6; //mapper register $C000-FFFF nes_cpu_wr( 0xC000, bank ); buff->cur_byte = nes_cpu_page_rd_poll( buff->data, addrH, buff->id, //id contains MSb of page when <256B buffer buff->last_idx, ~FALSE ); break; } //if ((buff->mapper == BxROM) || (buff->mapper == CDREAM)) { // //write bank value to bank table // //page_num shift by 7 bits A15 >> A8(0) // bank = (buff->page_num)>>7; // //Lizard bank table @ FF94 // nes_cpu_wr( (0xFF94+bank), bank ); // //HH85 // //nes_cpu_wr( (0xFFE0+bank), bank ); // //Mojon bank table @ FF94 // //nes_cpu_wr( 0x800C, 0x00); //select first bank (only one with table) // //nes_cpu_wr( (0xCC43+bank), bank ); //then select desired bank //} if (buff->mapper == A53) { //write bank value to bank table //page_num shift by 7 bits A15 >> A8(0) bank = (buff->page_num)>>7; //Setup as CNROM, then scroll through outer banks. //cpu_wr(0x5000, 0x80); //reg select mode // xxSSPPMM SS-size: 0-32KB, PP-prg mode: 0,1 32KB, MM-mirror //cpu_wr(0x8000, 0b00000000); //reg value 256KB inner, 32KB banks nes_cpu_wr(0x5000, 0x81); //outer reg select mode nes_cpu_wr(0x8000, bank); //outer bank nes_cpu_wr(0x5000, 0x00); //chr reg select act like CNROM } if (buff->mapper == EZNSF) { //addrH &= 0b1000 1111 A14-12 must always be low addrH &= 0x8F; //write bank value to bank table //page_num shift by 4 bits A12 >> A8(0) bank = (buff->page_num)>>4; nes_cpu_wr(0x5000, bank); //bank @ $8000-8FFF } buff->cur_byte = nes_cpu_page_rd_poll( buff->data, addrH, buff->id, //id contains MSb of page when <256B buffer buff->last_idx, ~FALSE ); break; case CHRROM: //$0000 //if (buff->mapper == NROM) { // buff->cur_byte = nes_ppu_page_rd_poll( buff->data, addrH, buff->id, // buff->last_idx, ~FALSE ); //} //if (buff->mapper == MMC3) { // THIS IS HANDLED from the host side using NESPPU_4KB //} //if (buff->mapper == CNROM) { // //select bank // //8KB banks $0000-1FFF // //page_num shift by 5 bits A13 >> A8(0) // bank = (buff->page_num)>>5; // //write bank to register // //TODO account for bus conflicts // nes_cpu_wr(0x8000, bank); // // addrH &= 0x1F; //only A12-8 are directly addressable // buff->cur_byte = nes_ppu_page_rd_poll( buff->data, addrH, buff->id, // buff->last_idx, ~FALSE ); //} //if (buff->mapper == CDREAM) { // //select bank // //8KB banks $0000-1FFF // //page_num shift by 5 bits A13 >> A8(0) // bank = (buff->page_num)>>5; // //write bank to register // //TODO account for bus conflicts // nes_cpu_wr(0xFFFF, bank<<4); // // addrH &= 0x1F; //only A12-8 are directly addressable // buff->cur_byte = nes_ppu_page_rd_poll( buff->data, addrH, buff->id, // buff->last_idx, ~FALSE ); //} if (buff->mapper == DPROM) { //select bank //8KB banks $0000-1FFF //page_num shift by 5 bits A13 >> A8(0) bank = (buff->page_num)>>5; //write bank to register nes_ppu_wr(0x3FFF, bank); addrH &= 0x1F; //only A12-8 are directly addressable buff->cur_byte = nes_dualport_page_rd_poll( buff->data, addrH, buff->id, buff->last_idx, ~FALSE ); } if (buff->mapper == MMC1) { //write bank value to bank table //page_num shift by 4 bits A12 >> A8(0) bank = (buff->page_num)>>4; bank &= 0x1F; //only 5 bits in CHR regs //LSb doesn't matter in 32KB mode mmc1_wr(0x8000, 0x10, 1); //set to 4KB bank mode mmc1_wr(0xA000, bank, 0); //write bank to CHR-ROM bank register //TODO SXROM/SUROM require writting PRG-ROM MSb of address to CHR registers addrH &= 0x0F; //only A11-8 are directly addressable buff->cur_byte = nes_ppu_page_rd_poll( buff->data, addrH, buff->id, buff->last_idx, ~FALSE ); } break; case PRGRAM: addrH |= 0x60; //$6000 buff->cur_byte = nes_cpu_page_rd_poll( buff->data, addrH, buff->id, buff->last_idx, ~FALSE ); break; case SNESROM: if (buff->mapper == LOROM) { addrH |= 0x80; //$8000 LOROM space //need to split page_num //A14-8 page_num[6-0] //A15 high (LOROM) //A23-16 page_num[14-7] bank = (buff->page_num)>>7; } if (buff->mapper == HIROM) { //need to split page_num //A15-8 page_num[7-0] //A21-16 page_num[13-8] //A22 high (HIROM) //A23 ~page_num[14] (bank CO starts first half, bank 40 starts second) bank = ((((buff->page_num)>>8) | 0x40) & 0x7F); } HADDR_SET( bank ); buff->cur_byte = snes_rom_page_rd_poll( buff->data, addrH, buff->id, //id contains MSb of page when <256B buffer buff->last_idx, ~FALSE ); case SNESRAM: //warn addrX = ((buff->page_num)>>8); break; default: return ERR_BUFF_UNSUP_MEM_TYPE; } return SUCCESS; }