Merge pull request #732 from reicast/wip/naomi-support

Naomi support. Enjoy.

To build, edit core/build.h to DC_PLATFORM_NAOMI (or, -D TARGET_NAOMI at the makefile level)
This commit is contained in:
Stefanos Kornilios Mitsis Poiitidis 2015-08-11 19:21:00 +02:00
commit 417dfc5d8f
30 changed files with 1782 additions and 76 deletions

View File

@ -118,16 +118,13 @@
#define NO_MMU
#define DC_PLATFORM_MASK 7
#define DC_PLATFORM_NORMAL 0 /* Works, for the most part */
#define DC_PLATFORM_DREAMCAST 0 /* Works, for the most part */
#define DC_PLATFORM_DEV_UNIT 1 /* This is missing hardware */
#define DC_PLATFORM_NAOMI 2 /* Works, for the most part */
#define DC_PLATFORM_NAOMI2 3 /* Needs to be done, 2xsh4 + 2xpvr + custom TNL */
#define DC_PLATFORM_ATOMISWAVE 4 /* Needs to be done, DC-like hardware with possibly more ram */
#define DC_PLATFORM_HIKARU 5 /* Needs to be done, 2xsh4, 2x aica , custom vpu */
#define DC_PLATFORM_AURORA 6 /* Needs to be done, Uses newer 300 mhz sh4 + 150 mhz pvr mbx SoC */
#define DC_PLATFORM DC_PLATFORM_NORMAL
//HOST_OS
@ -206,6 +203,11 @@
#error Invalid Target: TARGET_* not defined
#endif
#if defined(TARGET_NAOMI)
#define DC_PLATFORM DC_PLATFORM_NAOMI
#undef TARGET_NAOMI
#endif
#if defined(TARGET_NO_REC)
#define FEAT_SHREC DYNAREC_NONE
#define FEAT_AREC DYNAREC_NONE
@ -234,6 +236,11 @@
#endif
//defaults
#ifndef DC_PLATFORM
#define DC_PLATFORM DC_PLATFORM_DREAMCAST
#endif
#ifndef FEAT_SHREC
#define FEAT_SHREC DYNAREC_JIT
#endif

View File

@ -8,8 +8,8 @@ RZDCY_SRC_DIR ?= $(call my-dir)
RZDCY_MODULES := cfg/ hw/arm7/ hw/aica/ hw/holly/ hw/ hw/gdrom/ hw/maple/ \
hw/mem/ hw/pvr/ hw/sh4/ hw/sh4/interpr/ hw/sh4/modules/ plugins/ profiler/ oslib/ \
hw/extdev/ hw/arm/ imgread/ linux/ ./ deps/coreio/ deps/zlib/ deps/chdr/ deps/crypto/ \
deps/libelf/ deps/chdpsr/ arm_emitter/ rend/ reios/ deps/libpng/
hw/extdev/ hw/arm/ hw/naomi/ imgread/ linux/ ./ deps/coreio/ deps/zlib/ deps/chdr/ deps/crypto/ \
deps/libelf/ deps/chdpsr/ arm_emitter/ rend/ reios/ deps/libpng/
ifdef WEBUI

View File

