-added back some missing cover converting code for jpegs

-added some more debug information and more safety code
This commit is contained in:
fix94.1 2014-03-24 18:59:24 +00:00
parent d31f40a84b
commit 3b1dcf389a
15 changed files with 228 additions and 88 deletions

View File

@ -11,6 +11,8 @@ all:
@echo Make WiiFlow Loader @echo Make WiiFlow Loader
@$(MAKE) --no-print-directory -C $(CURDIR_TMP)/resources/extldr \ @$(MAKE) --no-print-directory -C $(CURDIR_TMP)/resources/extldr \
-f $(CURDIR_TMP)/resources/extldr/Makefile -f $(CURDIR_TMP)/resources/extldr/Makefile
@mv -u $(CURDIR_TMP)/resources/extldr/extldr.bin \
$(CURDIR_TMP)/out/bins/ext_loader.bin
@echo Make WiiFlow Booter @echo Make WiiFlow Booter
@$(MAKE) --no-print-directory -C $(CURDIR_TMP)/resources/wiiflow_game_booter \ @$(MAKE) --no-print-directory -C $(CURDIR_TMP)/resources/wiiflow_game_booter \

View File

@ -151,7 +151,7 @@ all:
clean: clean:
@echo clean ... @echo clean ...
@rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).dol $(CURDIR)/source/svnrev.h \ @rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).dol $(CURDIR)/source/svnrev.h \
$(CURDIR)/source/loader/alt_ios_gen.h \ $(CURDIR)/source/loader/alt_ios_gen.h $(CURDIR)/out/bins/ext_loader.bin \
$(CURDIR)/out/bins/ext_booter.bin $(CURDIR)/out/bins/app_booter.bin $(CURDIR)/out/bins/ext_booter.bin $(CURDIR)/out/bins/app_booter.bin
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------

View File

@ -136,11 +136,11 @@ $(OUTPUT).elf: $(OFILES)
# This rule links in binary data with the .jpg extension # This rule links in binary data with the .jpg extension
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
%.bin: %.elf %.bin: %.elf
@echo "output ... $@" @echo "output ... $(TARGET).bin"
$(Q)$(OBJCOPY) -O binary $< $@ $(Q)$(OBJCOPY) -O binary $< $@
%.elf: link.ld $(OFILES) %.elf: link.ld $(OFILES)
@echo "linking ... $@" @echo "linking ... $(TARGET).elf"
$(Q)$(CC) -n -T $^ $(LDFLAGS) -o $@ $(Q)$(CC) -n -T $^ $(LDFLAGS) -o $@
%.o: %.c %.o: %.c

View File

@ -10,16 +10,16 @@ OBJCOPY = $(PREFIX)objcopy
RANLIB = $(PREFIX)ranlib RANLIB = $(PREFIX)ranlib
STRIP = $(PREFIX)strip STRIP = $(PREFIX)strip
MACHDEP = -mcpu=750 -mno-eabi -mhard-float MACHDEP = -mcpu=750 -mno-eabi
CFLAGS = $(MACHDEP) -O1 -Werror -Wall -pipe -ffunction-sections -finline-functions-called-once -mno-sdata CFLAGS = $(MACHDEP) -O1 -Werror -Wall -pipe -mno-sdata
LDFLAGS = $(MACHDEP) -n -nostartfiles -nostdlib -Wl,-T,link.ld -L. LDFLAGS = $(MACHDEP) -n -nostartfiles -nostdlib -Wl,-T,link.ld -L.
ASFLAGS = -D_LANGUAGE_ASSEMBLY -DHW_RVL ASFLAGS = -D_LANGUAGE_ASSEMBLY -DHW_RVL
TARGET_LINKED = boot.elf TARGET_LINKED = boot.elf
TARGET = ../../data/extldr.bin TARGET = extldr.bin
CFILES = string.c sync.c main.c CFILES = string.c sync.c usbgecko.c main.c
OBJS = crt0.o string.o sync.o main.o OBJS = crt0.o string.o sync.o usbgecko.o main.o
DEPDIR = .deps DEPDIR = .deps

33
resources/extldr/exi.h Normal file
View File

