/* Dreamcast 'area 0' emulation Pretty much all peripheral registers are mapped here Routing is mostly handled here, as well as flash/SRAM emulation */ #include "types.h" #include "sh4_mem.h" #include "sb.h" #include "dc/pvr/pvr_if.h" #include "dc/gdrom/gdrom_if.h" #include "dc/aica/aica_if.h" #include "naomi/naomi.h" #include "plugins/plugin_manager.h" u32 patchRB=0; void PatchRandB(u8* addr,int sz) { if (settings.dreamcast.region==0) { u8* address=addr; u8* patchaddr=&address[0x1A002^3]; memcpy(patchaddr,"0",1); patchaddr=&address[0x1A0A2^3]; memcpy(patchaddr,"0",1); } else if (settings.dreamcast.region==1) { u8* address=addr; u8* patchaddr=&address[0x1A002^3]; memcpy(patchaddr,"1",1); patchaddr=&address[0x1A0A2^3]; memcpy(patchaddr,"1",1); } else if (settings.dreamcast.region==2) { u8* address=addr; u8* patchaddr=&address[0x1A002^3]; memcpy(patchaddr,"2",1); patchaddr=&address[0x1A0A2^3]; memcpy(patchaddr,"2",1); } if (settings.dreamcast.broadcast==0) { u8* address=addr; u8* patchaddr=&address[0x1A004^3]; memcpy(patchaddr,"0",1); patchaddr=&address[0x1A0A4^3]; memcpy(patchaddr,"0",1); } else if (settings.dreamcast.broadcast==1) { u8* address=addr; u8* patchaddr=&address[0x1A004^3]; memcpy(patchaddr,"1",1); patchaddr=&address[0x1A0A4^3]; memcpy(patchaddr,"1",1); } else if (settings.dreamcast.broadcast==2) { u8* address=addr; u8* patchaddr=&address[0x1A004^3]; memcpy(patchaddr,"2",1); patchaddr=&address[0x1A0A4^3]; memcpy(patchaddr,"2",1); } else if (settings.dreamcast.broadcast==3) { u8* address=addr; u8* patchaddr=&address[0x1A004^3]; memcpy(patchaddr,"3",1); patchaddr=&address[0x1A0A4^3]; memcpy(patchaddr,"3",1); } } struct MemChip { u8* data; u32 size; u32 mask; MemChip(u32 size) { this->data=new u8[size]; this->size=size; this->mask=size-1;//must be power of 2 } ~MemChip() { delete[] data; } u32 Read(u32 addr,u32 sz) { if ((size==0x20000) & (patchRB==0) & (DC_PLATFORM==DC_PLATFORM_NORMAL)) { PatchRandB(data,sz); patchRB=1; } addr&=mask; switch (sz) { case 1: return data[addr^3]; case 2: return *(u16*)&data[addr^2]; case 4: return *(u32*)&data[addr]; } die("invalid access size"); return 0; } bool Load(char* file) { FILE* f=fopen(file,"rb"); if (f) { bool rv=fread(data,1,size,f)==size; fclose(f); u32 i; u32 * d=(u32 *)data; for(i=0;i especialy when we can use templates :p template T __fastcall ReadMem_area0(u32 addr) { addr &= 0x01FFFFFF;//to get rid of non needed bits const u32 base_start=b_start & 0x01FF; const u32 base_end=b_end & 0x01FF; //map 0x0000 to 0x01FF to Default handler //mirror 0x0200 to 0x03FF , from 0x0000 to 0x03FFF //map 0x0000 to 0x001F if ((base_start<=0x001F))// :MPX System/Boot ROM { return ReadBios(addr,sz); } //map 0x0020 to 0x0021 else if ((base_start>= 0x0020) && (base_end<= 0x0021)) // :Flash Memory { return ReadFlash(addr&0x1FFFF,sz); } //map 0x005F to 0x005F else if ((base_start >=0x005F) && (base_end <=0x005F) /*&& (addr>= 0x00400000)*/ && (addr<= 0x005F67FF)) // :Unassigned { EMUERROR2("Read from area0_32 not implemented [Unassigned], addr=%x",addr); } else if ((base_start >=0x005F) && (base_end <=0x005F) && (addr>= 0x005F7000) && (addr<= 0x005F70FF)) // :GD-ROM { //EMUERROR3("Read from area0_32 not implemented [GD-ROM], addr=%x,size=%d",addr,sz); #if defined(BUILD_NAOMI ) || defined(BUILD_ATOMISWAVE) u32 data = ReadMem_naomi(addr,sz); #else u32 data = ReadMem_gdrom(addr,sz); #endif return (T) data; } else if ((base_start >=0x005F) && (base_end <=0x005F) && (addr>= 0x005F6800) && (addr<=0x005F7CFF)) // /*:PVR i/f Control Reg.*/ -> ALL SB registers now { //EMUERROR2("Read from area0_32 not implemented [PVR i/f Control Reg], addr=%x",addr); u32 data = sb_ReadMem(addr,sz); return (T) data; } else if ((base_start >=0x005F) && (base_end <=0x005F) && (addr>= 0x005F8000) && (addr<=0x005F9FFF)) // :TA / PVR Core Reg. { //EMUERROR2("Read from area0_32 not implemented [TA / PVR Core Reg], addr=%x",addr); u32 data = pvr_readreg_TA(addr,sz); return (T) data; } //map 0x0060 to 0x0060 else if ((base_start >=0x0060) && (base_end <=0x0060) /*&& (addr>= 0x00600000)*/ && (addr<= 0x006007FF)) // :MODEM { return (T)libExtDevice.ReadMem_A0_006(addr,sz); //EMUERROR2("Read from area0_32 not implemented [MODEM], addr=%x",addr); } //map 0x0060 to 0x006F else if ((base_start >=0x0060) && (base_end <=0x006F) && (addr>= 0x00600800) && (addr<= 0x006FFFFF)) // :G2 (Reserved) { EMUERROR2("Read from area0_32 not implemented [G2 (Reserved)], addr=%x",addr); } //map 0x0070 to 0x0070 else if ((base_start >=0x0070) && (base_end <=0x0070) /*&& (addr>= 0x00700000)*/ && (addr<=0x00707FFF)) // :AICA- Sound Cntr. Reg. { //EMUERROR2("Read from area0_32 not implemented [AICA- Sound Cntr. Reg], addr=%x",addr); u32 data = ReadMem_aica_reg(addr,sz);//libAICA.ReadMem_aica_reg(addr,sz); return (T) data; } //map 0x0071 to 0x0071 else if ((base_start >=0x0071) && (base_end <=0x0071) /*&& (addr>= 0x00710000)*/ && (addr<= 0x0071000B)) // :AICA- RTC Cntr. Reg. { //EMUERROR2("Read from area0_32 not implemented [AICA- RTC Cntr. Reg], addr=%x",addr); u32 data = ReadMem_aica_rtc(addr,sz); return (T) data; } //map 0x0080 to 0x00FF else if ((base_start >=0x0080) && (base_end <=0x00FF) /*&& (addr>= 0x00800000) && (addr<=0x00FFFFFF)*/) // :AICA- Wave Memory { EMUERROR2("Read from area0_32 not implemented [AICA- Wave Memory], addr=%x",addr); //return (T)libAICA.ReadMem_aica_ram(addr,sz); } //map 0x0100 to 0x01FF else if ((base_start >=0x0100) && (base_end <=0x01FF) /*&& (addr>= 0x01000000) && (addr<= 0x01FFFFFF)*/) // :Ext. Device { // EMUERROR2("Read from area0_32 not implemented [Ext. Device], addr=%x",addr); return (T)libExtDevice.ReadMem_A0_010(addr,sz); } //rest of it ;P /*else { EMUERROR2("Read from area0_32 not mapped!!! , addr=%x",addr); }*/ return 0; } #include u64 time_gdrom=0; template void __fastcall WriteMem_area0(u32 addr,T data) { addr &= 0x01FFFFFF;//to get rid of non needed bits // printf("WriteMem_area0 %08x %08x %d\n",addr,data,sz); const u32 base_start=b_start & 0x01FF; const u32 base_end=b_end & 0x01FF; //map 0x0000 to 0x001F if ((base_start >=0x0000) && (base_end <=0x001F) /*&& (addr<=0x001FFFFF)*/)// :MPX System/Boot ROM { //EMUERROR4("Write to [MPX System/Boot ROM] is not possible, addr=%x,data=%x,size=%d",addr,data,sz); WriteBios(addr,data,sz); } //map 0x0020 to 0x0021 else if ((base_start >=0x0020) && (base_end <=0x0021) /*&& (addr>= 0x00200000) && (addr<= 0x0021FFFF)*/) // :Flash Memory { //EMUERROR4("Write to [Flash Memory] , sz?!, addr=%x,data=%x,size=%d",addr,data,sz); WriteFlash(addr,data,sz); } //map 0x0040 to 0x005F -> actualy , i'l olny map 0x005F to 0x005F , b/c the rest of it is unpammed (left to defalt handler) //map 0x005F to 0x005F else if ((base_start >=0x005F) && (base_end <=0x005F) /*&& (addr>= 0x00400000) */&& (addr<= 0x005F67FF)) // :Unassigned { EMUERROR4("Write to area0_32 not implemented [Unassigned], addr=%x,data=%x,size=%d",addr,data,sz); } else if ((base_start >=0x005F) && (base_end <=0x005F) && (addr>= 0x005F7000) && (addr<= 0x005F70FF)) // :GD-ROM { //EMUERROR4("Write to area0_32 not implemented [GD-ROM], addr=%x,data=%x,size=%d",addr,data,sz); u64 gdr=mftb(); #if defined(BUILD_NAOMI ) || defined(BUILD_ATOMISWAVE) WriteMem_naomi(addr,data,sz); #else WriteMem_gdrom(addr,data,sz); #endif gdr=mftb()-gdr; time_gdrom+=gdr; } else if ((base_start >=0x005F) && (base_end <=0x005F) && (addr>= 0x005F6800) && (addr<=0x005F7CFF)) // /*:PVR i/f Control Reg.*/ -> ALL SB registers { //EMUERROR4("Write to area0_32 not implemented [PVR i/f Control Reg], addr=%x,data=%x,size=%d",addr,data,sz); sb_WriteMem(addr,data,sz); } else if ((base_start >=0x005F) && (base_end <=0x005F) && (addr>= 0x005F8000) && (addr<=0x005F9FFF)) // :TA / PVR Core Reg. { //EMUERROR4("Write to area0_32 not implemented [TA / PVR Core Reg], addr=%x,data=%x,size=%d",addr,data,sz); pvr_writereg_TA(addr,data,sz); return; } //map 0x0060 to 0x0060 else if ((base_start >=0x0060) && (base_end <=0x0060) /*&& (addr>= 0x00600000)*/ && (addr<= 0x006007FF)) // :MODEM { //EMUERROR4("Write to area0_32 not implemented [MODEM], addr=%x,data=%x,size=%d",addr,data,sz); libExtDevice.WriteMem_A0_006(addr,data,sz); } //map 0x0060 to 0x006F else if ((base_start >=0x0060) && (base_end <=0x006F) && (addr>= 0x00600800) && (addr<= 0x006FFFFF)) // :G2 (Reserved) { EMUERROR4("Write to area0_32 not implemented [G2 (Reserved)], addr=%x,data=%x,size=%d",addr,data,sz); } //map 0x0070 to 0x0070 else if ((base_start >=0x0070) && (base_end <=0x0070) /*&& (addr>= 0x00700000)*/ && (addr<=0x00707FFF)) // :AICA- Sound Cntr. Reg. { //EMUERROR4("Write to area0_32 not implemented [AICA- Sound Cntr. Reg], addr=%x,data=%x,size=%d",addr,data,sz); //aica_writereg(addr,data,sz); //libAICA.WriteMem_aica_reg(addr,data,sz); WriteMem_aica_reg(addr,data,sz); return; } //map 0x0071 to 0x0071 else if ((base_start >=0x0071) && (base_end <=0x0071) /*&& (addr>= 0x00710000)*/ && (addr<= 0x0071000B)) // :AICA- RTC Cntr. Reg. { //EMUERROR4("Write to area0_32 not implemented [AICA- RTC Cntr. Reg], addr=%x,data=%x,size=%d",addr,data,sz); WriteMem_aica_rtc(addr,data,sz); return; } //map 0x0080 to 0x00FF else if ((base_start >=0x0080) && (base_end <=0x00FF) /*&& (addr>= 0x00800000) && (addr<=0x00FFFFFF)*/) // :AICA- Wave Memory { EMUERROR4("Write to area0_32 not implemented [AICA- Wave Memory], addr=%x,data=%x,size=%d",addr,data,sz); //aica_writeram(addr,data,sz); //libAICA.WriteMem_aica_ram(addr,data,sz); return; } //map 0x0100 to 0x01FF else if ((base_start >=0x0100) && (base_end <=0x01FF) /*&& (addr>= 0x01000000) && (addr<= 0x01FFFFFF)*/) // :Ext. Device { //EMUERROR4("Write to area0_32 not implemented [Ext. Device], addr=%x,data=%x,size=%d",addr,data,sz); libExtDevice.WriteMem_A0_010(addr,data,sz); } /*else { EMUERROR4("Write to area0_32 not mapped!!! , addr=%x,data=%x,size=%d",addr,data,sz); }*/ return; } //Init/Res/Term void sh4_area0_Init() { sb_Init(); } void sh4_area0_Reset(bool Manual) { sb_Reset(Manual); } void sh4_area0_Term() { sb_Term(); } //AREA 0 _vmem_handler area0_handler_00_1F; _vmem_handler area0_handler_20_21; _vmem_handler area0_handler_5F_5F; _vmem_handler area0_handler_60_60; _vmem_handler area0_handler_61_6F; _vmem_handler area0_handler_70_70; _vmem_handler area0_handler_71_71; //_vmem_handler area0_handler_80_FF; _vmem_handler area0_handler_100_1FF; //Different mem mapping regions for area0 //0x0000-0x001f //0x0020-0x0021 //0x005F-0x005F //0x0060-0x0060 //0x0061-0x006F //0x0070-0x0070 //0x0071-0x0071 //0x0080-0x00FF //0x0100-0x01FF //Count : 9 void map_area0_init() { //area0_handler = _vmem_register_handler(ReadMem8_area0,ReadMem16_area0,ReadMem32_area0, // WriteMem8_area0,WriteMem16_area0,WriteMem32_area0); area0_handler_00_1F = _vmem_register_handler_Template2(ReadMem_area0,WriteMem_area0,0x0000,0x001F); area0_handler_20_21 = _vmem_register_handler_Template2(ReadMem_area0,WriteMem_area0,0x0020,0x0021); area0_handler_5F_5F = _vmem_register_handler_Template2(ReadMem_area0,WriteMem_area0,0x005F,0x005F); area0_handler_60_60 = _vmem_register_handler_Template2(ReadMem_area0,WriteMem_area0,0x0060,0x0060); area0_handler_61_6F = _vmem_register_handler_Template2(ReadMem_area0,WriteMem_area0,0x0061,0x006F); area0_handler_70_70 = _vmem_register_handler_Template2(ReadMem_area0,WriteMem_area0,0x0070,0x0070); area0_handler_71_71 = _vmem_register_handler_Template2(ReadMem_area0,WriteMem_area0,0x0071,0x0071); //area0_handler_80_FF = _vmem_register_handler_Template2(ReadMem_area0,WriteMem_area0,0x0080,0x00FF); area0_handler_100_1FF = _vmem_register_handler_Template2(ReadMem_area0,WriteMem_area0,0x0100,0x01FF); } void map_area0(u32 base) { verify(base<0xE000); //Map 0x0000 to 0x01FF //u32 start=0x0000 | base; //u32 end =start+0x01FF; //_vmem_map_handler(area0_handler,start,end); //0x0000-0x001f _vmem_map_handler(area0_handler_00_1F,0x0000|base,0x001F|base); //0x0020-0x0021 _vmem_map_handler(area0_handler_20_21,0x0020|base,0x0021|base); //0x005F-0x005F _vmem_map_handler(area0_handler_5F_5F,0x005F|base,0x005F|base); //0x0060-0x0060 _vmem_map_handler(area0_handler_60_60,0x0060|base,0x0060|base); //0x0061-0x006F _vmem_map_handler(area0_handler_61_6F,0x0061|base,0x006F|base); //0x0070-0x0070 _vmem_map_handler(area0_handler_70_70,0x0070|base,0x0070|base); //0x0071-0x0071 _vmem_map_handler(area0_handler_71_71,0x0071|base,0x0071|base); //0x0080-0x00FF //_vmem_map_handler(area0_handler_80_FF,0x0080|base,0x00FF|base); _vmem_map_block_mirror(aica_ram.data,0x0080|base,0x00FF|base,ARAM_SIZE); //0x0100-0x01FF _vmem_map_handler(area0_handler_100_1FF,0x0100|base,0x01FF|base); //0x0240 to 0x03FF mirrors 0x0040 to 0x01FF (no flashrom or bios) //0x0200 to 0x023F are unused _vmem_mirror_mapping(0x0240|base,0x0040|base,0x0200-0x40); }