Merge pull request #1548 from reicast/fh/float-vmu
Float VMU option. Android renderer native thread. 90° screen rotation option. AW fixes.
This commit is contained in:
commit
8cdbb9c2fd
|
@ -1,4 +1,5 @@
|
|||
#include "aica.h"
|
||||
#include "aica_if.h"
|
||||
#include "sgc_if.h"
|
||||
#include "aica_mem.h"
|
||||
#include <math.h>
|
||||
|
@ -180,6 +181,7 @@ template void WriteAicaReg<2>(u32 reg,u32 data);
|
|||
s32 libAICA_Init()
|
||||
{
|
||||
init_mem();
|
||||
aica_Init();
|
||||
|
||||
verify(sizeof(*CommonData)==0x508);
|
||||
verify(sizeof(*DSPData)==0x15C8);
|
||||
|
@ -203,9 +205,12 @@ s32 libAICA_Init()
|
|||
return rv_ok;
|
||||
}
|
||||
|
||||
void libAICA_Reset(bool m)
|
||||
void libAICA_Reset(bool manual)
|
||||
{
|
||||
if (!manual)
|
||||
init_mem();
|
||||
sgc_Init();
|
||||
aica_Reset(manual);
|
||||
}
|
||||
|
||||
void libAICA_Term()
|
||||
|
|
|
@ -18,6 +18,7 @@ u32 VREG;//video reg =P
|
|||
u32 ARMRST;//arm reset reg
|
||||
u32 rtc_EN=0;
|
||||
int dma_sched_id;
|
||||
u32 RealTimeClock;
|
||||
|
||||
u32 GetRTC_now()
|
||||
{
|
||||
|
@ -39,9 +40,9 @@ u32 ReadMem_aica_rtc(u32 addr,u32 sz)
|
|||
switch( addr & 0xFF )
|
||||
{
|
||||
case 0:
|
||||
return settings.dreamcast.RTC>>16;
|
||||
return RealTimeClock>>16;
|
||||
case 4:
|
||||
return settings.dreamcast.RTC &0xFFFF;
|
||||
return RealTimeClock &0xFFFF;
|
||||
case 8:
|
||||
return 0;
|
||||
}
|
||||
|
@ -57,16 +58,16 @@ void WriteMem_aica_rtc(u32 addr,u32 data,u32 sz)
|
|||
case 0:
|
||||
if (rtc_EN)
|
||||
{
|
||||
settings.dreamcast.RTC&=0xFFFF;
|
||||
settings.dreamcast.RTC|=(data&0xFFFF)<<16;
|
||||
RealTimeClock&=0xFFFF;
|
||||
RealTimeClock|=(data&0xFFFF)<<16;
|
||||
rtc_EN=0;
|
||||
}
|
||||
return;
|
||||
case 4:
|
||||
if (rtc_EN)
|
||||
{
|
||||
settings.dreamcast.RTC&=0xFFFF0000;
|
||||
settings.dreamcast.RTC|= data&0xFFFF;
|
||||
RealTimeClock&=0xFFFF0000;
|
||||
RealTimeClock|= data&0xFFFF;
|
||||
//TODO: Clean the internal timer ?
|
||||
}
|
||||
return;
|
||||
|
@ -153,15 +154,12 @@ void WriteMem_aica_reg(u32 addr,u32 data,u32 sz)
|
|||
//Init/res/term
|
||||
void aica_Init()
|
||||
{
|
||||
//mmnnn ? gotta fill it w/ something
|
||||
RealTimeClock = GetRTC_now();
|
||||
}
|
||||
|
||||
void aica_Reset(bool Manual)
|
||||
{
|
||||
if (!Manual)
|
||||
{
|
||||
aica_ram.Zero();
|
||||
}
|
||||
aica_Init();
|
||||
}
|
||||
|
||||
void aica_Term()
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
extern u32 VREG;
|
||||
extern VArray2 aica_ram;
|
||||
extern u32 RealTimeClock;
|
||||
u32 ReadMem_aica_rtc(u32 addr,u32 sz);
|
||||
void WriteMem_aica_rtc(u32 addr,u32 data,u32 sz);
|
||||
u32 ReadMem_aica_reg(u32 addr,u32 sz);
|
||||
|
@ -17,4 +18,4 @@ void aica_Term();
|
|||
|
||||
void aica_sb_Init();
|
||||
void aica_sb_Reset(bool Manual);
|
||||
void aica_sb_Term();
|
||||
void aica_sb_Term();
|
||||
|
|
|
@ -115,7 +115,7 @@ bool maple_atomiswave_coin_chute(int slot)
|
|||
{
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
if (awave_button_mapping[i] == AWAVE_COIN_KEY && (kcode[slot] & (1 << i)) == 0)
|
||||
if ((kcode[slot] & (1 << i)) == 0 && awave_button_mapping[i] == AWAVE_COIN_KEY)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -149,16 +149,27 @@ void mcfg_CreateAtomisWaveControllers()
|
|||
// Game needs analog axes
|
||||
mcfg_Create(MDT_SegaController, 2, 5, 0);
|
||||
mcfg_Create(MDT_SegaController, 3, 5, 1);
|
||||
// Faster Than Speed needs 1 std controller on port 0 (digital inputs) and one on port 2 (analog axes)
|
||||
// Maximum Speed same
|
||||
}
|
||||
else if (settings.input.JammaSetup == 1)
|
||||
{
|
||||
// 4 players
|
||||
mcfg_Create(MDT_SegaController, 2, 5);
|
||||
mcfg_Create(MDT_SegaController, 3, 5);
|
||||
}
|
||||
else if (settings.input.JammaSetup == 5)
|
||||
{
|
||||
// Clay Challenge needs 2 std controllers on port 0 & 1 (digital in) and light guns on port 2 & 3
|
||||
// Sports Shooting same
|
||||
mcfg_Create(MDT_LightGun, 2, 5, 0);
|
||||
mcfg_Create(MDT_LightGun, 3, 5, 1);
|
||||
}
|
||||
else if (settings.input.JammaSetup == 3)
|
||||
{
|
||||
// Sega Bass Fishing Challenge needs a mouse (track-ball) on port 2
|
||||
mcfg_Create(MDT_Mouse, 2, 5, 0);
|
||||
}
|
||||
// mcfg_Create(MDT_LightGun, 2, 5, 0);
|
||||
// mcfg_Create(MDT_LightGun, 3, 5, 1);
|
||||
// mcfg_Create(MDT_Mouse, 2, 5, 0);
|
||||
// Guilty Gear Isuka (4P) needs 4 std controllers
|
||||
// Faster Than Speed needs 1 std controller on port 0 (digital inputs) and one on port 2 (analog axes)
|
||||
// Maximum Speed same
|
||||
// Clay Challenge needs 2 std controllers on port 0 & 1 (digital in) and light guns on port 2 & 3
|
||||
// Sports Shooting same
|
||||
// Sega Bass Fishing Challenge needs a mouse (track-ball) on port 3
|
||||
}
|
||||
|
||||
void mcfg_CreateDevices()
|
||||
|
|
|
@ -199,6 +199,35 @@ struct maple_base: maple_device
|
|||
*/
|
||||
struct maple_sega_controller: maple_base
|
||||
{
|
||||
virtual u32 get_capabilities() {
|
||||
// byte 0: 0 0 0 0 0 0 0 0
|
||||
// byte 1: 0 0 a5 a4 a3 a2 a1 a0
|
||||
// byte 2: R2 L2 D2 U2 D X Y Z
|
||||
// byte 3: R L D U St A B C
|
||||
|
||||
return 0xfe060f00; // 4 analog axes (0-3) X Y A B Start U D L R
|
||||
}
|
||||
|
||||
virtual u32 transform_kcode(u32 kcode) {
|
||||
return kcode;
|
||||
}
|
||||
|
||||
virtual u32 get_analog_axis(int index, const PlainJoystickState &pjs) {
|
||||
switch (index)
|
||||
{
|
||||
case 0:
|
||||
return pjs.trigger[PJTI_R]; // Right trigger
|
||||
case 1:
|
||||
return pjs.trigger[PJTI_L]; // Left trigger
|
||||
case 2:
|
||||
return pjs.joy[PJAI_X1]; // Stick X
|
||||
case 3:
|
||||
return pjs.joy[PJAI_Y1]; // Stick Y
|
||||
default:
|
||||
return 0x80; // unused
|
||||
}
|
||||
}
|
||||
|
||||
virtual MapleDeviceType get_device_type()
|
||||
{
|
||||
return MDT_SegaController;
|
||||
|
@ -216,14 +245,9 @@ struct maple_sega_controller: maple_base
|
|||
|
||||
//struct data
|
||||
//3*4
|
||||
#if DC_PLATFORM != DC_PLATFORM_ATOMISWAVE
|
||||
w32(0xfe060f00);
|
||||
#else
|
||||
// More buttons, more digital axes
|
||||
w32(0xff663f00);
|
||||
#endif
|
||||
w32( 0);
|
||||
w32( 0);
|
||||
w32(get_capabilities());
|
||||
w32(0);
|
||||
w32(0);
|
||||
|
||||
//1 area code
|
||||
w8(0xFF);
|
||||
|
@ -254,54 +278,28 @@ struct maple_sega_controller: maple_base
|
|||
//4
|
||||
w32(MFID_0_Input);
|
||||
|
||||
#if DC_PLATFORM != DC_PLATFORM_ATOMISWAVE
|
||||
//state data
|
||||
//2 key code
|
||||
w16(pjs.kcode);
|
||||
w16(transform_kcode(pjs.kcode));
|
||||
|
||||
//triggers
|
||||
//1 R
|
||||
w8(pjs.trigger[PJTI_R]);
|
||||
w8(get_analog_axis(0, pjs));
|
||||
//1 L
|
||||
w8(pjs.trigger[PJTI_L]);
|
||||
w8(get_analog_axis(1, pjs));
|
||||
|
||||
//joyx
|
||||
//1
|
||||
w8(pjs.joy[PJAI_X1]);
|
||||
w8(get_analog_axis(2, pjs));
|
||||
//joyy
|
||||
//1
|
||||
w8(pjs.joy[PJAI_Y1]);
|
||||
w8(get_analog_axis(3, pjs));
|
||||
|
||||
//not used
|
||||
//1
|
||||
w8(0x80);
|
||||
w8(get_analog_axis(4, pjs));
|
||||
//1
|
||||
w8(0x80);
|
||||
#else
|
||||
//state data
|
||||
//2 key code
|
||||
w16(pjs.kcode | AWAVE_TRIGGER_KEY);
|
||||
|
||||
//not used
|
||||
//1
|
||||
w8(0);
|
||||
//1
|
||||
w8(0);
|
||||
|
||||
//joyx
|
||||
//1
|
||||
w8(pjs.joy[PJAI_X1]);
|
||||
//joyy
|
||||
//1
|
||||
w8(pjs.joy[PJAI_Y1]);
|
||||
|
||||
//joyrx
|
||||
//1
|
||||
w8(pjs.joy[PJAI_X2]);
|
||||
//joyry
|
||||
//1
|
||||
w8(pjs.joy[PJAI_Y2]);
|
||||
#endif
|
||||
w8(get_analog_axis(5, pjs));
|
||||
}
|
||||
|
||||
return MDRS_DataTransfer;
|
||||
|
@ -313,6 +311,38 @@ struct maple_sega_controller: maple_base
|
|||
}
|
||||
};
|
||||
|
||||
struct maple_atomiswave_controller: maple_sega_controller
|
||||
{
|
||||
virtual u32 get_capabilities() override {
|
||||
// byte 0: 0 0 0 0 0 0 0 0
|
||||
// byte 1: 0 0 a5 a4 a3 a2 a1 a0
|
||||
// byte 2: R2 L2 D2 U2 D X Y Z
|
||||
// byte 3: R L D U St A B C
|
||||
|
||||
return 0xff663f00; // 6 analog axes, X Y L2/D2(?) A B C Start U D L R
|
||||
}
|
||||
|
||||
virtual u32 transform_kcode(u32 kcode) override {
|
||||
return kcode | AWAVE_TRIGGER_KEY;
|
||||
}
|
||||
|
||||
virtual u32 get_analog_axis(int index, const PlainJoystickState &pjs) override {
|
||||
switch (index)
|
||||
{
|
||||
case 2:
|
||||
return pjs.joy[PJAI_X1];
|
||||
case 3:
|
||||
return pjs.joy[PJAI_Y1];
|
||||
case 4:
|
||||
return pjs.joy[PJAI_X2];
|
||||
case 5:
|
||||
return pjs.joy[PJAI_Y2];
|
||||
default:
|
||||
return 0x80;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Sega Dreamcast Visual Memory Unit
|
||||
This is pretty much done (?)
|
||||
|
@ -1299,6 +1329,10 @@ struct maple_mouse : maple_base
|
|||
|
||||
struct maple_lightgun : maple_base
|
||||
{
|
||||
virtual u32 transform_kcode(u32 kcode) {
|
||||
return kcode | 0xFF01;
|
||||
}
|
||||
|
||||
virtual MapleDeviceType get_device_type()
|
||||
{
|
||||
return MDT_LightGun;
|
||||
|
@ -1347,21 +1381,13 @@ struct maple_lightgun : maple_base
|
|||
PlainJoystickState pjs;
|
||||
config->GetInput(&pjs);
|
||||
|
||||
// Also use the mouse buttons
|
||||
if (!(mo_buttons & 4)) // Left button
|
||||
pjs.kcode &= ~4; // A
|
||||
if (!(mo_buttons & 2)) // Right button
|
||||
pjs.kcode &= ~2; // B
|
||||
if (!(mo_buttons & 8)) // Wheel button
|
||||
pjs.kcode &= ~8; // Start
|
||||
|
||||
//caps
|
||||
//4
|
||||
w32(MFID_0_Input);
|
||||
|
||||
//state data
|
||||
//2 key code
|
||||
w16(pjs.kcode | 0xFF01);
|
||||
w16(transform_kcode(pjs.kcode));
|
||||
|
||||
//not used
|
||||
//2
|
||||
|
@ -1387,6 +1413,13 @@ struct maple_lightgun : maple_base
|
|||
}
|
||||
};
|
||||
|
||||
struct atomiswave_lightgun : maple_lightgun
|
||||
{
|
||||
virtual u32 transform_kcode(u32 kcode) override {
|
||||
return (kcode & AWAVE_TRIGGER_KEY) == 0 ? ~AWAVE_BTN0_KEY : ~0;
|
||||
}
|
||||
};
|
||||
|
||||
extern u16 kcode[4];
|
||||
extern s8 joyx[4],joyy[4];
|
||||
extern u8 rt[4], lt[4];
|
||||
|
@ -2592,7 +2625,11 @@ maple_device* maple_Create(MapleDeviceType type)
|
|||
switch(type)
|
||||
{
|
||||
case MDT_SegaController:
|
||||
rv=new maple_sega_controller();
|
||||
#if DC_PLATFORM != DC_PLATFORM_ATOMISWAVE
|
||||
rv = new maple_sega_controller();
|
||||
#else
|
||||
rv = new maple_atomiswave_controller();
|
||||
#endif
|
||||
break;
|
||||
|
||||
case MDT_Microphone:
|
||||
|
@ -2616,7 +2653,11 @@ maple_device* maple_Create(MapleDeviceType type)
|
|||
break;
|
||||
|
||||
case MDT_LightGun:
|
||||
#if DC_PLATFORM != DC_PLATFORM_ATOMISWAVE
|
||||
rv = new maple_lightgun();
|
||||
#else
|
||||
rv = new atomiswave_lightgun();
|
||||
#endif
|
||||
break;
|
||||
|
||||
case MDT_NaomiJamma:
|
||||
|
|
|
@ -232,7 +232,7 @@ int AicaUpdate(int tag, int c, int j)
|
|||
|
||||
int DreamcastSecond(int tag, int c, int j)
|
||||
{
|
||||
settings.dreamcast.RTC++;
|
||||
RealTimeClock++;
|
||||
|
||||
#if 1 //HOST_OS==OS_WINDOWS
|
||||
prof_periodical();
|
||||
|
|
|
@ -213,12 +213,14 @@ void LoadSpecialSettings()
|
|||
printf("Enabling JVS rotary encoders for game %s\n", naomi_game_id);
|
||||
settings.input.JammaSetup = 2;
|
||||
}
|
||||
else if (!strcmp("POWER STONE 2 JAPAN", naomi_game_id))
|
||||
else if (!strcmp("POWER STONE 2 JAPAN", naomi_game_id) // Naomi
|
||||
|| !strcmp("GUILTY GEAR isuka", naomi_game_id)) // AW
|
||||
{
|
||||
printf("Enabling 4-player setup for game %s\n", naomi_game_id);
|
||||
settings.input.JammaSetup = 1;
|
||||
}
|
||||
else if (!strcmp("SEGA MARINE FISHING JAPAN", naomi_game_id))
|
||||
else if (!strcmp("SEGA MARINE FISHING JAPAN", naomi_game_id)
|
||||
|| !strcmp(naomi_game_id, "BASS FISHING SIMULATOR VER.A")) // AW
|
||||
{
|
||||
printf("Enabling specific JVS setup for game %s\n", naomi_game_id);
|
||||
settings.input.JammaSetup = 3;
|
||||
|
@ -228,9 +230,11 @@ void LoadSpecialSettings()
|
|||
printf("Enabling specific JVS setup for game %s\n", naomi_game_id);
|
||||
settings.input.JammaSetup = 4;
|
||||
}
|
||||
else if (!strcmp("NINJA ASSAULT", naomi_game_id))
|
||||
else if (!strcmp("NINJA ASSAULT", naomi_game_id)
|
||||
|| !strcmp(naomi_game_id, "Sports Shooting USA") // AW
|
||||
|| !strcmp(naomi_game_id, "SEGA CLAY CHALLENGE")) // AW
|
||||
{
|
||||
printf("Enabling specific JVS setup for game %s\n", naomi_game_id);
|
||||
printf("Enabling lightgun setup for game %s\n", naomi_game_id);
|
||||
settings.input.JammaSetup = 5;
|
||||
}
|
||||
else if (!strcmp(" BIOHAZARD GUN SURVIVOR2", naomi_game_id))
|
||||
|
@ -309,7 +313,6 @@ int dc_start_game(const char *path)
|
|||
{
|
||||
InitSettings();
|
||||
LoadSettings(false);
|
||||
settings.dreamcast.RTC = GetRTC_now(); // FIXME This shouldn't be in settings anymore
|
||||
#if DC_PLATFORM == DC_PLATFORM_DREAMCAST
|
||||
if (!settings.bios.UseReios)
|
||||
#endif
|
||||
|
@ -347,7 +350,6 @@ int dc_start_game(const char *path)
|
|||
return 0;
|
||||
}
|
||||
|
||||
settings.dreamcast.RTC = GetRTC_now(); // FIXME This shouldn't be in settings anymore
|
||||
if (settings.bios.UseReios || !LoadRomFiles(get_readonly_data_path(DATA_PATH)))
|
||||
{
|
||||
#ifdef USE_REIOS
|
||||
|
@ -487,7 +489,6 @@ void dc_exit()
|
|||
|
||||
void InitSettings()
|
||||
{
|
||||
settings.dreamcast.RTC = GetRTC_now();
|
||||
settings.dynarec.Enable = true;
|
||||
settings.dynarec.idleskip = true;
|
||||
settings.dynarec.unstable_opt = false;
|
||||
|
@ -518,6 +519,8 @@ void InitSettings()
|
|||
settings.rend.ScreenScaling = 100;
|
||||
settings.rend.ScreenStretching = 100;
|
||||
settings.rend.Fog = true;
|
||||
settings.rend.FloatVMUs = false;
|
||||
settings.rend.Rotate90 = false;
|
||||
|
||||
settings.pvr.ta_skip = 0;
|
||||
settings.pvr.rend = 0;
|
||||
|
@ -604,6 +607,8 @@ void LoadSettings(bool game_specific)
|
|||
settings.rend.ScreenScaling = min(max(1, settings.rend.ScreenScaling), 100);
|
||||
settings.rend.ScreenStretching = cfgLoadInt(config_section, "rend.ScreenStretching", settings.rend.ScreenStretching);
|
||||
settings.rend.Fog = cfgLoadBool(config_section, "rend.Fog", settings.rend.Fog);
|
||||
settings.rend.FloatVMUs = cfgLoadBool(config_section, "rend.FloatVMUs", settings.rend.FloatVMUs);
|
||||
settings.rend.Rotate90 = cfgLoadBool(config_section, "rend.Rotate90", settings.rend.Rotate90);
|
||||
|
||||
settings.pvr.ta_skip = cfgLoadInt(config_section, "ta.skip", settings.pvr.ta_skip);
|
||||
settings.pvr.rend = cfgLoadInt(config_section, "pvr.rend", settings.pvr.rend);
|
||||
|
@ -730,6 +735,8 @@ void SaveSettings()
|
|||
cfgSaveInt("config", "rend.ScreenScaling", settings.rend.ScreenScaling);
|
||||
cfgSaveInt("config", "rend.ScreenStretching", settings.rend.ScreenStretching);
|
||||
cfgSaveBool("config", "rend.Fog", settings.rend.Fog);
|
||||
cfgSaveBool("config", "rend.FloatVMUs", settings.rend.FloatVMUs);
|
||||
cfgSaveBool("config", "rend.Rotate90", settings.rend.Rotate90);
|
||||
cfgSaveInt("config", "ta.skip", settings.pvr.ta_skip);
|
||||
cfgSaveInt("config", "pvr.rend", settings.pvr.rend);
|
||||
|
||||
|
|
|
@ -331,23 +331,23 @@ void initABuffer()
|
|||
{
|
||||
char source[16384];
|
||||
sprintf(source, final_shader_source, 1);
|
||||
gl4CompilePipelineShader(&g_abuffer_final_shader, source);
|
||||
gl4CompilePipelineShader(&g_abuffer_final_shader, false, source);
|
||||
}
|
||||
if (g_abuffer_final_nosort_shader.program == 0)
|
||||
{
|
||||
char source[16384];
|
||||
sprintf(source, final_shader_source, 0);
|
||||
gl4CompilePipelineShader(&g_abuffer_final_nosort_shader, source);
|
||||
gl4CompilePipelineShader(&g_abuffer_final_nosort_shader, false, source);
|
||||
}
|
||||
if (g_abuffer_clear_shader.program == 0)
|
||||
gl4CompilePipelineShader(&g_abuffer_clear_shader, clear_shader_source);
|
||||
gl4CompilePipelineShader(&g_abuffer_clear_shader, false, clear_shader_source);
|
||||
if (g_abuffer_tr_modvol_shaders[0].program == 0)
|
||||
{
|
||||
char source[16384];
|
||||
for (int mode = 0; mode < ModeCount; mode++)
|
||||
{
|
||||
sprintf(source, tr_modvol_shader_source, mode);
|
||||
gl4CompilePipelineShader(&g_abuffer_tr_modvol_shaders[mode], source);
|
||||
gl4CompilePipelineShader(&g_abuffer_tr_modvol_shaders[mode], false, source);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -417,6 +417,17 @@ void termABuffer()
|
|||
glDeleteBuffers(1, &g_quadBuffer);
|
||||
g_quadBuffer = 0;
|
||||
}
|
||||
glcache.DeleteProgram(g_abuffer_final_shader.program);
|
||||
g_abuffer_final_shader.program = 0;
|
||||
glcache.DeleteProgram(g_abuffer_final_nosort_shader.program);
|
||||
g_abuffer_final_nosort_shader.program = 0;
|
||||
glcache.DeleteProgram(g_abuffer_clear_shader.program);
|
||||
g_abuffer_clear_shader.program = 0;
|
||||
for (int mode = 0; mode < ModeCount; mode++)
|
||||
{
|
||||
glcache.DeleteProgram(g_abuffer_tr_modvol_shaders[mode].program);
|
||||
g_abuffer_tr_modvol_shaders[mode].program = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void reshapeABuffer(int w, int h)
|
||||
|
|
|
@ -45,6 +45,7 @@ struct gl4_ctx
|
|||
} modvol_shader;
|
||||
|
||||
std::unordered_map<u32, gl4PipelineShader> shaders;
|
||||
bool rotate90;
|
||||
|
||||
struct
|
||||
{
|
||||
|
@ -66,7 +67,8 @@ bool gl4_render_output_framebuffer();
|
|||
void abufferDrawQuad(bool upsideDown = false, float x = 0.f, float y = 0.f, float w = 0.f, float h = 0.f);
|
||||
|
||||
extern const char *gl4PixelPipelineShader;
|
||||
bool gl4CompilePipelineShader(gl4PipelineShader* s, const char *source = gl4PixelPipelineShader);
|
||||
bool gl4CompilePipelineShader(gl4PipelineShader* s, bool rotate_90, const char *source = gl4PixelPipelineShader);
|
||||
void gl4_delete_shaders();
|
||||
|
||||
extern GLuint stencilTexId;
|
||||
extern GLuint depthTexId;
|
||||
|
|
|
@ -49,6 +49,11 @@ static gl4PipelineShader *gl4GetProgram(u32 cp_AlphaTest, u32 pp_ClipTestMode,
|
|||
u32 pp_Texture, u32 pp_UseAlpha, u32 pp_IgnoreTexA, u32 pp_ShadInstr, u32 pp_Offset,
|
||||
u32 pp_FogCtrl, bool pp_TwoVolumes, u32 pp_DepthFunc, bool pp_Gouraud, bool pp_BumpMap, bool fog_clamping, int pass)
|
||||
{
|
||||
if (settings.rend.Rotate90 != gl4.rotate90)
|
||||
{
|
||||
gl4_delete_shaders();
|
||||
gl4.rotate90 = settings.rend.Rotate90;
|
||||
}
|
||||
u32 rv=0;
|
||||
|
||||
rv|=pp_ClipTestMode;
|
||||
|
@ -83,7 +88,7 @@ static gl4PipelineShader *gl4GetProgram(u32 cp_AlphaTest, u32 pp_ClipTestMode,
|
|||
shader->pp_BumpMap = pp_BumpMap;
|
||||
shader->fog_clamping = fog_clamping;
|
||||
shader->pass = pass;
|
||||
gl4CompilePipelineShader(shader);
|
||||
gl4CompilePipelineShader(shader, settings.rend.Rotate90);
|
||||
}
|
||||
|
||||
return shader;
|
||||
|
|
|
@ -14,6 +14,7 @@ static const char* VertexShaderSource =
|
|||
"\
|
||||
#version 140 \n\
|
||||
#define pp_Gouraud %d \n\
|
||||
#define ROTATE_90 %d \n\
|
||||
\n\
|
||||
#if pp_Gouraud == 0 \n\
|
||||
#define INTERPOLATION flat \n\
|
||||
|
@ -56,6 +57,9 @@ void main() \n\
|
|||
\n\
|
||||
vpos.w = extra_depth_scale / vpos.z; \n\
|
||||
vpos.z = vpos.w; \n\
|
||||
#if ROTATE_90 == 1 \n\
|
||||
vpos.xy = vec2(vpos.y, -vpos.x); \n\
|
||||
#endif \n\
|
||||
vpos.xy=vpos.xy*scale.xy-scale.zw; \n\
|
||||
vpos.xy*=vpos.w; \n\
|
||||
gl_Position = vpos; \n\
|
||||
|
@ -393,11 +397,11 @@ gl4_ctx gl4;
|
|||
|
||||
struct gl4ShaderUniforms_t gl4ShaderUniforms;
|
||||
|
||||
bool gl4CompilePipelineShader( gl4PipelineShader* s, const char *source /* = PixelPipelineShader */)
|
||||
bool gl4CompilePipelineShader( gl4PipelineShader* s, bool rotate_90, const char *source /* = PixelPipelineShader */)
|
||||
{
|
||||
char vshader[16384];
|
||||
|
||||
sprintf(vshader, VertexShaderSource, s->pp_Gouraud);
|
||||
sprintf(vshader, VertexShaderSource, s->pp_Gouraud, rotate_90);
|
||||
|
||||
char pshader[16384];
|
||||
|
||||
|
@ -478,27 +482,45 @@ bool gl4CompilePipelineShader( gl4PipelineShader* s, const char *source /* = Pix
|
|||
|
||||
void gl_term();
|
||||
|
||||
void gl4_delete_shaders()
|
||||
{
|
||||
for (auto it : gl4.shaders)
|
||||
{
|
||||
if (it.second.program != 0)
|
||||
glcache.DeleteProgram(it.second.program);
|
||||
}
|
||||
gl4.shaders.clear();
|
||||
glcache.DeleteProgram(gl4.modvol_shader.program);
|
||||
gl4.modvol_shader.program = 0;
|
||||
}
|
||||
|
||||
static void gles_term(void)
|
||||
{
|
||||
glDeleteProgram(gl4.modvol_shader.program);
|
||||
glDeleteBuffers(1, &gl4.vbo.geometry);
|
||||
gl4.vbo.geometry = 0;
|
||||
glDeleteBuffers(1, &gl4.vbo.modvols);
|
||||
glDeleteBuffers(1, &gl4.vbo.idxs);
|
||||
glDeleteBuffers(1, &gl4.vbo.idxs2);
|
||||
glDeleteBuffers(1, &gl4.vbo.tr_poly_params);
|
||||
for (auto it = gl4.shaders.begin(); it != gl4.shaders.end(); it++)
|
||||
{
|
||||
if (it->second.program != 0)
|
||||
glDeleteProgram(it->second.program);
|
||||
}
|
||||
gl4.shaders.clear();
|
||||
gl4_delete_shaders();
|
||||
glDeleteVertexArrays(1, &gl4.vbo.main_vao);
|
||||
glDeleteVertexArrays(1, &gl4.vbo.modvol_vao);
|
||||
|
||||
gl_term();
|
||||
}
|
||||
|
||||
static void create_modvol_shader()
|
||||
{
|
||||
if (gl4.modvol_shader.program != 0)
|
||||
return;
|
||||
char vshader[16384];
|
||||
sprintf(vshader, VertexShaderSource, 1, settings.rend.Rotate90);
|
||||
|
||||
gl4.modvol_shader.program=gl_CompileAndLink(vshader, ModifierVolumeShader);
|
||||
gl4.modvol_shader.scale = glGetUniformLocation(gl4.modvol_shader.program, "scale");
|
||||
gl4.modvol_shader.extra_depth_scale = glGetUniformLocation(gl4.modvol_shader.program, "extra_depth_scale");
|
||||
}
|
||||
|
||||
static bool gl_create_resources()
|
||||
{
|
||||
if (gl4.vbo.geometry != 0)
|
||||
|
@ -520,12 +542,7 @@ static bool gl_create_resources()
|
|||
gl4SetupMainVBO();
|
||||
gl4SetupModvolVBO();
|
||||
|
||||
char vshader[16384];
|
||||
sprintf(vshader, VertexShaderSource, 1);
|
||||
|
||||
gl4.modvol_shader.program=gl_CompileAndLink(vshader, ModifierVolumeShader);
|
||||
gl4.modvol_shader.scale = glGetUniformLocation(gl4.modvol_shader.program, "scale");
|
||||
gl4.modvol_shader.extra_depth_scale = glGetUniformLocation(gl4.modvol_shader.program, "extra_depth_scale");
|
||||
create_modvol_shader();
|
||||
|
||||
gl_load_osd_resources();
|
||||
|
||||
|
@ -603,6 +620,7 @@ static bool RenderFrame()
|
|||
old_screen_scaling = settings.rend.ScreenScaling;
|
||||
}
|
||||
DoCleanup();
|
||||
create_modvol_shader();
|
||||
|
||||
bool is_rtt=pvrrc.isRTT;
|
||||
|
||||
|
@ -661,17 +679,41 @@ static bool RenderFrame()
|
|||
/*
|
||||
Handle Dc to screen scaling
|
||||
*/
|
||||
float screen_scaling = is_rtt ? 1.f : settings.rend.ScreenScaling / 100.f;
|
||||
float screen_scaling = settings.rend.ScreenScaling / 100.f;
|
||||
float screen_stretching = settings.rend.ScreenStretching / 100.f;
|
||||
|
||||
float dc2s_scale_h = is_rtt ? (screen_width / dc_width) : (screen_height / 480.0);
|
||||
float ds2s_offs_x = is_rtt ? 0 : ((screen_width - dc2s_scale_h * 640.0 * screen_stretching) / 2);
|
||||
float dc2s_scale_h;
|
||||
float ds2s_offs_x;
|
||||
|
||||
//-1 -> too much to left
|
||||
gl4ShaderUniforms.scale_coefs[0] = 2.0f / (screen_width / dc2s_scale_h * scale_x) * screen_stretching;
|
||||
gl4ShaderUniforms.scale_coefs[1] = (is_rtt ? 2 : -2) / dc_height; // FIXME CT2 needs 480 here instead of dc_height=512
|
||||
gl4ShaderUniforms.scale_coefs[2] = 1 - 2 * ds2s_offs_x / screen_width;
|
||||
gl4ShaderUniforms.scale_coefs[3] = (is_rtt ? 1 : -1);
|
||||
if (is_rtt)
|
||||
{
|
||||
gl4ShaderUniforms.scale_coefs[0] = 2.0f / dc_width;
|
||||
gl4ShaderUniforms.scale_coefs[1] = 2.0f / dc_height; // FIXME CT2 needs 480 here instead of dc_height=512
|
||||
gl4ShaderUniforms.scale_coefs[2] = 1;
|
||||
gl4ShaderUniforms.scale_coefs[3] = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (settings.rend.Rotate90)
|
||||
{
|
||||
dc2s_scale_h = screen_height / 640.0;
|
||||
ds2s_offs_x = (screen_width - dc2s_scale_h * 480.0 * screen_stretching) / 2;
|
||||
gl4ShaderUniforms.scale_coefs[0] = 2.0f / (screen_width / dc2s_scale_h * scale_x) * screen_stretching;
|
||||
gl4ShaderUniforms.scale_coefs[1] = -2.0f / dc_width;
|
||||
gl4ShaderUniforms.scale_coefs[2] = 1 - 2 * ds2s_offs_x / screen_width;
|
||||
gl4ShaderUniforms.scale_coefs[3] = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
dc2s_scale_h = screen_height / 480.0;
|
||||
ds2s_offs_x = (screen_width - dc2s_scale_h * 640.0 * screen_stretching) / 2;
|
||||
//-1 -> too much to left
|
||||
gl4ShaderUniforms.scale_coefs[0] = 2.0f / (screen_width / dc2s_scale_h * scale_x) * screen_stretching;
|
||||
gl4ShaderUniforms.scale_coefs[1] = -2.0f / dc_height;
|
||||
gl4ShaderUniforms.scale_coefs[2] = 1 - 2 * ds2s_offs_x / screen_width;
|
||||
gl4ShaderUniforms.scale_coefs[3] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
gl4ShaderUniforms.extra_depth_scale = settings.rend.ExtraDepthScale;
|
||||
|
||||
|
@ -826,11 +868,20 @@ static bool RenderFrame()
|
|||
float min_y = pvrrc.fb_Y_CLIP.min / scale_y;
|
||||
if (!is_rtt)
|
||||
{
|
||||
if (settings.rend.Rotate90)
|
||||
{
|
||||
float t = width;
|
||||
width = height;
|
||||
height = t;
|
||||
t = min_x;
|
||||
min_x = min_y;
|
||||
min_y = 640 - t - height;
|
||||
}
|
||||
// Add x offset for aspect ratio > 4/3
|
||||
min_x = min_x * dc2s_scale_h * screen_stretching + ds2s_offs_x * screen_scaling;
|
||||
min_x = (min_x * dc2s_scale_h * screen_stretching + ds2s_offs_x) * screen_scaling;
|
||||
// Invert y coordinates when rendering to screen
|
||||
min_y = (screen_height - (min_y + height) * dc2s_scale_h) * screen_scaling;
|
||||
width *= dc2s_scale_h * screen_scaling * screen_stretching;
|
||||
width *= dc2s_scale_h * screen_stretching * screen_scaling;
|
||||
height *= dc2s_scale_h * screen_scaling;
|
||||
|
||||
if (ds2s_offs_x > 0)
|
||||
|
|
|
@ -149,6 +149,19 @@ public:
|
|||
return _texture_ids[--_texture_cache_size];
|
||||
}
|
||||
|
||||
void DeleteProgram(GLuint program)
|
||||
{
|
||||
GLsizei shader_count;
|
||||
GLuint shaders[2];
|
||||
glGetAttachedShaders(program, ARRAY_SIZE(shaders), &shader_count, shaders);
|
||||
for (int i = 0; i < shader_count; i++)
|
||||
glDeleteShader(shaders[i]);
|
||||
|
||||
glDeleteProgram(program);
|
||||
if (_program == program)
|
||||
_program = 0;
|
||||
}
|
||||
|
||||
void Reset() {
|
||||
_texture = 0xFFFFFFFFu;
|
||||
_src_blend_factor = 0xFFFFFFFFu;
|
||||
|
|
|
@ -114,13 +114,30 @@ s32 SetTileClip(u32 val, GLint uniform)
|
|||
csy /= scale_y;
|
||||
cex /= scale_x;
|
||||
cey /= scale_y;
|
||||
float t = cey;
|
||||
cey = 480 - csy;
|
||||
csy = 480 - t;
|
||||
float dc2s_scale_h = screen_height / 480.0f;
|
||||
float ds2s_offs_x = (screen_width - dc2s_scale_h * 640) / 2;
|
||||
csx = csx * dc2s_scale_h + ds2s_offs_x;
|
||||
cex = cex * dc2s_scale_h + ds2s_offs_x;
|
||||
float dc2s_scale_h;
|
||||
float ds2s_offs_x;
|
||||
float screen_stretching = settings.rend.ScreenStretching / 100.f;
|
||||
|
||||
if (settings.rend.Rotate90)
|
||||
{
|
||||
float t = cex;
|
||||
cex = cey;
|
||||
cey = 640 - csx;
|
||||
csx = csy;
|
||||
csy = 640 - t;
|
||||
dc2s_scale_h = screen_height / 640.0f;
|
||||
ds2s_offs_x = (screen_width - dc2s_scale_h * 480.0 * screen_stretching) / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
float t = cey;
|
||||
cey = 480 - csy;
|
||||
csy = 480 - t;
|
||||
dc2s_scale_h = screen_height / 480.0f;
|
||||
ds2s_offs_x = (screen_width - dc2s_scale_h * 640.0 * screen_stretching) / 2;
|
||||
}
|
||||
csx = csx * dc2s_scale_h * screen_stretching + ds2s_offs_x;
|
||||
cex = cex * dc2s_scale_h * screen_stretching + ds2s_offs_x;
|
||||
csy = csy * dc2s_scale_h;
|
||||
cey = cey * dc2s_scale_h;
|
||||
}
|
||||
|
|
|
@ -79,6 +79,7 @@ const char* VertexShaderSource =
|
|||
%s \n\
|
||||
#define TARGET_GL %s \n\
|
||||
#define pp_Gouraud %d \n\
|
||||
#define ROTATE_90 %d \n\
|
||||
\n\
|
||||
#define GLES2 0 \n\
|
||||
#define GLES3 1 \n\
|
||||
|
@ -136,6 +137,9 @@ void main() \n\
|
|||
vpos.z = vpos.w; \n\
|
||||
#else \n\
|
||||
vpos.z=depth_scale.x+depth_scale.y*vpos.w; \n\
|
||||
#endif \n\
|
||||
#if ROTATE_90 == 1 \n\
|
||||
vpos.xy = vec2(vpos.y, -vpos.x); \n\
|
||||
#endif \n\
|
||||
vpos.xy=vpos.xy*scale.xy-scale.zw; \n\
|
||||
vpos.xy*=vpos.w; \n\
|
||||
|
@ -850,9 +854,20 @@ GLuint fogTextureId;
|
|||
extern void gl_term();
|
||||
#endif
|
||||
|
||||
static void gl_delete_shaders()
|
||||
{
|
||||
for (auto it : gl.shaders)
|
||||
{
|
||||
if (it.second.program != 0)
|
||||
glcache.DeleteProgram(it.second.program);
|
||||
}
|
||||
gl.shaders.clear();
|
||||
glcache.DeleteProgram(gl.modvol_shader.program);
|
||||
gl.modvol_shader.program = 0;
|
||||
}
|
||||
|
||||
static void gles_term()
|
||||
{
|
||||
glDeleteProgram(gl.modvol_shader.program);
|
||||
glDeleteBuffers(1, &gl.vbo.geometry);
|
||||
gl.vbo.geometry = 0;
|
||||
glDeleteBuffers(1, &gl.vbo.modvols);
|
||||
|
@ -865,7 +880,7 @@ static void gles_term()
|
|||
gl_free_osd_resources();
|
||||
free_output_framebuffer();
|
||||
|
||||
gl.shaders.clear();
|
||||
gl_delete_shaders();
|
||||
gl_term();
|
||||
}
|
||||
|
||||
|
@ -1018,6 +1033,11 @@ PipelineShader *GetProgram(u32 cp_AlphaTest, u32 pp_ClipTestMode,
|
|||
u32 pp_Texture, u32 pp_UseAlpha, u32 pp_IgnoreTexA, u32 pp_ShadInstr, u32 pp_Offset,
|
||||
u32 pp_FogCtrl, bool pp_Gouraud, bool pp_BumpMap, bool fog_clamping, bool trilinear)
|
||||
{
|
||||
if (settings.rend.Rotate90 != gl.rotate90)
|
||||
{
|
||||
gl_delete_shaders();
|
||||
gl.rotate90 = settings.rend.Rotate90;
|
||||
}
|
||||
u32 rv=0;
|
||||
|
||||
rv|=pp_ClipTestMode;
|
||||
|
@ -1058,7 +1078,7 @@ bool CompilePipelineShader( PipelineShader* s)
|
|||
{
|
||||
char vshader[8192];
|
||||
|
||||
sprintf(vshader, VertexShaderSource, gl.glsl_version_header, gl.gl_version, s->pp_Gouraud);
|
||||
sprintf(vshader, VertexShaderSource, gl.glsl_version_header, gl.gl_version, s->pp_Gouraud, settings.rend.Rotate90);
|
||||
|
||||
char pshader[8192];
|
||||
|
||||
|
@ -1144,13 +1164,30 @@ void gl_load_osd_resources()
|
|||
|
||||
void gl_free_osd_resources()
|
||||
{
|
||||
glDeleteProgram(gl.OSD_SHADER.program);
|
||||
glcache.DeleteProgram(gl.OSD_SHADER.program);
|
||||
|
||||
if (osd_tex != 0) {
|
||||
glcache.DeleteTextures(1, &osd_tex);
|
||||
osd_tex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void create_modvol_shader()
|
||||
{
|
||||
if (gl.modvol_shader.program != 0)
|
||||
return;
|
||||
char vshader[8192];
|
||||
sprintf(vshader, VertexShaderSource, gl.glsl_version_header, gl.gl_version, 1, settings.rend.Rotate90);
|
||||
char fshader[8192];
|
||||
sprintf(fshader, ModifierVolumeShader, gl.glsl_version_header, gl.gl_version);
|
||||
|
||||
gl.modvol_shader.program=gl_CompileAndLink(vshader, fshader);
|
||||
gl.modvol_shader.scale = glGetUniformLocation(gl.modvol_shader.program, "scale");
|
||||
gl.modvol_shader.sp_ShaderColor = glGetUniformLocation(gl.modvol_shader.program, "sp_ShaderColor");
|
||||
gl.modvol_shader.depth_scale = glGetUniformLocation(gl.modvol_shader.program, "depth_scale");
|
||||
gl.modvol_shader.extra_depth_scale = glGetUniformLocation(gl.modvol_shader.program, "extra_depth_scale");
|
||||
}
|
||||
|
||||
bool gl_create_resources()
|
||||
{
|
||||
if (gl.vbo.geometry != 0)
|
||||
|
@ -1174,25 +1211,7 @@ bool gl_create_resources()
|
|||
glGenBuffers(1, &gl.vbo.idxs);
|
||||
glGenBuffers(1, &gl.vbo.idxs2);
|
||||
|
||||
char vshader[8192];
|
||||
sprintf(vshader, VertexShaderSource, gl.glsl_version_header, gl.gl_version, 1);
|
||||
char fshader[8192];
|
||||
sprintf(fshader, ModifierVolumeShader, gl.glsl_version_header, gl.gl_version);
|
||||
|
||||
gl.modvol_shader.program=gl_CompileAndLink(vshader, fshader);
|
||||
gl.modvol_shader.scale = glGetUniformLocation(gl.modvol_shader.program, "scale");
|
||||
gl.modvol_shader.sp_ShaderColor = glGetUniformLocation(gl.modvol_shader.program, "sp_ShaderColor");
|
||||
gl.modvol_shader.depth_scale = glGetUniformLocation(gl.modvol_shader.program, "depth_scale");
|
||||
gl.modvol_shader.extra_depth_scale = glGetUniformLocation(gl.modvol_shader.program, "extra_depth_scale");
|
||||
|
||||
//#define PRECOMPILE_SHADERS
|
||||
#ifdef PRECOMPILE_SHADERS
|
||||
for (u32 i=0;i<sizeof(gl.pogram_table)/sizeof(gl.pogram_table[0]);i++)
|
||||
{
|
||||
if (!CompilePipelineShader( &gl.pogram_table[i] ))
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
create_modvol_shader();
|
||||
|
||||
gl_load_osd_resources();
|
||||
|
||||
|
@ -1512,6 +1531,7 @@ static void upload_vertex_indices()
|
|||
bool RenderFrame()
|
||||
{
|
||||
DoCleanup();
|
||||
create_modvol_shader();
|
||||
|
||||
bool is_rtt=pvrrc.isRTT;
|
||||
|
||||
|
@ -1681,15 +1701,38 @@ bool RenderFrame()
|
|||
float screen_stretching = settings.rend.ScreenStretching / 100.f;
|
||||
float screen_scaling = settings.rend.ScreenScaling / 100.f;
|
||||
|
||||
float dc2s_scale_h = is_rtt ? (screen_width / dc_width) : (screen_height / 480.0);
|
||||
float ds2s_offs_x = is_rtt ? 0 : ((screen_width - dc2s_scale_h * 640.0 * screen_stretching) / 2);
|
||||
|
||||
//-1 -> too much to left
|
||||
ShaderUniforms.scale_coefs[0] = 2.0f / (screen_width / dc2s_scale_h * scale_x) * screen_stretching;
|
||||
ShaderUniforms.scale_coefs[1]= (is_rtt ? 2 : -2) / dc_height; // FIXME CT2 needs 480 here instead of dc_height=512
|
||||
ShaderUniforms.scale_coefs[2]= 1 - 2 * ds2s_offs_x / screen_width;
|
||||
ShaderUniforms.scale_coefs[3]= (is_rtt ? 1 : -1);
|
||||
float dc2s_scale_h;
|
||||
float ds2s_offs_x;
|
||||
|
||||
if (is_rtt)
|
||||
{
|
||||
ShaderUniforms.scale_coefs[0] = 2.0f / dc_width;
|
||||
ShaderUniforms.scale_coefs[1] = 2.0f / dc_height; // FIXME CT2 needs 480 here instead of dc_height=512
|
||||
ShaderUniforms.scale_coefs[2] = 1;
|
||||
ShaderUniforms.scale_coefs[3] = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (settings.rend.Rotate90)
|
||||
{
|
||||
dc2s_scale_h = screen_height / 640.0f;
|
||||
ds2s_offs_x = (screen_width - dc2s_scale_h * 480.0f * screen_stretching) / 2;
|
||||
ShaderUniforms.scale_coefs[0] = 2.0f / (screen_width / dc2s_scale_h * scale_x) * screen_stretching;
|
||||
ShaderUniforms.scale_coefs[1] = -2.0f / dc_width;
|
||||
ShaderUniforms.scale_coefs[2] = 1 - 2 * ds2s_offs_x / screen_width;
|
||||
ShaderUniforms.scale_coefs[3] = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
dc2s_scale_h = screen_height / 480.0f;
|
||||
ds2s_offs_x = (screen_width - dc2s_scale_h * 640.0f * screen_stretching) / 2;
|
||||
ShaderUniforms.scale_coefs[0] = 2.0f / (screen_width / dc2s_scale_h * scale_x) * screen_stretching;
|
||||
ShaderUniforms.scale_coefs[1] = -2.0f / dc_height;
|
||||
ShaderUniforms.scale_coefs[2] = 1 - 2 * ds2s_offs_x / screen_width;
|
||||
ShaderUniforms.scale_coefs[3] = -1;
|
||||
}
|
||||
//-1 -> too much to left
|
||||
}
|
||||
|
||||
ShaderUniforms.depth_coefs[0]=2/(vtx_max_fZ-vtx_min_fZ);
|
||||
ShaderUniforms.depth_coefs[1]=-vtx_min_fZ-1;
|
||||
|
@ -1857,11 +1900,20 @@ bool RenderFrame()
|
|||
float min_y = pvrrc.fb_Y_CLIP.min / scale_y;
|
||||
if (!is_rtt)
|
||||
{
|
||||
if (settings.rend.Rotate90)
|
||||
{
|
||||
float t = width;
|
||||
width = height;
|
||||
height = t;
|
||||
t = min_x;
|
||||
min_x = min_y;
|
||||
min_y = 640 - t - height;
|
||||
}
|
||||
// Add x offset for aspect ratio > 4/3
|
||||
min_x = min_x * dc2s_scale_h * screen_stretching + ds2s_offs_x * screen_scaling;
|
||||
min_x = (min_x * dc2s_scale_h * screen_stretching + ds2s_offs_x) * screen_scaling;
|
||||
// Invert y coordinates when rendering to screen
|
||||
min_y = (screen_height - (min_y + height) * dc2s_scale_h) * screen_scaling;
|
||||
width *= dc2s_scale_h * screen_scaling * screen_stretching;
|
||||
width *= dc2s_scale_h * screen_stretching * screen_scaling;
|
||||
height *= dc2s_scale_h * screen_scaling;
|
||||
|
||||
if (ds2s_offs_x > 0)
|
||||
|
|
|
@ -96,6 +96,7 @@ struct gl_ctx
|
|||
} modvol_shader;
|
||||
|
||||
std::unordered_map<u32, PipelineShader> shaders;
|
||||
bool rotate90;
|
||||
|
||||
struct
|
||||
{
|
||||
|
|
|
@ -490,15 +490,9 @@ void ImGui_ImplOpenGL3_DestroyDeviceObjects()
|
|||
if (g_ElementsHandle) glDeleteBuffers(1, &g_ElementsHandle);
|
||||
g_VboHandle = g_ElementsHandle = 0;
|
||||
|
||||
if (g_ShaderHandle && g_VertHandle) glDetachShader(g_ShaderHandle, g_VertHandle);
|
||||
if (g_VertHandle) glDeleteShader(g_VertHandle);
|
||||
glcache.DeleteProgram(g_ShaderHandle);
|
||||
g_VertHandle = 0;
|
||||
|
||||
if (g_ShaderHandle && g_FragHandle) glDetachShader(g_ShaderHandle, g_FragHandle);
|
||||
if (g_FragHandle) glDeleteShader(g_FragHandle);
|
||||
g_FragHandle = 0;
|
||||
|
||||
if (g_ShaderHandle) glDeleteProgram(g_ShaderHandle);
|
||||
g_ShaderHandle = 0;
|
||||
|
||||
ImGui_ImplOpenGL3_DestroyFontsTexture();
|
||||
|
|
|
@ -296,7 +296,9 @@ static void gui_display_commands()
|
|||
if (!settings_opening)
|
||||
ImGui_ImplOpenGL3_DrawBackground();
|
||||
|
||||
display_vmus();
|
||||
if (!settings.rend.FloatVMUs)
|
||||
// If floating VMUs, they are already visible on the background
|
||||
display_vmus();
|
||||
|
||||
ImGui::SetNextWindowPos(ImVec2(screen_width / 2.f, screen_height / 2.f), ImGuiCond_Always, ImVec2(0.5f, 0.5f));
|
||||
ImGui::SetNextWindowSize(ImVec2(330 * scaling, 0));
|
||||
|
@ -619,6 +621,8 @@ void directory_selected_callback(bool cancelled, std::string selection)
|
|||
|
||||
static void gui_display_settings()
|
||||
{
|
||||
static bool maple_devices_changed;
|
||||
|
||||
ImGui_Impl_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
|
||||
|
@ -641,10 +645,14 @@ static void gui_display_settings()
|
|||
gui_state = Commands;
|
||||
else
|
||||
gui_state = Main;
|
||||
if (maple_devices_changed)
|
||||
{
|
||||
maple_devices_changed = false;
|
||||
#if DC_PLATFORM == DC_PLATFORM_DREAMCAST
|
||||
maple_ReconnectDevices();
|
||||
reset_vmus();
|
||||
maple_ReconnectDevices();
|
||||
reset_vmus();
|
||||
#endif
|
||||
}
|
||||
SaveSettings();
|
||||
}
|
||||
if (game_started)
|
||||
|
@ -798,13 +806,14 @@ static void gui_display_settings()
|
|||
if (ImGui::BeginTabItem("Controls"))
|
||||
{
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, normal_padding);
|
||||
#if DC_PLATFORM == DC_PLATFORM_DREAMCAST
|
||||
#if DC_PLATFORM == DC_PLATFORM_DREAMCAST || DC_PLATFORM == DC_PLATFORM_ATOMISWAVE
|
||||
if (ImGui::CollapsingHeader("Dreamcast Devices", ImGuiTreeNodeFlags_DefaultOpen))
|
||||
{
|
||||
for (int bus = 0; bus < MAPLE_PORTS; bus++)
|
||||
{
|
||||
ImGui::Text("Device %c", bus + 'A');
|
||||
ImGui::SameLine();
|
||||
#if DC_PLATFORM == DC_PLATFORM_DREAMCAST
|
||||
char device_name[32];
|
||||
sprintf(device_name, "##device%d", bus);
|
||||
float w = ImGui::CalcItemWidth() / 3;
|
||||
|
@ -815,7 +824,10 @@ static void gui_display_settings()
|
|||
{
|
||||
bool is_selected = settings.input.maple_devices[bus] == maple_device_type_from_index(i);
|
||||
if (ImGui::Selectable(maple_device_types[i], &is_selected))
|
||||
{
|
||||
settings.input.maple_devices[bus] = maple_device_type_from_index(i);
|
||||
maple_devices_changed = true;
|
||||
}
|
||||
if (is_selected)
|
||||
ImGui::SetItemDefaultFocus();
|
||||
}
|
||||
|
@ -833,7 +845,10 @@ static void gui_display_settings()
|
|||
{
|
||||
bool is_selected = settings.input.maple_expansion_devices[bus][port] == maple_expansion_device_type_from_index(i);
|
||||
if (ImGui::Selectable(maple_expansion_device_types[i], &is_selected))
|
||||
{
|
||||
settings.input.maple_expansion_devices[bus][port] = maple_expansion_device_type_from_index(i);
|
||||
maple_devices_changed = true;
|
||||
}
|
||||
if (is_selected)
|
||||
ImGui::SetItemDefaultFocus();
|
||||
}
|
||||
|
@ -842,6 +857,10 @@ static void gui_display_settings()
|
|||
ImGui::PopID();
|
||||
}
|
||||
ImGui::PopItemWidth();
|
||||
#elif DC_PLATFORM == DC_PLATFORM_ATOMISWAVE
|
||||
if (MapleDevices[bus][5] != NULL)
|
||||
ImGui::Text("%s", maple_device_name(MapleDevices[bus][5]->get_device_type()));
|
||||
#endif
|
||||
}
|
||||
ImGui::Spacing();
|
||||
}
|
||||
|
@ -951,6 +970,12 @@ static void gui_display_settings()
|
|||
ImGui::Checkbox("Show FPS Counter", &settings.rend.ShowFPS);
|
||||
ImGui::SameLine();
|
||||
ShowHelpMarker("Show on-screen frame/sec counter");
|
||||
ImGui::Checkbox("Show VMU in game", &settings.rend.FloatVMUs);
|
||||
ImGui::SameLine();
|
||||
ShowHelpMarker("Show the VMU LCD screens while in game");
|
||||
ImGui::Checkbox("Rotate screen 90°", &settings.rend.Rotate90);
|
||||
ImGui::SameLine();
|
||||
ShowHelpMarker("Rotate the screen 90° counterclockwise");
|
||||
ImGui::SliderInt("Scaling", (int *)&settings.rend.ScreenScaling, 1, 100);
|
||||
ImGui::SameLine();
|
||||
ShowHelpMarker("Downscaling factor relative to native screen resolution. Higher is better");
|
||||
|
@ -1503,26 +1528,32 @@ void gui_display_osd()
|
|||
if (osd_message.empty())
|
||||
{
|
||||
message = getFPSNotification();
|
||||
if (message.empty())
|
||||
return;
|
||||
}
|
||||
else
|
||||
message = osd_message;
|
||||
|
||||
ImGui_Impl_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
if (!message.empty() || settings.rend.FloatVMUs)
|
||||
{
|
||||
ImGui_Impl_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
|
||||
ImGui::SetNextWindowBgAlpha(0);
|
||||
ImGui::SetNextWindowPos(ImVec2(0, screen_height), ImGuiCond_Always, ImVec2(0.f, 1.f)); // Lower left corner
|
||||
if (!message.empty())
|
||||
{
|
||||
ImGui::SetNextWindowBgAlpha(0);
|
||||
ImGui::SetNextWindowPos(ImVec2(0, screen_height), ImGuiCond_Always, ImVec2(0.f, 1.f)); // Lower left corner
|
||||
|
||||
ImGui::Begin("##osd", NULL, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoNav
|
||||
| ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoBackground);
|
||||
ImGui::SetWindowFontScale(1.5);
|
||||
ImGui::TextColored(ImVec4(1, 1, 0, 0.7), "%s", message.c_str());
|
||||
ImGui::End();
|
||||
ImGui::Begin("##osd", NULL, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoNav
|
||||
| ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoBackground);
|
||||
ImGui::SetWindowFontScale(1.5);
|
||||
ImGui::TextColored(ImVec4(1, 1, 0, 0.7), "%s", message.c_str());
|
||||
ImGui::End();
|
||||
}
|
||||
if (settings.rend.FloatVMUs)
|
||||
display_vmus();
|
||||
|
||||
ImGui::Render();
|
||||
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
||||
ImGui::Render();
|
||||
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
||||
}
|
||||
}
|
||||
|
||||
void gui_open_onboarding()
|
||||
|
|
|
@ -635,6 +635,8 @@ struct settings_t
|
|||
int ScreenScaling; // in percent. 50 means half the native resolution
|
||||
int ScreenStretching; // in percent. 150 means stretch from 4/3 to 6/3
|
||||
bool Fog;
|
||||
bool FloatVMUs;
|
||||
bool Rotate90; // Rotate the screen 90 deg CC
|
||||
} rend;
|
||||
|
||||
struct
|
||||
|
@ -655,7 +657,6 @@ struct settings_t
|
|||
struct
|
||||
{
|
||||
u32 cable; // 0 -> VGA, 1 -> VGA, 2 -> RGB, 3 -> TV
|
||||
u32 RTC;
|
||||
u32 region; // 0 -> JP, 1 -> USA, 2 -> EU, 3 -> default
|
||||
u32 broadcast; // 0 -> NTSC, 1 -> PAL, 2 -> PAL/M, 3 -> PAL/N, 4 -> default
|
||||
u32 language; // 0 -> JP, 1 -> EN, 2 -> DE, 3 -> FR, 4 -> SP, 5 -> IT, 6 -> default
|
||||
|
|
|
@ -749,6 +749,7 @@ cThread::cThread(ThreadEntryFP* function,void* prm)
|
|||
|
||||
void cThread::Start()
|
||||
{
|
||||
verify(hThread == NULL);
|
||||
hThread=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)Entry,param,0,NULL);
|
||||
ResumeThread(hThread);
|
||||
}
|
||||
|
@ -756,6 +757,8 @@ void cThread::Start()
|
|||
void cThread::WaitToEnd()
|
||||
{
|
||||
WaitForSingleObject(hThread,INFINITE);
|
||||
CloseHandle(hThread);
|
||||
hThread = NULL;
|
||||
}
|
||||
//End thread class
|
||||
|
||||
|
|
|
@ -52,5 +52,56 @@
|
|||
android:scheme="file" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity-alias
|
||||
android:name="com.reicast.emulator.MainActivity"
|
||||
android:targetActivity="com.reicast.emulator.NativeGLActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data
|
||||
android:host="*"
|
||||
android:mimeType="*/*"
|
||||
android:pathPattern=".*\\.GDI"
|
||||
android:scheme="file" />
|
||||
<data
|
||||
android:host="*"
|
||||
android:mimeType="*/*"
|
||||
android:pathPattern=".*\\.gdi"
|
||||
android:scheme="file" />
|
||||
<data
|
||||
android:host="*"
|
||||
android:mimeType="*/*"
|
||||
android:pathPattern=".*\\.CHD"
|
||||
android:scheme="file" />
|
||||
<data
|
||||
android:host="*"
|
||||
android:mimeType="*/*"
|
||||
android:pathPattern=".*\\.chd"
|
||||
android:scheme="file" />
|
||||
<data
|
||||
android:host="*"
|
||||
android:mimeType="*/*"
|
||||
android:pathPattern=".*\\.CDI"
|
||||
android:scheme="file" />
|
||||
<data
|
||||
android:host="*"
|
||||
android:mimeType="*/*"
|
||||
android:pathPattern=".*\\.cdi"
|
||||
android:scheme="file" />
|
||||
<data
|
||||
android:host="*"
|
||||
android:mimeType="*/*"
|
||||
android:pathPattern=".*\\.CUE"
|
||||
android:scheme="file" />
|
||||
<data
|
||||
android:host="*"
|
||||
android:mimeType="*/*"
|
||||
android:pathPattern=".*\\.cue"
|
||||
android:scheme="file" />
|
||||
</intent-filter>
|
||||
</activity-alias>
|
||||
</application>
|
||||
</manifest>
|
|
@ -61,6 +61,16 @@
|
|||
<category android:name="android.intent.category.LEANBACK_LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity-alias
|
||||
android:name="com.reicast.emulator.MainActivity"
|
||||
android:targetActivity="com.reicast.emulator.NativeGLActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
<category android:name="tv.ouya.intent.category.GAME" />
|
||||
<category android:name="android.intent.category.LEANBACK_LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity-alias>
|
||||
<provider
|
||||
android:name="android.support.v4.content.FileProvider"
|
||||
android:authorities="${applicationId}.provider"
|
||||
|
|
|
@ -21,8 +21,7 @@ public final class JNIdc
|
|||
public static native int send(int cmd, int opt);
|
||||
public static native int data(int cmd, byte[] data);
|
||||
|
||||
public static native void rendinitNative(Surface surface, int w, int h);
|
||||
public static native boolean rendframeNative();
|
||||
public static native void rendinitNative(Surface surface);
|
||||
public static native void rendinitJava(int w, int h);
|
||||
public static native boolean rendframeJava();
|
||||
public static native void rendtermJava();
|
||||
|
|
|
@ -19,8 +19,6 @@ import com.reicast.emulator.NativeGLActivity;
|
|||
import com.reicast.emulator.config.Config;
|
||||
|
||||
public class NativeGLView extends SurfaceView implements SurfaceHolder.Callback {
|
||||
private Handler handler = new Handler();
|
||||
|
||||
private boolean surfaceReady = false;
|
||||
private boolean paused = false;
|
||||
VirtualJoystickDelegate vjoyDelegate;
|
||||
|
@ -66,23 +64,6 @@ public class NativeGLView extends SurfaceView implements SurfaceHolder.Callback
|
|||
|
||||
if (NativeGLActivity.syms != null)
|
||||
JNIdc.data(1, NativeGLActivity.syms);
|
||||
|
||||
startRendering();
|
||||
}
|
||||
|
||||
private void startRendering() {
|
||||
// Continuously render frames
|
||||
handler.removeCallbacksAndMessages(null);
|
||||
handler.postAtTime(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!paused)
|
||||
{
|
||||
JNIdc.rendframeNative();
|
||||
handler.post(this);
|
||||
}
|
||||
}
|
||||
}, SystemClock.uptimeMillis() + 500);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -111,7 +92,7 @@ public class NativeGLView extends SurfaceView implements SurfaceHolder.Callback
|
|||
public void surfaceChanged(SurfaceHolder surfaceHolder, int format, int w, int h) {
|
||||
//Log.i("reicast", "NativeGLView.surfaceChanged: " + w + "x" + h);
|
||||
surfaceReady = true;
|
||||
JNIdc.rendinitNative(surfaceHolder.getSurface(), w, h);
|
||||
JNIdc.rendinitNative(surfaceHolder.getSurface());
|
||||
Emulator.getCurrentActivity().handleStateChange(false);
|
||||
}
|
||||
|
||||
|
@ -119,7 +100,7 @@ public class NativeGLView extends SurfaceView implements SurfaceHolder.Callback
|
|||
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
|
||||
//Log.i("reicast", "NativeGLView.surfaceDestroyed");
|
||||
surfaceReady = false;
|
||||
JNIdc.rendinitNative(null, 0, 0);
|
||||
JNIdc.rendinitNative(null);
|
||||
Emulator.getCurrentActivity().handleStateChange(true);
|
||||
}
|
||||
|
||||
|
@ -142,7 +123,6 @@ public class NativeGLView extends SurfaceView implements SurfaceHolder.Callback
|
|||
requestFocus();
|
||||
JNIdc.resume();
|
||||
}
|
||||
startRendering();
|
||||
}
|
||||
|
||||
@TargetApi(19)
|
||||
|
|
|
@ -91,8 +91,7 @@ JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_destroy(JNIEnv *env,j
|
|||
JNIEXPORT jint JNICALL Java_com_reicast_emulator_emu_JNIdc_send(JNIEnv *env,jobject obj,jint id, jint v) __attribute__((visibility("default")));
|
||||
JNIEXPORT jint JNICALL Java_com_reicast_emulator_emu_JNIdc_data(JNIEnv *env,jobject obj,jint id, jbyteArray d) __attribute__((visibility("default")));
|
||||
|
||||
JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_rendinitNative(JNIEnv *env, jobject obj, jobject surface, jint w, jint h) __attribute__((visibility("default")));
|
||||
JNIEXPORT jboolean JNICALL Java_com_reicast_emulator_emu_JNIdc_rendframeNative(JNIEnv *env,jobject obj) __attribute__((visibility("default")));
|
||||
JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_rendinitNative(JNIEnv *env, jobject obj, jobject surface) __attribute__((visibility("default")));
|
||||
JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_rendinitJava(JNIEnv *env, jobject obj, jint w, jint h) __attribute__((visibility("default")));
|
||||
JNIEXPORT jboolean JNICALL Java_com_reicast_emulator_emu_JNIdc_rendframeJava(JNIEnv *env, jobject obj) __attribute__((visibility("default")));
|
||||
JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_rendtermJava(JNIEnv *env, jobject obj) __attribute__((visibility("default")));
|
||||
|
@ -404,35 +403,57 @@ JNIEXPORT jint JNICALL Java_com_reicast_emulator_emu_JNIdc_data(JNIEnv *env, job
|
|||
|
||||
extern void gl_swap();
|
||||
extern void egl_stealcntx();
|
||||
volatile static bool render_running;
|
||||
volatile static bool render_reinit;
|
||||
|
||||
JNIEXPORT jboolean JNICALL Java_com_reicast_emulator_emu_JNIdc_rendframeNative(JNIEnv *env,jobject obj)
|
||||
void *render_thread_func(void *)
|
||||
{
|
||||
if (g_window == NULL)
|
||||
return false;
|
||||
if (!egl_makecurrent())
|
||||
return false;
|
||||
jboolean ret = (jboolean)rend_single_frame();
|
||||
if (ret)
|
||||
gl_swap();
|
||||
return ret;
|
||||
render_running = true;
|
||||
|
||||
rend_init_renderer();
|
||||
|
||||
while (render_running) {
|
||||
if (render_reinit)
|
||||
{
|
||||
render_reinit = false;
|
||||
rend_init_renderer();
|
||||
}
|
||||
else
|
||||
if (!egl_makecurrent())
|
||||
break;;
|
||||
|
||||
bool ret = rend_single_frame();
|
||||
if (ret)
|
||||
gl_swap();
|
||||
}
|
||||
egl_makecurrent();
|
||||
rend_term_renderer();
|
||||
ANativeWindow_release(g_window);
|
||||
g_window = NULL;
|
||||
render_running = false;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_rendinitNative(JNIEnv * env, jobject obj, jobject surface, jint width, jint height)
|
||||
static cThread render_thread(render_thread_func, NULL);
|
||||
|
||||
JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_rendinitNative(JNIEnv * env, jobject obj, jobject surface)
|
||||
{
|
||||
if (g_window != NULL)
|
||||
{
|
||||
egl_makecurrent();
|
||||
rend_term_renderer();
|
||||
ANativeWindow_release(g_window);
|
||||
g_window = NULL;
|
||||
}
|
||||
if (surface != NULL)
|
||||
{
|
||||
if (render_thread.hThread != NULL)
|
||||
{
|
||||
if (surface == NULL)
|
||||
{
|
||||
render_running = false;
|
||||
render_thread.WaitToEnd();
|
||||
}
|
||||
else
|
||||
render_reinit = true;
|
||||
}
|
||||
else if (surface != NULL)
|
||||
{
|
||||
g_window = ANativeWindow_fromSurface(env, surface);
|
||||
rend_init_renderer();
|
||||
screen_width = width;
|
||||
screen_height = height;
|
||||
}
|
||||
render_thread.Start();
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_rendinitJava(JNIEnv * env, jobject obj, jint width, jint height)
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
android:name="com.reicast.emulator.Emulator">
|
||||
|
||||
<activity
|
||||
android:name="com.reicast.emulator.MainActivity">
|
||||
android:name="com.reicast.emulator.NativeGLActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
|
@ -62,5 +62,66 @@
|
|||
android:scheme="file" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity-alias
|
||||
android:name="com.reicast.emulator.MainActivity"
|
||||
android:targetActivity="com.reicast.emulator.NativeGLActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data
|
||||
android:host="*"
|
||||
android:mimeType="*/*"
|
||||
android:pathPattern=".*\\.LST"
|
||||
android:scheme="file" />
|
||||
<data
|
||||
android:host="*"
|
||||
android:mimeType="*/*"
|
||||
android:pathPattern=".*\\.lst"
|
||||
android:scheme="file" />
|
||||
<data
|
||||
android:host="*"
|
||||
android:mimeType="*/*"
|
||||
android:pathPattern=".*\\.BIN"
|
||||
android:scheme="file" />
|
||||
<data
|
||||
android:host="*"
|
||||
android:mimeType="*/*"
|
||||
android:pathPattern=".*\\.bin"
|
||||
android:scheme="file" />
|
||||
<data
|
||||
android:host="*"
|
||||
android:mimeType="*/*"
|
||||
android:pathPattern=".*\\.DAT"
|
||||
android:scheme="file" />
|
||||
<data
|
||||
android:host="*"
|
||||
android:mimeType="*/*"
|
||||
android:pathPattern=".*\\.dat"
|
||||
android:scheme="file" />
|
||||
<data
|
||||
android:host="*"
|
||||
android:mimeType="*/*"
|
||||
android:pathPattern=".*\\.ZIP"
|
||||
android:scheme="file" />
|
||||
<data
|
||||
android:host="*"
|
||||
android:mimeType="*/*"
|
||||
android:pathPattern=".*\\.zip"
|
||||
android:scheme="file" />
|
||||
<data
|
||||
android:host="*"
|
||||
android:mimeType="*/*"
|
||||
android:pathPattern=".*\\.7Z"
|
||||
android:scheme="file" />
|
||||
<data
|
||||
android:host="*"
|
||||
android:mimeType="*/*"
|
||||
android:pathPattern=".*\\.7z"
|
||||
android:scheme="file" />
|
||||
</intent-filter>
|
||||
</activity-alias>
|
||||
</application>
|
||||
</manifest>
|
||||
|
|
Loading…
Reference in New Issue