@ -0,0 +1,33 @@
#ifndef __EXI_H_
/* Retrieve the I/O register base for a given EXI channel */
#define EXI_ADDR(channel) (0xCD006800 + (channel) * 0x14)
#define EXI_CSR 0x0000 /* EXI Channel 0 Parameter Register */
#define EXI_CSR_ROMDIS (1 << 13) /* EXI0: de-scramble logic disabled */
#define EXI_CSR_EXT (1 << 12) /* Device connected if 1 */
#define EXI_CSR_EXTINT (1 << 11) /* External Insertion Interrupt Status */
#define EXI_CSR_EXTINTMASK (1 << 10) /* EXT interrupt mask */
#define EXI_CSR_CLK_1MHZ (0 << 4) /* Clock: 1MHz */
#define EXI_CSR_CLK_2MHZ (1 << 4) /* Clock: 2MHz */
#define EXI_CSR_CLK_4MHZ (2 << 4) /* Clock: 4MHz */
#define EXI_CSR_CLK_8MHZ (3 << 4) /* Clock: 8MHz */
#define EXI_CSR_CLK_16MHZ (4 << 4) /* Clock: 16MHz */
#define EXI_CSR_CLK_32MHZ (5 << 4) /* Clock: 32MHz */
#define EXI_CSR_CS(x) ((x) << 7) /* Chip select */
#define EXI_CSR_TCINT (1 << 3) /* Transfer complete interrupt status */
#define EXI_CSR_TCINTMASK (1 << 2) /* Transfer complete interrupt mask */
#define EXI_CSR_EXTSTAT (1 << 1) /* Interrupt status */
#define EXI_CSR_EXTSTATMASK (1 << 0) /* EXI interrupt mask */
#define EXI_CR 0x0000c /* EXI Channel 0 Control Register */
#define EXI_CR_TLEN_1 (0 << 4) /* Transfer length: 1 byte */
#define EXI_CR_TLEN_2 (1 << 4) /* Transfer length: 2 byte */
#define EXI_CR_TLEN_3 (2 << 4) /* Transfer length: 3 byte */
#define EXI_CR_TLEN_4 (4 << 4) /* Transfer length: 4 byte */
#define EXI_CR_RW_R (0 << 2) /* Transfer type: read */
#define EXI_CR_RW_W (1 << 2) /* Transfer type: write */
#define EXI_CR_RW_RW (2 << 2) /* Transfer type: read/write */
#define EXI_CR_DMA (1 << 1) /* DMA transfer mode */
#define EXI_CR_TSTART (1 << 0) /* Start transfer */
#define EXI_DATA 0x0010 /* EXI Channel 0 Immediate Data */
#endif

View File

@ -2,14 +2,17 @@
#include <stdarg.h> #include <stdarg.h>
#include "string.h" #include "string.h"
#include "sync.h" #include "sync.h"
#include "usbgecko.h"
typedef void (*entrypoint) (void); typedef void (*entrypoint) (void);
unsigned char *cfg = (unsigned char*)0x80A7FFF0; static entrypoint exeEntryPoint = (entrypoint)0x80A80000;
unsigned char *start = (unsigned char*)0x80A80000; static unsigned char *start = (unsigned char*)0x80A80000;
unsigned char *buffer = (unsigned char*)0x90100000; static unsigned char *buffer = (unsigned char*)0x90110000;
void _main(void) void _main(void)
{ {
entrypoint exeEntryPoint = (entrypoint)start; usbgecko_init();
memcpy(cfg, buffer, 0x01000000); //1mb safe copying of cfg and booter gprintf("Copying External Booter...\n");
sync_before_exec(cfg, 0x01000000); memcpy(start, buffer, 0xF0000); //960kb safe copying of booter
sync_before_exec(start, 0xF0000);
gprintf("Done! Jumping to Entrypoint...\n");
exeEntryPoint(); exeEntryPoint();
} }

View File

