/* PCSX2 - PS2 Emulator for PCs * Copyright (C) 2002-2014 David Quintana [gigaherz] * * PCSX2 is free software: you can redistribute it and/or modify it under the terms * of the GNU Lesser General Public License as published by the Free Software Found- * ation, either version 3 of the License, or (at your option) any later version. * * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with PCSX2. * If not, see . */ #define WINVER 0x0600 #define _WIN32_WINNT 0x0600 #include #include #include #include #include #include #include #include #define EXTERN #include "DEV9.h" #undef EXTERN #include "Config.h" #include "smap.h" #include "ata.h" #ifdef __WIN32__ #pragma warning(disable:4244) HINSTANCE hInst=NULL; #endif //#define HDD_48BIT u8 eeprom[] = { //0x6D, 0x76, 0x63, 0x61, 0x31, 0x30, 0x08, 0x01, 0x76, 0x6D, 0x61, 0x63, 0x30, 0x31, 0x07, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; u32 *iopPC; const unsigned char version = PS2E_DEV9_VERSION; const unsigned char revision = 0; const unsigned char build = 3; // increase that with each version static char *libraryName = "GiGaHeRz's DEV9 Driver" #ifdef _DEBUG "(debug)" #endif ; HANDLE hEeprom; HANDLE mapping; u32 CALLBACK PS2EgetLibType() { return PS2E_LT_DEV9; } char* CALLBACK PS2EgetLibName() { return libraryName; } u32 CALLBACK PS2EgetLibVersion2(u32 type) { return (version<<16) | (revision<<8) | build; } // Warning: The below log function is SLOW. Better fix it before attempting to use it. int Log = 0; void __Log(char *fmt, ...) { if (!Log) return; va_list list; static int ticks=-1; int nticks=GetTickCount(); if(ticks==-1) ticks=nticks; if(iopPC!=NULL) { fprintf(dev9Log,"[%10d + %4d, IOP PC = %08x] ",nticks,nticks-ticks,*iopPC); } else { fprintf(dev9Log,"[%10d + %4d] ",nticks,nticks-ticks); } ticks=nticks; va_start(list, fmt); vfprintf(dev9Log, fmt, list); va_end(list); } s32 CALLBACK DEV9init() { #ifdef DEV9_LOG_ENABLE dev9Log = fopen("logs/dev9Log.txt", "w"); setvbuf(dev9Log, NULL, _IONBF, 0); DEV9_LOG("DEV9init\n"); #endif memset(&dev9, 0, sizeof(dev9)); DEV9_LOG("DEV9init2\n"); DEV9_LOG("DEV9init3\n"); FLASHinit(); hEeprom = CreateFile( "eeprom.dat", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_WRITE_THROUGH, NULL ); if(hEeprom==INVALID_HANDLE_VALUE) { dev9.eeprom=(u16*)eeprom; } else { mapping=CreateFileMapping(hEeprom,NULL,PAGE_READWRITE,0,0,NULL); if(mapping==INVALID_HANDLE_VALUE) { CloseHandle(hEeprom); dev9.eeprom=(u16*)eeprom; } else { dev9.eeprom = (u16*)MapViewOfFile(mapping,FILE_MAP_WRITE,0,0,0); if(dev9.eeprom==NULL) { CloseHandle(mapping); CloseHandle(hEeprom); dev9.eeprom=(u16*)eeprom; } } } { int rxbi; for(rxbi=0;rxbi<(SMAP_BD_SIZE/8);rxbi++) { smap_bd_t *pbd = (smap_bd_t *)&dev9.dev9R[SMAP_BD_RX_BASE & 0xffff]; pbd = &pbd[rxbi]; pbd->ctrl_stat = SMAP_BD_RX_EMPTY; pbd->length = 0; } } DEV9_LOG("DEV9init ok\n"); return 0; } void CALLBACK DEV9shutdown() { DEV9_LOG("DEV9shutdown\n"); #ifdef DEV9_LOG_ENABLE fclose(dev9Log); #endif } bool tx_p_first; s32 CALLBACK DEV9open(void *pDsp) { DEV9_LOG("DEV9open\n"); LoadConf(); DEV9_LOG("open r+: %s\n", config.Hdd); config.HddSize = 8*1024; tx_p_first=false; // reset stack init hack so it works on game reboots iopPC = (u32*)pDsp; #ifdef ENABLE_ATA ata_init(); #endif return _DEV9open(); } void CALLBACK DEV9close() { DEV9_LOG("DEV9close\n"); #ifdef ENABLE_ATA ata_term(); #endif _DEV9close(); } int CALLBACK _DEV9irqHandler(void) { //dev9Ru16(SPD_R_INTR_STAT)|= dev9.irqcause; DEV9_LOG("_DEV9irqHandler %x, %x\n", dev9.irqcause, dev9Ru16(SPD_R_INTR_MASK)); if (dev9.irqcause & dev9Ru16(SPD_R_INTR_MASK)) return 1; return 0; } DEV9handler CALLBACK DEV9irqHandler(void) { return (DEV9handler)_DEV9irqHandler; } void _DEV9irq(int cause, int cycles) { DEV9_LOG("_DEV9irq %x, %x\n", cause, dev9Ru16(SPD_R_INTR_MASK)); dev9.irqcause|= cause; if(cycles<1) DEV9irq(1); else DEV9irq(cycles); } u8 CALLBACK DEV9read8(u32 addr) { u8 hard; if (addr>=ATA_DEV9_HDD_BASE && addr(addr); #else return 0; #endif } if (addr>=SMAP_REGBASE && addr>11; dev9.eeprom_bit++; if(dev9.eeprom_bit==16) { dev9.eeprom_address++; dev9.eeprom_bit=0; } } else hard=0; } else hard=0; return hard; case DEV9_R_REV: hard = 0x32; // expansion bay break; default: if ((addr >= FLASH_REGBASE) && (addr < (FLASH_REGBASE + FLASH_REGSIZE))) { return (u8)FLASHread32(addr, 1); } hard = dev9Ru8(addr); DEV9_LOG("*Unknown 8bit read at address %lx value %x\n", addr, hard); return hard; } DEV9_LOG("*Known 8bit read at address %lx value %x\n", addr, hard); return hard; } u16 CALLBACK DEV9read16(u32 addr) { u16 hard; if (addr>=ATA_DEV9_HDD_BASE && addr(addr); #else return 0; #endif } if (addr>=SMAP_REGBASE && addr= FLASH_REGBASE) && (addr < (FLASH_REGBASE + FLASH_REGSIZE))) { return (u16)FLASHread32(addr, 2); } hard = dev9Ru16(addr); DEV9_LOG("*Unknown 16bit read at address %lx value %x\n", addr, hard); return hard; } DEV9_LOG("*Known 16bit read at address %lx value %x\n", addr, hard); return hard; } u32 CALLBACK DEV9read32(u32 addr) { u32 hard; if (addr>=ATA_DEV9_HDD_BASE && addr(addr); #else return 0; #endif } if (addr>=SMAP_REGBASE && addr= FLASH_REGBASE) && (addr < (FLASH_REGBASE + FLASH_REGSIZE))) { return (u32)FLASHread32(addr, 4); } hard = dev9Ru32(addr); DEV9_LOG("*Unknown 32bit read at address %lx value %x\n", addr, hard); return hard; } DEV9_LOG("*Known 32bit read at address %lx: %lx\n", addr, hard); return hard; } void CALLBACK DEV9write8(u32 addr, u8 value) { if (addr>=ATA_DEV9_HDD_BASE && addr(addr,value); #endif return; } if (addr>=SMAP_REGBASE && addr>4)&3; return; case SPD_R_PIO_DATA: //DEV9_LOG("SPD_R_PIO_DATA 8bit write %x\n", value); if((value&0xc0)!=0xc0) return; switch(dev9.eeprom_state) { case EEPROM_READY: dev9.eeprom_command=0; dev9.eeprom_state++; break; case EEPROM_OPCD0: dev9.eeprom_command = (value>>4)&2; dev9.eeprom_state++; dev9.eeprom_bit=0xFF; break; case EEPROM_OPCD1: dev9.eeprom_command |= (value>>5)&1; dev9.eeprom_state++; break; case EEPROM_ADDR0: case EEPROM_ADDR1: case EEPROM_ADDR2: case EEPROM_ADDR3: case EEPROM_ADDR4: case EEPROM_ADDR5: dev9.eeprom_address = (dev9.eeprom_address&(63^(1<<(dev9.eeprom_state-EEPROM_ADDR0))))| ((value>>(dev9.eeprom_state-EEPROM_ADDR0))&(0x20>>(dev9.eeprom_state-EEPROM_ADDR0))); dev9.eeprom_state++; break; case EEPROM_TDATA: { if(dev9.eeprom_command==1) //write { dev9.eeprom[dev9.eeprom_address] = (dev9.eeprom[dev9.eeprom_address]&(63^(1<>dev9.eeprom_bit)&(0x8000>>dev9.eeprom_bit)); dev9.eeprom_bit++; if(dev9.eeprom_bit==16) { dev9.eeprom_address++; dev9.eeprom_bit=0; } } } break; } return; default: if ((addr >= FLASH_REGBASE) && (addr < (FLASH_REGBASE + FLASH_REGSIZE))) { FLASHwrite32(addr, (u32)value, 1); return; } dev9Ru8(addr) = value; DEV9_LOG("*Unknown 8bit write at address %lx value %x\n", addr, value); return; } dev9Ru8(addr) = value; DEV9_LOG("*Known 8bit write at address %lx value %x\n", addr, value); } void CALLBACK DEV9write16(u32 addr, u16 value) { if (addr>=ATA_DEV9_HDD_BASE && addr(addr,value); #endif return; } if (addr>=SMAP_REGBASE && addr= FLASH_REGBASE) && (addr < (FLASH_REGBASE + FLASH_REGSIZE))) { FLASHwrite32(addr, (u32)value, 2); return; } dev9Ru16(addr) = value; DEV9_LOG("*Unknown 16bit write at address %lx value %x\n", addr, value); return; } dev9Ru16(addr) = value; DEV9_LOG("*Known 16bit write at address %lx value %x\n", addr, value); } void CALLBACK DEV9write32(u32 addr, u32 value) { if (addr>=ATA_DEV9_HDD_BASE && addr(addr,value); #endif return; } if (addr>=SMAP_REGBASE && addr= FLASH_REGBASE) && (addr < (FLASH_REGBASE + FLASH_REGSIZE))) { FLASHwrite32(addr, (u32)value, 4); return; } dev9Ru32(addr) = value; DEV9_LOG("*Unknown 32bit write at address %lx write %x\n", addr, value); return; } dev9Ru32(addr) = value; DEV9_LOG("*Known 32bit write at address %lx value %lx\n", addr, value); } void CALLBACK DEV9readDMA8Mem(u32 *pMem, int size) { DEV9_LOG("*DEV9readDMA8Mem: size %x\n", size); emu_printf("rDMA\n"); smap_readDMA8Mem(pMem,size); #ifdef ENABLE_ATA ata_readDMA8Mem(pMem,size); #endif } void CALLBACK DEV9writeDMA8Mem(u32* pMem, int size) { DEV9_LOG("*DEV9writeDMA8Mem: size %x\n", size); emu_printf("wDMA\n"); smap_writeDMA8Mem(pMem,size); #ifdef ENABLE_ATA ata_writeDMA8Mem(pMem,size); #endif } //plugin interface void CALLBACK DEV9irqCallback(void (*callback)(int cycles)) { DEV9irq = callback; } // extended funcs s32 CALLBACK DEV9test() { return 0; } void CALLBACK DEV9setSettingsDir(const char* dir) { // Grab the ini directory. // TODO: Use // s_strIniPath = (dir == NULL) ? "inis" : dir; } int emu_printf(const char *fmt, ...) { va_list vl; int ret; va_start(vl,fmt); ret = vfprintf(stderr,fmt,vl); va_end(vl); fflush(stderr); return ret; }