diff options
| -rw-r--r-- | src/AREngine.cpp | 77 | ||||
| -rw-r--r-- | src/ARMJIT.cpp | 2 | ||||
| -rw-r--r-- | src/CP15.cpp | 6 | ||||
| -rw-r--r-- | src/Config.cpp | 4 | ||||
| -rw-r--r-- | src/Config.h | 2 | ||||
| -rw-r--r-- | src/DSi.cpp | 71 | ||||
| -rw-r--r-- | src/DSi_NWifi.cpp | 39 | ||||
| -rw-r--r-- | src/DSi_NWifi.h | 4 | ||||
| -rw-r--r-- | src/GPU.h | 1 | ||||
| -rw-r--r-- | src/GPU2D.cpp | 77 | ||||
| -rw-r--r-- | src/GPU3D.cpp | 28 | ||||
| -rw-r--r-- | src/GPU3D_OpenGL.cpp | 349 | ||||
| -rw-r--r-- | src/GPU_OpenGL.cpp | 7 | ||||
| -rw-r--r-- | src/NDS.cpp | 5 | ||||
| -rw-r--r-- | src/NDS.h | 2 | ||||
| -rw-r--r-- | src/SPI.cpp | 26 | ||||
| -rw-r--r-- | src/SPI.h | 1 | ||||
| -rw-r--r-- | src/SPU.cpp | 2 | ||||
| -rw-r--r-- | src/Wifi.cpp | 9 | ||||
| -rw-r--r-- | src/frontend/qt_sdl/Platform.cpp | 4 | ||||
| -rw-r--r-- | src/frontend/qt_sdl/PlatformConfig.cpp | 8 | ||||
| -rw-r--r-- | src/frontend/qt_sdl/PlatformConfig.h | 2 | ||||
| -rw-r--r-- | src/frontend/qt_sdl/VideoSettingsDialog.cpp | 7 | ||||
| -rw-r--r-- | src/frontend/qt_sdl/VideoSettingsDialog.h | 1 | ||||
| -rw-r--r-- | src/frontend/qt_sdl/VideoSettingsDialog.ui | 12 | ||||
| -rw-r--r-- | src/frontend/qt_sdl/WifiSettingsDialog.cpp | 59 | ||||
| -rw-r--r-- | src/frontend/qt_sdl/WifiSettingsDialog.h | 7 | ||||
| -rw-r--r-- | src/frontend/qt_sdl/WifiSettingsDialog.ui | 12 | ||||
| -rw-r--r-- | src/frontend/qt_sdl/main.cpp | 39 | 
29 files changed, 585 insertions, 278 deletions
| diff --git a/src/AREngine.cpp b/src/AREngine.cpp index 8ebf46c..b47bcd4 100644 --- a/src/AREngine.cpp +++ b/src/AREngine.cpp @@ -19,6 +19,7 @@  #include <stdio.h>  #include <string.h>  #include "NDS.h" +#include "DSi.h"  #include "AREngine.h" @@ -28,6 +29,13 @@ namespace AREngine  // AR code file - frontend is responsible for managing this  ARCodeFile* CodeFile; +u8 (*BusRead8)(u32 addr); +u16 (*BusRead16)(u32 addr); +u32 (*BusRead32)(u32 addr); +void (*BusWrite8)(u32 addr, u8 val); +void (*BusWrite16)(u32 addr, u16 val); +void (*BusWrite32)(u32 addr, u32 val); +  bool Init()  { @@ -43,6 +51,25 @@ void DeInit()  void Reset()  {      CodeFile = nullptr; + +    if (NDS::ConsoleType == 1) +    { +        BusRead8 = DSi::ARM7Read8; +        BusRead16 = DSi::ARM7Read16; +        BusRead32 = DSi::ARM7Read32; +        BusWrite8 = DSi::ARM7Write8; +        BusWrite16 = DSi::ARM7Write16; +        BusWrite32 = DSi::ARM7Write32; +    } +    else +    { +        BusRead8 = NDS::ARM7Read8; +        BusRead16 = NDS::ARM7Read16; +        BusRead32 = NDS::ARM7Read32; +        BusWrite8 = NDS::ARM7Write8; +        BusWrite16 = NDS::ARM7Write16; +        BusWrite32 = NDS::ARM7Write32; +    }  } @@ -102,15 +129,15 @@ void RunCheat(ARCode& arcode)          switch (op)          {          case16(0x00): // 32-bit write -            NDS::ARM7Write32((a & 0x0FFFFFFF) + offset, b); +            BusWrite32((a & 0x0FFFFFFF) + offset, b);              break;          case16(0x10): // 16-bit write -            NDS::ARM7Write16((a & 0x0FFFFFFF) + offset, b & 0xFFFF); +            BusWrite16((a & 0x0FFFFFFF) + offset, b & 0xFFFF);              break;          case16(0x20): // 8-bit write -            NDS::ARM7Write8((a & 0x0FFFFFFF) + offset, b & 0xFF); +            BusWrite8((a & 0x0FFFFFFF) + offset, b & 0xFF);              break;          case16(0x30): // IF b > u32[a] @@ -118,7 +145,7 @@ void RunCheat(ARCode& arcode)                  condstack <<= 1;                  condstack |= cond; -                u32 chk = NDS::ARM7Read32(a & 0x0FFFFFFF); +                u32 chk = BusRead32(a & 0x0FFFFFFF);                  cond = (b > chk) ? 1:0;              } @@ -129,7 +156,7 @@ void RunCheat(ARCode& arcode)                  condstack <<= 1;                  condstack |= cond; -                u32 chk = NDS::ARM7Read32(a & 0x0FFFFFFF); +                u32 chk = BusRead32(a & 0x0FFFFFFF);                  cond = (b < chk) ? 1:0;              } @@ -140,7 +167,7 @@ void RunCheat(ARCode& arcode)                  condstack <<= 1;                  condstack |= cond; -                u32 chk = NDS::ARM7Read32(a & 0x0FFFFFFF); +                u32 chk = BusRead32(a & 0x0FFFFFFF);                  cond = (b == chk) ? 1:0;              } @@ -151,7 +178,7 @@ void RunCheat(ARCode& arcode)                  condstack <<= 1;                  condstack |= cond; -                u32 chk = NDS::ARM7Read32(a & 0x0FFFFFFF); +                u32 chk = BusRead32(a & 0x0FFFFFFF);                  cond = (b != chk) ? 1:0;              } @@ -162,7 +189,7 @@ void RunCheat(ARCode& arcode)                  condstack <<= 1;                  condstack |= cond; -                u16 val = NDS::ARM7Read16(a & 0x0FFFFFFF); +                u16 val = BusRead16(a & 0x0FFFFFFF);                  u16 chk = ~(b >> 16);                  chk &= val; @@ -175,7 +202,7 @@ void RunCheat(ARCode& arcode)                  condstack <<= 1;                  condstack |= cond; -                u16 val = NDS::ARM7Read16(a & 0x0FFFFFFF); +                u16 val = BusRead16(a & 0x0FFFFFFF);                  u16 chk = ~(b >> 16);                  chk &= val; @@ -188,7 +215,7 @@ void RunCheat(ARCode& arcode)                  condstack <<= 1;                  condstack |= cond; -                u16 val = NDS::ARM7Read16(a & 0x0FFFFFFF); +                u16 val = BusRead16(a & 0x0FFFFFFF);                  u16 chk = ~(b >> 16);                  chk &= val; @@ -201,7 +228,7 @@ void RunCheat(ARCode& arcode)                  condstack <<= 1;                  condstack |= cond; -                u16 val = NDS::ARM7Read16(a & 0x0FFFFFFF); +                u16 val = BusRead16(a & 0x0FFFFFFF);                  u16 chk = ~(b >> 16);                  chk &= val; @@ -210,7 +237,7 @@ void RunCheat(ARCode& arcode)              break;          case16(0xB0): // offset = u32[a + offset] -            offset = NDS::ARM7Read32((a & 0x0FFFFFFF) + offset); +            offset = BusRead32((a & 0x0FFFFFFF) + offset);              break;          case 0xC0: // FOR 0..b @@ -247,7 +274,7 @@ void RunCheat(ARCode& arcode)              break;          case 0xC6: // u32[b] = offset -            NDS::ARM7Write32(b, offset); +            BusWrite32(b, offset);              break;          case 0xD0: // ENDIF @@ -296,30 +323,30 @@ void RunCheat(ARCode& arcode)              break;          case 0xD6: // u32[b+offset] = datareg / offset += 4 -            NDS::ARM7Write32(b + offset, datareg); +            BusWrite32(b + offset, datareg);              offset += 4;              break;          case 0xD7: // u16[b+offset] = datareg / offset += 2 -            NDS::ARM7Write16(b + offset, datareg & 0xFFFF); +            BusWrite16(b + offset, datareg & 0xFFFF);              offset += 2;              break;          case 0xD8: // u8[b+offset] = datareg / offset += 1 -            NDS::ARM7Write8(b + offset, datareg & 0xFF); +            BusWrite8(b + offset, datareg & 0xFF);              offset += 1;              break;          case 0xD9: // datareg = u32[b+offset] -            datareg = NDS::ARM7Read32(b + offset); +            datareg = BusRead32(b + offset);              break;          case 0xDA: // datareg = u16[b+offset] -            datareg = NDS::ARM7Read16(b + offset); +            datareg = BusRead16(b + offset);              break;          case 0xDB: // datareg = u8[b+offset] -            datareg = NDS::ARM7Read8(b + offset); +            datareg = BusRead8(b + offset);              break;          case 0xDC: // offset += b @@ -334,8 +361,8 @@ void RunCheat(ARCode& arcode)                  u32 bytesleft = b;                  while (bytesleft >= 8)                  { -                    NDS::ARM7Write32(dstaddr, *code++); dstaddr += 4; -                    NDS::ARM7Write32(dstaddr, *code++); dstaddr += 4; +                    BusWrite32(dstaddr, *code++); dstaddr += 4; +                    BusWrite32(dstaddr, *code++); dstaddr += 4;                      bytesleft -= 8;                  }                  if (bytesleft > 0) @@ -344,13 +371,13 @@ void RunCheat(ARCode& arcode)                      code += 2;                      if (bytesleft >= 4)                      { -                        NDS::ARM7Write32(dstaddr, *(u32*)leftover); dstaddr += 4; +                        BusWrite32(dstaddr, *(u32*)leftover); dstaddr += 4;                          leftover += 4;                          bytesleft -= 4;                      }                      while (bytesleft > 0)                      { -                        NDS::ARM7Write8(dstaddr, *leftover++); dstaddr++; +                        BusWrite8(dstaddr, *leftover++); dstaddr++;                          bytesleft--;                      }                  } @@ -366,14 +393,14 @@ void RunCheat(ARCode& arcode)                  u32 bytesleft = b;                  while (bytesleft >= 4)                  { -                    NDS::ARM7Write32(dstaddr, NDS::ARM7Read32(srcaddr)); +                    BusWrite32(dstaddr, BusRead32(srcaddr));                      srcaddr += 4;                      dstaddr += 4;                      bytesleft -= 4;                  }                  while (bytesleft > 0)                  { -                    NDS::ARM7Write8(dstaddr, NDS::ARM7Read8(srcaddr)); +                    BusWrite8(dstaddr, BusRead8(srcaddr));                      srcaddr++;                      dstaddr++;                      bytesleft--; diff --git a/src/ARMJIT.cpp b/src/ARMJIT.cpp index 59f7f54..31983f6 100644 --- a/src/ARMJIT.cpp +++ b/src/ARMJIT.cpp @@ -480,7 +480,7 @@ InterpreterFunc InterpretARM[ARMInstrInfo::ak_Count] =      F_ALU(CMN,),      F(MUL), F(MLA), F(UMULL), F(UMLAL), F(SMULL), F(SMLAL), F(SMLAxy), F(SMLAWy), F(SMULWy), F(SMLALxy), F(SMULxy), -    F(CLZ), F(QADD), F(QDADD), F(QSUB), F(QDSUB), +    F(CLZ), F(QADD), F(QSUB), F(QDADD), F(QDSUB),      F_MEM_WB(STR),      F_MEM_WB(STRB), diff --git a/src/CP15.cpp b/src/CP15.cpp index f6476ab..3f9e79d 100644 --- a/src/CP15.cpp +++ b/src/CP15.cpp @@ -616,11 +616,11 @@ void ARMv5::CP15Write(u32 id, u32 val)      case 0xF00:          //printf("cache debug index register %08X\n", val);          return; -     +      case 0xF10:          //printf("cache debug instruction tag %08X\n", val);          return; -     +      case 0xF20:          //printf("cache debug data tag %08X\n", val);          return; @@ -632,7 +632,7 @@ void ARMv5::CP15Write(u32 id, u32 val)      case 0xF40:          //printf("cache debug data cache %08X\n", val);          return; -     +      }      if ((id & 0xF00) == 0xF00) // test/debug shit? diff --git a/src/Config.cpp b/src/Config.cpp index d198093..949c1bf 100644 --- a/src/Config.cpp +++ b/src/Config.cpp @@ -37,6 +37,8 @@ char DSiBIOS7Path[1024];  char DSiFirmwarePath[1024];  char DSiNANDPath[1024]; +int RandomizeMAC; +  #ifdef JIT_ENABLED  int JIT_Enable = false;  int JIT_MaxBlockSize = 32; @@ -56,6 +58,8 @@ ConfigEntry ConfigFile[] =      {"DSiFirmwarePath", 1, DSiFirmwarePath, 0, "", 1023},      {"DSiNANDPath", 1, DSiNANDPath, 0, "", 1023}, +    {"RandomizeMAC", 0, &RandomizeMAC, 0, NULL, 0}, +  #ifdef JIT_ENABLED      {"JIT_Enable", 0, &JIT_Enable, 0, NULL, 0},      {"JIT_MaxBlockSize", 0, &JIT_MaxBlockSize, 32, NULL, 0}, diff --git a/src/Config.h b/src/Config.h index 5916b4a..a0f09dc 100644 --- a/src/Config.h +++ b/src/Config.h @@ -51,6 +51,8 @@ extern char DSiBIOS7Path[1024];  extern char DSiFirmwarePath[1024];  extern char DSiNANDPath[1024]; +extern int RandomizeMAC; +  #ifdef JIT_ENABLED  extern int JIT_Enable;  extern int JIT_MaxBlockSize; diff --git a/src/DSi.cpp b/src/DSi.cpp index 42541fe..66b8ed0 100644 --- a/src/DSi.cpp +++ b/src/DSi.cpp @@ -699,20 +699,37 @@ void MapNWRAMRange(u32 cpu, u32 num, u32 val)      }  } +void ApplyNewRAMSize(u32 size) +{ +    switch (size) +    { +    case 0: +    case 1: +        NDS::MainRAMMask = 0x3FFFFF; +        printf("RAM: 4MB\n"); +        break; +    case 2: +    case 3: // TODO: debug console w/ 32MB? +        NDS::MainRAMMask = 0xFFFFFF; +        printf("RAM: 16MB\n"); +        break; +    } +} +  void Set_SCFG_Clock9(u16 val)  { -    SCFG_Clock9 = val & 0x0187; -    return; -      NDS::ARM9Timestamp >>= NDS::ARM9ClockShift; +    NDS::ARM9Target    >>= NDS::ARM9ClockShift;      printf("CLOCK9=%04X\n", val);      SCFG_Clock9 = val & 0x0187;      if (SCFG_Clock9 & (1<<0)) NDS::ARM9ClockShift = 2;      else                      NDS::ARM9ClockShift = 1; +      NDS::ARM9Timestamp <<= NDS::ARM9ClockShift; +    NDS::ARM9Target    <<= NDS::ARM9ClockShift;      NDS::ARM9->UpdateRegionTimings(0x00000000, 0xFFFFFFFF);  } @@ -1549,25 +1566,37 @@ void ARM9IOWrite32(u32 addr, u32 val)      switch (addr)      {      case 0x04004008: -        SCFG_EXT[0] &= ~0x8007F19F; -        SCFG_EXT[0] |= (val & 0x8007F19F); -        SCFG_EXT[1] &= ~0x0000F080; -        SCFG_EXT[1] |= (val & 0x0000F080); -        printf("SCFG_EXT = %08X / %08X (val9 %08X)\n", SCFG_EXT[0], SCFG_EXT[1], val); -        /*switch ((SCFG_EXT[0] >> 14) & 0x3)          { -        case 0: -        case 1: -            NDS::MainRAMMask = 0x3FFFFF; -            printf("RAM: 4MB\n"); -            break; -        case 2: -        case 3: // TODO: debug console w/ 32MB? -            NDS::MainRAMMask = 0xFFFFFF; -            printf("RAM: 16MB\n"); -            break; -        }*/ -        printf("from %08X, ARM7 %08X, %08X\n", NDS::GetPC(0), NDS::GetPC(1), NDS::ARM7->R[1]); +            u32 oldram = (SCFG_EXT[0] >> 14) & 0x3; +            u32 newram = (val >> 14) & 0x3; + +            SCFG_EXT[0] &= ~0x8007F19F; +            SCFG_EXT[0] |= (val & 0x8007F19F); +            SCFG_EXT[1] &= ~0x0000F080; +            SCFG_EXT[1] |= (val & 0x0000F080); +            printf("SCFG_EXT = %08X / %08X (val9 %08X)\n", SCFG_EXT[0], SCFG_EXT[1], val); +            /*switch ((SCFG_EXT[0] >> 14) & 0x3) +            { +            case 0: +            case 1: +                NDS::MainRAMMask = 0x3FFFFF; +                printf("RAM: 4MB\n"); +                //baziderp=true; +                break; +            case 2: +            case 3: // TODO: debug console w/ 32MB? +                NDS::MainRAMMask = 0xFFFFFF; +                printf("RAM: 16MB\n"); +                break; +            }*/ +            // HAX!! +            // a change to the RAM size setting is supposed to apply immediately (it does so on hardware) +            // however, doing so will cause DS-mode app startup to break, because the change happens while the ARM7 +            // is still busy clearing/relocating shit +            //if (newram != oldram) +            //    NDS::ScheduleEvent(NDS::Event_DSi_RAMSizeChange, false, 512*512*512, ApplyNewRAMSize, newram); +            printf("from %08X, ARM7 %08X, %08X\n", NDS::GetPC(0), NDS::GetPC(1), NDS::ARM7->R[1]); +        }          return;      case 0x04004040: diff --git a/src/DSi_NWifi.cpp b/src/DSi_NWifi.cpp index 73cf4b4..54719cf 100644 --- a/src/DSi_NWifi.cpp +++ b/src/DSi_NWifi.cpp @@ -165,6 +165,36 @@ void DSi_NWifi::Reset()      printf("NWifi MAC: %02X:%02X:%02X:%02X:%02X:%02X\n",             mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); +    u8 type = SPI_Firmware::GetNWifiVersion(); +    switch (type) +    { +    case 1: // AR6002 +        ROMID = 0x20000188; +        ChipID = 0x02000001; +        HostIntAddr = 0x00500400; +        break; + +    case 2: // AR6013 +        ROMID = 0x23000024; +        ChipID = 0x0D000000; +        HostIntAddr = 0x00520000; +        break; + +    case 3: // AR6014 (3DS) +        ROMID = 0x2300006F; +        ChipID = 0x0D000001; +        HostIntAddr = 0x00520000; +        printf("NWifi: hardware is 3DS type, unchecked\n"); +        break; + +    default: +        printf("NWifi: unknown hardware type %02X, assuming AR6002\n"); +        ROMID = 0x20000188; +        ChipID = 0x02000001; +        HostIntAddr = 0x00500400; +        break; +    } +      memset(EEPROM, 0, 0x400);      *(u32*)&EEPROM[0x000] = 0x300; @@ -755,8 +785,7 @@ void DSi_NWifi::BMI_Command()      case 0x08: // BMI_GET_TARGET_ID          MB_Write32(4, 0xFFFFFFFF);          MB_Write32(4, 0x0000000C); -        //MB_Write32(4, 0x20000118); -        MB_Write32(4, 0x23000024); // ROM version (TODO: how to determine correct one?) +        MB_Write32(4, ROMID);          MB_Write32(4, 0x00000002);          return; @@ -1436,7 +1465,7 @@ u32 DSi_NWifi::WindowRead(u32 addr)  {      printf("NWifi: window read %08X\n", addr); -    if ((addr & 0xFFFF00) == 0x520000) +    if ((addr & 0xFFFF00) == HostIntAddr)      {          // RAM host interest area          // TODO: different base based on hardware version @@ -1462,9 +1491,7 @@ u32 DSi_NWifi::WindowRead(u32 addr)      switch (addr)      {      case 0x40EC: // chip ID -        // 0D000000 / 0D000001 == AR6013 -        // TODO: check firmware.bin to determine the correct value -        return 0x0D000001; +        return ChipID;      // SOC_RESET_CAUSE      case 0x40C0: return 2; diff --git a/src/DSi_NWifi.h b/src/DSi_NWifi.h index a72d54d..7efd40c 100644 --- a/src/DSi_NWifi.h +++ b/src/DSi_NWifi.h @@ -127,6 +127,10 @@ private:      u32 WindowData, WindowReadAddr, WindowWriteAddr; +    u32 ROMID; +    u32 ChipID; +    u32 HostIntAddr; +      u8 EEPROM[0x400];      u32 EEPROMReady; @@ -79,6 +79,7 @@ typedef struct      bool Soft_Threaded;      int GL_ScaleFactor; +    bool GL_BetterPolygons;  } RenderSettings; diff --git a/src/GPU2D.cpp b/src/GPU2D.cpp index 604a4ee..2c3086c 100644 --- a/src/GPU2D.cpp +++ b/src/GPU2D.cpp @@ -35,9 +35,6 @@  // * [Gericom] bit15 is used as bottom green bit for palettes. TODO: check where this applies.  //   tested on the normal BG palette and applies there  // -// oh also, changing DISPCNT bit16-17 midframe doesn't work (ignored? applied for next frame?) -// TODO, eventually: check whether other DISPCNT bits can be changed midframe -//  // for VRAM display mode, VRAM must be mapped to LCDC  //  // FIFO display mode: @@ -78,7 +75,10 @@  // * for rotscaled sprites: coordinates that are inside the sprite are clamped to the sprite region  //   after being transformed for mosaic -// TODO: find which parts of DISPCNT are latched. for example, not possible to change video mode midframe. +// TODO: master brightness, display capture and mainmem FIFO are separate circuitry, distinct from +// the tile renderers. +// for example these aren't affected by POWCNT GPU-disable bits. +// to model the hardware more accurately, the relevant logic should be moved to GPU.cpp.  GPU2D::GPU2D(u32 num) @@ -309,8 +309,6 @@ u32 GPU2D::Read32(u32 addr)  void GPU2D::Write8(u32 addr, u8 val)  { -    if (!Enabled) return; -      switch (addr & 0x00000FFF)      {      case 0x000: @@ -329,7 +327,12 @@ void GPU2D::Write8(u32 addr, u8 val)          DispCnt = (DispCnt & 0x00FFFFFF) | (val << 24);          if (Num) DispCnt &= 0xC0B1FFF7;          return; +    } +    if (!Enabled) return; + +    switch (addr & 0x00000FFF) +    {      case 0x008: BGCnt[0] = (BGCnt[0] & 0xFF00) | val; return;      case 0x009: BGCnt[0] = (BGCnt[0] & 0x00FF) | (val << 8); return;      case 0x00A: BGCnt[1] = (BGCnt[1] & 0xFF00) | val; return; @@ -405,8 +408,6 @@ void GPU2D::Write8(u32 addr, u8 val)  void GPU2D::Write16(u32 addr, u16 val)  { -    if (!Enabled) return; -      switch (addr & 0x00000FFF)      {      case 0x000: @@ -418,6 +419,22 @@ void GPU2D::Write16(u32 addr, u16 val)          if (Num) DispCnt &= 0xC0B1FFF7;          return; +    case 0x068: +        DispFIFO[DispFIFOWritePtr] = val; +        return; +    case 0x06A: +        DispFIFO[DispFIFOWritePtr+1] = val; +        DispFIFOWritePtr += 2; +        DispFIFOWritePtr &= 0xF; +        return; + +    case 0x06C: MasterBrightness = val; return; +    } + +    if (!Enabled) return; + +    switch (addr & 0x00000FFF) +    {      case 0x008: BGCnt[0] = val; return;      case 0x00A: BGCnt[1] = val; return;      case 0x00C: BGCnt[2] = val; return; @@ -526,17 +543,6 @@ void GPU2D::Write16(u32 addr, u16 val)          EVY = val & 0x1F;          if (EVY > 16) EVY = 16;          return; - -    case 0x068: -        DispFIFO[DispFIFOWritePtr] = val; -        return; -    case 0x06A: -        DispFIFO[DispFIFOWritePtr+1] = val; -        DispFIFOWritePtr += 2; -        DispFIFOWritePtr &= 0xF; -        return; - -    case 0x06C: MasterBrightness = val; return;      }      //printf("unknown GPU write16 %08X %04X\n", addr, val); @@ -544,8 +550,6 @@ void GPU2D::Write16(u32 addr, u16 val)  void GPU2D::Write32(u32 addr, u32 val)  { -    if (!Enabled) return; -      switch (addr & 0x00000FFF)      {      case 0x000: @@ -553,6 +557,24 @@ void GPU2D::Write32(u32 addr, u32 val)          if (Num) DispCnt &= 0xC0B1FFF7;          return; +    case 0x064: +        // TODO: check what happens when writing to it during display +        // esp. if a capture is happening +        CaptureCnt = val & 0xEF3F1F1F; +        return; + +    case 0x068: +        DispFIFO[DispFIFOWritePtr] = val & 0xFFFF; +        DispFIFO[DispFIFOWritePtr+1] = val >> 16; +        DispFIFOWritePtr += 2; +        DispFIFOWritePtr &= 0xF; +        return; +    } + +    if (!Enabled) return; + +    switch (addr & 0x00000FFF) +    {      case 0x028:          if (val & 0x08000000) val |= 0xF0000000;          BGXRef[0] = val; @@ -574,19 +596,6 @@ void GPU2D::Write32(u32 addr, u32 val)          BGYRef[1] = val;          if (GPU::VCount < 192) BGYRefInternal[1] = BGYRef[1];          return; - -    case 0x064: -        // TODO: check what happens when writing to it during display -        // esp. if a capture is happening -        CaptureCnt = val & 0xEF3F1F1F; -        return; - -    case 0x068: -        DispFIFO[DispFIFOWritePtr] = val & 0xFFFF; -        DispFIFO[DispFIFOWritePtr+1] = val >> 16; -        DispFIFOWritePtr += 2; -        DispFIFOWritePtr &= 0xF; -        return;      }      Write16(addr, val&0xFFFF); diff --git a/src/GPU3D.cpp b/src/GPU3D.cpp index bd27783..d9d6ba8 100644 --- a/src/GPU3D.cpp +++ b/src/GPU3D.cpp @@ -401,8 +401,33 @@ void DoSavestate(Savestate* file)      file->Var32(&NumTestCommands);      file->Var32(&DispCnt); +    file->Var8(&AlphaRefVal);      file->Var8(&AlphaRef); +    file->VarArray(ToonTable, 32*2); +    file->VarArray(EdgeTable, 8*2); + +    file->Var32(&FogColor); +    file->Var32(&FogOffset); +    file->VarArray(FogDensityTable, 32); + +    file->Var32(&ClearAttr1); +    file->Var32(&ClearAttr2); + +    file->Var32(&RenderDispCnt); +    file->Var8(&RenderAlphaRef); + +    file->VarArray(RenderToonTable, 32*2); +    file->VarArray(RenderEdgeTable, 8*2); + +    file->Var32(&RenderFogColor); +    file->Var32(&RenderFogOffset); +    file->Var32(&RenderFogShift); +    file->VarArray(RenderFogDensityTable, 34); + +    file->Var32(&RenderClearAttr1); +    file->Var32(&RenderClearAttr2); +      file->Var32(&ZeroDotWLimit);      file->Var32(&GXStat); @@ -471,9 +496,6 @@ void DoSavestate(Savestate* file)      file->Var32(&NumPolygons);      file->Var32(&NumOpaquePolygons); -    file->Var32(&ClearAttr1); -    file->Var32(&ClearAttr2); -      file->Var32(&FlushRequest);      file->Var32(&FlushAttributes); diff --git a/src/GPU3D_OpenGL.cpp b/src/GPU3D_OpenGL.cpp index 8a06874..658b261 100644 --- a/src/GPU3D_OpenGL.cpp +++ b/src/GPU3D_OpenGL.cpp @@ -113,7 +113,7 @@ GLuint TexMemID;  GLuint TexPalMemID;  int ScaleFactor; -bool Antialias; +bool BetterPolygons;  int ScreenW, ScreenH;  GLuint FramebufferTex[8]; @@ -342,9 +342,6 @@ bool Init()      SetupDefaultTexParams(FramebufferTex[5]);      SetupDefaultTexParams(FramebufferTex[7]); -    // downscale framebuffer for antialiased mode -    SetupDefaultTexParams(FramebufferTex[2]); -      // downscale framebuffer for display capture (always 256x192)      SetupDefaultTexParams(FramebufferTex[3]);      glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 192, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); @@ -372,6 +369,8 @@ bool Init()      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);      glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB5_A1, 1024, 48, 0, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, NULL); +    glBindFramebuffer(GL_FRAMEBUFFER, 0); +      return true;  } @@ -404,52 +403,27 @@ void Reset()  void SetRenderSettings(GPU::RenderSettings& settings)  {      int scale = settings.GL_ScaleFactor; -    bool antialias = false; // REMOVE ME! - -    if (antialias) scale *= 2;      ScaleFactor = scale; -    Antialias = antialias; +    BetterPolygons = settings.GL_BetterPolygons;      ScreenW = 256 * scale;      ScreenH = 192 * scale; -    if (!antialias) -    { -        glBindTexture(GL_TEXTURE_2D, FramebufferTex[0]); -        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ScreenW, ScreenH, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); -        glBindTexture(GL_TEXTURE_2D, FramebufferTex[1]); -        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ScreenW, ScreenH, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); -        glBindTexture(GL_TEXTURE_2D, FramebufferTex[2]); -        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); -        glBindTexture(GL_TEXTURE_2D, FramebufferTex[4]); -        glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, ScreenW, ScreenH, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL); -        //glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH32F_STENCIL8, ScreenW, ScreenH, 0, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, NULL); -        glBindTexture(GL_TEXTURE_2D, FramebufferTex[5]); -        //glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8UI, ScreenW, ScreenH, 0, GL_RGB_INTEGER, GL_UNSIGNED_BYTE, NULL); -        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, ScreenW, ScreenH, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); -        glBindTexture(GL_TEXTURE_2D, FramebufferTex[6]); -        glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, 1, 1, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL); -        glBindTexture(GL_TEXTURE_2D, FramebufferTex[7]); -        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8UI, 1, 1, 0, GL_RGB_INTEGER, GL_UNSIGNED_BYTE, NULL); -    } -    else -    { -        glBindTexture(GL_TEXTURE_2D, FramebufferTex[0]); -        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ScreenW/2, ScreenH/2, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); -        glBindTexture(GL_TEXTURE_2D, FramebufferTex[1]); -        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ScreenW/2, ScreenH/2, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); -        glBindTexture(GL_TEXTURE_2D, FramebufferTex[2]); -        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ScreenW, ScreenH, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); -        glBindTexture(GL_TEXTURE_2D, FramebufferTex[4]); -        glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, ScreenW/2, ScreenH/2, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL); -        glBindTexture(GL_TEXTURE_2D, FramebufferTex[5]); -        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8UI, ScreenW/2, ScreenH/2, 0, GL_RGB_INTEGER, GL_UNSIGNED_BYTE, NULL); -        glBindTexture(GL_TEXTURE_2D, FramebufferTex[6]); -        glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, ScreenW, ScreenH, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL); -        glBindTexture(GL_TEXTURE_2D, FramebufferTex[7]); -        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8UI, ScreenW, ScreenH, 0, GL_RGB_INTEGER, GL_UNSIGNED_BYTE, NULL); -    } +    glBindTexture(GL_TEXTURE_2D, FramebufferTex[0]); +    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ScreenW, ScreenH, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); +    glBindTexture(GL_TEXTURE_2D, FramebufferTex[1]); +    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ScreenW, ScreenH, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + +    glBindTexture(GL_TEXTURE_2D, FramebufferTex[4]); +    glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, ScreenW, ScreenH, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL); +    glBindTexture(GL_TEXTURE_2D, FramebufferTex[5]); +    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, ScreenW, ScreenH, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); + +    glBindTexture(GL_TEXTURE_2D, FramebufferTex[6]); +    glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, ScreenW, ScreenH, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL); +    glBindTexture(GL_TEXTURE_2D, FramebufferTex[7]); +    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, ScreenW, ScreenH, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);      glBindFramebuffer(GL_FRAMEBUFFER, FramebufferID[3]);      glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, FramebufferTex[3], 0); @@ -464,12 +438,6 @@ void SetRenderSettings(GPU::RenderSettings& settings)      glBindFramebuffer(GL_FRAMEBUFFER, FramebufferID[1]);      glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, FramebufferTex[1], 0); -    glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, FramebufferTex[4], 0); -    glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, FramebufferTex[5], 0); -    glDrawBuffers(2, fbassign); - -    glBindFramebuffer(GL_FRAMEBUFFER, FramebufferID[2]); -    glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, FramebufferTex[2], 0);      glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, FramebufferTex[6], 0);      glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, FramebufferTex[7], 0);      glDrawBuffers(2, fbassign); @@ -479,6 +447,8 @@ void SetRenderSettings(GPU::RenderSettings& settings)      glBindBuffer(GL_PIXEL_PACK_BUFFER, PixelbufferID);      glBufferData(GL_PIXEL_PACK_BUFFER, 256*192*4, NULL, GL_DYNAMIC_READ); +    glBindFramebuffer(GL_FRAMEBUFFER, 0); +      //glLineWidth(scale);      //glLineWidth(1.5);  } @@ -527,6 +497,67 @@ void SetupPolygon(RendererPolygon* rp, Polygon* polygon)      }  } +u32* SetupVertex(Polygon* poly, int vid, Vertex* vtx, u32 vtxattr, u32* vptr) +{ +    u32 z = poly->FinalZ[vid]; +    u32 w = poly->FinalW[vid]; + +    u32 alpha = (poly->Attr >> 16) & 0x1F; + +    // Z should always fit within 16 bits, so it's okay to do this +    u32 zshift = 0; +    while (z > 0xFFFF) { z >>= 1; zshift++; } + +    u32 x, y; +    if (ScaleFactor > 1) +    { +        x = (vtx->HiresPosition[0] * ScaleFactor) >> 4; +        y = (vtx->HiresPosition[1] * ScaleFactor) >> 4; +    } +    else +    { +        x = vtx->FinalPosition[0]; +        y = vtx->FinalPosition[1]; +    } + +    // correct nearly-vertical edges that would look vertical on the DS +    /*{ +        int vtopid = vid - 1; +        if (vtopid < 0) vtopid = poly->NumVertices-1; +        Vertex* vtop = poly->Vertices[vtopid]; +        if (vtop->FinalPosition[1] >= vtx->FinalPosition[1]) +        { +            vtopid = vid + 1; +            if (vtopid >= poly->NumVertices) vtopid = 0; +            vtop = poly->Vertices[vtopid]; +        } +        if ((vtop->FinalPosition[1] < vtx->FinalPosition[1]) && +            (vtx->FinalPosition[0] == vtop->FinalPosition[0]-1)) +        { +            if (ScaleFactor > 1) +                x = (vtop->HiresPosition[0] * ScaleFactor) >> 4; +            else +                x = vtop->FinalPosition[0]; +        } +    }*/ + +    *vptr++ = x | (y << 16); +    *vptr++ = z | (w << 16); + +    *vptr++ =  (vtx->FinalColor[0] >> 1) | +              ((vtx->FinalColor[1] >> 1) << 8) | +              ((vtx->FinalColor[2] >> 1) << 16) | +              (alpha << 24); + +    *vptr++ = (u16)vtx->TexCoords[0] | ((u16)vtx->TexCoords[1] << 16); + +    *vptr++ = vtxattr | (zshift << 16); +    *vptr++ = poly->TexParam; +    *vptr++ = poly->TexPalette; + +    return vptr; +} +  void BuildPolygons(RendererPolygon* polygons, int npolys)  {      u32* vptr = &VertexBuffer[0]; @@ -564,43 +595,16 @@ void BuildPolygons(RendererPolygon* polygons, int npolys)              {                  Vertex* vtx = poly->Vertices[j]; -                u32 z = poly->FinalZ[j]; -                u32 w = poly->FinalW[j]; - -                // Z should always fit within 16 bits, so it's okay to do this -                u32 zshift = 0; -                while (z > 0xFFFF) { z >>= 1; zshift++; } - -                u32 x, y; -                if (ScaleFactor > 1) -                { -                    x = (vtx->HiresPosition[0] * ScaleFactor) >> 4; -                    y = (vtx->HiresPosition[1] * ScaleFactor) >> 4; -                } -                else -                { -                    x = vtx->FinalPosition[0]; -                    y = vtx->FinalPosition[1]; -                } -                  if (j > 0)                  { -                    if (lastx == x && lasty == y) continue; +                    if (lastx == vtx->FinalPosition[0] && +                        lasty == vtx->FinalPosition[1]) continue;                  } -                *vptr++ = x | (y << 16); -                *vptr++ = z | (w << 16); +                lastx = vtx->FinalPosition[0]; +                lasty = vtx->FinalPosition[1]; -                *vptr++ =  (vtx->FinalColor[0] >> 1) | -                          ((vtx->FinalColor[1] >> 1) << 8) | -                          ((vtx->FinalColor[2] >> 1) << 16) | -                          (alpha << 24); - -                *vptr++ = (u16)vtx->TexCoords[0] | ((u16)vtx->TexCoords[1] << 16); - -                *vptr++ = vtxattr | (zshift << 16); -                *vptr++ = poly->TexParam; -                *vptr++ = poly->TexPalette; +                vptr = SetupVertex(poly, j, vtx, vtxattr, vptr);                  *iptr++ = vidx;                  rp->NumIndices++; @@ -610,57 +614,148 @@ void BuildPolygons(RendererPolygon* polygons, int npolys)                  if (nout >= 2) break;              }          } -        else +        else if (poly->NumVertices == 3) // regular triangle          {              rp->PrimType = GL_TRIANGLES; -            for (int j = 0; j < poly->NumVertices; j++) +            for (int j = 0; j < 3; j++)              {                  Vertex* vtx = poly->Vertices[j]; -                u32 z = poly->FinalZ[j]; -                u32 w = poly->FinalW[j]; +                vptr = SetupVertex(poly, j, vtx, vtxattr, vptr); +                vidx++; +            } -                // Z should always fit within 16 bits, so it's okay to do this -                u32 zshift = 0; -                while (z > 0xFFFF) { z >>= 1; zshift++; } +            // build a triangle +            *iptr++ = vidx_first; +            *iptr++ = vidx - 2; +            *iptr++ = vidx - 1; +            rp->NumIndices += 3; +        } +        else // quad, pentagon, etc +        { +            rp->PrimType = GL_TRIANGLES; + +            if (!BetterPolygons) +            { +                // regular triangle-splitting -                u32 x, y; -                if (ScaleFactor > 1) +                for (int j = 0; j < poly->NumVertices; j++)                  { -                    x = (vtx->HiresPosition[0] * ScaleFactor) >> 4; -                    y = (vtx->HiresPosition[1] * ScaleFactor) >> 4; +                    Vertex* vtx = poly->Vertices[j]; + +                    vptr = SetupVertex(poly, j, vtx, vtxattr, vptr); + +                    if (j >= 2) +                    { +                        // build a triangle +                        *iptr++ = vidx_first; +                        *iptr++ = vidx - 1; +                        *iptr++ = vidx; +                        rp->NumIndices += 3; +                    } + +                    vidx++;                  } -                else +            } +            else +            { +                // attempt at 'better' splitting +                // this doesn't get rid of the error while splitting a bigger polygon into triangles +                // but we can attempt to reduce it + +                u32 cX = 0, cY = 0; +                float cZ = 0; +                float cW = 0; + +                float cR = 0, cG = 0, cB = 0; +                float cS = 0, cT = 0; + +                for (int j = 0; j < poly->NumVertices; j++)                  { -                    x = vtx->FinalPosition[0]; -                    y = vtx->FinalPosition[1]; +                    Vertex* vtx = poly->Vertices[j]; + +                    cX += vtx->HiresPosition[0]; +                    cY += vtx->HiresPosition[1]; + +                    float fw = (float)poly->FinalW[j] * poly->NumVertices; +                    cW += 1.0f / fw; + +                    if (poly->WBuffer) cZ += poly->FinalZ[j] / fw; +                    else               cZ += poly->FinalZ[j]; + +                    cR += (vtx->FinalColor[0] >> 1) / fw; +                    cG += (vtx->FinalColor[1] >> 1) / fw; +                    cB += (vtx->FinalColor[2] >> 1) / fw; + +                    cS += vtx->TexCoords[0] / fw; +                    cT += vtx->TexCoords[1] / fw;                  } -                *vptr++ = x | (y << 16); +                cX /= poly->NumVertices; +                cY /= poly->NumVertices; + +                cW = 1.0f / cW; + +                if (poly->WBuffer) cZ *= cW; +                else               cZ /= poly->NumVertices; + +                cR *= cW; +                cG *= cW; +                cB *= cW; + +                cS *= cW; +                cT *= cW; + +                cX = (cX * ScaleFactor) >> 4; +                cY = (cY * ScaleFactor) >> 4; + +                u32 w = (u32)cW; + +                u32 z = (u32)cZ; +                u32 zshift = 0; +                while (z > 0xFFFF) { z >>= 1; zshift++; } + +                // build center vertex +                *vptr++ = cX | (cY << 16);                  *vptr++ = z | (w << 16); -                *vptr++ =  (vtx->FinalColor[0] >> 1) | -                          ((vtx->FinalColor[1] >> 1) << 8) | -                          ((vtx->FinalColor[2] >> 1) << 16) | +                *vptr++ =  (u32)cR | +                          ((u32)cG << 8) | +                          ((u32)cB << 16) |                            (alpha << 24); -                *vptr++ = (u16)vtx->TexCoords[0] | ((u16)vtx->TexCoords[1] << 16); +                *vptr++ = (u16)cS | ((u16)cT << 16);                  *vptr++ = vtxattr | (zshift << 16);                  *vptr++ = poly->TexParam;                  *vptr++ = poly->TexPalette; -                if (j >= 2) +                vidx++; + +                // build the final polygon +                for (int j = 0; j < poly->NumVertices; j++)                  { -                    // build a triangle -                    *iptr++ = vidx_first; -                    *iptr++ = vidx - 1; -                    *iptr++ = vidx; -                    rp->NumIndices += 3; +                    Vertex* vtx = poly->Vertices[j]; + +                    vptr = SetupVertex(poly, j, vtx, vtxattr, vptr); + +                    if (j >= 1) +                    { +                        // build a triangle +                        *iptr++ = vidx_first; +                        *iptr++ = vidx - 1; +                        *iptr++ = vidx; +                        rp->NumIndices += 3; +                    } + +                    vidx++;                  } -                vidx++; +                *iptr++ = vidx_first; +                *iptr++ = vidx - 1; +                *iptr++ = vidx_first + 1; +                rp->NumIndices += 3;              }          } @@ -741,6 +836,10 @@ void RenderSceneChunk(int y, int h)      GLboolean fogenable = (RenderDispCnt & (1<<7)) ? GL_TRUE : GL_FALSE; +    // TODO: proper 'equal' depth test! +    // (has margin of +-0x200 in Z-buffer mode, +-0xFF in W-buffer mode) +    // for now we're using GL_LEQUAL to make it work to some extent +      // pass 1: opaque pixels      UseRenderShader(flags); @@ -759,8 +858,10 @@ void RenderSceneChunk(int y, int h)          if (rp->PolyData->IsShadowMask) { i++; continue; } -        // zorp -        glDepthFunc(GL_LESS); +        if (rp->PolyData->Attr & (1<<14)) +            glDepthFunc(GL_LEQUAL); +        else +            glDepthFunc(GL_LESS);          u32 polyattr = rp->PolyData->Attr;          u32 polyid = (polyattr >> 24) & 0x3F; @@ -845,8 +946,10 @@ void RenderSceneChunk(int y, int h)                  {                      UseRenderShader(flags | RenderFlag_Trans); -                    // zorp -                    glDepthFunc(GL_LESS); +                    if (rp->PolyData->Attr & (1<<14)) +                        glDepthFunc(GL_LEQUAL); +                    else +                        glDepthFunc(GL_LESS);                      u32 polyattr = rp->PolyData->Attr;                      u32 polyid = (polyattr >> 24) & 0x3F; @@ -936,8 +1039,10 @@ void RenderSceneChunk(int y, int h)                  if (!(polyattr & (1<<15))) transfog = fogenable;                  else                       transfog = GL_FALSE; -                // zorp -                glDepthFunc(GL_LESS); +                if (rp->PolyData->Attr & (1<<14)) +                    glDepthFunc(GL_LEQUAL); +                else +                    glDepthFunc(GL_LESS);                  if (rp->PolyData->IsShadow)                  { @@ -1003,9 +1108,9 @@ void RenderSceneChunk(int y, int h)          glStencilMask(0);          glActiveTexture(GL_TEXTURE0); -        glBindTexture(GL_TEXTURE_2D, FramebufferTex[4]); +        glBindTexture(GL_TEXTURE_2D, FramebufferTex[FrontBuffer ? 6 : 4]);          glActiveTexture(GL_TEXTURE1); -        glBindTexture(GL_TEXTURE_2D, FramebufferTex[5]); +        glBindTexture(GL_TEXTURE_2D, FramebufferTex[FrontBuffer ? 7 : 5]);          glBindBuffer(GL_ARRAY_BUFFER, ClearVertexBufferID);          glBindVertexArray(ClearVertexArrayID); @@ -1055,8 +1160,8 @@ void RenderFrame()  {      CurShaderID = -1; -    if (Antialias) glBindFramebuffer(GL_FRAMEBUFFER, FramebufferID[2]); -    else           glBindFramebuffer(GL_FRAMEBUFFER, FramebufferID[FrontBuffer]); +    glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); +    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, FramebufferID[FrontBuffer]);      ShaderConfig.uScreenSize[0] = ScreenW;      ShaderConfig.uScreenSize[1] = ScreenH; @@ -1218,14 +1323,6 @@ void RenderFrame()          RenderSceneChunk(0, 192);      } -    if (Antialias) -    { -        glBindFramebuffer(GL_READ_FRAMEBUFFER, FramebufferID[2]); -        glBindFramebuffer(GL_DRAW_FRAMEBUFFER, FramebufferID[FrontBuffer]); -        glBlitFramebuffer(0, 0, ScreenW, ScreenH, 0, 0, ScreenW/2, ScreenH/2, GL_COLOR_BUFFER_BIT, GL_LINEAR); -    } - -    //glBindFramebuffer(GL_FRAMEBUFFER, FramebufferID[FrontBuffer]);      FrontBuffer = FrontBuffer ? 0 : 1;  } diff --git a/src/GPU_OpenGL.cpp b/src/GPU_OpenGL.cpp index 1cb6864..359e9cd 100644 --- a/src/GPU_OpenGL.cpp +++ b/src/GPU_OpenGL.cpp @@ -121,6 +121,8 @@ bool Init()      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); +    glBindFramebuffer(GL_FRAMEBUFFER, 0); +      return true;  } @@ -157,12 +159,15 @@ void SetRenderSettings(RenderSettings& settings)      glBindFramebuffer(GL_FRAMEBUFFER, CompScreenOutputFB);      glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, CompScreenOutputTex, 0);      glDrawBuffers(1, fbassign); + +    glBindFramebuffer(GL_FRAMEBUFFER, 0);  }  void RenderFrame()  { -    glBindFramebuffer(GL_FRAMEBUFFER, CompScreenOutputFB); +    glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); +    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, CompScreenOutputFB);      glDisable(GL_DEPTH_TEST);      glDisable(GL_STENCIL_TEST); diff --git a/src/NDS.cpp b/src/NDS.cpp index 823d39a..bb579f6 100644 --- a/src/NDS.cpp +++ b/src/NDS.cpp @@ -1817,15 +1817,16 @@ void debug(u32 param)          fwrite(&val, 4, 1, shit);      }      fclose(shit);*/ +      FILE* -    shit = fopen("debug/dump9.bin", "wb"); +    shit = fopen("debug/picto9.bin", "wb");      for (u32 i = 0x02000000; i < 0x04000000; i+=4)      {          u32 val = DSi::ARM9Read32(i);          fwrite(&val, 4, 1, shit);      }      fclose(shit); -    shit = fopen("debug/dump7.bin", "wb"); +    shit = fopen("debug/picto7.bin", "wb");      for (u32 i = 0x02000000; i < 0x04000000; i+=4)      {          u32 val = DSi::ARM7Read32(i); @@ -47,6 +47,8 @@ enum      Event_DSi_SDIOTransfer,      Event_DSi_NWifi, +    Event_DSi_RAMSizeChange, +      Event_MAX  }; diff --git a/src/SPI.cpp b/src/SPI.cpp index eff0a05..2ba5e66 100644 --- a/src/SPI.cpp +++ b/src/SPI.cpp @@ -179,24 +179,25 @@ void Reset()          //Firmware[userdata+0x64] &= 0xBF;          *(u16*)&Firmware[userdata+0x72] = CRC16(&Firmware[userdata], 0x70, 0xFFFF); + +        if (Config::RandomizeMAC) +        { +            // replace MAC address with random address +            Firmware[0x36] = 0x00; +            Firmware[0x37] = 0x09; +            Firmware[0x38] = 0xBF; +            Firmware[0x39] = rand()&0xFF; +            Firmware[0x3A] = rand()&0xFF; +            Firmware[0x3B] = rand()&0xFF; + +            *(u16*)&Firmware[0x2A] = CRC16(&Firmware[0x2C], *(u16*)&Firmware[0x2C], 0x0000); +        }      } -#if 0 -    // replace MAC address with random address -    // TODO: make optional? -    Firmware[0x36] = 0x00; -    Firmware[0x37] = 0x09; -    Firmware[0x38] = 0xBF; -    Firmware[0x39] = rand()&0xFF; -    Firmware[0x3A] = rand()&0xFF; -    Firmware[0x3B] = rand()&0xFF; -#endif      printf("MAC: %02X:%02X:%02X:%02X:%02X:%02X\n",             Firmware[0x36], Firmware[0x37], Firmware[0x38],             Firmware[0x39], Firmware[0x3A], Firmware[0x3B]); -    //*(u16*)&Firmware[0x2A] = CRC16(&Firmware[0x2C], *(u16*)&Firmware[0x2C], 0x0000); -      // verify shit      printf("FW: WIFI CRC16 = %s\n", VerifyCRC16(0x0000, 0x2C, *(u16*)&Firmware[0x2C], 0x2A)?"GOOD":"BAD");      printf("FW: AP1 CRC16 = %s\n", VerifyCRC16(0x0000, 0x7FA00&FirmwareMask, 0xFE, 0x7FAFE&FirmwareMask)?"GOOD":"BAD"); @@ -241,6 +242,7 @@ void SetupDirectBoot()  u8 GetConsoleType() { return Firmware[0x1D]; }  u8 GetWifiVersion() { return Firmware[0x2F]; } +u8 GetNWifiVersion() { return Firmware[0x1FD]; } // for DSi; will return 0xFF on a DS  u8 GetRFVersion() { return Firmware[0x40]; }  u8* GetWifiMAC() { return &Firmware[0x36]; } @@ -28,6 +28,7 @@ void SetupDirectBoot();  u8 GetConsoleType();  u8 GetWifiVersion(); +u8 GetNWifiVersion();  u8 GetRFVersion();  u8* GetWifiMAC(); diff --git a/src/SPU.cpp b/src/SPU.cpp index cd5c5b8..5b74bda 100644 --- a/src/SPU.cpp +++ b/src/SPU.cpp @@ -420,6 +420,8 @@ void Channel::Run(s32* buf, u32 samples)  {      if (!(Cnt & (1<<31))) return; +    if ((type < 3) && ((Length+LoopPos) < 16)) return; +      if (KeyOn)      {          Start(); diff --git a/src/Wifi.cpp b/src/Wifi.cpp index 8188151..8a06041 100644 --- a/src/Wifi.cpp +++ b/src/Wifi.cpp @@ -816,6 +816,9 @@ bool CheckRX(bool block)      if (!(IOPORT(W_RXCnt) & 0x8000))          return false; +    if (IOPORT(W_RXBufBegin) == IOPORT(W_RXBufEnd)) +        return false; +      u16 framelen;      u16 framectl;      u8 txrate; @@ -1049,7 +1052,7 @@ void USTimer(u32 param)          if (!(RXTime & RXHalfwordTimeMask))          {              u16 addr = IOPORT(W_RXTXAddr) << 1; -            *(u16*)&RAM[addr] = *(u16*)&RXBuffer[RXBufferPtr]; +            if (addr < 0x1FFF) *(u16*)&RAM[addr] = *(u16*)&RXBuffer[RXBufferPtr];              IncrementRXAddr(addr);              RXBufferPtr += 2; @@ -1146,7 +1149,7 @@ void RFTransfer_Type3()  // TODO: wifi waitstates  u16 Read(u32 addr) -{ +{//printf("WIFI READ %08X\n", addr);      if (addr >= 0x04810000)          return 0; @@ -1236,7 +1239,7 @@ u16 Read(u32 addr)  }  void Write(u32 addr, u16 val) -{ +{//printf("WIFI WRITE %08X %04X\n", addr, val);      if (addr >= 0x04810000)          return; diff --git a/src/frontend/qt_sdl/Platform.cpp b/src/frontend/qt_sdl/Platform.cpp index 05a0c2d..b9d3235 100644 --- a/src/frontend/qt_sdl/Platform.cpp +++ b/src/frontend/qt_sdl/Platform.cpp @@ -77,7 +77,7 @@ u8 PacketBuffer[2048];  void Init(int argc, char** argv)  { -#if defined(__WIN32__) || defined(UNIX_PORTABLE) +#if defined(__WIN32__) || defined(PORTABLE)      if (argc > 0 && strlen(argv[0]) > 0)      {          int len = strlen(argv[0]); @@ -167,7 +167,7 @@ FILE* OpenLocalFile(const char* path, const char* mode)      else      {  #ifdef PORTABLE -        fullpath = path; +        fullpath = QString(EmuDirectory) + QDir::separator() + path;  #else          // Check user configuration directory          QDir config(QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation)); diff --git a/src/frontend/qt_sdl/PlatformConfig.cpp b/src/frontend/qt_sdl/PlatformConfig.cpp index 76c5f4b..4468d0e 100644 --- a/src/frontend/qt_sdl/PlatformConfig.cpp +++ b/src/frontend/qt_sdl/PlatformConfig.cpp @@ -51,7 +51,7 @@ int _3DRenderer;  int Threaded3D;  int GL_ScaleFactor; -int GL_Antialias; +int GL_BetterPolygons;  int LimitFPS;  int AudioSync; @@ -135,15 +135,15 @@ ConfigEntry PlatformConfigFile[] =      {"IntegerScaling", 0, &IntegerScaling, 0, NULL, 0},      {"ScreenFilter",   0, &ScreenFilter,   1, NULL, 0}, -    {"ScreenUseGL",         0, &ScreenUseGL,         1, NULL, 0}, +    {"ScreenUseGL",         0, &ScreenUseGL,         0, NULL, 0},      {"ScreenVSync",         0, &ScreenVSync,         0, NULL, 0},      {"ScreenVSyncInterval", 0, &ScreenVSyncInterval, 1, NULL, 0}, -    {"3DRenderer", 0, &_3DRenderer, 1, NULL, 0}, +    {"3DRenderer", 0, &_3DRenderer, 0, NULL, 0},      {"Threaded3D", 0, &Threaded3D, 1, NULL, 0},      {"GL_ScaleFactor", 0, &GL_ScaleFactor, 1, NULL, 0}, -    {"GL_Antialias", 0, &GL_Antialias, 0, NULL, 0}, +    {"GL_BetterPolygons", 0, &GL_BetterPolygons, 0, NULL, 0},      {"LimitFPS", 0, &LimitFPS, 0, NULL, 0},      {"AudioSync", 0, &AudioSync, 1, NULL, 0}, diff --git a/src/frontend/qt_sdl/PlatformConfig.h b/src/frontend/qt_sdl/PlatformConfig.h index bc9bba4..9deee7f 100644 --- a/src/frontend/qt_sdl/PlatformConfig.h +++ b/src/frontend/qt_sdl/PlatformConfig.h @@ -64,7 +64,7 @@ extern int _3DRenderer;  extern int Threaded3D;  extern int GL_ScaleFactor; -extern int GL_Antialias; +extern int GL_BetterPolygons;  extern int LimitFPS;  extern int AudioSync; diff --git a/src/frontend/qt_sdl/VideoSettingsDialog.cpp b/src/frontend/qt_sdl/VideoSettingsDialog.cpp index ba433c3..ac1ed7a 100644 --- a/src/frontend/qt_sdl/VideoSettingsDialog.cpp +++ b/src/frontend/qt_sdl/VideoSettingsDialog.cpp @@ -167,3 +167,10 @@ void VideoSettingsDialog::on_cbxGLResolution_currentIndexChanged(int idx)      emit updateVideoSettings(false);  } + +void VideoSettingsDialog::on_cbBetterPolygons_stateChanged(int state) +{ +    Config::GL_BetterPolygons = (state != 0); + +    emit updateVideoSettings(false); +} diff --git a/src/frontend/qt_sdl/VideoSettingsDialog.h b/src/frontend/qt_sdl/VideoSettingsDialog.h index 2311d4d..f18793c 100644 --- a/src/frontend/qt_sdl/VideoSettingsDialog.h +++ b/src/frontend/qt_sdl/VideoSettingsDialog.h @@ -64,6 +64,7 @@ private slots:      void on_sbVSyncInterval_valueChanged(int val);      void on_cbxGLResolution_currentIndexChanged(int idx); +    void on_cbBetterPolygons_stateChanged(int state);      void on_cbSoftwareThreaded_stateChanged(int state); diff --git a/src/frontend/qt_sdl/VideoSettingsDialog.ui b/src/frontend/qt_sdl/VideoSettingsDialog.ui index 6cdd5d8..6985304 100644 --- a/src/frontend/qt_sdl/VideoSettingsDialog.ui +++ b/src/frontend/qt_sdl/VideoSettingsDialog.ui @@ -7,7 +7,7 @@      <x>0</x>      <y>0</y>      <width>482</width> -    <height>237</height> +    <height>244</height>     </rect>    </property>    <property name="sizePolicy"> @@ -43,6 +43,16 @@          </property>         </widget>        </item> +      <item row="2" column="0"> +       <widget class="QCheckBox" name="cbBetterPolygons"> +        <property name="whatsThis"> +         <string><html><head/><body><p>Enabling this may help reduce distortion on quads and more complex polygons, but may also reduce performance.</p></body></html></string> +        </property> +        <property name="text"> +         <string>Improved polygon splitting</string> +        </property> +       </widget> +      </item>       </layout>      </widget>     </item> diff --git a/src/frontend/qt_sdl/WifiSettingsDialog.cpp b/src/frontend/qt_sdl/WifiSettingsDialog.cpp index 457a78d..67297ad 100644 --- a/src/frontend/qt_sdl/WifiSettingsDialog.cpp +++ b/src/frontend/qt_sdl/WifiSettingsDialog.cpp @@ -17,7 +17,7 @@  */  #include <stdio.h> -#include <QFileDialog> +#include <QMessageBox>  #include "types.h"  #include "Platform.h" @@ -41,6 +41,10 @@  WifiSettingsDialog* WifiSettingsDialog::currentDlg = nullptr; +bool WifiSettingsDialog::needsReset = false; + +extern bool RunningSomething; +  WifiSettingsDialog::WifiSettingsDialog(QWidget* parent) : QDialog(parent), ui(new Ui::WifiSettingsDialog)  { @@ -53,6 +57,7 @@ WifiSettingsDialog::WifiSettingsDialog(QWidget* parent) : QDialog(parent), ui(ne      ui->cbDirectMode->setText("Direct mode (requires " PCAP_NAME " and ethernet connection)");      ui->cbBindAnyAddr->setChecked(Config::SocketBindAnyAddr != 0); +    ui->cbRandomizeMAC->setChecked(Config::RandomizeMAC != 0);      int sel = 0;      for (int i = 0; i < LAN_PCap::NumAdapters; i++) @@ -77,33 +82,49 @@ WifiSettingsDialog::~WifiSettingsDialog()      delete ui;  } -void WifiSettingsDialog::on_WifiSettingsDialog_accepted() +void WifiSettingsDialog::done(int r)  { -    Config::SocketBindAnyAddr = ui->cbBindAnyAddr->isChecked() ? 1:0; -    Config::DirectLAN = ui->cbDirectMode->isChecked() ? 1:0; +    needsReset = false; -    int sel = ui->cbxDirectAdapter->currentIndex(); -    if (sel < 0 || sel >= LAN_PCap::NumAdapters) sel = 0; -    if (LAN_PCap::NumAdapters < 1) -    { -        Config::LANDevice[0] = '\0'; -    } -    else +    if (r == QDialog::Accepted)      { -        strncpy(Config::LANDevice, LAN_PCap::Adapters[sel].DeviceName, 127); -        Config::LANDevice[127] = '\0'; +        int randommac = ui->cbRandomizeMAC->isChecked() ? 1:0; + +        if (randommac != Config::RandomizeMAC) +        { +            if (RunningSomething +                && QMessageBox::warning(this, "Reset necessary to apply changes", +                    "The emulation will be reset for the changes to take place.", +                    QMessageBox::Ok, QMessageBox::Cancel) != QMessageBox::Ok) +                return; +        } + +        Config::SocketBindAnyAddr = ui->cbBindAnyAddr->isChecked() ? 1:0; +        Config::RandomizeMAC = randommac; +        Config::DirectLAN = ui->cbDirectMode->isChecked() ? 1:0; + +        int sel = ui->cbxDirectAdapter->currentIndex(); +        if (sel < 0 || sel >= LAN_PCap::NumAdapters) sel = 0; +        if (LAN_PCap::NumAdapters < 1) +        { +            Config::LANDevice[0] = '\0'; +        } +        else +        { +            strncpy(Config::LANDevice, LAN_PCap::Adapters[sel].DeviceName, 127); +            Config::LANDevice[127] = '\0'; +        } + +        Config::Save(); + +        needsReset = true;      } -    Config::Save(); +    QDialog::done(r);      closeDlg();  } -void WifiSettingsDialog::on_WifiSettingsDialog_rejected() -{ -    closeDlg(); -} -  void WifiSettingsDialog::on_cbDirectMode_stateChanged(int state)  {      updateAdapterControls(); diff --git a/src/frontend/qt_sdl/WifiSettingsDialog.h b/src/frontend/qt_sdl/WifiSettingsDialog.h index f8aad1b..6c1f863 100644 --- a/src/frontend/qt_sdl/WifiSettingsDialog.h +++ b/src/frontend/qt_sdl/WifiSettingsDialog.h @@ -42,7 +42,7 @@ public:          }          currentDlg = new WifiSettingsDialog(parent); -        currentDlg->show(); +        currentDlg->open();          return currentDlg;      }      static void closeDlg() @@ -50,9 +50,10 @@ public:          currentDlg = nullptr;      } +    static bool needsReset; +  private slots: -    void on_WifiSettingsDialog_accepted(); -    void on_WifiSettingsDialog_rejected(); +    void done(int r);      void on_cbDirectMode_stateChanged(int state);      void on_cbxDirectAdapter_currentIndexChanged(int sel); diff --git a/src/frontend/qt_sdl/WifiSettingsDialog.ui b/src/frontend/qt_sdl/WifiSettingsDialog.ui index bfee1fd..6668d88 100644 --- a/src/frontend/qt_sdl/WifiSettingsDialog.ui +++ b/src/frontend/qt_sdl/WifiSettingsDialog.ui @@ -7,7 +7,7 @@      <x>0</x>      <y>0</y>      <width>479</width> -    <height>217</height> +    <height>240</height>     </rect>    </property>    <property name="sizePolicy"> @@ -39,6 +39,16 @@          </property>         </widget>        </item> +      <item row="1" column="0"> +       <widget class="QCheckBox" name="cbRandomizeMAC"> +        <property name="whatsThis"> +         <string><html><head/><body><p>Randomizes the console's MAC address upon reset. Required for local multiplayer if each melonDS instance uses the same firmware file.</p></body></html></string> +        </property> +        <property name="text"> +         <string>Randomize MAC address</string> +        </property> +       </widget> +      </item>       </layout>      </widget>     </item> diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index f91f879..f8cdd24 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -405,8 +405,11 @@ void EmuThread::run()                      videoRenderer = hasOGL ? Config::_3DRenderer : 0;                  videoSettingsDirty = false; +                  videoSettings.Soft_Threaded = Config::Threaded3D != 0;                  videoSettings.GL_ScaleFactor = Config::GL_ScaleFactor; +                videoSettings.GL_BetterPolygons = Config::GL_BetterPolygons; +                  GPU::SetRenderSettings(videoRenderer, videoSettings);              } @@ -1333,7 +1336,7 @@ void MainWindow::dragEnterEvent(QDragEnterEvent* event)      QString filename = urls.at(0).toLocalFile();      QString ext = filename.right(3); -    if (ext == "nds" || ext == "srl" || (ext == "gba" && RunningSomething)) +    if (ext == "nds" || ext == "srl" || ext == "dsi" || (ext == "gba" && RunningSomething))          event->acceptProposedAction();  } @@ -1747,14 +1750,14 @@ void MainWindow::onAudioSettingsFinished(int res)  void MainWindow::onOpenWifiSettings()  { +    emuThread->emuPause(); +      WifiSettingsDialog* dlg = WifiSettingsDialog::openDlg(this);      connect(dlg, &WifiSettingsDialog::finished, this, &MainWindow::onWifiSettingsFinished);  }  void MainWindow::onWifiSettingsFinished(int res)  { -    emuThread->emuPause(); -      if (Wifi::MPInited)      {          Platform::MP_DeInit(); @@ -1764,6 +1767,9 @@ void MainWindow::onWifiSettingsFinished(int res)      Platform::LAN_DeInit();      Platform::LAN_Init(); +    if (WifiSettingsDialog::needsReset) +        onReset(); +      emuThread->emuUnpause();  } @@ -1874,14 +1880,27 @@ void MainWindow::onTitleUpdate(QString title)  void MainWindow::onEmuStart()  { -    for (int i = 1; i < 9; i++) +    // TODO: make savestates work in DSi mode!! +    if (Config::ConsoleType == 1)      { -        actSaveState[i]->setEnabled(true); -        actLoadState[i]->setEnabled(Frontend::SavestateExists(i)); +        for (int i = 0; i < 9; i++) +        { +            actSaveState[i]->setEnabled(false); +            actLoadState[i]->setEnabled(false); +        } +        actUndoStateLoad->setEnabled(false); +    } +    else +    { +        for (int i = 1; i < 9; i++) +        { +            actSaveState[i]->setEnabled(true); +            actLoadState[i]->setEnabled(Frontend::SavestateExists(i)); +        } +        actSaveState[0]->setEnabled(true); +        actLoadState[0]->setEnabled(true); +        actUndoStateLoad->setEnabled(false);      } -    actSaveState[0]->setEnabled(true); -    actLoadState[0]->setEnabled(true); -    actUndoStateLoad->setEnabled(false);      actPause->setEnabled(true);      actPause->setChecked(false); @@ -2066,7 +2085,7 @@ int main(int argc, char** argv)          char* file = argv[1];          char* ext = &file[strlen(file)-3]; -        if (!strcasecmp(ext, "nds") || !strcasecmp(ext, "srl")) +        if (!strcasecmp(ext, "nds") || !strcasecmp(ext, "srl") || !strcasecmp(ext, "dsi"))          {              int res = Frontend::LoadROM(file, Frontend::ROMSlot_NDS); |