@ -0,0 +1,90 @@
#include "exi.h"
#include "usbgecko.h"
#define USBGECKO_CMD_IDENTIFY 0x90000000
#define USBGECKO_IDENTIFY_RESPONSE 0x04700000
#define USBGECKO_CMD_TX_STATUS 0xc0000000
#define USBGECKO_TX_FIFO_READY 0x04000000
#define USBGECKO_CMD_RX_STATUS 0xd0000000
#define USBGECKO_RX_FIFO_READY 0x04000000
#define USBGECKO_CMD_RECEIVE 0xa0000000
#define USBGECKO_CMD_TRANSMIT(ch) (0xb0000000 | ((ch) << 20))
/* We're poking registers; so ensure any access is volatile! */
typedef volatile unsigned int vuint32_t;
typedef unsigned int uint32_t;
static int usb_gecko_channel = -1;
static uint32_t
usbgecko_transaction(int ch, uint32_t data)
{
volatile void* exi_base = (volatile void*)EXI_ADDR(ch);
/* 5.9.1.2: Selecting a specific EXI device: select the USB Gecko device */
*(vuint32_t*)(exi_base + EXI_CSR) = EXI_CSR_CLK_32MHZ | EXI_CSR_CS(1);
/* 5.9.1.4: Perform IMM operation: setup data */
*(vuint32_t*)(exi_base + EXI_DATA) = data;
/* 5.9.1.4: Perform IMM operation: schedule read/write; 2 bytes; start now */
*(vuint32_t*)(exi_base + EXI_CR) = EXI_CR_TLEN_2 | EXI_CR_RW_RW | EXI_CR_TSTART;
/* 5.9.1.4: Perform IMM operation: Wait until transfer is completed */
while (1) {
if ((*(vuint32_t*)(exi_base + EXI_CR) & EXI_CR_TSTART) == 0)
break;
/* XXX barrier */
}
/* 5.9.1.4: Fetch the data */
data = *(vuint32_t*)(exi_base + EXI_DATA);
/* 5.9.1.3: Deselecting EXI devices */
*(vuint32_t*)(exi_base + EXI_CSR) = 0;
return data;
}
static void usbgecko_putch(char ch)
{
if (usb_gecko_channel < 0)
return;
int timeout = 16;
while (1) {
if (usbgecko_transaction(usb_gecko_channel, USBGECKO_CMD_TX_STATUS) & USBGECKO_TX_FIFO_READY)
break;
timeout--;
if (timeout < 0) {
break;
}
}
usbgecko_transaction(usb_gecko_channel, USBGECKO_CMD_TRANSMIT(ch));
/* XXX hack to get newlines right */
if (ch == '\n')
usbgecko_putch('\r');
}
void gprintf(const char* string)
{
char* temp = (char*)string;
while (*temp != '\x0')
{
usbgecko_putch(*temp);
temp++;
}
}
void usbgecko_init()
{
int i;
for (i = 0; i < 2; i++) {
uint32_t d = usbgecko_transaction(i, USBGECKO_CMD_IDENTIFY);
if (d != USBGECKO_IDENTIFY_RESPONSE)
continue;
usb_gecko_channel = i;
}
}
/* vim:set ts=2 sw=2: */

View File

@ -0,0 +1,7 @@
#ifndef __USBGECKO_H__
#define __USBGECKO_H__
void usbgecko_init();
void gprintf(const char* string);
#endif

View File

@ -33,7 +33,7 @@
#include "wdvd.h" #include "wdvd.h"
#include "gecko.h" #include "gecko.h"
#define EXT_ADDR_CFG ((vu32*)0x80A7FFF0) #define EXT_ADDR_CFG ((vu32*)0x90100000)
using namespace std; using namespace std;
IOS_Info CurrentIOS; IOS_Info CurrentIOS;

View File

