311 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			311 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #ifdef _NES_MAPPER_CPP_
 | |
| 
 | |
| /////////////////////////////////////////////////////////////////////
 | |
| // Mapper 20
 | |
| void NES_mapper20::Reset()
 | |
| {
 | |
|   // Init ExSound
 | |
|   parent_NES->apu->SelectExSound(4);
 | |
| 
 | |
|   FILE* fp = NULL;
 | |
|   char fn[256];
 | |
| 
 | |
|   GetModuleFileName(NULL, fn, 256);
 | |
|   int pt = strlen(fn);
 | |
|   while(fn[pt] != '\\') pt--;
 | |
|   fn[pt+1] = '\0';
 | |
|   strcat(fn, "DISKSYS.ROM");
 | |
| 
 | |
|   if((fp = fopen(fn, "rb")) != NULL)
 | |
|   {
 | |
|     uint8 head1 = fgetc(fp);
 | |
|     uint8 head2 = fgetc(fp);
 | |
|     uint8 head3 = fgetc(fp);
 | |
|     if(head1 == 'N' && head2 == 'E' && head3 == 'S')
 | |
|     {
 | |
|       fseek(fp, 0x6010, SEEK_SET);
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|       fseek(fp, 0, SEEK_SET);
 | |
|     }
 | |
|     for(uint32 i = 0; i < 0x2000; i++)
 | |
|     {
 | |
|       bios[i] = fgetc(fp);
 | |
|     }
 | |
|     fclose(fp);
 | |
|   }
 | |
|   else
 | |
|   {
 | |
|     throw "DISKSYS.ROM not found.";
 | |
|   }
 | |
| 
 | |
|   // cancel license screen
 | |
|   //bios[0xfb0] = 0x00;
 | |
| 
 | |
|   NES_6502::Context context;
 | |
|   parent_NES->cpu->GetContext(&context);
 | |
|   context.mem_page[3] = wram + 0x0000;
 | |
|   context.mem_page[4] = wram + 0x2000;
 | |
|   context.mem_page[5] = wram + 0x4000;
 | |
|   context.mem_page[6] = wram + 0x6000;
 | |
|   context.mem_page[7] = bios;
 | |
|   parent_NES->cpu->SetContext(&context);
 | |
| 
 | |
|   // read FDS disk image
 | |
|   if(ROM_banks[0] == 'F' && ROM_banks[1] == 'D' && ROM_banks[2] == 'S')
 | |
|   {
 | |
|     for(uint32 i = 0; i < ROM_banks[4]; i++)
 | |
|     {
 | |
|       for(uint32 j = 0; j < 65500; j++)
 | |
|       {
 | |
|         disk[0x10000*i+j] = ROM_banks[16+65500*i+j];
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   else
 | |
|   {
 | |
|     throw "Invalid DISK image.";
 | |
|   }
 | |
| 
 | |
|   if(parent_NES->fds_id() == 0xc7525744) // Reflect World
 | |
|   {
 | |
|     parent_NES->frame_irq_disenabled = 1;
 | |
|   }
 | |
| 
 | |
|   irq_enabled = 0;
 | |
|   irq_counter = 0;
 | |
|   irq_latch = 0;
 | |
|   irq_wait = 0;
 | |
| 
 | |
|   access_flag = 0;
 | |
|   disk_enabled = 1;
 | |
|   head_position = 0;
 | |
|   write_skip = 0;
 | |
|   disk_status = 0;
 | |
|   write_reg = 0;
 | |
|   current_side = 1;
 | |
|   last_side = 1;
 | |
|   insert_wait = 180;
 | |
| }
 | |
| 
 | |
| uint8 NES_mapper20::MemoryReadLow(uint32 addr)
 | |
| {
 | |
|   uint8 val = 0x00;
 | |
| 
 | |
|   switch (addr)
 | |
|   {
 | |
|     case 0x4030:
 | |
|       {
 | |
|         val = disk_status;
 | |
|       }
 | |
|       break;
 | |
| 
 | |
|     case 0x4031:
 | |
|       {
 | |
|         if((current_side != 0) && (current_side == last_side))
 | |
|         {
 | |
|           val = disk[(current_side-1)*0x10000+head_position];
 | |
|           if(write_reg & 0x01)
 | |
|           {
 | |
|             head_position += (head_position < 64999) ? 1 : 0;
 | |
|             irq_wait = 2;
 | |
|           }
 | |
|           access_flag = 1;
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|           val = 0xff;
 | |
|         }
 | |
|       }
 | |
|       break;
 | |
| 
 | |
|     case 0x4032:
 | |
|       {
 | |
|         uint8 eject = ((current_side != 0) && (current_side == last_side)) ? 0 : 1;
 | |
|         val = 0x40;
 | |
|         val |= eject ? 1 : 0;
 | |
|         val |= eject ? 4 : 0;
 | |
|         val |= (!eject && (write_reg & 0x01) && !(write_reg & 0x02)) ? 0 : 2;
 | |
| 
 | |
|         if(last_side != current_side)
 | |
|         {
 | |
|           // wait 2.0 sec for change disk
 | |
|           if(insert_wait > 120)
 | |
|           {
 | |
|             last_side = current_side;
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|       break;
 | |
| 
 | |
|     case 0x4033:
 | |
|       {
 | |
|         val = 0x80;
 | |
|       }
 | |
|       break;
 | |
| 
 | |
|     default:
 | |
|       {
 | |
|         val = parent_NES->apu->ExRead(addr);
 | |
|       }
 | |
|       break;
 | |
|   }
 | |
| 
 | |
|   return val;
 | |
| }
 | |
| 
 | |
| void NES_mapper20::MemoryWriteLow(uint32 addr, uint8 data)
 | |
| {
 | |
|   switch (addr)
 | |
|   {
 | |
|     case 0x4020:
 | |
|       {
 | |
|         irq_latch = (irq_latch & 0xFF00) | data;
 | |
|       }
 | |
|       break;
 | |
| 
 | |
|     case 0x4021:
 | |
|       {
 | |
|         irq_latch = (irq_latch & 0x00FF) | ((uint32)data << 8);
 | |
|       }
 | |
|       break;
 | |
| 
 | |
|     case 0x4022:
 | |
|       {
 | |
|         irq_counter = irq_latch;
 | |
|         irq_enabled = data & 0x03;
 | |
|       }
 | |
|       break;
 | |
| 
 | |
|     case 0x4023:
 | |
|       {
 | |
|         disk_enabled = data & 0x01;
 | |
|       }
 | |
|       break;
 | |
| 
 | |
|     case 0x4024:
 | |
|       {
 | |
|         if((current_side != 0) && (current_side == last_side))
 | |
|         {
 | |
|           if(disk_enabled && !(write_reg & 0x04) && head_position < 65000)
 | |
|           {
 | |
|             if(write_skip)
 | |
|             {
 | |
|               write_skip--;
 | |
|             }
 | |
|             else if(head_position >= 2)
 | |
|             {
 | |
|               disk[(current_side-1)*0x10000+head_position-2] = data;
 | |
|               access_flag = 1;
 | |
|             }
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|       break;
 | |
| 
 | |
|     case 0x4025:
 | |
|       {
 | |
|         if(data & 0x08)
 | |
|         {
 | |
|           set_mirroring(NES_PPU::MIRROR_HORIZ);
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|           set_mirroring(NES_PPU::MIRROR_VERT);
 | |
|         }
 | |
|         if((current_side != 0) && (current_side == last_side))
 | |
|         {
 | |
|           if((write_reg & 0x40) && !(data & 0x10) && !(data & 0x40))
 | |
|           {
 | |
|             head_position = (head_position < 2) ? 0 : head_position - 2;
 | |
|           }
 | |
|           if(!(data & 0x04))
 | |
|           {
 | |
|             write_skip = 2;
 | |
|           }
 | |
|           if(data & 0x02)
 | |
|           {
 | |
|             head_position = 0;
 | |
|             irq_wait = 2;
 | |
|           }
 | |
|           if(data & 0x80)
 | |
|           {
 | |
|             irq_wait = 2;
 | |
|           }
 | |
|         }
 | |
|         write_reg = data;
 | |
|       }
 | |
|       break;
 | |
| 
 | |
|     default:
 | |
|       {
 | |
|         parent_NES->apu->ExWrite(addr, data);
 | |
|       }
 | |
|       break;
 | |
|   }
 | |
| }
 | |
| 
 | |
| void NES_mapper20::MemoryWriteSaveRAM(uint32 addr, uint8 data)
 | |
| {
 | |
|   wram[addr - 0x6000] = data;
 | |
| }
 | |
| 
 | |
| void NES_mapper20::MemoryWrite(uint32 addr, uint8 data)
 | |
| {
 | |
|   if(addr < 0xE000)
 | |
|   {
 | |
|     wram[addr - 0x6000] = data;
 | |
|   }
 | |
| }
 | |
| 
 | |
| void NES_mapper20::HSync(uint32 scanline)
 | |
| {
 | |
|   disk_status &= 0xfc;
 | |
| 
 | |
|   if(irq_enabled)
 | |
|   {
 | |
|     if(irq_counter < 113)
 | |
|     {
 | |
|       irq_enabled &= 0x01;
 | |
|       irq_counter = irq_latch;
 | |
|       disk_status |= 0x01;
 | |
|       parent_NES->cpu->DoIRQ();
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|       irq_counter -= 113;
 | |
|     }
 | |
|   }
 | |
|   else if(irq_wait)
 | |
|   {
 | |
|     irq_wait--;
 | |
|     if(!irq_wait && (write_reg & 0x80))
 | |
|     {
 | |
|       disk_status |= 0x02;
 | |
|       parent_NES->cpu->DoIRQ();
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| void NES_mapper20::VSync()
 | |
| {
 | |
|   // count MAX 3sec
 | |
|   insert_wait += (insert_wait < 180) ? 1 : 0;
 | |
| }
 | |
| 
 | |
| void NES_mapper20::SNSS_fixup()
 | |
| {
 | |
|   NES_6502::Context context;
 | |
|   parent_NES->cpu->GetContext(&context);
 | |
|   context.mem_page[3] = wram + 0x0000;
 | |
|   context.mem_page[4] = wram + 0x2000;
 | |
|   context.mem_page[5] = wram + 0x4000;
 | |
|   context.mem_page[6] = wram + 0x6000;
 | |
|   context.mem_page[7] = bios;
 | |
|   parent_NES->cpu->SetContext(&context);
 | |
| }
 | |
| /////////////////////////////////////////////////////////////////////
 | |
| 
 | |
| #endif
 |