@ -2114,8 +2114,9 @@ s32 ARM::imma;
void armEmit32(u32 emit32)
{
if (icPtr >= (ICache+ICacheSize-1024))
if (icPtr >= (ICache + ICacheSize - 64*1024)) {
die("ICache is full, invalidate old entries ..."); //ifdebug
}
x86e->Emit(op_mov32,ECX,emit32);
x86e->Emit(op_call,x86_ptr_imm(virt_arm_op));

View File

@ -172,7 +172,7 @@ struct DCFlashChip : MemChip // I think its Micronix :p
{
u32 rv=MemChip::Read8(addr);
#if DC_PLATFORM==DC_PLATFORM_NORMAL
#if DC_PLATFORM==DC_PLATFORM_DREAMCAST
if ((addr==0x1A002 || addr==0x1A0A2) && settings.dreamcast.region<=2)
return '0' + settings.dreamcast.region;
else if ((addr==0x1A004 || addr==0x1A0A4) && settings.dreamcast.broadcast<=3)

View File

@ -11,9 +11,7 @@
#include "hw/maple/maple_if.h"
#include "hw/aica/aica_if.h"
#if defined(BUILD_NAOMI) || defined(BUILD_ATOMISWAVE)
#include "../../naomi/naomi.h"
#endif
#include "hw/naomi/naomi.h"
Array<RegisterStruct> sb_regs(0x540);

View File

@ -12,7 +12,7 @@
#include "hw/pvr/pvr_mem.h"
#include "hw/gdrom/gdrom_if.h"
#include "hw/aica/aica_if.h"
//#include "naomi/naomi.h"
#include "hw/naomi/naomi.h"
#include "hw/flashrom/flashrom.h"
#include "reios/reios.h"
@ -63,7 +63,7 @@ bool LoadHle(const string& root) {
return reios_init(sys_rom.data, sys_nvmem.data);
}
#if (DC_PLATFORM == DC_PLATFORM_NORMAL) || (DC_PLATFORM == DC_PLATFORM_DEV_UNIT) || (DC_PLATFORM == DC_PLATFORM_NAOMI) || (DC_PLATFORM == DC_PLATFORM_NAOMI2)
#if (DC_PLATFORM == DC_PLATFORM_DREAMCAST) || (DC_PLATFORM == DC_PLATFORM_DEV_UNIT) || (DC_PLATFORM == DC_PLATFORM_NAOMI) || (DC_PLATFORM == DC_PLATFORM_NAOMI2)
u32 ReadBios(u32 addr,u32 sz) { return sys_rom.Read(addr,sz); }
void WriteBios(u32 addr,u32 data,u32 sz) { EMUERROR4("Write to [Boot ROM] is not possible, addr=%x,data=%x,size=%d",addr,data,sz); }
@ -151,7 +151,7 @@ T DYNACALL ReadMem_area0(u32 addr)
else if ((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)
#if DC_PLATFORM == DC_PLATFORM_NAOMI
return (T)ReadMem_naomi(addr,sz);
#else
return (T)ReadMem_gdrom(addr,sz);
@ -238,7 +238,7 @@ void DYNACALL WriteMem_area0(u32 addr,T data)
else if ((addr>= 0x005F7000) && (addr<= 0x005F70FF)) // GD-ROM
{
//EMUERROR4("Write to area0_32 not implemented [GD-ROM], addr=%x,data=%x,size=%d",addr,data,sz);
#if defined(BUILD_NAOMI ) || defined(BUILD_ATOMISWAVE)
#if DC_PLATFORM == DC_PLATFORM_NAOMI || DC_PLATFORM == DC_PLATFORM_ATOMISWAVE
WriteMem_naomi(addr,data,sz);
#else
WriteMem_gdrom(addr,data,sz);

View File

@ -66,25 +66,17 @@ void mcfg_Create(MapleDeviceType type,u32 bus,u32 port)
MapleDevices[bus][port]=dev;
}
#ifndef _ANDROID
void mcfg_CreateDevices()
{
#if DC_PLATFORM == DC_PLATFORM_DREAMCAST
mcfg_Create(MDT_SegaController,0,5);
#ifdef HAS_VMU
mcfg_Create(MDT_SegaVMU,0,0);
mcfg_Create(MDT_SegaVMU,0,1);
#endif
}
#else
void mcfg_CreateDevices()
{
mcfg_Create(MDT_SegaController,0,5);
mcfg_Create(MDT_SegaVMU,0,0);
mcfg_Create(MDT_SegaVMU,0,1);
}
mcfg_Create(MDT_NaomiJamma, 0, 5);
#endif
}
void mcfg_DestroyDevices()
{

View File

@ -25,8 +25,6 @@ const char* maple_sega_mic_name = "MicDevice for Dreameye";
const char* maple_sega_brand = "Produced By or Under License From SEGA ENTERPRISES,LTD.";
#define HAS_VMU
enum MapleFunctionID
{
MFID_0_Input = 0x01000000, //DC Controller, Lightgun buttons, arcade stick .. stuff like that
@ -243,7 +241,7 @@ struct maple_sega_controller: maple_base
Sega Dreamcast Visual Memory Unit
This is pretty much done (?)
*/
#ifdef HAS_VMU
u8 vmu_default[] = {
0x78,0x9c,0xed,0xd2,0x31,0x4e,0x02,0x61,0x10,0x06,0xd0,0x8f,0x04,0x28,0x4c,0x2c,
@ -572,8 +570,8 @@ struct maple_sega_vmu: maple_base
lgLcdBitmap160x43x1 bmp;
bmp.hdr.Format = LGLCD_BMP_FORMAT_160x43x1;
const BYTE white=0x00;
const BYTE black=0xFF;
const u8 white=0x00;
const u8 black=0xFF;
//make it all black...
memset(bmp.pixels,black,sizeof(bmp.pixels));
@ -581,11 +579,11 @@ struct maple_sega_vmu: maple_base
//decode from the VMU
for(int y=0;y<32;++y)
{
BYTE *dst=bmp.pixels+5816+((-y)*(48+112)); //ugly way to make things look right :p
BYTE *src=dev->lcd.data+6*y+5;
u8 *dst=bmp.pixels+5816+((-y)*(48+112)); //ugly way to make things look right :p
u8 *src=dev->lcd.data+6*y+5;
for(int x=0;x<48/8;++x)
{
BYTE val=*src;
u8 val=*src;
for(int m=0;m<8;++m)
{
if(val&(1<<(m)))
@ -664,7 +662,7 @@ struct maple_sega_vmu: maple_base
}
}
};
#endif
struct maple_microphone: maple_base
{
@ -846,6 +844,445 @@ struct maple_microphone: maple_base
}
};
char EEPROM[0x100];
bool EEPROM_loaded = false;
struct _NaomiState
{
u8 Cmd;
u8 Mode;
u8 Node;
};
_NaomiState State;
enum NAOMI_KEYS
{
NAOMI_SERVICE_KEY_1 = 1 << 0,
NAOMI_TEST_KEY_1 = 1 << 1,
NAOMI_SERVICE_KEY_2 = 1 << 2,
NAOMI_TEST_KEY_2 = 1 << 3,
NAOMI_START_KEY = 1 << 4,
NAOMI_UP_KEY = 1 << 5,
NAOMI_DOWN_KEY = 1 << 6,
NAOMI_LEFT_KEY = 1 << 7,
NAOMI_RIGHT_KEY = 1 << 8,
NAOMI_BTN0_KEY = 1 << 9,
NAOMI_BTN1_KEY = 1 << 10,
NAOMI_BTN2_KEY = 1 << 11,
NAOMI_BTN3_KEY = 1 << 12,
NAOMI_BTN4_KEY = 1 << 13,
NAOMI_BTN5_KEY = 1 << 14,
NAOMI_COIN_KEY = 1 << 15,
};
void printState(u32 cmd, u32* buffer_in, u32 buffer_in_len)
{
printf("Command : 0x%X", cmd);
if (buffer_in_len>0)
printf(",Data : %d bytes\n", buffer_in_len);
else
printf("\n");
buffer_in_len >>= 2;
while (buffer_in_len-->0)
{
printf("%08X ", *buffer_in++);
if (buffer_in_len == 0)
printf("\n");
}
}
/*
Sega Dreamcast Controller
No error checking of any kind, but works just fine
*/
struct maple_naomi_jamma : maple_sega_controller
{
virtual u32 dma(u32 cmd)
{
u32* buffer_in = (u32*)dma_buffer_in;
u32* buffer_out = (u32*)dma_buffer_out;
u8* buffer_in_b = dma_buffer_in;
u8* buffer_out_b = dma_buffer_out;
u32& buffer_out_len = *dma_count_out;
u32 buffer_in_len = dma_count_in;
switch (cmd)
{
case 0x86:
{
u32 subcode = *(u8*)buffer_in;
//printf("Naomi 0x86 : %x\n",SubCode);
switch (subcode)
{
case 0x15:
case 0x33:
{
PlainJoystickState pjs;
config->GetInput(&pjs);
buffer_out[0] = 0xffffffff;
buffer_out[1] = 0xffffffff;
u32 keycode = ~pjs.kcode;
u32 keycode2 = ~pjs.kcode;
if (keycode&NAOMI_SERVICE_KEY_2) //Service
buffer_out[0] &= ~(1 << 0x1b);
if (keycode&NAOMI_TEST_KEY_2) //Test
buffer_out[0] &= ~(1 << 0x1a);
if (State.Mode == 0 && subcode != 0x33) //Get Caps
{
buffer_out_b[0x11 + 1] = 0x8E; //Valid data check
buffer_out_b[0x11 + 2] = 0x01;
buffer_out_b[0x11 + 3] = 0x00;
buffer_out_b[0x11 + 4] = 0xFF;
buffer_out_b[0x11 + 5] = 0xE0;
buffer_out_b[0x11 + 8] = 0x01;
switch (State.Cmd)
{
//Reset, in : 2 bytes, out : 0
case 0xF0:
break;
//Find nodes?
//In addressing Slave address, in : 2 bytes, out : 1
case 0xF1:
{
buffer_out_len = 4 * 4;
}
break;
//Speed Change, in : 2 bytes, out : 0
case 0xF2:
break;
//Name
//"In the I / O ID" "Reading each slave ID data"
//"NAMCO LTD.; I / O PCB-1000; ver1.0; for domestic only, no analog input"
//in : 1 byte, out : max 102
case 0x10:
{
static char ID1[102] = "nullDC Team; I/O Plugin-1; ver0.2; for nullDC or other emus";
buffer_out_b[0x8 + 0x10] = (u8)strlen(ID1) + 3;
for (int i = 0; ID1[i] != 0; ++i)
{
buffer_out_b[0x8 + 0x13 + i] = ID1[i];
}
}
break;
//CMD Version
//REV in command|Format command to read the (revision)|One|Two
//in : 1 byte, out : 2 bytes
case 0x11:
{
buffer_out_b[0x8 + 0x13] = 0x13;
}
break;
//JVS Version
//In JV REV|JAMMA VIDEO standard reading (revision)|One|Two
//in : 1 byte, out : 2 bytes
case 0x12:
{
buffer_out_b[0x8 + 0x13] = 0x30;
}
break;
//COM Version
//VER in the communication system|Read a communication system compliant version of |One|Two
//in : 1 byte, out : 2 bytes
case 0x13:
{
buffer_out_b[0x8 + 0x13] = 0x10;
}
break;
//Features
//Check in feature |Each features a slave to read |One |6 to
//in : 1 byte, out : 6 + (?)
case 0x14:
{
unsigned char *FeatPtr = buffer_out_b + 0x8 + 0x13;
buffer_out_b[0x8 + 0x9 + 0x3] = 0x0;
buffer_out_b[0x8 + 0x9 + 0x9] = 0x1;
#define ADDFEAT(Feature,Count1,Count2,Count3) *FeatPtr++=Feature; *FeatPtr++=Count1; *FeatPtr++=Count2; *FeatPtr++=Count3;
ADDFEAT(1, 2, 12, 0); //Feat 1=Digital Inputs. 2 Players. 10 bits
ADDFEAT(2, 2, 0, 0); //Feat 2=Coin inputs. 2 Inputs
ADDFEAT(3, 2, 0, 0); //Feat 3=Analog. 2 Chans
ADDFEAT(0, 0, 0, 0); //End of list
}
break;
default:
printf("unknown CAP %X\n", State.Cmd);
return 0;
}
buffer_out_len = 4 * 4;
}
else if (State.Mode == 1 || State.Mode == 2 || subcode == 0x33) //Get Data
{
unsigned char glbl = 0x00;
unsigned char p1_1 = 0x00;
unsigned char p1_2 = 0x00;
unsigned char p2_1 = 0x00;
unsigned char p2_2 = 0x00;
static unsigned char LastKey[256];
static unsigned short coin1 = 0x0000;
static unsigned short coin2 = 0x0000;
unsigned char Key[256] = { 0 };
#if HOST_OS == OS_WINDOWS
GetKeyboardState(Key);
#endif
if (keycode&NAOMI_SERVICE_KEY_1) //Service ?
glbl |= 0x80;
if (keycode&NAOMI_TEST_KEY_1) //Test
p1_1 |= 0x40;
if (keycode&NAOMI_START_KEY) //start ?
p1_1 |= 0x80;
if (keycode&NAOMI_UP_KEY) //up
p1_1 |= 0x20;
if (keycode&NAOMI_DOWN_KEY) //down
p1_1 |= 0x10;
if (keycode&NAOMI_LEFT_KEY) //left
p1_1 |= 0x08;
if (keycode&NAOMI_RIGHT_KEY) //right
p1_1 |= 0x04;
if (keycode&NAOMI_BTN0_KEY) //btn1
p1_1 |= 0x02;
if (keycode&NAOMI_BTN1_KEY) //btn2
p1_1 |= 0x01;
if (keycode&NAOMI_BTN2_KEY) //btn3
p1_2 |= 0x80;
if (keycode&NAOMI_BTN3_KEY) //btn4
p1_2 |= 0x40;
if (keycode&NAOMI_BTN4_KEY) //btn5
p1_2 |= 0x20;
if (keycode&NAOMI_BTN5_KEY) //btn6
p1_2 |= 0x10;
if (keycode2&NAOMI_TEST_KEY_1) //Test
p2_1 |= 0x40;
if (keycode2&NAOMI_START_KEY) //start ?
p2_1 |= 0x80;
if (keycode2&NAOMI_UP_KEY) //up
p2_1 |= 0x20;
if (keycode2&NAOMI_DOWN_KEY) //down
p2_1 |= 0x10;
if (keycode2&NAOMI_LEFT_KEY) //left
p2_1 |= 0x08;
if (keycode2&NAOMI_RIGHT_KEY) //right
p2_1 |= 0x04;
if (keycode2&NAOMI_BTN0_KEY) //btn1
p2_1 |= 0x02;
if (keycode2&NAOMI_BTN1_KEY) //btn2
p2_1 |= 0x01;
if (keycode2&NAOMI_BTN2_KEY) //btn3
p2_2 |= 0x80;
if (keycode2&NAOMI_BTN3_KEY) //btn4
p2_2 |= 0x40;
if (keycode2&NAOMI_BTN4_KEY) //btn5
p2_2 |= 0x20;
if (keycode2&NAOMI_BTN5_KEY) //btn6
p2_2 |= 0x10;
static bool old_coin = false;
static bool old_coin2 = false;
if ((old_coin == false) && (keycode&NAOMI_COIN_KEY))
coin1++;
old_coin = (keycode&NAOMI_COIN_KEY) ? true : false;
if ((old_coin2 == false) && (keycode2&NAOMI_COIN_KEY))
coin2++;
old_coin2 = (keycode2&NAOMI_COIN_KEY) ? true : false;
buffer_out_b[0x11 + 0] = 0x00;
buffer_out_b[0x11 + 1] = 0x8E; //Valid data check
buffer_out_b[0x11 + 2] = 0x01;
buffer_out_b[0x11 + 3] = 0x00;
buffer_out_b[0x11 + 4] = 0xFF;
buffer_out_b[0x11 + 5] = 0xE0;
buffer_out_b[0x11 + 8] = 0x01;
//memset(OutData+8+0x11,0x00,0x100);
buffer_out_b[8 + 0x12 + 0] = 1;
buffer_out_b[8 + 0x12 + 1] = glbl;
buffer_out_b[8 + 0x12 + 2] = p1_1;
buffer_out_b[8 + 0x12 + 3] = p1_2;
buffer_out_b[8 + 0x12 + 4] = p2_1;
buffer_out_b[8 + 0x12 + 5] = p2_2;
buffer_out_b[8 + 0x12 + 6] = 1;
buffer_out_b[8 + 0x12 + 7] = coin1 >> 8;
buffer_out_b[8 + 0x12 + 8] = coin1 & 0xff;
buffer_out_b[8 + 0x12 + 9] = coin2 >> 8;
buffer_out_b[8 + 0x12 + 10] = coin2 & 0xff;
buffer_out_b[8 + 0x12 + 11] = 1;
buffer_out_b[8 + 0x12 + 12] = 0x00;
buffer_out_b[8 + 0x12 + 13] = 0x00;
buffer_out_b[8 + 0x12 + 14] = 0x00;
buffer_out_b[8 + 0x12 + 15] = 0x00;
buffer_out_b[8 + 0x12 + 16] = 0x00;
buffer_out_b[8 + 0x12 + 17] = 0x00;
buffer_out_b[8 + 0x12 + 18] = 0x00;
buffer_out_b[8 + 0x12 + 19] = 0x00;
buffer_out_b[8 + 0x12 + 20] = 0x00;
memcpy(LastKey, Key, sizeof(Key));
if (State.Mode == 1)
{
buffer_out_b[0x11 + 0x7] = 19;
buffer_out_b[0x11 + 0x4] = 19 + 5;
}
else
{
buffer_out_b[0x11 + 0x7] = 17;
buffer_out_b[0x11 + 0x4] = 17 - 1;
}
//OutLen=8+0x11+16;
buffer_out_len = 8 + 0x12 + 22;
}
/*ID.Keys=0xFFFFFFFF;
if(GetKeyState(VK_F1)&0x8000) //Service
ID.Keys&=~(1<<0x1b);
if(GetKeyState(VK_F2)&0x8000) //Test
ID.Keys&=~(1<<0x1a);
memcpy(OutData,&ID,sizeof(ID));
OutData[0x12]=0x8E;
OutLen=sizeof(ID);
*/
}
return 8;
case 0x17: //Select Subdevice
{
State.Mode = 0;
State.Cmd = buffer_in_b[8];
State.Node = buffer_in_b[9];
buffer_out_len = 0;
}
return (7);
case 0x27: //Transfer request
{
State.Mode = 1;
State.Cmd = buffer_in_b[8];
State.Node = buffer_in_b[9];
buffer_out_len = 0;
}
return (7);
case 0x21: //Transfer request with repeat
{
State.Mode = 2;
State.Cmd = buffer_in_b[8];
State.Node = buffer_in_b[9];
buffer_out_len = 0;
}
return (7);
case 0x0B: //EEPROM write
{
int address = buffer_in_b[1];
int size = buffer_in_b[2];
//printf("EEprom write %08X %08X\n",address,size);
//printState(Command,buffer_in,buffer_in_len);
memcpy(EEPROM + address, buffer_in_b + 4, size);
#ifdef SAVE_EPPROM
wchar eeprom_file[512];
host.ConfigLoadStr(L"emu", L"gamefile", eeprom_file, L"");
wcscat(eeprom_file, L".eeprom");
FILE* f = _wfopen(eeprom_file, L"wb");
if (f)
{
fwrite(EEPROM, 1, 0x80, f);
fclose(f);
wprintf(L"SAVED EEPROM to %s\n", eeprom_file);
}
#endif
}
return (7);
case 0x3: //EEPROM read
{
#ifdef SAVE_EPPROM
if (!EEPROM_loaded)
{
EEPROM_loaded = true;
wchar eeprom_file[512];
host.ConfigLoadStr(L"emu", L"gamefile", eeprom_file, L"");
wcscat(eeprom_file, L".eeprom");
FILE* f = _wfopen(eeprom_file, L"rb");
if (f)
{
fread(EEPROM, 1, 0x80, f);
fclose(f);
wprintf(L"LOADED EEPROM from %s\n", eeprom_file);
}
}
#endif
//printf("EEprom READ ?\n");
int address = buffer_in_b[1];
//printState(Command,buffer_in,buffer_in_len);
memcpy(buffer_out, EEPROM + address, 0x80);
buffer_out_len = 0x80;
}
return 8;
//IF I return all FF, then board runs in low res
case 0x31:
{
buffer_out[0] = 0xffffffff;
buffer_out[1] = 0xffffffff;
}
return (8);
//case 0x3:
// break;
//case 0x1:
// break;
default:
printf("Unknown 0x86 : SubCommand 0x%X - State: Cmd 0x%X Mode : 0x%X Node : 0x%X\n", subcode, State.Cmd, State.Mode, State.Node);
printState(cmd, buffer_in, buffer_in_len);
}
return 8;//MAPLE_RESPONSE_DATATRF
}
break;
case 0x82:
{
const char *ID = "315-6149 COPYRIGHT SEGA E\x83\x00\x20\x05NTERPRISES CO,LTD. ";
memset(buffer_out_b, 0x20, 256);
memcpy(buffer_out_b, ID, 0x38 - 4);
buffer_out_len = 256;
return (0x83);
}
case 1:
case 9:
return maple_sega_controller::dma(cmd);
default:
printf("unknown MAPLE Frame\n");
//printState(Command, buffer_in, buffer_in_len);
break;
}
return MDRE_UnknownFunction;
}
};
maple_device* maple_Create(MapleDeviceType type)
{
maple_device* rv=0;
@ -854,14 +1291,19 @@ maple_device* maple_Create(MapleDeviceType type)
case MDT_SegaController:
rv=new maple_sega_controller();
break;
case MDT_Microphone:
rv=new maple_microphone();
break;
#ifdef HAS_VMU
case MDT_SegaVMU:
rv = new maple_sega_vmu();
break;
#endif
case MDT_NaomiJamma:
rv = new maple_naomi_jamma();
break;
default:
return 0;

View File

@ -7,6 +7,8 @@ enum MapleDeviceType
MDT_SegaVMU,
MDT_Microphone,
MDT_NaomiJamma,
MDT_Count
};

View File

@ -336,7 +336,7 @@ void _vmem_map_block(void* base,u32 start,u32 end,u32 mask)
u32 j=0;
for (u32 i=start;i<=end;i++)
{
_vmem_MemInfo_ptr[i]=&(((u8*)base)[j]) + FindMask(mask);
_vmem_MemInfo_ptr[i]=&(((u8*)base)[j&mask]) + FindMask(mask) - (j & mask);
j+=0x1000000;
}
}

812
core/hw/naomi/naomi.cpp Normal file
View File

@ -0,0 +1,812 @@
/*
This file is a mix of my code, Zezu's, and duno wtf-else (most likely ElSemi's ?)
*/
#include "types.h"
#include "cfg/cfg.h"
#include "hw/holly/sb.h"
#include "hw/sh4/sh4_mem.h"
#include "hw/holly/holly_intc.h"
#include "naomi.h"
#include "naomi_cart.h"
#include "naomi_regs.h"
u32 naomi_updates;
//#define NAOMI_COMM
u32 RomPioOffset=0;
u32 DmaOffset;
u32 DmaCount;
u32 BoardID=0x980055AA;
u32 GSerialBuffer=0,BSerialBuffer=0;
int GBufPos=0,BBufPos=0;
int GState=0,BState=0;
int GOldClk=0,BOldClk=0;
int BControl=0,BCmd=0,BLastCmd=0;
int GControl=0,GCmd=0,GLastCmd=0;
int SerStep=0,SerStep2=0;
#ifdef NAOMI_COMM
u32 CommOffset;
u32* CommSharedMem;
HANDLE CommMapFile=INVALID_HANDLE_VALUE;
#endif
/*
El numero de serie solo puede contener:
0-9 (0x30-0x39)
A-H (0x41-0x48)
J-N (0x4A-0x4E)
P-Z (0x50-0x5A)
*/
static unsigned char BSerial[]="\xB7"/*CRC1*/"\x19"/*CRC2*/"0123234437897584372973927387463782196719782697849162342198671923649";
static unsigned char GSerial[]="\xB7"/*CRC1*/"\x19"/*CRC2*/"0123234437897584372973927387463782196719782697849162342198671923649";
unsigned int ShiftCRC(unsigned int CRC,unsigned int rounds)
{
const unsigned int Magic=0x10210000;
unsigned int i;
for(i=0;i<rounds;++i)
{
if(CRC&0x80000000)
CRC=(CRC<<1)+Magic;
else
CRC=(CRC<<1);
}
return CRC;
}
unsigned short CRCSerial(unsigned char *Serial,unsigned int len)
{
unsigned int CRC=0xDEBDEB00;
unsigned int i;
for(i=0;i<len;++i)
{
unsigned char c=Serial[i];
//CRC&=0xFFFFFF00;
CRC|=c;
CRC=ShiftCRC(CRC,8);
}
CRC=ShiftCRC(CRC,8);
return (u16)(CRC>>16);
}
void NaomiInit()
{
//RomOffset=0;
DmaCount=0xffff;
DmaOffset=0;
u16 CRC;
CRC=CRCSerial(BSerial+2,0x2E);
BSerial[0]=(u8)(CRC>>8);
BSerial[1]=(u8)(CRC);
CRC=CRCSerial(GSerial+2,0x2E);
GSerial[0]=(u8)(CRC>>8);
GSerial[1]=(u8)(CRC);
}
void NaomiBoardIDWrite(const u16 Data)
{
int Dat=Data&8;
int Clk=Data&4;
int Rst=Data&0x20;
int Sta=Data&0x10;
if(Rst)
{
BState=0;
BBufPos=0;
}
if(Clk!=BOldClk && !Clk) //Falling Edge clock
{
//State change
if(BState==0 && Sta)
BState=1;
if(BState==1 && !Sta)
BState=2;
if((BControl&0xfff)==0xFF0) //Command mode
{
BCmd<<=1;
if(Dat)
BCmd|=1;
else
BCmd&=0xfffffffe;
}
//State processing
if(BState==1) //LoadBoardID
{
BSerialBuffer=BoardID;
BBufPos=0; //??
}
if(BState==2) //ShiftBoardID
{
BBufPos++;
}
}
BOldClk=Clk;
}
u16 NaomiBoardIDRead()
{
if((BControl&0xff)==0xFE)
return 0xffff;
return (BSerialBuffer&(1<<(31-BBufPos)))?8:0;
}
static u32 AdaptByte(u8 val)
{
return val<<24;
}
void NaomiBoardIDWriteControl(const u16 Data)
{
if((Data&0xfff)==0xF30 && BCmd!=BLastCmd)
{
if((BCmd&0x81)==0x81)
{
SerStep2=(BCmd>>1)&0x3f;
BSerialBuffer=0x00000000; //First block contains CRC
BBufPos=0;
}
if((BCmd&0xff)==0x55) //Load Offset 0
{
BState=2;
BBufPos=0;
BSerialBuffer=AdaptByte(BSerial[8*SerStep2])>>1;
}
if((BCmd&0xff)==0xAA) //Load Offset 1
{
BState=2;
BBufPos=0;
BSerialBuffer=AdaptByte(BSerial[8*SerStep2+1]);
}
if((BCmd&0xff)==0x54)
{
BState=2;
BBufPos=0;
BSerialBuffer=AdaptByte(BSerial[8*SerStep2+2]);
}
if((BCmd&0xff)==0xA8)
{
BState=2;
BBufPos=0;
BSerialBuffer=AdaptByte(BSerial[8*SerStep2+3]);
}
if((BCmd&0xff)==0x50)
{
BState=2;
BBufPos=0;
BSerialBuffer=AdaptByte(BSerial[8*SerStep2+4]);
}
if((BCmd&0xff)==0xA0)
{
BState=2;
BBufPos=0;
BSerialBuffer=AdaptByte(BSerial[8*SerStep2+5]);
}
if((BCmd&0xff)==0x40)
{
BState=2;
BBufPos=0;
BSerialBuffer=AdaptByte(BSerial[8*SerStep2+6]);
}
if((BCmd&0xff)==0x80)
{
BState=2;
BBufPos=0;
BSerialBuffer=AdaptByte(BSerial[8*SerStep2+7]);
}
BLastCmd=BCmd;
}
BControl=Data;
}
void NaomiGameIDProcessCmd()
{
if(GCmd!=GLastCmd)
{
if((GCmd&0x81)==0x81)
{
SerStep=(GCmd>>1)&0x3f;
GSerialBuffer=0x00000000; //First block contains CRC
GBufPos=0;
}
if((GCmd&0xff)==0x55) //Load Offset 0
{
GState=2;
GBufPos=0;
GSerialBuffer=AdaptByte(GSerial[8*SerStep])>>0;
}
if((GCmd&0xff)==0xAA) //Load Offset 1
{
GState=2;
GBufPos=0;
GSerialBuffer=AdaptByte(GSerial[8*SerStep+1]);
}
if((GCmd&0xff)==0x54)
{
GState=2;
GBufPos=0;
GSerialBuffer=AdaptByte(GSerial[8*SerStep+2]);
}
if((GCmd&0xff)==0xA8)
{
GState=2;
GBufPos=0;
GSerialBuffer=AdaptByte(GSerial[8*SerStep+3]);
}
if((GCmd&0xff)==0x50)
{
GState=2;
GBufPos=0;
GSerialBuffer=AdaptByte(GSerial[8*SerStep+4]);
}
if((GCmd&0xff)==0xA0)
{
GState=2;
GBufPos=0;
GSerialBuffer=AdaptByte(GSerial[8*SerStep+5]);
}
if((GCmd&0xff)==0x40)
{
GState=2;
GBufPos=0;
GSerialBuffer=AdaptByte(GSerial[8*SerStep+6]);
}
if((GCmd&0xff)==0x80)
{
GState=2;
GBufPos=0;
GSerialBuffer=AdaptByte(GSerial[8*SerStep+7]);
}
GLastCmd=GCmd;
}
}
void NaomiGameIDWrite(const u16 Data)
{
int Dat=Data&0x01;
int Clk=Data&0x02;
int Rst=Data&0x04;
int Sta=Data&0x08;
int Cmd=Data&0x10;
if(Rst)
{
GState=0;
GBufPos=0;
}
if(Clk!=GOldClk && !Clk) //Falling Edge clock
{
//State change
if(GState==0 && Sta)
GState=1;
if(GState==1 && !Sta)
GState=2;
//State processing
if(GState==1) //LoadBoardID
{
GSerialBuffer=BoardID;
GBufPos=0; //??
}
if(GState==2) //ShiftBoardID
GBufPos++;
if(GControl!=Cmd && !Cmd)
{
NaomiGameIDProcessCmd();
}
GControl=Cmd;
}
if(Clk!=GOldClk && Clk) //Rising Edge clock
{
if(Cmd) //Command mode
{
GCmd<<=1;
if(Dat)
GCmd|=1;
else
GCmd&=0xfffffffe;
GControl=Cmd;
}
}
GOldClk=Clk;
}
u16 NaomiGameIDRead()
{
return (GSerialBuffer&(1<<(31-GBufPos)))?1:0;
}
u32 _ReadMem_naomi(u32 Addr, u32 sz)
{
verify(sz!=1);
printf("naomi?WTF? ReadMem: %X, %d\n", Addr, sz);
return 1;
}
void _WriteMem_naomi(u32 Addr, u32 data, u32 sz)
{
printf("naomi?WTF? WriteMem: %X <= %X, %d\n", Addr, data, sz);
}
//DIMM board
//Uses interrupt ext#3 (holly_EXT_PCI)
//status/flags ? 0x1 is some completion/init flag(?), 0x100 is the interrupt disable flag (?)
//n1 bios rev g (n2/epr-23605b has similar behavior of not same):
//3c=0x1E03
//40=0
//44=0
//48=0
//read 4c
//wait for 4c not 0
//4c=[4c]-1
//Naomi 2 bios epr-23609
//read 3c
//wait 4c to be non 0
//
//SO the writes to 3c/stuff are not relaced with 4c '1'
//If the dimm board has some internal cpu/pic logic
//4c '1' seems to be the init done bit (?)
//n1/n2 clears it after getting a non 0 value
//n1 bios writes the value -1, meaning it expects the bit 0 to be set
//.//
u32 reg_dimm_3c; //IO window ! writen, 0x1E03 some flag ?
u32 reg_dimm_40; //parameters
u32 reg_dimm_44; //parameters
u32 reg_dimm_48; //parameters
u32 reg_dimm_4c=0x11; //status/control reg ?
bool NaomiDataRead = false;
void naomi_process(u32 r3c,u32 r40,u32 r44, u32 r48)
{
printf("Naomi process 0x%04X 0x%04X 0x%04X 0x%04X\n",r3c,r40,r44,r48);
printf("Possible format 0 %d 0x%02X 0x%04X\n",r3c>>15,(r3c&0x7e00)>>9,r3c&0x1FF);
printf("Possible format 1 0x%02X 0x%02X\n",(r3c&0xFF00)>>8,r3c&0xFF);
u32 param=(r3c&0xFF);
if (param==0xFF)
{
printf("invalid opcode or smth ?");
}
static int opcd=0;
//else if (param!=3)
if (opcd<255)
{
reg_dimm_3c=0x8000 | (opcd%12<<9) | (0x0);
printf("new reg is 0x%X\n",reg_dimm_3c);
asic_RaiseInterrupt(holly_EXP_PCI);
printf("Interrupt raised\n");
opcd++;
}
}
u32 ReadMem_naomi(u32 Addr, u32 sz)
{
verify(sz!=1);
// printf("+naomi?WTF? ReadMem: %X, %d\n", Addr, sz);
switch(Addr&255)
{
case 0x3c:
//printf("naomi GD? READ: %X, %d\n", Addr, sz);
return reg_dimm_3c | (NaomiDataRead ? 0 : -1); //pretend the board isn't there for the bios
case 0x40:
printf("naomi GD? READ: %X, %d\n", Addr, sz);
return reg_dimm_40;
case 0x44:
printf("naomi GD? READ: %X, %d\n", Addr, sz);
return reg_dimm_44;
case 0x48:
printf("naomi GD? READ: %X, %d\n", Addr, sz);
return reg_dimm_48;
//These are known to be valid on normal ROMs and DIMM board
case NAOMI_ROM_OFFSETH_addr&255:
return RomPioOffset>>16;
case NAOMI_ROM_OFFSETL_addr&255:
return RomPioOffset&0xFFFF;
case NAOMI_ROM_DATA_addr & 255:
{
u32 rv = 0;
naomi_cart_Read(RomPioOffset, 2, &rv);
RomPioOffset += 2;
return rv;
}
break;
case NAOMI_DMA_COUNT_addr&255:
return (u16) DmaCount;
case NAOMI_BOARDID_READ_addr&255:
return NaomiGameIDRead()?0x8000:0x0000;
//What should i do to emulate 'nothing' ?
case NAOMI_COMM_OFFSET_addr&255:
#ifdef NAOMI_COMM
printf("naomi COMM offs READ: %X, %d\n", Addr, sz);
return CommOffset;
#endif
case NAOMI_COMM_DATA_addr&255:
#ifdef NAOMI_COMM
printf("naomi COMM data read: %X, %d\n", CommOffset, sz);
if (CommSharedMem)
{
return CommSharedMem[CommOffset&0xF];
}
#endif
return 1;
//This should be valid
case NAOMI_DMA_OFFSETH_addr&255:
return DmaOffset>>16;
case NAOMI_DMA_OFFSETL_addr&255:
return DmaOffset&0xFFFF;
case NAOMI_BOARDID_WRITE_addr&255:
printf("naomi ReadMem: %X, %d\n", Addr, sz);
return 1;
case 0x04C:
printf("naomi GD? READ: %X, %d\n", Addr, sz);
return reg_dimm_4c;
case 0x18:
printf("naomi reg 0x18 : returning random data\n");
return 0x4000^rand();
break;
default: break;
}
printf("naomi?WTF? ReadMem: %X, %d\n", Addr, sz);
return 0;
}
void WriteMem_naomi(u32 Addr, u32 data, u32 sz)
{
// printf("+naomi WriteMem: %X <= %X, %d\n", Addr, data, sz);
switch(Addr&255)
{
case 0x3c:
if (0x1E03==data)
{
/*
if (!(reg_dimm_4c&0x100))
asic_RaiseInterrupt(holly_EXP_PCI);
reg_dimm_4c|=1;*/
}
reg_dimm_3c=data;
printf("naomi GD? Write: %X <= %X, %d\n", Addr, data, sz);
return;
case 0x40:
reg_dimm_40=data;
printf("naomi GD? Write: %X <= %X, %d\n", Addr, data, sz);
return;
case 0x44:
reg_dimm_44=data;
printf("naomi GD? Write: %X <= %X, %d\n", Addr, data, sz);
return;
case 0x48:
reg_dimm_48=data;
printf("naomi GD? Write: %X <= %X, %d\n", Addr, data, sz);
return;
case 0x4C:
if (data&0x100)
{
asic_CancelInterrupt(holly_EXP_PCI);
naomi_updates=100;
}
else if ((data&1)==0)
{
/*FILE* ramd=fopen("c:\\ndc.ram.bin","wb");
fwrite(mem_b.data,1,RAM_SIZE,ramd);
fclose(ramd);*/
naomi_process(reg_dimm_3c,reg_dimm_40,reg_dimm_44,reg_dimm_48);
}
reg_dimm_4c=data&~0x100;
printf("naomi GD? Write: %X <= %X, %d\n", Addr, data, sz);
return;
//These are known to be valid on normal ROMs and DIMM board
case NAOMI_ROM_OFFSETH_addr&255:
RomPioOffset&=0x0000ffff;
RomPioOffset|=(data<<16)&0x7fff0000;
return;
case NAOMI_ROM_OFFSETL_addr&255:
RomPioOffset&=0xffff0000;
RomPioOffset|=data;
return;
case NAOMI_ROM_DATA_addr&255:
printf("naomi WriteMem:Write to rom ? sure ? no , i dont think so %%) %X <= %X, %d\n", Addr, data, sz);
return;
case NAOMI_DMA_OFFSETH_addr&255:
DmaOffset&=0x0000ffff;
DmaOffset|=(data&0x7fff)<<16;
return;
case NAOMI_DMA_OFFSETL_addr&255:
DmaOffset&=0xffff0000;
DmaOffset|=data;
return;
case NAOMI_DMA_COUNT_addr&255:
{
DmaCount=data;
}
return;
case NAOMI_BOARDID_WRITE_addr&255:
NaomiGameIDWrite((u16)data);
return;
//What should i do to emulate 'nothing' ?
case NAOMI_COMM_OFFSET_addr&255:
#ifdef NAOMI_COMM
printf("naomi COMM ofset Write: %X <= %X, %d\n", Addr, data, sz);
CommOffset=data&0xFFFF;
#endif
return;
case NAOMI_COMM_DATA_addr&255:
#ifdef NAOMI_COMM
printf("naomi COMM data Write: %X <= %X, %d\n", CommOffset, data, sz);
if (CommSharedMem)
{
CommSharedMem[CommOffset&0xF]=data;
}
#endif
return;
//This should be valid
case NAOMI_BOARDID_READ_addr&255:
printf("naomi WriteMem: %X <= %X, %d\n", Addr, data, sz);
return;
default: break;
}
printf("naomi?WTF? WriteMem: %X <= %X, %d\n", Addr, data, sz);
}
u32 NAOMI_ROM_OFFSETH;
u32 NAOMI_ROM_OFFSETL;
u32 NAOMI_ROM_DATA;
u32 NAOMI_DMA_OFFSETH;
u32 NAOMI_DMA_OFFSETL;
u32 NAOMI_DMA_COUNT;
u32 NAOMI_BOARDID_WRITE;
u32 NAOMI_BOARDID_READ;
u32 NAOMI_COMM_OFFSET;
u32 NAOMI_COMM_DATA;
//Dma Start
void Naomi_DmaStart(u32 addr, u32 data)
{
if (SB_GDEN==0)
{
printf("Invalid (NAOMI)GD-DMA start, SB_GDEN=0.Ingoring it.\n");
return;
}
NaomiDataRead = true;
SB_GDST|=data&1;
if (SB_GDST==1)
{
verify(1 == SB_GDDIR );
SB_GDSTARD=SB_GDSTAR+SB_GDLEN;
SB_GDLEND=SB_GDLEN;
SB_GDST=0;
void* ptr = naomi_cart_GetPtr(DmaOffset & 0x0FFFffff, SB_GDLEN);
WriteMemBlock_nommu_ptr(SB_GDSTAR, (u32*)ptr, SB_GDLEN);
asic_RaiseInterrupt(holly_GDROM_DMA);
}
}
void Naomi_DmaEnable(u32 addr, u32 data)
{
SB_GDEN=data&1;
if (SB_GDEN==0 && SB_GDST==1)
{
printf("(NAOMI)GD-DMA aborted\n");
SB_GDST=0;
}
}
void naomi_reg_Init()
{
#ifdef NAOMI_COMM
CommMapFile = CreateFileMapping(
INVALID_HANDLE_VALUE, // use paging file
NULL, // default security
PAGE_READWRITE, // read/write access
0, // max. object size
0x1000*4, // buffer size
L"Global\\nullDC_103_naomi_comm"); // name of mapping object
if (CommMapFile == NULL || CommMapFile==INVALID_HANDLE_VALUE)
{
_tprintf(TEXT("Could not create file mapping object (%d).\nTrying to open existing one\n"), GetLastError());
CommMapFile=OpenFileMapping(
FILE_MAP_ALL_ACCESS, // read/write access
FALSE, // do not inherit the name
L"Global\\nullDC_103_naomi_comm"); // name of mapping object
}
if (CommMapFile == NULL || CommMapFile==INVALID_HANDLE_VALUE)
{
_tprintf(TEXT("Could not open existing file either\n"), GetLastError());
CommMapFile=INVALID_HANDLE_VALUE;
}
else
{
printf("NAOMI: Created \"Global\\nullDC_103_naomi_comm\"\n");
CommSharedMem = (u32*) MapViewOfFile(CommMapFile, // handle to map object
FILE_MAP_ALL_ACCESS, // read/write permission
0,
0,
0x1000*4);
if (CommSharedMem == NULL)
{
_tprintf(TEXT("Could not map view of file (%d).\n"),
GetLastError());
CloseHandle(CommMapFile);
CommMapFile=INVALID_HANDLE_VALUE;
}
else
printf("NAOMI: Mapped CommSharedMem\n");
}
#endif
NaomiInit();
sb_rio_register(SB_GDST_addr, RIO_WF, 0, &Naomi_DmaStart);
sb_rio_register(SB_GDEN_addr, RIO_WF, 0, &Naomi_DmaEnable);
}
void naomi_reg_Term()
{
#ifdef NAOMI_COMM
if (CommSharedMem)
{
UnmapViewOfFile(CommSharedMem);
}
if (CommMapFile!=INVALID_HANDLE_VALUE)
{
CloseHandle(CommMapFile);
}
#endif
}
void naomi_reg_Reset(bool Manual)
{
NaomiDataRead = false;
}
void Update_naomi()
{
/*
if (naomi_updates>1)
{
naomi_updates--;
}
else if (naomi_updates==1)
{
naomi_updates=0;
asic_RaiseInterrupt(holly_EXP_PCI);
}*/
#if 0
if(!(SB_GDST&1) || !(SB_GDEN &1))
return;
//SB_GDST=0;
//TODO : Fix dmaor
u32 dmaor = DMAC_DMAOR.full;
u32 src = SB_GDSTARD,
len = SB_GDLEN-SB_GDLEND ;
//len=min(len,(u32)32);
// do we need to do this for gdrom dma ?
if(0x8201 != (dmaor &DMAOR_MASK)) {
printf("\n!\tGDROM: DMAOR has invalid settings (%X) !\n", dmaor);
//return;
}
if(len & 0x1F) {
printf("\n!\tGDROM: SB_GDLEN has invalid size (%X) !\n", len);
return;
}
if(0 == len)
{
printf("\n!\tGDROM: Len: %X, Abnormal Termination !\n", len);
}
u32 len_backup=len;
if( 1 == SB_GDDIR )
{
WriteMemBlock_nommu_ptr(dst,NaomiRom+(DmaOffset&0x7ffffff),size);
DmaCount=0xffff;
}
else
msgboxf(L"GDROM: SB_GDDIR %X (TO AICA WAVE MEM?)",MBX_ICONERROR, SB_GDDIR);
//SB_GDLEN = 0x00000000; //13/5/2k7 -> acording to docs these regs are not updated by hardware
//SB_GDSTAR = (src + len_backup);
SB_GDLEND+= len_backup;
SB_GDSTARD+= len_backup;//(src + len_backup)&0x1FFFFFFF;
if (SB_GDLEND==SB_GDLEN)
{
//printf("Streamed GDMA end - %d bytes trasnfered\n",SB_GDLEND);
SB_GDST=0;//done
// The DMA end interrupt flag
asic_RaiseInterrupt(holly_GDROM_DMA);
}
//Readed ALL sectors
if (read_params.remaining_sectors==0)
{
u32 buff_size =read_buff.cache_size - read_buff.cache_index;
//And all buffer :p
if (buff_size==0)
{
verify(!SB_GDST&1)
gd_set_state(gds_procpacketdone);
}
}
#endif
}

39
core/hw/naomi/naomi.h Normal file
View File

@ -0,0 +1,39 @@
/*
** naomi.h
*/
#pragma once
void naomi_reg_Init();
void naomi_reg_Term();
void naomi_reg_Reset(bool Manual);
void Update_naomi();
u32 ReadMem_naomi(u32 Addr, u32 sz);
void WriteMem_naomi(u32 Addr, u32 data, u32 sz);
void NaomiBoardIDWrite(const u16 Data);
void NaomiBoardIDWriteControl(const u16 Data);
u16 NaomiBoardIDRead();

View File

@ -0,0 +1,247 @@
#include "naomi_cart.h"
#include "cfg/cfg.h"
u8* RomPtr;
u32 RomSize;
#if HOST_OS == OS_WINDOWS
typedef HANDLE fd_t;
#define INVALID_FD INVALID_HANDLE_VALUE
#else
typedef int fd_t;
#define INVALID_FD -1
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#endif
fd_t* RomCacheMap;
u32 RomCacheMapCount;
char SelectedFile[512];
bool naomi_cart_LoadRom(char* file)
{
printf("\nnullDC-Naomi rom loader v1.2\n");
size_t folder_pos = strlen(file) - 1;
while (folder_pos>1 && (file[folder_pos] != '\\' && file[folder_pos] != '/'))
folder_pos--;
folder_pos++;
char t[512];
strcpy(t, file);
FILE* fl = fopen(t, "r");
if (!fl)
return false;
char* line = fgets(t, 512, fl);
if (!line)
{
fclose(fl);
return false;
}
char* eon = strstr(line, "\n");
if (!eon)
printf("+Loading naomi rom that has no name\n", line);
else
*eon = 0;
printf("+Loading naomi rom : %s\n", line);
line = fgets(t, 512, fl);
if (!line)
{
fclose(fl);
return false;
}
vector<string> files;
vector<u32> fstart;
vector<u32> fsize;
u32 setsize = 0;
RomSize = 0;
while (line)
{
char filename[512];
u32 addr, sz;
sscanf(line, "\"%[^\"]\",%x,%x", filename, &addr, &sz);
files.push_back(filename);
fstart.push_back(addr);
fsize.push_back(sz);
setsize += sz;
RomSize = max(RomSize, (addr + sz));
line = fgets(t, 512, fl);
}
fclose(fl);
printf("+%d romfiles, %.2f MB set size, %.2f MB set address space\n", files.size(), setsize / 1024.f / 1024.f, RomSize / 1024.f / 1024.f);
if (RomCacheMap)
{
RomCacheMapCount = 0;
delete RomCacheMap;
}
RomCacheMapCount = (u32)files.size();
RomCacheMap = new fd_t[files.size()];
strcpy(t, file);
t[folder_pos] = 0;
strcat(t, "ndcn-composed.cache");
//Allocate space for the ram, so we are sure we have a segment of continius ram
#if HOST_OS == OS_WINDOWS
RomPtr = (u8*)VirtualAlloc(0, RomSize, MEM_RESERVE, PAGE_NOACCESS);
#else
RomPtr = (u8*)mmap(0, RomSize, PROT_NONE, MAP_PRIVATE | MAP_ANON, -1, 0);
#endif
verify(RomPtr != 0);
verify(RomPtr != (void*)-1);
strcpy(t, file);
//Create File Mapping Objects
for (size_t i = 0; i<files.size(); i++)
{
t[folder_pos] = 0;
strcat(t, files[i].c_str());
fd_t RomCache;
if (strcmp(files[i].c_str(), "null") == 0)
{
RomCacheMap[i] = INVALID_FD;
continue;
}
#if HOST_OS == OS_WINDOWS
RomCache = CreateFile(t, FILE_READ_ACCESS, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
#else
RomCache = open(t, O_RDONLY);
#endif
if (RomCache == INVALID_FD)
{
wprintf(L"-Unable to read file %s\n", files[i].c_str());
RomCacheMap[i] = INVALID_FD;
continue;
}
#if HOST_OS == OS_WINDOWS
RomCacheMap[i] = CreateFileMapping(RomCache, 0, PAGE_READONLY, 0, fsize[i], 0);
verify(CloseHandle(RomCache));
#else
RomCacheMap[i] = RomCache;
#endif
verify(RomCacheMap[i] != INVALID_FD);
wprintf(L"-Preparing \"%s\" at 0x%08X, size 0x%08X\n", files[i].c_str(), fstart[i], fsize[i]);
}
//We have all file mapping objects, we start to map the ram
printf("+Mapping ROM\n");
//Release the segment we reserved so we can map the files there
#if HOST_OS == OS_WINDOWS
verify(VirtualFree(RomPtr, 0, MEM_RELEASE));
#else
munmap(RomPtr, RomSize);
#endif
//Map the files into the segment of the ram that was reserved
for (size_t i = 0; i<RomCacheMapCount; i++)
{
u8* RomDest = RomPtr + fstart[i];
if (RomCacheMap[i] == INVALID_FD)
{
wprintf(L"-Reserving ram at 0x%08X, size 0x%08X\n", fstart[i], fsize[i]);
#if HOST_OS == OS_WINDOWS
bool mapped = RomDest == VirtualAlloc(RomDest, fsize[i], MEM_RESERVE, PAGE_NOACCESS);
#else
bool mapped = RomDest == (u8*)mmap(RomDest, RomSize, PROT_NONE, MAP_PRIVATE, 0, 0);
#endif
verify(mapped);
}
else
{
wprintf(L"-Mapping \"%s\" at 0x%08X, size 0x%08X\n", files[i].c_str(), fstart[i], fsize[i]);
#if HOST_OS == OS_WINDOWS
bool mapped = RomDest != MapViewOfFileEx(RomCacheMap[i], FILE_MAP_READ, 0, 0, fsize[i], RomDest);
#else
bool mapped = RomDest != mmap(RomDest, fsize[i], PROT_READ, MAP_PRIVATE, RomCacheMap[i], 0 );
#endif
if (!mapped)
{
printf("-Mapping ROM FAILED\n");
//unmap file
return false;
}
}
}
//done :)
printf("\nMapped ROM Successfully !\n\n");
return true;
}
bool naomi_cart_SelectFile(void* handle)
{
cfgLoadStr("config", "image", SelectedFile, "null");
#if HOST_OS == OS_WINDOWS
if (strcmp(SelectedFile, "null") == 0) {
OPENFILENAME ofn = { 0 };
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hInstance = (HINSTANCE)GetModuleHandle(0);
ofn.lpstrFile = SelectedFile;
ofn.nMaxFile = MAX_PATH;
ofn.lpstrFilter = "*.lst\0*.lst\0\0";
ofn.nFilterIndex = 0;
ofn.hwndOwner = (HWND)handle;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR;
if (GetOpenFileName(&ofn) <= 0)
return true;
}
#endif
if (!naomi_cart_LoadRom(SelectedFile))
{
cfgSaveStr("emu", "gamefile", "naomi_bios");
}
else
{
cfgSaveStr("emu", "gamefile", SelectedFile);
}
printf("EEPROM file : %s.eeprom\n", SelectedFile);
return true;
}
bool naomi_cart_Read(u32 offset, u32 size, void* dst) {
if (!RomPtr)
return false;
memcpy(dst, naomi_cart_GetPtr(offset, size), size);
return true;
}
void* naomi_cart_GetPtr(u32 offset, u32 size) {
offset &= 0x0FFFffff;
verify(offset < RomSize);
verify((offset + size) < RomSize);
return &RomPtr[offset];
}

View File

@ -0,0 +1,5 @@
#include "types.h"
bool naomi_cart_Read(u32 offset, u32 size, void* dst);
void* naomi_cart_GetPtr(u32 offset, u32 size);
bool naomi_cart_SelectFile(void* handle);

View File

@ -0,0 +1,32 @@
/*
** naomi_regs.h
*/
#pragma once
enum
{
NAOMI_ROM_OFFSETH_addr = 0x5f7000,
NAOMI_ROM_OFFSETL_addr = 0x5f7004,
NAOMI_ROM_DATA_addr = 0x5f7008,
NAOMI_DMA_OFFSETH_addr = 0x5f700C,
NAOMI_DMA_OFFSETL_addr = 0x5f7010,
NAOMI_DMA_COUNT_addr = 0x5f7014,
NAOMI_BOARDID_WRITE_addr = 0x5F7078,
NAOMI_BOARDID_READ_addr = 0x5F707C,
NAOMI_COMM_OFFSET_addr = 0x5F7050,
NAOMI_COMM_DATA_addr = 0x5F7054,
};
extern u32 NAOMI_ROM_OFFSETH;
extern u32 NAOMI_ROM_OFFSETL;
extern u32 NAOMI_ROM_DATA;
extern u32 NAOMI_DMA_OFFSETH;
extern u32 NAOMI_DMA_OFFSETL;
extern u32 NAOMI_DMA_COUNT;
extern u32 NAOMI_BOARDID_WRITE;
extern u32 NAOMI_BOARDID_READ;
extern u32 NAOMI_COMM_OFFSET;
extern u32 NAOMI_COMM_DATA;

View File

@ -87,7 +87,7 @@ blkmap_t blkmap;
u32 bm_gc_luc,bm_gcf_luc;
#define FPCA(x) ((DynarecCodeEntryPtr&)sh4rcb.fpcb[(x>>1)&(8*1024*1024-1)])
#define FPCA(x) ((DynarecCodeEntryPtr&)sh4rcb.fpcb[(x>>1)&FPCB_MASK])
DynarecCodeEntryPtr DYNACALL bm_GetCode(u32 addr)
{
@ -386,7 +386,7 @@ void bm_Reset()
#if (HOST_OS == OS_DARWIN) || defined(TARGET_NO_NVMEM)
//lazy allocation isn't working on iOS
for (u32 i=0;i<(8*1024*1024);i++)
for (u32 i=0;i<FPCB_SIZE;i++)
{
sh4rcb.fpcb[i]=(void*)ngen_FailedToFindBlock;
}

View File

@ -408,13 +408,7 @@ void recSh4_Init()
bm_Init();
bm_Reset();
#if HOST_CPU == CPU_X64
verify(rcb_noffs(p_sh4rcb->fpcb) == -67371008);
#elif HOST_CPU == CPU_GENERIC
verify(rcb_noffs(p_sh4rcb->fpcb) == -33816576 || rcb_noffs(p_sh4rcb->fpcb) == -67371008);
#else
verify(rcb_noffs(p_sh4rcb->fpcb) == -33816576);
#endif
verify(rcb_noffs(p_sh4rcb->fpcb) == FPCB_OFFSET);
verify(rcb_noffs(p_sh4rcb->sq_buffer) == -512);

View File

@ -250,6 +250,7 @@ void Sh4_int_Init()
rtc_schid=sh4_sched_register(0,&DreamcastSecond);
sh4_sched_request(rtc_schid,SH4_MAIN_CLOCK);
memset(&p_sh4rcb->cntx, 0, sizeof(p_sh4rcb->cntx));
}
void Sh4_int_Term()

View File

@ -3,13 +3,15 @@
#include "types.h"
#include "hw/sh4/sh4_mmr.h"
#include "hw/naomi/naomi.h"
BSC_PDTRA_type BSC_PDTRA;
void write_BSC_PCTRA(u32 addr, u32 data)
{
BSC_PCTRA.full=(u16)data;
#if defined(BUILD_NAOMI ) || defined(BUILD_ATOMISWAVE)
#if DC_PLATFORM == DC_PLATFORM_NAOMI
NaomiBoardIDWriteControl((u16)data);
#else
//printf("C:BSC_PCTRA = %08X\n",data);
@ -21,14 +23,14 @@ void write_BSC_PDTRA(u32 addr, u32 data)
BSC_PDTRA.full=(u16)data;
//printf("D:BSC_PDTRA = %08X\n",data);
#if defined(BUILD_NAOMI ) || defined(BUILD_ATOMISWAVE)
#if DC_PLATFORM == DC_PLATFORM_NAOMI
NaomiBoardIDWrite((u16)data);
#endif
}
u32 read_BSC_PDTRA(u32 addr)
{
#if defined(BUILD_NAOMI ) || defined(BUILD_ATOMISWAVE)
#if DC_PLATFORM == DC_PLATFORM_NAOMI
return NaomiBoardIDRead();
@ -111,6 +113,11 @@ void bsc_init()
sh4_rio_reg(BSC,BSC_GPIOIC_addr,RIO_DATA,16);
//note: naomi//aw might depend on rfcr
#if DC_PLATFORM == DC_PLATFORM_NAOMI
sh4_rio_reg(BSC, BSC_RFCR_addr, RIO_RO, 16);
BSC_RFCR.full = 17;
#endif
}

View File

@ -305,10 +305,15 @@ void DYNACALL do_sqw_nommu_full(u32 dst, u8* sqb);
typedef void DYNACALL sqw_fp(u32 dst,u8* sqb);
typedef void DYNACALL TaListVoidFP(void* data);
#define FPCB_SIZE (RAM_SIZE/2)
#define FPCB_MASK (FPCB_SIZE -1)
//#defeine FPCB_PAD 0x40000
#define FPCB_PAD 0x100000
#define FPCB_OFFSET (-(FPCB_SIZE*sizeof(void*) + FPCB_PAD))
struct Sh4RCB
{
void* fpcb[8*1024*1024];
u64 _pad[(0x40000-sizeof(Sh4Context)-64-sizeof(void*)*2)/8];
void* fpcb[FPCB_SIZE];
u64 _pad[(FPCB_PAD-sizeof(Sh4Context)-64-sizeof(void*)*2)/8];
TaListVoidFP* tacmd_voud; //*TODO* remove (not used)
sqw_fp* do_sqw_nommu;
u64 sq_buffer[64/8];
@ -343,4 +348,4 @@ s32 rcb_poffs(T* ptr)
//Get an interface to sh4 interpreter
void Get_Sh4Interpreter(sh4_if* cpu);
void Get_Sh4Recompiler(sh4_if* cpu);
void Get_Sh4Recompiler(sh4_if* cpu);

View File

@ -14,6 +14,7 @@
#include "hw/sh4/sh4_mem.h"
#include "webui/server.h"
#include "hw/naomi/naomi_cart.h"
settings_t settings;
@ -90,9 +91,8 @@ s32 plugins_Init()
if (s32 rv = libGDR_Init())
return rv;
#ifdef BUILD_NAOMI
if (!NaomiSelectFile(GetRenderTargetHandle()))
#if DC_PLATFORM == DC_PLATFORM_NAOMI
if (!naomi_cart_SelectFile(libPvr_GetRenderTarget()))
return rv_serror;
#endif

View File

@ -173,8 +173,13 @@ do_iter:
HIDDEN(no_update)
CSYM(no_update): @ next_pc _MUST_ be on r4 *R4 NOT R0 anymore*
#if DC_PLATFORM == DC_PLATFORM_NAOMI
sub r2,r8,#0x4100000
ubfx r1,r4,#1,#24
#else
sub r2,r8,#33816576
ubfx r1,r4,#1,#23
#endif
ldr pc,[r2,r1,lsl #2]
@bic r1,r4,#0xFF000000

View File

@ -408,8 +408,13 @@ u32 DynaRBI::Relink()
case BET_DynamicJump:
{
#ifdef CALLSTACK
SUB(r2,r8,33816576);
UBFX(r1,r4,1,23);
#error offset broken
SUB(r2, r8, -FPCB_OFFSET);
#if RAM_SIZE == 33554432
UBFX(r1, r4, 1, 24);
#else
UBFX(r1, r4, 1, 23);
#endif
if (BlockType==BET_DynamicRet)
{
@ -431,8 +436,12 @@ u32 DynaRBI::Relink()
#if 1
//this is faster
//why ? (Icache ?)
SUB(r2,r8,33816576);
UBFX(r1,r4,1,23);
SUB(r2, r8, -FPCB_OFFSET);
#if RAM_SIZE == 33554432
UBFX(r1, r4, 1, 24);
#else
UBFX(r1, r4, 1, 23);
#endif
LDR(r15,r2,r1,Offset,true,S_LSL,2);
#else
@ -445,8 +454,13 @@ u32 DynaRBI::Relink()
}
else
{
SUB(r2,r8,33816576); //1
UBFX(r1,r4,1,23); //1
SUB(r2, r8, -FPCB_OFFSET);
#if RAM_SIZE == 33554432
UBFX(r1, r4, 1, 24);
#else
UBFX(r1, r4, 1, 23);
#endif
NOP();NOP(); //2
LDR(r15,r2,r1,Offset,true,S_LSL,2); //1
}
@ -456,8 +470,13 @@ u32 DynaRBI::Relink()
{
verify(pBranchBlock==0);
SUB(r2,r8,33816576);
UBFX(r1,r4,1,23);
#if RAM_SIZE == 33554432
SUB(r2, r8, 67371008);
UBFX(r1, r4, 1, 24);
#else
SUB(r2, r8, 33816576);
UBFX(r1, r4, 1, 23);
#endif
LDR(r15,r2,r1,Offset,true,S_LSL,2);
}
#endif

View File

@ -438,7 +438,70 @@ u32 DynaRBI::Relink()
x86e->x86_size=512;
x86e->do_realloc=false;
if (BlockType==BET_StaticCall || BlockType==BET_DynamicCall)
//#define SIMPLELINK
#ifdef SIMPLELINK
switch (BlockType) {
case BET_StaticJump:
case BET_StaticCall:
//next_pc = block->BranchBlock;
x86e->Emit(op_mov32, ECX, BranchBlock);
break;
case BET_Cond_0:
case BET_Cond_1:
{
//next_pc = next_pc_value;
//if (*jdyn == 0)
//next_pc = branch_pc_value;
x86e->Emit(op_mov32, ECX, NextBlock);
u32* ptr = &sr.T;
if (has_jcond)
ptr = &Sh4cntx.jdyn;
x86e->Emit(op_cmp32, ptr, BlockType & 1);
x86_Label* lbl = x86e->CreateLabel(false, 8);
x86e->Emit(op_jne, lbl);
x86e->Emit(op_mov32, ECX, BranchBlock);
x86e->MarkLabel(lbl);
}
break;
case BET_DynamicJump:
case BET_DynamicCall:
case BET_DynamicRet:
//next_pc = *jdyn;
x86e->Emit(op_mov32, ECX, &Sh4cntx.jdyn);
break;
case BET_DynamicIntr:
case BET_StaticIntr:
if (BlockType == BET_StaticIntr)
{
x86e->Emit(op_mov32, &next_pc, NextBlock);
}
else
{
x86e->Emit(op_mov32, EAX, GetRegPtr(reg_pc_dyn));
x86e->Emit(op_mov32, &next_pc, EAX);
}
x86e->Emit(op_call, x86_ptr_imm(UpdateINTC));
x86e->Emit(op_mov32, ECX, &next_pc);
break;
default:
die("Invalid block end type");
}
x86e->Emit(op_jmp, x86_ptr_imm(loop_no_update));
#else
if (BlockType == BET_StaticCall || BlockType == BET_DynamicCall)
{
//csc_push(this);
}
@ -532,6 +595,7 @@ u32 DynaRBI::Relink()
break;
}
#endif
@ -556,7 +620,10 @@ u32 DynaRBI::Relink()
W F32v2 B,S{,M}
*/
#if !defined(TARGET_NO_NVMEM)
extern u8* virt_ram_base;
#endif
#include "hw/sh4/sh4_mmr.h"
enum mem_op_type
@ -584,6 +651,7 @@ void gen_hande(u32 w, u32 sz, u32 mode)
u32 si=x86e->x86_indx;
#ifndef TARGET_NO_NVMEM
if (mode==0)
{
//Buffer
@ -616,7 +684,9 @@ void gen_hande(u32 w, u32 sz, u32 mode)
}
}
}
else if (mode==1)
else
#endif
if (mode==1)
{
//SQ
verify(w==1);

View File

@ -105,7 +105,6 @@ void ngen_CC_Param(shil_opcode* op,shil_param* par,CanonicalParamType tp)
case CPT_ptr:
verify(par->is_reg());
die("FAIL");
x86e->Emit(op_push,(unat)par->reg_ptr());
for (u32 ri=0; ri<(*par).count(); ri++)
@ -179,7 +178,9 @@ void DYNACALL VERIFYME(u32 addr)
verify((addr>>26)==0x38);
}
#if !defined(TARGET_NO_NVMEM)
extern u8* virt_ram_base;
#endif
/*
@ -500,6 +501,8 @@ void ngen_opcode(RuntimeBlockInfo* block, shil_opcode* op,x86_block* x86e, bool
if (size==8 && optimise)
{
die("unreachable");
#ifdef OPTIMIZATION_GRAVEYARD
verify(op->rd.count()==2 && reg.IsAllocf(op->rd,0) && reg.IsAllocf(op->rd,1));
x86e->Emit(op_mov32,EDX,ECX);
@ -507,6 +510,7 @@ void ngen_opcode(RuntimeBlockInfo* block, shil_opcode* op,x86_block* x86e, bool
x86e->Emit(op_movss,reg.mapfv(op->rd,0),x86_mrm(EDX,x86_ptr(virt_ram_base)));
x86e->Emit(op_movss,reg.mapfv(op->rd,1),x86_mrm(EDX,x86_ptr(4+virt_ram_base)));
break;
#endif
}
if (!isram)
{
@ -649,7 +653,7 @@ void ngen_opcode(RuntimeBlockInfo* block, shil_opcode* op,x86_block* x86e, bool
break;
}
#endif
#ifdef OPTIMIZATION_GRAVEYARD
die("woohoo");
/*
if (size==8 && optimise)
@ -827,6 +831,7 @@ void ngen_opcode(RuntimeBlockInfo* block, shil_opcode* op,x86_block* x86e, bool
}
reg.ThawXMM();
}
#endif
}
done_writem:
break;

View File

@ -192,7 +192,11 @@ vram_block* libCore_vramlock_Lock(u32 start_offset64,u32 end_offset64,void* user
vramlist_lock.Lock();
vram.LockRegion(block->start,block->len);
vram.LockRegion(block->start + VRAM_SIZE,block->len);
if (VRAM_SIZE == 0x800000) {
vram.LockRegion(block->start + VRAM_SIZE, block->len);
}
vramlock_list_add(block);
vramlist_lock.Unlock();

View File

@ -201,7 +201,7 @@ struct vram_block
};
#if (DC_PLATFORM==DC_PLATFORM_NORMAL)
#if (DC_PLATFORM==DC_PLATFORM_DREAMCAST)
#define BUILD_DREAMCAST 1
@ -232,9 +232,6 @@ struct vram_block
#define NVR_OPTIONAL 0
#elif (DC_PLATFORM==DC_PLATFORM_NAOMI)
#define BUILD_NAOMI 1
#define BUILD_NAOMI1 1
//Naomi : 32 mb ram, 16 mb vram, 8 mb aram, 2 mb bios, ? flash
#define RAM_SIZE (32*1024*1024)
@ -248,9 +245,6 @@ struct vram_block
#define NVR_OPTIONAL 1
#elif (DC_PLATFORM==DC_PLATFORM_NAOMI2)
#define BUILD_NAOMI 1
#define BUILD_NAOMI2 1
//Naomi2 : 32 mb ram, 16 mb vram, 8 mb aram, 2 mb bios, ? flash
#define RAM_SIZE (32*1024*1024)

View File

@ -126,10 +126,12 @@ LONG ExeptionHandler(EXCEPTION_POINTERS *ExceptionInfo)
{
return EXCEPTION_CONTINUE_EXECUTION;
}
#ifndef TARGET_NO_NVMEM
else if (BM_LockedWrite(address))
{
return EXCEPTION_CONTINUE_EXECUTION;
}
#endif
#if FEAT_SHREC == DYNAREC_JIT && HOST_CPU == CPU_X86
else if ( ngen_Rewrite((unat&)ep->ContextRecord->Eip,*(unat*)ep->ContextRecord->Esp,ep->ContextRecord->Eax) )
{

View File

@ -95,6 +95,8 @@
<ClCompile Include="..\core\hw\maple\maple_helper.cpp" />
<ClCompile Include="..\core\hw\maple\maple_if.cpp" />
<ClCompile Include="..\core\hw\mem\_vmem.cpp" />
<ClCompile Include="..\core\hw\naomi\naomi.cpp" />
<ClCompile Include="..\core\hw\naomi\naomi_cart.cpp" />
<ClCompile Include="..\core\hw\pvr\drkPvr.cpp" />
<ClCompile Include="..\core\hw\pvr\pvr_mem.cpp" />
<ClCompile Include="..\core\hw\pvr\pvr_regs.cpp" />
@ -258,6 +260,9 @@
<ClInclude Include="..\core\hw\maple\maple_helper.h" />
<ClInclude Include="..\core\hw\maple\maple_if.h" />
<ClInclude Include="..\core\hw\mem\_vmem.h" />
<ClInclude Include="..\core\hw\naomi\naomi.h" />
<ClInclude Include="..\core\hw\naomi\naomi_cart.h" />
<ClInclude Include="..\core\hw\naomi\naomi_regs.h" />
<ClInclude Include="..\core\hw\pvr\config.h" />
<ClInclude Include="..\core\hw\pvr\drkPvr.h" />
<ClInclude Include="..\core\hw\pvr\helper_classes.h" />

View File

@ -420,6 +420,12 @@
<ClCompile Include="..\core\rend\soft\softrend.cpp">
<Filter>rend\soft</Filter>
</ClCompile>
<ClCompile Include="..\core\hw\naomi\naomi.cpp">
<Filter>hw\naomi</Filter>
</ClCompile>
<ClCompile Include="..\core\hw\naomi\naomi_cart.cpp">
<Filter>hw\naomi</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Filter Include="hw">
@ -554,6 +560,9 @@
<Filter Include="rend\soft">
<UniqueIdentifier>{6c4b2d69-54c0-4660-9969-a98fd0339a15}</UniqueIdentifier>
</Filter>
<Filter Include="hw\naomi">
<UniqueIdentifier>{1752487d-0739-47bf-8c6b-1d38e6f389f7}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\core\hw\aica\aica.h">
@ -922,6 +931,15 @@
<ClInclude Include="..\core\rec-x86\rec_x86_ngen.h">
<Filter>rec-x86</Filter>
</ClInclude>
<ClInclude Include="..\core\hw\naomi\naomi.h">
<Filter>hw\naomi</Filter>
</ClInclude>
<ClInclude Include="..\core\hw\naomi\naomi_regs.h">
<Filter>hw\naomi</Filter>
</ClInclude>
<ClInclude Include="..\core\hw\naomi\naomi_cart.h">
<Filter>hw\naomi</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\core\deps\zlib\Makefile">