@ -38,13 +38,13 @@
/* External WiiFlow Game Booter */ /* External WiiFlow Game Booter */
the_CFG normalCFG; the_CFG normalCFG;
#define EXT_ADDR_CFG ((vu32*)0x90100000) //later for 0x80A7FFF0 #define EXT_ADDR_CFG ((vu32*)0x90100000)
#define EXT_ADDR ((u8*)0x90100010) //later for 0x80A80000 #define EXT_ADDR ((u8*)0x90110000) //later for 0x80A80000
#define LDR_ADDR ((u8*)0x93300000) #define LDR_ADDR ((u8*)0x93300000)
#define LDR_ENTRY ((entry)LDR_ADDR) #define LDR_ENTRY ((entry)LDR_ADDR)
extern const u8 extldr_bin[]; u8 *extldr_ptr = NULL;
extern const u32 extldr_bin_size; size_t extldr_size = 0;
extern "C" { extern "C" {
u8 configbytes[2]; u8 configbytes[2];
@ -101,21 +101,25 @@ void WiiFlow_ExternalBooter(u8 vidMode, bool vipatch, bool countryString, u8 pat
memcpy(EXT_ADDR, booter_ptr, booter_size); memcpy(EXT_ADDR, booter_ptr, booter_size);
DCFlushRange(EXT_ADDR, booter_size); DCFlushRange(EXT_ADDR, booter_size);
/* Loader just for the booter */ /* Loader just for the booter */
memcpy(LDR_ADDR, extldr_bin, extldr_bin_size); memcpy(LDR_ADDR, extldr_ptr, extldr_size);
DCFlushRange(LDR_ADDR, extldr_bin_size); DCFlushRange(LDR_ADDR, extldr_size);
/* Boot it */ /* Boot it */
JumpToEntry(LDR_ENTRY); JumpToEntry(LDR_ENTRY);
} }
bool ExternalBooter_LoadBooter(const char *booter_path) bool ExternalBooter_LoadBins(const char *binDir)
{ {
fsop_GetFileSizeBytes(booter_path, &booter_size); extldr_ptr = fsop_ReadFile(fmt("%s/ext_loader.bin", binDir), &extldr_size);
if(booter_size > 0) if(extldr_size == 0 || extldr_ptr == NULL)
{ return false;
booter_ptr = fsop_ReadFile(booter_path, &booter_size);
if(booter_ptr != NULL) booter_ptr = fsop_ReadFile(fmt("%s/ext_booter.bin", binDir), &booter_size);
if(booter_size > 0 && booter_ptr != NULL)
return true; return true;
}
free(extldr_ptr);
extldr_ptr = NULL;
extldr_size = 0;
return false; return false;
} }

View File

@ -30,7 +30,7 @@ extern u32 hooktype;
void WiiFlow_ExternalBooter(u8 vidMode, bool vipatch, bool countryString, u8 patchVidMode, void WiiFlow_ExternalBooter(u8 vidMode, bool vipatch, bool countryString, u8 patchVidMode,
int aspectRatio, u32 returnTo, u8 BootType, bool use_led); int aspectRatio, u32 returnTo, u8 BootType, bool use_led);
bool ExternalBooter_LoadBooter(const char *booter_path); bool ExternalBooter_LoadBins(const char *binDir);
void ExternalBooter_ChannelSetup(u64 title, bool dol); void ExternalBooter_ChannelSetup(u64 title, bool dol);
void ExternalBooter_WiiGameSetup(bool wbfs, bool dvd, bool patchregion, const char *ID); void ExternalBooter_WiiGameSetup(bool wbfs, bool dvd, bool patchregion, const char *ID);
void ShutdownBeforeExit(void); void ShutdownBeforeExit(void);

View File

@ -709,9 +709,20 @@ void decodeRealJpeg(const u8* data, int size, VideoFrame& dest, bool fancy)
tjhandle _jpegDecompressor = tjInitDecompress(); tjhandle _jpegDecompressor = tjInitDecompress();
tjDecompressHeader2(_jpegDecompressor, src, size, &width, &height, &jpegSubsamp); tjDecompressHeader2(_jpegDecompressor, src, size, &width, &height, &jpegSubsamp);
/* decode to buffer */ /* decode to buffer */
if(fancy)
{
width = ALIGN(4, width);
height = ALIGN(4, height);
dest.resize(width, height); dest.resize(width, height);
tjDecompress2(_jpegDecompressor, src, size, dest.data, width, 0, height, tjDecompress2(_jpegDecompressor, src, size, dest.data, width, 0, height,
TJPF_RGBA, fancy ? TJFLAG_ACCURATEDCT : (TJFLAG_FASTDCT | TJFLAG_FASTUPSAMPLE)); TJPF_RGBA, TJFLAG_ACCURATEDCT);
}
else
{
dest.resize(width, height);
tjDecompress2(_jpegDecompressor, src, size, dest.data, width, 0, height,
TJPF_RGBA, TJFLAG_FASTDCT | TJFLAG_FASTUPSAMPLE);
}
tjDestroy(_jpegDecompressor); tjDestroy(_jpegDecompressor);
g_isLoading = false; g_isLoading = false;
} }

View File

@ -43,29 +43,31 @@ static inline u32 coordsRGB565(u32 x, u32 y, u32 w)
static inline void _convertToRGBA(u8 *dst, const u8 *src, u32 width, u32 height) static inline void _convertToRGBA(u8 *dst, const u8 *src, u32 width, u32 height)
{ {
for (u32 y = 0; y < height; ++y) u32 x,y,i,j;
for (y = 0; y < height; ++y)
for (x = 0; x < width; ++x)
{ {
for (u32 x = 0; x < width; ++x) i = (x + y * width) * 4;
{ j = coordsRGBA8(x, y, width);
u32 i = (x + y * width) * 4; dst[i] = src[j + 1];
dst[i] = src[coordsRGBA8(x, y, width) + 1]; dst[i + 1] = src[j + 32];
dst[i + 1] = src[coordsRGBA8(x, y, width) + 32]; dst[i + 2] = src[j + 33];
dst[i + 2] = src[coordsRGBA8(x, y, width) + 33]; dst[i + 3] = src[j];
dst[i + 3] = src[coordsRGBA8(x, y, width)];
}
} }
} }
static inline void _convertToRGBA8(u8 *dst, const u8 *src, u32 width, u32 height) static inline void _convertToRGBA8(u8 *dst, const u8 *src, u32 width, u32 height)
{ {
for (u32 y = 0; y < height; ++y) u32 x,y,i,j;
for (u32 x = 0; x < width; ++x) for (y = 0; y < height; ++y)
for (x = 0; x < width; ++x)
{ {
u32 i = (x + y * width) * 4; i = (x + y * width) * 4;
dst[coordsRGBA8(x, y, width) + 1] = src[i]; j = coordsRGBA8(x, y, width);
dst[coordsRGBA8(x, y, width) + 32] = src[i + 1]; dst[j + 1] = src[i];
dst[coordsRGBA8(x, y, width) + 33] = src[i + 2]; dst[j + 32] = src[i + 1];
dst[coordsRGBA8(x, y, width)] = src[i + 3]; dst[j + 33] = src[i + 2];
dst[j] = src[i + 3];
} }
} }

View File

@ -11,11 +11,16 @@
#include "fileOps/fileOps.h" #include "fileOps/fileOps.h"
#include "gecko/gecko.hpp" #include "gecko/gecko.hpp"
#define EXECUTE_ADDR ((u8 *)0x92000000) static u8 *EXECUTE_ADDR = (u8*)0x92000000;
#define BOOTER_ADDR ((u8 *)0x93300000)
#define ARGS_ADDR ((u8 *)0x90100000)
#define BOOTER_ENTRY ((entry)BOOTER_ADDR)
static u8 *BOOTER_ADDR = (u8*)0x93300000;
static entry BOOTER_ENTRY = (entry)BOOTER_ADDR;
static __argv *ARGS_ADDR = (__argv*)0x90100000;
static char *CMD_ADDR = (char*)ARGS_ADDR + sizeof(struct __argv);
u8 *appbooter_ptr = NULL;
u32 appbooter_size = 0;
using namespace std; using namespace std;
extern const u8 stub_bin[]; extern const u8 stub_bin[];
@ -46,15 +51,10 @@ void AddBootArgument(const char * argv)
bool LoadAppBooter(const char *filepath) bool LoadAppBooter(const char *filepath)
{ {
u32 filesize = 0; appbooter_ptr = fsop_ReadFile(filepath, &appbooter_size);
fsop_GetFileSizeBytes(filepath, &filesize); if(appbooter_size == 0 || appbooter_ptr == NULL)
if(filesize > 0)
{
fsop_ReadFileLoc(filepath, filesize, BOOTER_ADDR);
DCFlushRange(BOOTER_ADDR, filesize);
return true;
}
return false; return false;
return true;
} }
bool LoadHomebrew(const char *filepath) bool LoadHomebrew(const char *filepath)
@ -75,40 +75,29 @@ bool LoadHomebrew(const char *filepath)
return true; return true;
} }
int SetupARGV(struct __argv * args) static int SetupARGV()
{ {
if(!args) __argv *args = ARGS_ADDR;
return -1;
memset(args, 0, sizeof(struct __argv)); memset(args, 0, sizeof(struct __argv));
args->argvMagic = ARGV_MAGIC; args->argvMagic = ARGV_MAGIC;
u32 argc = 0;
u32 position = 0; u32 position = 0;
u32 stringlength = 1;
/** Append Arguments **/ /** Count Arguments Size **/
u32 stringlength = 1;
for(u32 i = 0; i < Arguments.size(); i++) for(u32 i = 0; i < Arguments.size(); i++)
stringlength += Arguments[i].size()+1; stringlength += Arguments[i].size()+1;
args->length = stringlength; args->length = stringlength;
//! Put the argument into mem2 too, to avoid overwriting it
args->commandLine = (char *) ARGS_ADDR + sizeof(struct __argv);
/** Append Arguments **/ /** Append Arguments **/
for(u32 i = 0; i < Arguments.size(); i++) args->argc = Arguments.size();
args->commandLine = CMD_ADDR;
for(int i = 0; i < args->argc; i++)
{ {
strcpy(&args->commandLine[position], Arguments[i].c_str()); strcpy(&args->commandLine[position], Arguments[i].c_str());
position += Arguments[i].size() + 1; position += Arguments[i].size() + 1;
argc++;
} }
args->argc = argc;
args->commandLine[args->length - 1] = '\0'; args->commandLine[args->length - 1] = '\0';
args->argv = &args->commandLine;
args->endARGV = args->argv + 1;
Arguments.clear(); Arguments.clear();
return 0; return 0;
@ -134,14 +123,13 @@ void writeStub()
void BootHomebrew() void BootHomebrew()
{ {
__argv args;
if(!IsDollZ(EXECUTE_ADDR) && !IsSpecialELF(EXECUTE_ADDR)) if(!IsDollZ(EXECUTE_ADDR) && !IsSpecialELF(EXECUTE_ADDR))
SetupARGV(&args); SetupARGV();
else else
gprintf("Homebrew Boot Arguments disabled\n"); gprintf("Homebrew Boot Arguments disabled\n");
memmove(ARGS_ADDR, &args, sizeof(args)); memcpy(BOOTER_ADDR, appbooter_ptr, appbooter_size);
DCFlushRange(ARGS_ADDR, sizeof(args) + args.length); DCFlushRange(BOOTER_ADDR, appbooter_size);
JumpToEntry(BOOTER_ENTRY); JumpToEntry(BOOTER_ENTRY);
} }

View File

@ -406,7 +406,7 @@ bool CMenu::_startVideo()
if(fsop_FileExist(THP_Path)) if(fsop_FileExist(THP_Path))
{ {
m_gameSound.FreeMemory(); m_gameSound.FreeMemory();
MusicPlayer.Stop(); CheckGameSoundThread();
m_banner.SetShowBanner(false); m_banner.SetShowBanner(false);
/* Lets play the movie */ /* Lets play the movie */
movie.Init(THP_Path); movie.Init(THP_Path);
@ -1257,7 +1257,7 @@ void CMenu::_launchChannel(dir_discHdr *hdr)
while(1) usleep(500); while(1) usleep(500);
} }
} }
if(WII_Launch == false && ExternalBooter_LoadBooter(fmt("%s/ext_booter.bin", m_binsDir.c_str())) == false) if(WII_Launch == false && ExternalBooter_LoadBins(m_binsDir.c_str()) == false)
Sys_Exit(); Sys_Exit();
if(_loadIOS(gameIOS, userIOS, id, !NAND_Emu) == LOAD_IOS_FAILED) if(_loadIOS(gameIOS, userIOS, id, !NAND_Emu) == LOAD_IOS_FAILED)
Sys_Exit(); Sys_Exit();
@ -1494,7 +1494,7 @@ void CMenu::_launchGame(dir_discHdr *hdr, bool dvd)
gprintf("Check\n"); gprintf("Check\n");
patchregion = NandHandle.Do_Region_Change(id, true); patchregion = NandHandle.Do_Region_Change(id, true);
} }
if(ExternalBooter_LoadBooter(fmt("%s/ext_booter.bin", m_binsDir.c_str())) == false) if(ExternalBooter_LoadBins(m_binsDir.c_str()) == false)
Sys_Exit(); Sys_Exit();
if((!dvd || neek2o()) && !Sys_DolphinMode()) if((!dvd || neek2o()) && !Sys_DolphinMode())
{ {