Merge remote-tracking branch 'refs/remotes/origin/master'

This commit is contained in:
nretro
2019-05-25 02:10:11 +02:00
16 changed files with 1003 additions and 665 deletions

View File

@@ -86,6 +86,7 @@
<ClCompile Include="sxmlc.c" />
<ClCompile Include="tzx2wav.cpp" />
<ClCompile Include="user_io.cpp" />
<ClCompile Include="video.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="battery.h" />
@@ -135,6 +136,7 @@
<ClInclude Include="sxmlc.h" />
<ClInclude Include="tzx2wav.h" />
<ClInclude Include="user_io.h" />
<ClInclude Include="video.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">

View File

@@ -142,6 +142,9 @@
<ClCompile Include="scaler.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="video.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="battery.h">
@@ -285,5 +288,8 @@
<ClInclude Include="scaler.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="video.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@@ -25,6 +25,7 @@
#include "input.h"
#include "miniz_zip.h"
#include "scheduler.h"
#include "video.h"
#define MIN(a,b) (((a)<(b)) ? (a) : (b))
@@ -766,7 +767,7 @@ void FindStorage(void)
device = 0;
MiSTer_ini_parse();
device = saveddev;
parse_video_mode();
video_mode_load();
user_io_send_buttons(1);
printf("Waiting for USB...\n");

View File

@@ -8,6 +8,7 @@
#include <sys/poll.h>
#include <sys/sysinfo.h>
#include <dirent.h>
#include <errno.h>
#include "input.h"
#include "user_io.h"
@@ -16,7 +17,7 @@
#include "cfg.h"
#include "fpga_io.h"
#include "osd.h"
#include "errno.h"
#include "video.h"
#define NUMDEV 20
#define NUMPLAYERS 6
@@ -998,6 +999,8 @@ typedef struct
uint8_t has_kbdmap;
uint8_t kbdmap[256];
uint16_t guncal[4];
int accx, accy;
int quirk;
@@ -1242,6 +1245,24 @@ void finish_map_setting(int dismiss)
}
}
void input_lightgun_cal(uint16_t *cal)
{
FileSaveConfig("wiimote_cal.cfg", cal, 4 * sizeof(uint16_t));
for (int i = 0; i < NUMDEV; i++)
{
if (input[i].quirk == QUIRK_WIIMOTE) memcpy(input[i].guncal, cal, sizeof(input[i].guncal));
}
}
int input_has_lightgun()
{
for (int i = 0; i < NUMDEV; i++)
{
if (input[i].quirk == QUIRK_WIIMOTE) return 1;
}
return 0;
}
uint16_t get_map_vid()
{
return (mapping && mapping_dev >= 0) ? input[mapping_dev].vid : 0;
@@ -2330,6 +2351,11 @@ int input_test(int getchar)
else
{
input[n].quirk = QUIRK_WIIMOTE;
input[n].guncal[0] = 0;
input[n].guncal[1] = 767;
input[n].guncal[2] = 1;
input[n].guncal[3] = 1023;
FileLoadConfig("wiimote_cal.cfg", input[n].guncal, 4 * sizeof(uint16_t));
}
}
@@ -2465,7 +2491,6 @@ int input_test(int getchar)
input[dev].lightgun = 0;
if (absinfo.maximum == 1023 || absinfo.maximum == 767)
{
if (user_io_osd_is_visible()) continue;
if (ev.code == 16)
{
ev.value = absinfo.maximum - ev.value;
@@ -2597,6 +2622,33 @@ int input_test(int getchar)
}
}
if (ev.type == EV_ABS && input[i].quirk == QUIRK_WIIMOTE && input[dev].lightgun)
{
menu_lightgun_cb(ev.type, ev.code, ev.value);
// don't pass IR tracking to OSD
if (user_io_osd_is_visible()) continue;
if (!ev.code)
{
absinfo.minimum = input[i].guncal[2];
absinfo.maximum = input[i].guncal[3];
}
else
{
absinfo.minimum = input[i].guncal[0];
absinfo.maximum = input[i].guncal[1];
}
}
if (ev.type == EV_KEY && user_io_osd_is_visible())
{
if (input[i].quirk == QUIRK_WIIMOTE)
{
if (menu_lightgun_cb(ev.type, ev.code, ev.value)) continue;
}
}
if(!noabs) input_cb(&ev, &absinfo, i);
//sumulate digital directions from analog

View File

@@ -52,4 +52,7 @@ uint32_t get_amiga_code(uint16_t key);
uint32_t get_atari_code(uint16_t key);
uint32_t get_archie_code(uint16_t key);
int input_has_lightgun();
void input_lightgun_cal(uint16_t *cal);
#endif

134
menu.cpp
View File

@@ -36,6 +36,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <sys/statvfs.h>
#include <stdbool.h>
#include <stdio.h>
#include <sched.h>
#include <string.h>
#include "file_io.h"
#include "osd.h"
@@ -49,6 +50,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "battery.h"
#include "bootcore.h"
#include "cheats.h"
#include "video.h"
#include "support.h"
@@ -111,6 +113,9 @@ enum MENU
MENU_BTPAIR,
MENU_WMPAIR,
MENU_WMPAIR1,
MENU_LGCAL,
MENU_LGCAL1,
MENU_LGCAL2,
MENU_CHEATS1,
MENU_CHEATS2,
@@ -734,6 +739,12 @@ const char* get_rbf_name_bootcore(char *str)
static int joymap_first = 0;
static int wm_x = 0;
static int wm_y = 0;
static int wm_ok = 0;
static int wm_side = 0;
static uint16_t wm_pos[4] = {};
void HandleUI(void)
{
switch (user_io_core_type())
@@ -816,6 +827,15 @@ void HandleUI(void)
{
menustate = MENU_WMPAIR;
}
else if(input_has_lightgun())
{
menustate = MENU_LGCAL;
}
break;
//debug
case KEY_F9:
video_fb_enable(!video_fb_state());
break;
// Within the menu the esc key acts as the menu key. problem:
@@ -1152,7 +1172,7 @@ void HandleUI(void)
while((p[0] == 'H' || p[0] == 'D') && strlen(p)>2)
{
int flg = (hdmask & (1<<getIdx(p))) ? 1 : 0;
if (p[0] == 'H') h = flg; else d = flg;
if (p[0] == 'H') h |= flg; else d |= flg;
p += 2;
}
@@ -1358,7 +1378,7 @@ void HandleUI(void)
while ((p[0] == 'H' || p[0] == 'D') && strlen(p) > 2)
{
int flg = (hdmask & (1 << getIdx(p))) ? 1 : 0;
if (p[0] == 'H') h = flg; else d = flg;
if (p[0] == 'H') h |= flg; else d |= flg;
p += 2;
}
@@ -1503,22 +1523,22 @@ void HandleUI(void)
OsdWrite(n++, s, menusub == 3);
}
if (user_io_get_scaler_flt() >= 0)
if (video_get_scaler_flt() >= 0)
{
OsdWrite(n++);
menumask |= 0x60;
sprintf(s, " Scale Filter - %s", config_scaler_msg[user_io_get_scaler_flt() ? 1 : 0]);
sprintf(s, " Scale Filter - %s", config_scaler_msg[video_get_scaler_flt() ? 1 : 0]);
OsdWrite(n++, s, menusub == 5);
memset(s, 0, sizeof(s));
s[0] = ' ';
if (strlen(user_io_get_scaler_coeff())) strncpy(s+1, user_io_get_scaler_coeff(),25);
if (strlen(video_get_scaler_coeff())) strncpy(s+1, video_get_scaler_coeff(),25);
else strcpy(s, " < none >");
while(strlen(s) < 26) strcat(s, " ");
strcat(s, " \x16 ");
OsdWrite(n++, s, menusub == 6, !user_io_get_scaler_flt() || !S_ISDIR(getFileType(COEFF_DIR)));
OsdWrite(n++, s, menusub == 6, !video_get_scaler_flt() || !S_ISDIR(getFileType(COEFF_DIR)));
}
m = 0;
@@ -1603,14 +1623,14 @@ void HandleUI(void)
break;
case 5:
user_io_set_scaler_flt(user_io_get_scaler_flt() ? 0 : 1);
video_set_scaler_flt(video_get_scaler_flt() ? 0 : 1);
menustate = MENU_8BIT_SYSTEM1;
break;
case 6:
if (user_io_get_scaler_flt())
if (video_get_scaler_flt())
{
sprintf(SelectedPath, COEFF_DIR"/%s", user_io_get_scaler_coeff());
sprintf(SelectedPath, COEFF_DIR"/%s", video_get_scaler_coeff());
SelectFile(0, SCANO_COEFF, MENU_COEFF_FILE_SELECTED, MENU_8BIT_SYSTEM1);
}
break;
@@ -1809,8 +1829,8 @@ void HandleUI(void)
case MENU_COEFF_FILE_SELECTED:
{
char *p = strrchr(SelectedPath, '/');
if (!p) user_io_set_scaler_coeff(SelectedPath);
else user_io_set_scaler_coeff(p+1);
if (!p) video_set_scaler_coeff(SelectedPath);
else video_set_scaler_coeff(p+1);
menustate = MENU_8BIT_SYSTEM1;
}
break;
@@ -2796,7 +2816,7 @@ void HandleUI(void)
OsdWrite(m++, " Startup config:");
for (uint i = 0; i < 10; i++)
{
const char *info = minimig_GetCfgInfo(i);
const char *info = minimig_get_cfg_info(i);
static char name[128];
if (info)
@@ -2838,7 +2858,7 @@ void HandleUI(void)
if (menusub<10)
{
OsdDisable();
minimig_LoadCfg(menusub);
minimig_cfg_load(menusub);
menustate = MENU_NONE1;
}
else
@@ -3071,7 +3091,7 @@ void HandleUI(void)
if (m)
{
menustate = MENU_NONE1;
MinimigReset();
minimig_reset();
}
else if(m == 2)
{
@@ -3107,7 +3127,7 @@ void HandleUI(void)
OsdWrite(m++, " Startup config:");
for (uint i = 0; i < 10; i++)
{
const char *info = minimig_GetCfgInfo(i);
const char *info = minimig_get_cfg_info(i);
static char name[128];
if (info)
@@ -3166,7 +3186,7 @@ void HandleUI(void)
strncat(minimig_config.info, p, sizeof(minimig_config.info) - strlen(minimig_config.info) - 1);
minimig_config.info[sizeof(minimig_config.info) - 1] = 0;
if (menusub<10) minimig_SaveCfg(menusub);
if (menusub<10) minimig_cfg_save(menusub);
menustate = MENU_MAIN1;
menusub = 9;
}
@@ -3397,7 +3417,7 @@ void HandleUI(void)
break;
case MENU_ROMFILE_SELECTED:
SetKickstart(SelectedPath);
minimig_set_kickstart(SelectedPath);
menustate = MENU_SETTINGS_MEMORY1;
break;
@@ -3585,7 +3605,7 @@ void HandleUI(void)
OsdWrite(5, s, menusub == 3, 0);
OsdWrite(6, "", 0, 0);
OsdWrite(7, "", 0, 0);
OsdWrite(8, user_io_minimig_get_adjust() ? " Finish screen adjustment" : " Adjust screen position", menusub == 4, 0);
OsdWrite(8, minimig_get_adjust() ? " Finish screen adjustment" : " Adjust screen position", menusub == 4, 0);
OsdWrite(9, "", 0, 0);
OsdWrite(10, "", 0, 0);
OsdWrite(11, "", 0, 0);
@@ -3630,7 +3650,7 @@ void HandleUI(void)
else if (menusub == 4)
{
menustate = MENU_NONE1;
user_io_minimig_set_adjust(!user_io_minimig_get_adjust());
minimig_set_adjust(minimig_get_adjust() ? 0 : 1);
}
else if (menusub == 5)
{
@@ -3816,6 +3836,49 @@ void HandleUI(void)
if (CheckTimer(menu_timer)) menustate = MENU_NONE1;
break;
case MENU_LGCAL:
helptext = 0;
OsdSetTitle("Wiimote Calibration", 0);
for (int i = 0; i < OsdGetSize(); i++) OsdWrite(i);
OsdWrite(9, " Point Wiimote to the edge");
OsdWrite(10, " of screen and press");
OsdWrite(11, " the button B to confirm");
OsdWrite(OsdGetSize() - 1, " Cancel", menusub == 0, 0);
wm_ok = 0;
wm_side = 0;
memset(wm_pos, 0, sizeof(wm_pos));
menustate = MENU_LGCAL1;
menusub = 0;
break;
case MENU_LGCAL1:
if (wm_side < 4) wm_pos[wm_side] = (wm_side < 2) ? wm_y : wm_x;
sprintf(s, " %c%04d%c", (wm_side == 0) ? 17 : 32, (wm_side == 0) ? wm_y : wm_pos[0], (wm_side == 0) ? 16 : 32);
OsdWrite(0, s);
sprintf(s, "%c%04d%c %c%04d%c", (wm_side == 2) ? 17 : 32, (wm_side == 2) ? wm_x : wm_pos[2], (wm_side == 2) ? 16 : 32,
(wm_side == 3) ? 17 : 32, (wm_side == 3) ? wm_x : wm_pos[3], (wm_side == 3) ? 16 : 32);
OsdWrite(7, s);
sprintf(s, " %c%04d%c", (wm_side == 1) ? 17 : 32, (wm_side == 1) ? wm_y : wm_pos[1], (wm_side == 1) ? 16 : 32);
OsdWrite(13, s);
if (menu || select) menustate = MENU_NONE1;
if (wm_ok == 1)
{
wm_ok = 0;
wm_side++;
}
if (wm_ok == 2)
{
wm_ok = 0;
if (wm_side == 4)
{
input_lightgun_cal(wm_pos);
menustate = MENU_NONE1;
}
}
break;
case MENU_SCRIPTS_PRE:
OsdSetTitle("Warning!!!", 0);
helptext = 0;
@@ -3880,6 +3943,11 @@ void HandleUI(void)
for (int i = 0; i < script_lines; i++) strcpy(script_output[i], "");
script_line=0;
script_exited = false;
cpu_set_t set;
CPU_ZERO(&set);
CPU_SET(0, &set);
CPU_SET(1, &set);
sched_setaffinity(0, sizeof(set), &set);
script_pipe=popen((parentstate != MENU_BTPAIR) ? getFullPath(SelectedPath) : "/usr/sbin/btpair", "r");
script_file = fileno(script_pipe);
fcntl(script_file, F_SETFL, O_NONBLOCK);
@@ -3906,6 +3974,10 @@ void HandleUI(void)
}
else {
pclose(script_pipe);
cpu_set_t set;
CPU_ZERO(&set);
CPU_SET(1, &set);
sched_setaffinity(0, sizeof(set), &set);
script_exited=true;
OsdWrite(OsdGetSize() - 1, " OK", menusub == 0, 0);
};
@@ -3919,6 +3991,10 @@ void HandleUI(void)
strcat(script_command, (parentstate == MENU_BTPAIR) ? "btpair" : flist_SelectedItem()->d_name);
system(script_command);
pclose(script_pipe);
cpu_set_t set;
CPU_ZERO(&set);
CPU_SET(1, &set);
sched_setaffinity(0, sizeof(set), &set);
script_exited = true;
};
@@ -4378,3 +4454,23 @@ void menu_bt_pair()
{
menustate = MENU_BTPAIR;
}
int menu_lightgun_cb(uint16_t type, uint16_t code, int value)
{
if (type == EV_ABS)
{
if (code == 0 && value) wm_x = value;
if (code == 1 && value != 1023) wm_y = value;
}
if (type == EV_KEY)
{
if (code == 0x131 && menustate == MENU_LGCAL1)
{
if (value == 1) wm_ok = 1;
if (value == 0) wm_ok = 2;
return 1;
}
}
return 0;
}

2
menu.h
View File

@@ -30,4 +30,6 @@ extern int joy_bcount;
void open_joystick_setup();
void menu_bt_pair();
int menu_lightgun_cb(uint16_t type, uint16_t code, int value);
#endif

BIN
releases/MiSTer_20190515 Normal file

Binary file not shown.

View File

@@ -445,7 +445,7 @@ void BootInit()
}
minimig_config.kickstart[0] = 0;
minimig_LoadCfg(0);
minimig_cfg_load(0);
}
void BootPrintEx(const char * str)

View File

@@ -267,12 +267,12 @@ static char* GetConfigurationName(int num, int chk)
return name+strlen(CONFIG_DIR)+1;
}
int minimig_SaveCfg(int num)
int minimig_cfg_save(int num)
{
return FileSaveConfig(GetConfigurationName(num, 0), &minimig_config, sizeof(minimig_config));
}
const char* minimig_GetCfgInfo(int num)
const char* minimig_get_cfg_info(int num)
{
char *filename = GetConfigurationName(num, 1);
if (!filename) return NULL;
@@ -366,7 +366,7 @@ static void ApplyConfiguration(char reloadkickstart)
ConfigAutofire(minimig_config.autofire, 0xC);
}
int minimig_LoadCfg(int num)
int minimig_cfg_load(int num)
{
static const char config_id[] = "MNMGCFG0";
char updatekickstart = 0;
@@ -486,13 +486,13 @@ int minimig_LoadCfg(int num)
return(result);
}
void MinimigReset()
void minimig_reset()
{
ApplyConfiguration(0);
user_io_rtc_reset();
}
void SetKickstart(char *name)
void minimig_set_kickstart(char *name)
{
uint len = strlen(name);
if (len > (sizeof(minimig_config.kickstart) - 1)) len = sizeof(minimig_config.kickstart) - 1;
@@ -500,3 +500,127 @@ void SetKickstart(char *name)
minimig_config.kickstart[len] = 0;
force_reload_kickstart = 1;
}
static char minimig_adjust = 0;
typedef struct
{
uint32_t mode;
uint32_t hpos;
uint32_t vpos;
uint32_t reserved;
} vmode_adjust_t;
vmode_adjust_t vmodes_adj[64] = {};
static void adjust_vsize(char force)
{
static uint16_t nres = 0;
spi_uio_cmd_cont(UIO_GET_VMODE);
uint16_t res = spi_w(0);
if ((res & 0x8000) && (nres != res || force))
{
nres = res;
uint16_t scr_hsize = spi_w(0);
uint16_t scr_vsize = spi_w(0);
DisableIO();
printf("\033[1;37mVMODE: resolution: %u x %u, mode: %u\033[0m\n", scr_hsize, scr_vsize, res & 255);
static int loaded = 0;
if (~loaded)
{
FileLoadConfig("minimig_vadjust.dat", vmodes_adj, sizeof(vmodes_adj));
loaded = 1;
}
uint32_t mode = scr_hsize | (scr_vsize << 12) | ((res & 0xFF) << 24);
if (mode)
{
for (uint i = 0; i < sizeof(vmodes_adj) / sizeof(vmodes_adj[0]); i++)
{
if (vmodes_adj[i].mode == mode)
{
spi_uio_cmd_cont(UIO_SET_VPOS);
spi_w(vmodes_adj[i].hpos >> 16);
spi_w(vmodes_adj[i].hpos);
spi_w(vmodes_adj[i].vpos >> 16);
spi_w(vmodes_adj[i].vpos);
printf("\033[1;37mVMODE: set positions: [%u-%u, %u-%u]\033[0m\n", vmodes_adj[i].hpos >> 16, (uint16_t)vmodes_adj[i].hpos, vmodes_adj[i].vpos >> 16, (uint16_t)vmodes_adj[i].vpos);
DisableIO();
return;
}
}
printf("\033[1;37mVMODE: preset not found.\033[0m\n");
spi_uio_cmd_cont(UIO_SET_VPOS); spi_w(0); spi_w(0); spi_w(0); spi_w(0);
DisableIO();
}
}
else
{
DisableIO();
}
}
static void store_vsize()
{
Info("Stored");
minimig_adjust = 0;
spi_uio_cmd_cont(UIO_GET_VMODE);
uint16_t res = spi_w(0);
uint16_t scr_hsize = spi_w(0);
uint16_t scr_vsize = spi_w(0);
uint16_t scr_hbl_l = spi_w(0);
uint16_t scr_hbl_r = spi_w(0);
uint16_t scr_vbl_t = spi_w(0);
uint16_t scr_vbl_b = spi_w(0);
DisableIO();
printf("\033[1;37mVMODE: store position: [%u-%u, %u-%u]\033[0m\n", scr_hbl_l, scr_hbl_r, scr_vbl_t, scr_vbl_b);
uint32_t mode = scr_hsize | (scr_vsize << 12) | ((res & 0xFF) << 24);
if (mode)
{
int applied = 0;
int empty = -1;
for (int i = 0; (uint)i < sizeof(vmodes_adj) / sizeof(vmodes_adj[0]); i++)
{
if (vmodes_adj[i].mode == mode)
{
vmodes_adj[i].hpos = (scr_hbl_l << 16) | scr_hbl_r;
vmodes_adj[i].vpos = (scr_vbl_t << 16) | scr_vbl_b;
applied = 1;
}
if (empty < 0 && !vmodes_adj[i].mode) empty = i;
}
if (!applied && empty >= 0)
{
vmodes_adj[empty].mode = mode;
vmodes_adj[empty].hpos = (scr_hbl_l << 16) | scr_hbl_r;
vmodes_adj[empty].vpos = (scr_vbl_t << 16) | scr_vbl_b;
applied = 1;
}
if (applied)
{
FileSaveConfig("minimig_vadjust.dat", vmodes_adj, sizeof(vmodes_adj));
}
}
}
// 0 - disable
// 1 - enable
// 2 - cancel
void minimig_set_adjust(char n)
{
if (minimig_adjust && !n) store_vsize();
minimig_adjust = (n == 1) ? 1 : 0;
if (n == 2) adjust_vsize(1);
}
char minimig_get_adjust()
{
return minimig_adjust;
}

View File

@@ -44,11 +44,14 @@ typedef struct
extern mm_configTYPE minimig_config;
int minimig_LoadCfg(int num);
int minimig_SaveCfg(int num);
const char* minimig_GetCfgInfo(int num);
int minimig_cfg_load(int num);
int minimig_cfg_save(int num);
const char* minimig_get_cfg_info(int num);
void MinimigReset();
void SetKickstart(char *name);
void minimig_reset();
void minimig_set_kickstart(char *name);
void minimig_set_adjust(char n);
char minimig_get_adjust();
#endif

View File

@@ -177,25 +177,28 @@ uint8_t* snes_get_header(fileTYPE *f)
{ //DSP1
hdr[1] |= 0x80;
}
else if (buf[addr + Mapper] == 0x20 && buf[addr + RomType] == 0x05)
{ //DSP2
hdr[1] |= 0x90;
}
else if (buf[addr + Mapper] == 0x30 && buf[addr + RomType] == 0x05 && buf[addr + Company] == 0xb2)
{ //DSP3
hdr[1] |= 0xA0;
}
else if (buf[addr + Mapper] == 0x30 && buf[addr + RomType] == 0x03)
{ //DSP4
hdr[1] |= 0xB0;
}
else if (buf[addr + Mapper] == 0x20 && buf[addr + RomType] == 0x05)
{ //DSP2
hdr[1] |= 0x90;
}
else if (buf[addr + Mapper] == 0x30 && buf[addr + RomType] == 0x05 && buf[addr + Company] == 0xb2)
{ //DSP3
hdr[1] |= 0xA0;
}
else if (buf[addr + Mapper] == 0x30 && buf[addr + RomType] == 0x03)
{ //DSP4
hdr[1] |= 0xB0;
}
else if (buf[addr + Mapper] == 0x30 && buf[addr + RomType] == 0xf6)
{
//ST010
{ //ST010
hdr[1] |= 0x88;
if(buf[addr + RomSize] < 10) hdr[1] |= 0x20; // ST011
//ramsz = 2;
}
else if (buf[addr + Mapper] == 0x30 && buf[addr + RomType] == 0x25)
{ //OBC1
hdr[1] |= 0xC0;
}
//CX4 4
if (buf[addr + Mapper] == 0x20 && buf[addr + RomType] == 0xf3)
@@ -224,7 +227,7 @@ uint8_t* snes_get_header(fileTYPE *f)
hdr[1] |= 0x70;
}
//1..3,C..F - reserved for other mappers.
//1..3,D..F - reserved for other mappers.
hdr[2] = 0;

View File

@@ -30,6 +30,7 @@
#include "scaler.h"
#include "miniz.h"
#include "cheats.h"
#include "video.h"
#include "support.h"
@@ -68,8 +69,6 @@ static bool caps_status = 0;
static bool num_status = 0;
static bool scrl_status = 0;
static char minimig_adjust = 0;
static char last_filename[1024] = {};
void user_io_store_filename(char *filename)
{
@@ -533,7 +532,8 @@ void user_io_init(const char *path)
{
bootcore_init(path);
}
parse_video_mode();
video_mode_load();
if(strlen(cfg.font)) LoadFont(cfg.font);
FileLoadConfig("Volume.dat", &vol_att, 1);
vol_att &= 0x1F;
@@ -1574,8 +1574,6 @@ void user_io_rtc_reset()
static int coldreset_req = 0;
static int adjust_video_mode(uint32_t vtime);
static uint32_t show_video_info(int force);
static uint32_t res_timer = 0;
void user_io_poll()
@@ -2149,15 +2147,9 @@ void user_io_poll()
else if(CheckTimer(res_timer))
{
res_timer = GetTimer(500);
if (!minimig_adjust)
if (!minimig_get_adjust())
{
uint32_t vtime = show_video_info(0);
if (vtime && cfg.vsync_adjust && !is_menu_core())
{
adjust_video_mode(vtime);
usleep(100000);
show_video_info(1);
}
video_mode_adjust();
}
}
@@ -2196,19 +2188,6 @@ char user_io_user_button()
return((!user_io_menu_button() && (fpga_get_buttons() & BUTTON_USR)) ? 1 : 0);
}
static void adjust_vsize(char force);
static void store_vsize();
void user_io_minimig_set_adjust(char n)
{
if (minimig_adjust & !n) store_vsize();
minimig_adjust = n;
}
char user_io_minimig_get_adjust()
{
return minimig_adjust;
}
static void send_keycode(unsigned short key, int press)
{
if (core_type == CORE_TYPE_MINIMIG2)
@@ -2239,11 +2218,11 @@ static void send_keycode(unsigned short key, int press)
}
code &= 0xff;
if (minimig_adjust)
if (minimig_get_adjust())
{
if (code == 0x44)
{
store_vsize();
minimig_set_adjust(0);
res_timer = 0;
return;
}
@@ -2252,8 +2231,7 @@ static void send_keycode(unsigned short key, int press)
{
Info("Canceled");
res_timer = 0;
minimig_adjust = 0;
adjust_vsize(1);
minimig_set_adjust(2);
return;
}
code |= OSD;
@@ -2470,7 +2448,7 @@ void user_io_check_reset(unsigned short modifiers, char useKeys)
switch (core_type)
{
case CORE_TYPE_MINIMIG2:
MinimigReset();
minimig_reset();
break;
case CORE_TYPE_ARCHIE:
@@ -2714,578 +2692,3 @@ unsigned char user_io_ext_idx(char *name, char* ext)
printf("not found! use 0\n");
return 0;
}
struct vmode_t
{
uint32_t vpar[8];
double Fpix;
};
vmode_t vmodes[] =
{
{ { 1280, 110, 40, 220, 720, 5, 5, 20 }, 74.25 }, //0
{ { 1024, 24, 136, 160, 768, 3, 6, 29 }, 65 }, //1
{ { 720, 16, 62, 60, 480, 9, 6, 30 }, 27 }, //2
{ { 720, 12, 64, 68, 576, 5, 5, 39 }, 27 }, //3
{ { 1280, 48, 112, 248, 1024, 1, 3, 38 }, 108 }, //4
{ { 800, 40, 128, 88, 600, 1, 4, 23 }, 40 }, //5
{ { 640, 16, 96, 48, 480, 10, 2, 33 }, 25.175 }, //6
{ { 1280, 440, 40, 220, 720, 5, 5, 20 }, 74.25 }, //7
{ { 1920, 88, 44, 148, 1080, 4, 5, 36 }, 148.5 }, //8
{ { 1920, 528, 44, 148, 1080, 4, 5, 36 }, 148.5 }, //9
{ { 1366, 70, 143, 213, 768, 3, 3, 24 }, 85.5 }, //10
{ { 1024, 40, 104, 144, 600, 1, 3, 18 }, 48.96 }, //11
};
#define VMODES_NUM (sizeof(vmodes) / sizeof(vmodes[0]))
struct vmode_custom_t
{
uint32_t item[32];
double Fpix;
};
static vmode_custom_t v_cur = {}, v_def = {}, v_pal = {}, v_ntsc = {};
static int vmode_def = 0, vmode_pal = 0, vmode_ntsc = 0;
static uint32_t getPLLdiv(uint32_t div)
{
if (div & 1) return 0x20000 | (((div / 2) + 1) << 8) | (div / 2);
return ((div / 2) << 8) | (div / 2);
}
static int findPLLpar(double Fout, uint32_t *pc, uint32_t *pm, double *pko)
{
uint32_t c = 1;
while ((Fout*c) < 400) c++;
while (1)
{
double fvco = Fout*c;
uint32_t m = (uint32_t)(fvco / 50);
double ko = ((fvco / 50) - m);
fvco = ko + m;
fvco *= 50.f;
if (ko && (ko <= 0.05f || ko >= 0.95f))
{
printf("Fvco=%f, C=%d, M=%d, K=%f ", fvco, c, m, ko);
if (fvco > 1500.f)
{
printf("-> No exact parameters found\n");
return 0;
}
printf("-> K is outside allowed range\n");
c++;
}
else
{
*pc = c;
*pm = m;
*pko = ko;
return 1;
}
}
//will never reach here
return 0;
}
static void setPLL(double Fout, vmode_custom_t *v)
{
double Fpix;
double fvco, ko;
uint32_t m, c;
printf("Calculate PLL for %.4f MHz:\n", Fout);
if (!findPLLpar(Fout, &c, &m, &ko))
{
c = 1;
while ((Fout*c) < 400) c++;
fvco = Fout*c;
m = (uint32_t)(fvco / 50);
ko = ((fvco / 50) - m);
//Make sure K is in allowed range.
if (ko <= 0.05f)
{
ko = 0;
}
else if (ko >= 0.95f)
{
m++;
ko = 0;
}
}
uint32_t k = ko ? (uint32_t)(ko * 4294967296) : 1;
fvco = ko + m;
fvco *= 50.f;
Fpix = fvco / c;
printf("Fvco=%f, C=%d, M=%d, K=%f(%u) -> Fpix=%f\n", fvco, c, m, ko, k, Fpix);
v->item[9] = 4;
v->item[10] = getPLLdiv(m);
v->item[11] = 3;
v->item[12] = 0x10000;
v->item[13] = 5;
v->item[14] = getPLLdiv(c);
v->item[15] = 9;
v->item[16] = 2;
v->item[17] = 8;
v->item[18] = 7;
v->item[19] = 7;
v->item[20] = k;
v->Fpix = Fpix;
}
static char scaler_flt_cfg[1024] = { 0 };
static char new_scaler = 0;
static void setScaler()
{
fileTYPE f = {};
static char filename[1024];
if (!spi_uio_cmd_cont(UIO_SET_FLTNUM))
{
DisableIO();
return;
}
new_scaler = 1;
spi8(scaler_flt_cfg[0]);
DisableIO();
sprintf(filename, COEFF_DIR"/%s", scaler_flt_cfg + 1);
if (FileOpen(&f, filename))
{
printf("Read scaler coefficients\n");
char *buf = (char*)malloc(f.size+1);
if (buf)
{
memset(buf, 0, f.size + 1);
int size;
if ((size = FileReadAdv(&f, buf, f.size)))
{
spi_uio_cmd_cont(UIO_SET_FLTCOEF);
char *end = buf + size;
char *pos = buf;
int phase = 0;
while (pos < end)
{
char *st = pos;
while ((pos < end) && *pos && (*pos != 10)) pos++;
*pos = 0;
while (*st == ' ' || *st == '\t' || *st == 13) st++;
if (*st == '#' || *st == ';' || !*st) pos++;
else
{
int c0, c1, c2, c3;
int n = sscanf(st, "%d,%d,%d,%d", &c0, &c1, &c2, &c3);
if (n == 4)
{
printf(" phase %c-%02d: %4d,%4d,%4d,%4d\n", (phase >= 16) ? 'V' : 'H', phase % 16, c0, c1, c2, c3);
//printf("%03X: %03X %03X %03X %03X;\n",phase*4, c0 & 0x1FF, c1 & 0x1FF, c2 & 0x1FF, c3 & 0x1FF);
spi_w((c0 & 0x1FF) | (((phase * 4) + 0) << 9));
spi_w((c1 & 0x1FF) | (((phase * 4) + 1) << 9));
spi_w((c2 & 0x1FF) | (((phase * 4) + 2) << 9));
spi_w((c3 & 0x1FF) | (((phase * 4) + 3) << 9));
phase++;
if (phase >= 32) break;
}
}
}
DisableIO();
}
free(buf);
}
}
}
int user_io_get_scaler_flt()
{
return new_scaler ? scaler_flt_cfg[0] : -1;
}
char* user_io_get_scaler_coeff()
{
return scaler_flt_cfg + 1;
}
static char scaler_cfg[128] = { 0 };
void user_io_set_scaler_flt(int n)
{
scaler_flt_cfg[0] = (char)n;
FileSaveConfig(scaler_cfg, &scaler_flt_cfg, sizeof(scaler_flt_cfg));
spi_uio_cmd8(UIO_SET_FLTNUM, scaler_flt_cfg[0]);
spi_uio_cmd(UIO_SET_FLTCOEF);
}
void user_io_set_scaler_coeff(char *name)
{
strcpy(scaler_flt_cfg + 1, name);
FileSaveConfig(scaler_cfg, &scaler_flt_cfg, sizeof(scaler_flt_cfg));
setScaler();
user_io_send_buttons(1);
}
static void loadScalerCfg()
{
sprintf(scaler_cfg, "%s_scaler.cfg", user_io_get_core_name_ex());
if (!FileLoadConfig(scaler_cfg, &scaler_flt_cfg, sizeof(scaler_flt_cfg) - 1) || scaler_flt_cfg[0]>4)
{
memset(scaler_flt_cfg, 0, sizeof(scaler_flt_cfg));
}
}
static void setVideo(vmode_custom_t *v)
{
loadScalerCfg();
setScaler();
printf("Send HDMI parameters:\n");
spi_uio_cmd_cont(UIO_SET_VIDEO);
printf("video: ");
for (int i = 1; i <= 8; i++)
{
v_cur.item[i] = v->item[i];
spi_w(v->item[i]);
printf("%d, ", v->item[i]);
}
printf("\nPLL: ");
for (int i = 9; i < 21; i++)
{
v_cur.item[i] = v->item[i];
printf("0x%X, ", v->item[i]);
if (i & 1) spi_w(v->item[i] | ((i == 9 && (is_menu_core() ? cfg.menu_pal : (cfg.vsync_adjust == 2))) ? 0x8000 : 0));
else
{
spi_w(v->item[i]);
spi_w(v->item[i] >> 16);
}
}
v_cur.Fpix = v->Fpix;
printf("Fpix=%f\n", v->Fpix);
DisableIO();
}
static int parse_custom_video_mode(char* vcfg, vmode_custom_t *v)
{
int khz = 0;
int cnt = 0;
char *orig = vcfg;
while (*vcfg)
{
char *next;
if (cnt == 9 && v->item[0] == 1)
{
double Fpix = khz ? strtoul(vcfg, &next, 0)/1000.f : strtod(vcfg, &next);
if (vcfg == next || (Fpix < 2.f || Fpix > 300.f))
{
printf("Error parsing video_mode parameter: ""%s""\n", orig);
return -1;
}
setPLL(Fpix, v);
break;
}
uint32_t val = strtoul(vcfg, &next, 0);
if (vcfg == next || (*next != ',' && *next))
{
printf("Error parsing video_mode parameter: ""%s""\n", orig);
return -1;
}
if (!cnt && val >= 100)
{
v->item[cnt++] = 1;
khz = 1;
}
if (cnt < 32) v->item[cnt] = val;
if (*next == ',') next++;
vcfg = next;
cnt++;
}
if (cnt == 1)
{
printf("Set predefined video_mode to %d\n", v->item[0]);
return v->item[0];
}
if ((v->item[0] == 0 && cnt < 21) || (v->item[0] == 1 && cnt < 9))
{
printf("Incorrect amount of items in video_mode parameter: %d\n", cnt);
return -1;
}
if (v->item[0] > 1)
{
printf("Incorrect video_mode parameter\n");
return -1;
}
return -2;
}
static int store_custom_video_mode(char* vcfg, vmode_custom_t *v)
{
int ret = parse_custom_video_mode(vcfg, v);
if (ret == -2) return 1;
uint mode = (ret < 0) ? 0 : ret;
if (mode >= VMODES_NUM) mode = 0;
for (int i = 0; i < 8; i++) v->item[i + 1] = vmodes[mode].vpar[i];
setPLL(vmodes[mode].Fpix, v);
return ret >= 0;
}
void parse_video_mode()
{
vmode_def = store_custom_video_mode(cfg.video_conf, &v_def);
vmode_pal = store_custom_video_mode(cfg.video_conf_pal, &v_pal);
vmode_ntsc = store_custom_video_mode(cfg.video_conf_ntsc, &v_ntsc);
setVideo(&v_def);
}
static int adjust_video_mode(uint32_t vtime)
{
printf("\033[1;33madjust_video_mode(%u): vsync_adjust=%d", vtime, cfg.vsync_adjust);
vmode_custom_t *v = &v_def;
if (vmode_pal && vmode_ntsc)
{
if (vtime > 1800000)
{
printf(", using PAL mode");
v = &v_pal;
}
else
{
printf(", using NTSC mode");
v = &v_ntsc;
}
}
printf(".\033[0m\n");
double Fpix = 100 * (v->item[1] + v->item[2] + v->item[3] + v->item[4]) * (v->item[5] + v->item[6] + v->item[7] + v->item[8]);
Fpix /= vtime;
if (Fpix < 2.f || Fpix > 300.f)
{
printf("Estimated Fpix(%.4f MHz) is outside supported range. Canceling auto-adjust.\n", Fpix);
return 0;
}
setPLL(Fpix, v);
setVideo(v);
user_io_send_buttons(1);
return 1;
}
typedef struct
{
uint32_t mode;
uint32_t hpos;
uint32_t vpos;
uint32_t reserved;
} vmode_adjust_t;
vmode_adjust_t vmodes_adj[64] = {};
static void adjust_vsize(char force)
{
static uint16_t nres = 0;
spi_uio_cmd_cont(UIO_GET_VMODE);
uint16_t res = spi_w(0);
if ((res & 0x8000) && (nres != res || force))
{
nres = res;
uint16_t scr_hsize = spi_w(0);
uint16_t scr_vsize = spi_w(0);
DisableIO();
printf("\033[1;37mVMODE: resolution: %u x %u, mode: %u\033[0m\n", scr_hsize, scr_vsize, res & 255);
static int loaded = 0;
if (~loaded)
{
FileLoadConfig("minimig_vadjust.dat", vmodes_adj, sizeof(vmodes_adj));
loaded = 1;
}
uint32_t mode = scr_hsize | (scr_vsize << 12) | ((res & 0xFF) << 24);
if (mode)
{
for (uint i = 0; i < sizeof(vmodes_adj) / sizeof(vmodes_adj[0]); i++)
{
if (vmodes_adj[i].mode == mode)
{
spi_uio_cmd_cont(UIO_SET_VPOS);
spi_w(vmodes_adj[i].hpos >> 16);
spi_w(vmodes_adj[i].hpos);
spi_w(vmodes_adj[i].vpos >> 16);
spi_w(vmodes_adj[i].vpos);
printf("\033[1;37mVMODE: set positions: [%u-%u, %u-%u]\033[0m\n", vmodes_adj[i].hpos >> 16, (uint16_t)vmodes_adj[i].hpos, vmodes_adj[i].vpos >> 16, (uint16_t)vmodes_adj[i].vpos);
DisableIO();
return;
}
}
printf("\033[1;37mVMODE: preset not found.\033[0m\n");
spi_uio_cmd_cont(UIO_SET_VPOS); spi_w(0); spi_w(0); spi_w(0); spi_w(0);
DisableIO();
}
}
else
{
DisableIO();
}
}
static void store_vsize()
{
Info("Stored");
minimig_adjust = 0;
spi_uio_cmd_cont(UIO_GET_VMODE);
uint16_t res = spi_w(0);
uint16_t scr_hsize = spi_w(0);
uint16_t scr_vsize = spi_w(0);
uint16_t scr_hbl_l = spi_w(0);
uint16_t scr_hbl_r = spi_w(0);
uint16_t scr_vbl_t = spi_w(0);
uint16_t scr_vbl_b = spi_w(0);
DisableIO();
printf("\033[1;37mVMODE: store position: [%u-%u, %u-%u]\033[0m\n", scr_hbl_l, scr_hbl_r, scr_vbl_t, scr_vbl_b);
uint32_t mode = scr_hsize | (scr_vsize << 12) | ((res & 0xFF) << 24);
if (mode)
{
int applied = 0;
int empty = -1;
for (int i = 0; (uint)i < sizeof(vmodes_adj) / sizeof(vmodes_adj[0]); i++)
{
if (vmodes_adj[i].mode == mode)
{
vmodes_adj[i].hpos = (scr_hbl_l << 16) | scr_hbl_r;
vmodes_adj[i].vpos = (scr_vbl_t << 16) | scr_vbl_b;
applied = 1;
}
if (empty < 0 && !vmodes_adj[i].mode) empty = i;
}
if (!applied && empty >= 0)
{
vmodes_adj[empty].mode = mode;
vmodes_adj[empty].hpos = (scr_hbl_l << 16) | scr_hbl_r;
vmodes_adj[empty].vpos = (scr_vbl_t << 16) | scr_vbl_b;
applied = 1;
}
if (applied)
{
FileSaveConfig("minimig_vadjust.dat", vmodes_adj, sizeof(vmodes_adj));
}
}
}
static int api1_5 = 0;
static uint32_t show_video_info(int force)
{
uint32_t ret = 0;
static uint8_t nres = 0;
spi_uio_cmd_cont(UIO_GET_VRES);
uint8_t res = spi_in();
if ((nres != res) || force)
{
nres = res;
uint32_t width = spi_w(0) | (spi_w(0) << 16);
uint32_t height = spi_w(0) | (spi_w(0) << 16);
uint32_t htime = spi_w(0) | (spi_w(0) << 16);
uint32_t vtime = spi_w(0) | (spi_w(0) << 16);
uint32_t ptime = spi_w(0) | (spi_w(0) << 16);
uint32_t vtimeh = spi_w(0) | (spi_w(0) << 16);
DisableIO();
float vrate = 100000000;
if (vtime) vrate /= vtime; else vrate = 0;
float hrate = 100000;
if (htime) hrate /= htime; else hrate = 0;
float prate = width * 100;
prate /= ptime;
printf("\033[1;33mINFO: Video resolution: %u x %u, fHorz = %.1fKHz, fVert = %.1fHz, fPix = %.2fMHz\033[0m\n", width, height, hrate, vrate, prate);
printf("\033[1;33mINFO: Frame time (100MHz counter): VGA = %d, HDMI = %d\033[0m\n", vtime, vtimeh);
if (vtimeh) api1_5 = 1;
if (hasAPI1_5() && cfg.video_info)
{
static char str[128];
float vrateh = 100000000;
if (vtimeh) vrateh /= vtimeh; else vrateh = 0;
sprintf(str, "%4dx%-4d %6.2fKHz %4.1fHz\n" \
"\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\n" \
"%4dx%-4d %6.2fMHz %4.1fHz",
width, height, hrate, vrate, v_cur.item[1], v_cur.item[5], v_cur.Fpix, vrateh);
Info(str, cfg.video_info * 1000);
}
uint32_t scrh = v_cur.item[5];
if (height && scrh)
{
if (cfg.vscale_border)
{
uint32_t border = cfg.vscale_border * 2;
if ((border + 100) > scrh) border = scrh - 100;
scrh -= border;
}
if (cfg.vscale_mode)
{
uint32_t div = 1 << (cfg.vscale_mode - 1);
uint32_t mag = (scrh*div) / height;
scrh = (height * mag) / div;
}
if(cfg.vscale_border || cfg.vscale_mode)
{
printf("*** Set vertical scaling to : %d\n", scrh);
spi_uio_cmd16(UIO_SETHEIGHT, scrh);
}
else
{
spi_uio_cmd16(UIO_SETHEIGHT, 0);
}
}
if (vtime && vtimeh) ret = vtime;
}
else
{
DisableIO();
}
adjust_vsize(0);
return ret;
}
int hasAPI1_5()
{
return api1_5;
}

View File

@@ -67,6 +67,8 @@
#define UIO_GET_VMODE 0x2C // Get video mode parameters
#define UIO_SET_VPOS 0x2D // Set video positions
#define UIO_GET_OSDMASK 0x2E // Get mask
#define UIO_SET_FBUF 0x2F // Set frame buffer for HPS output
#define UIO_WAIT_VSYNC 0x30 // Wait for VSync
// codes as used by 8bit for file loading from OSD
#define UIO_FILE_TX 0x53
@@ -222,7 +224,6 @@ void user_io_set_joyswap(int swap);
int user_io_get_joyswap();
char user_io_osd_is_visible();
void user_io_send_buttons(char);
void parse_video_mode();
void user_io_set_index(unsigned char index);
unsigned char user_io_ext_idx(char *, char*);
@@ -231,19 +232,9 @@ void user_io_check_reset(unsigned short modifiers, char useKeys);
void user_io_rtc_reset();
int hasAPI1_5();
const char* get_rbf_dir();
const char* get_rbf_name();
int user_io_get_scaler_flt();
char* user_io_get_scaler_coeff();
void user_io_set_scaler_flt(int n);
void user_io_set_scaler_coeff(char *name);
void user_io_minimig_set_adjust(char n);
char user_io_minimig_get_adjust();
#define HomeDir (is_minimig() ? "Amiga" : is_archie() ? "Archie" : is_menu_core() ? "Scripts" : user_io_get_core_name())
int GetUARTMode();

635
video.cpp Normal file
View File

@@ -0,0 +1,635 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include <sys/mman.h>
#include "hardware.h"
#include "user_io.h"
#include "spi.h"
#include "cfg.h"
#include "file_io.h"
#include "menu.h"
#include "video.h"
#include "support.h"
#define FB_SIZE (1024*1024*8) // 8MB x 3
#define FB_ADDR (0x20000000 + (32*1024*1024)) // 512mb + 32mb(Core's fb)
#define FB_FMT 2 // 0 - 16bit, 1 - 24bit(not supported), 2 - 32bit
#define FB_HDRSZ (256/(FB_FMT+2))
#if(FB_FMT == 2)
static volatile uint32_t *fb_base = 0;
#else
static volatile uint16_t *fb_base = 0;
#endif
static int fb_enabled = 0;
static int fb_width = 0;
static int fb_height = 0;
static int fb_stride = 0;
struct vmode_t
{
uint32_t vpar[8];
double Fpix;
};
vmode_t vmodes[] =
{
{ { 1280, 110, 40, 220, 720, 5, 5, 20 }, 74.25 }, //0
{ { 1024, 24, 136, 160, 768, 3, 6, 29 }, 65 }, //1
{ { 720, 16, 62, 60, 480, 9, 6, 30 }, 27 }, //2
{ { 720, 12, 64, 68, 576, 5, 5, 39 }, 27 }, //3
{ { 1280, 48, 112, 248, 1024, 1, 3, 38 }, 108 }, //4
{ { 800, 40, 128, 88, 600, 1, 4, 23 }, 40 }, //5
{ { 640, 16, 96, 48, 480, 10, 2, 33 }, 25.175 }, //6
{ { 1280, 440, 40, 220, 720, 5, 5, 20 }, 74.25 }, //7
{ { 1920, 88, 44, 148, 1080, 4, 5, 36 }, 148.5 }, //8
{ { 1920, 528, 44, 148, 1080, 4, 5, 36 }, 148.5 }, //9
{ { 1366, 70, 143, 213, 768, 3, 3, 24 }, 85.5 }, //10
{ { 1024, 40, 104, 144, 600, 1, 3, 18 }, 48.96 }, //11
};
#define VMODES_NUM (sizeof(vmodes) / sizeof(vmodes[0]))
struct vmode_custom_t
{
uint32_t item[32];
double Fpix;
};
static vmode_custom_t v_cur = {}, v_def = {}, v_pal = {}, v_ntsc = {};
static int vmode_def = 0, vmode_pal = 0, vmode_ntsc = 0;
static uint32_t getPLLdiv(uint32_t div)
{
if (div & 1) return 0x20000 | (((div / 2) + 1) << 8) | (div / 2);
return ((div / 2) << 8) | (div / 2);
}
static int findPLLpar(double Fout, uint32_t *pc, uint32_t *pm, double *pko)
{
uint32_t c = 1;
while ((Fout*c) < 400) c++;
while (1)
{
double fvco = Fout*c;
uint32_t m = (uint32_t)(fvco / 50);
double ko = ((fvco / 50) - m);
fvco = ko + m;
fvco *= 50.f;
if (ko && (ko <= 0.05f || ko >= 0.95f))
{
printf("Fvco=%f, C=%d, M=%d, K=%f ", fvco, c, m, ko);
if (fvco > 1500.f)
{
printf("-> No exact parameters found\n");
return 0;
}
printf("-> K is outside allowed range\n");
c++;
}
else
{
*pc = c;
*pm = m;
*pko = ko;
return 1;
}
}
//will never reach here
return 0;
}
static void setPLL(double Fout, vmode_custom_t *v)
{
double Fpix;
double fvco, ko;
uint32_t m, c;
printf("Calculate PLL for %.4f MHz:\n", Fout);
if (!findPLLpar(Fout, &c, &m, &ko))
{
c = 1;
while ((Fout*c) < 400) c++;
fvco = Fout*c;
m = (uint32_t)(fvco / 50);
ko = ((fvco / 50) - m);
//Make sure K is in allowed range.
if (ko <= 0.05f)
{
ko = 0;
}
else if (ko >= 0.95f)
{
m++;
ko = 0;
}
}
uint32_t k = ko ? (uint32_t)(ko * 4294967296) : 1;
fvco = ko + m;
fvco *= 50.f;
Fpix = fvco / c;
printf("Fvco=%f, C=%d, M=%d, K=%f(%u) -> Fpix=%f\n", fvco, c, m, ko, k, Fpix);
v->item[9] = 4;
v->item[10] = getPLLdiv(m);
v->item[11] = 3;
v->item[12] = 0x10000;
v->item[13] = 5;
v->item[14] = getPLLdiv(c);
v->item[15] = 9;
v->item[16] = 2;
v->item[17] = 8;
v->item[18] = 7;
v->item[19] = 7;
v->item[20] = k;
v->Fpix = Fpix;
}
static char scaler_flt_cfg[1024] = { 0 };
static char new_scaler = 0;
static void setScaler()
{
fileTYPE f = {};
static char filename[1024];
if (!spi_uio_cmd_cont(UIO_SET_FLTNUM))
{
DisableIO();
return;
}
new_scaler = 1;
spi8(scaler_flt_cfg[0]);
DisableIO();
sprintf(filename, COEFF_DIR"/%s", scaler_flt_cfg + 1);
if (FileOpen(&f, filename))
{
//printf("Read scaler coefficients\n");
char *buf = (char*)malloc(f.size+1);
if (buf)
{
memset(buf, 0, f.size + 1);
int size;
if ((size = FileReadAdv(&f, buf, f.size)))
{
spi_uio_cmd_cont(UIO_SET_FLTCOEF);
char *end = buf + size;
char *pos = buf;
int phase = 0;
while (pos < end)
{
char *st = pos;
while ((pos < end) && *pos && (*pos != 10)) pos++;
*pos = 0;
while (*st == ' ' || *st == '\t' || *st == 13) st++;
if (*st == '#' || *st == ';' || !*st) pos++;
else
{
int c0, c1, c2, c3;
int n = sscanf(st, "%d,%d,%d,%d", &c0, &c1, &c2, &c3);
if (n == 4)
{
//printf(" phase %c-%02d: %4d,%4d,%4d,%4d\n", (phase >= 16) ? 'V' : 'H', phase % 16, c0, c1, c2, c3);
//printf("%03X: %03X %03X %03X %03X;\n",phase*4, c0 & 0x1FF, c1 & 0x1FF, c2 & 0x1FF, c3 & 0x1FF);
spi_w((c0 & 0x1FF) | (((phase * 4) + 0) << 9));
spi_w((c1 & 0x1FF) | (((phase * 4) + 1) << 9));
spi_w((c2 & 0x1FF) | (((phase * 4) + 2) << 9));
spi_w((c3 & 0x1FF) | (((phase * 4) + 3) << 9));
phase++;
if (phase >= 32) break;
}
}
}
DisableIO();
}
free(buf);
}
}
}
int video_get_scaler_flt()
{
return new_scaler ? scaler_flt_cfg[0] : -1;
}
char* video_get_scaler_coeff()
{
return scaler_flt_cfg + 1;
}
static char scaler_cfg[128] = { 0 };
void video_set_scaler_flt(int n)
{
scaler_flt_cfg[0] = (char)n;
FileSaveConfig(scaler_cfg, &scaler_flt_cfg, sizeof(scaler_flt_cfg));
spi_uio_cmd8(UIO_SET_FLTNUM, scaler_flt_cfg[0]);
spi_uio_cmd(UIO_SET_FLTCOEF);
}
void video_set_scaler_coeff(char *name)
{
strcpy(scaler_flt_cfg + 1, name);
FileSaveConfig(scaler_cfg, &scaler_flt_cfg, sizeof(scaler_flt_cfg));
setScaler();
user_io_send_buttons(1);
}
static void loadScalerCfg()
{
sprintf(scaler_cfg, "%s_scaler.cfg", user_io_get_core_name_ex());
if (!FileLoadConfig(scaler_cfg, &scaler_flt_cfg, sizeof(scaler_flt_cfg) - 1) || scaler_flt_cfg[0]>4)
{
memset(scaler_flt_cfg, 0, sizeof(scaler_flt_cfg));
}
}
static void set_video(vmode_custom_t *v, double Fpix)
{
loadScalerCfg();
setScaler();
printf("Send HDMI parameters:\n");
spi_uio_cmd_cont(UIO_SET_VIDEO);
printf("video: ");
for (int i = 1; i <= 8; i++)
{
v_cur.item[i] = v->item[i];
spi_w(v_cur.item[i]);
printf("%d, ", v_cur.item[i]);
}
for (int i = 9; i < 21; i++) v_cur.item[i] = v->item[i];
v_cur.Fpix = v->Fpix;
if(Fpix) setPLL(Fpix, &v_cur);
printf("\nPLL: ");
for (int i = 9; i < 21; i++)
{
printf("0x%X, ", v_cur.item[i]);
if (i & 1) spi_w(v_cur.item[i] | ((i == 9 && (is_menu_core() ? cfg.menu_pal : (Fpix && cfg.vsync_adjust == 2))) ? 0x8000 : 0));
else
{
spi_w(v_cur.item[i]);
spi_w(v_cur.item[i] >> 16);
}
}
printf("Fpix=%f\n", v_cur.Fpix);
DisableIO();
}
static int parse_custom_video_mode(char* vcfg, vmode_custom_t *v)
{
int khz = 0;
int cnt = 0;
char *orig = vcfg;
while (*vcfg)
{
char *next;
if (cnt == 9 && v->item[0] == 1)
{
double Fpix = khz ? strtoul(vcfg, &next, 0)/1000.f : strtod(vcfg, &next);
if (vcfg == next || (Fpix < 2.f || Fpix > 300.f))
{
printf("Error parsing video_mode parameter: ""%s""\n", orig);
return -1;
}
setPLL(Fpix, v);
break;
}
uint32_t val = strtoul(vcfg, &next, 0);
if (vcfg == next || (*next != ',' && *next))
{
printf("Error parsing video_mode parameter: ""%s""\n", orig);
return -1;
}
if (!cnt && val >= 100)
{
v->item[cnt++] = 1;
khz = 1;
}
if (cnt < 32) v->item[cnt] = val;
if (*next == ',') next++;
vcfg = next;
cnt++;
}
if (cnt == 1)
{
printf("Set predefined video_mode to %d\n", v->item[0]);
return v->item[0];
}
if ((v->item[0] == 0 && cnt < 21) || (v->item[0] == 1 && cnt < 9))
{
printf("Incorrect amount of items in video_mode parameter: %d\n", cnt);
return -1;
}
if (v->item[0] > 1)
{
printf("Incorrect video_mode parameter\n");
return -1;
}
return -2;
}
static int store_custom_video_mode(char* vcfg, vmode_custom_t *v)
{
int ret = parse_custom_video_mode(vcfg, v);
if (ret == -2) return 1;
uint mode = (ret < 0) ? 0 : ret;
if (mode >= VMODES_NUM) mode = 0;
for (int i = 0; i < 8; i++) v->item[i + 1] = vmodes[mode].vpar[i];
setPLL(vmodes[mode].Fpix, v);
return ret >= 0;
}
static void fb_init()
{
if (!fb_base)
{
static int fd;
fb_base = 0;
if ((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1) return;
#if(FB_FMT == 2)
fb_base = (volatile uint32_t*)mmap(0, FB_SIZE * 3, PROT_READ | PROT_WRITE, MAP_SHARED, fd, FB_ADDR);
#else
fb_base = (volatile uint16_t*)mmap(0, FB_SIZE * 3, PROT_READ | PROT_WRITE, MAP_SHARED, fd, FB_ADDR);
#endif
if (fb_base == (void *)-1)
{
printf("Unable to mmap FB!\n");
fb_base = 0;
close(fd);
}
}
}
void video_mode_load()
{
fb_init();
vmode_def = store_custom_video_mode(cfg.video_conf, &v_def);
vmode_pal = store_custom_video_mode(cfg.video_conf_pal, &v_pal);
vmode_ntsc = store_custom_video_mode(cfg.video_conf_ntsc, &v_ntsc);
set_video(&v_def, 0);
}
static int api1_5 = 0;
int hasAPI1_5()
{
return api1_5;
}
static uint32_t show_video_info(int force)
{
uint32_t ret = 0;
static uint16_t nres = 0;
spi_uio_cmd_cont(UIO_GET_VRES);
uint16_t res = spi_w(0);
if ((nres != res) || force)
{
nres = res;
uint32_t width = spi_w(0) | (spi_w(0) << 16);
uint32_t height = spi_w(0) | (spi_w(0) << 16);
uint32_t htime = spi_w(0) | (spi_w(0) << 16);
uint32_t vtime = spi_w(0) | (spi_w(0) << 16);
uint32_t ptime = spi_w(0) | (spi_w(0) << 16);
uint32_t vtimeh = spi_w(0) | (spi_w(0) << 16);
DisableIO();
float vrate = 100000000;
if (vtime) vrate /= vtime; else vrate = 0;
float hrate = 100000;
if (htime) hrate /= htime; else hrate = 0;
float prate = width * 100;
prate /= ptime;
printf("\033[1;33mINFO: Video resolution: %u x %u%s, fHorz = %.1fKHz, fVert = %.1fHz, fPix = %.2fMHz\033[0m\n", width, height, (res & 0x100) ? "i" : "", hrate, vrate, prate);
printf("\033[1;33mINFO: Frame time (100MHz counter): VGA = %d, HDMI = %d\033[0m\n", vtime, vtimeh);
if (vtimeh) api1_5 = 1;
if (hasAPI1_5() && cfg.video_info)
{
static char str[128], res1[16], res2[16];
float vrateh = 100000000;
if (vtimeh) vrateh /= vtimeh; else vrateh = 0;
sprintf(res1, "%dx%d%s", width, height, (res & 0x100) ? "i" : "");
sprintf(res2, "%dx%d", v_cur.item[1], v_cur.item[5]);
sprintf(str, "%9s %6.2fKHz %4.1fHz\n" \
"\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\n" \
"%9s %6.2fMHz %4.1fHz",
res1, hrate, vrate, res2, v_cur.Fpix, vrateh);
Info(str, cfg.video_info * 1000);
}
uint32_t scrh = v_cur.item[5];
if (height && scrh)
{
if (cfg.vscale_border)
{
uint32_t border = cfg.vscale_border * 2;
if ((border + 100) > scrh) border = scrh - 100;
scrh -= border;
}
if (cfg.vscale_mode)
{
uint32_t div = 1 << (cfg.vscale_mode - 1);
uint32_t mag = (scrh*div) / height;
scrh = (height * mag) / div;
}
if(cfg.vscale_border || cfg.vscale_mode)
{
printf("Set vertical scaling to : %d\n", scrh);
spi_uio_cmd16(UIO_SETHEIGHT, scrh);
}
else
{
spi_uio_cmd16(UIO_SETHEIGHT, 0);
}
}
if (vtime && vtimeh) ret = vtime;
}
else
{
DisableIO();
}
minimig_set_adjust(2);
return ret;
}
void video_mode_adjust()
{
uint32_t vtime = show_video_info(0);
if (vtime && cfg.vsync_adjust && !is_menu_core())
{
printf("\033[1;33madjust_video_mode(%u): vsync_adjust=%d", vtime, cfg.vsync_adjust);
int adjust = 1;
vmode_custom_t *v = &v_def;
if (vmode_pal || vmode_ntsc)
{
if (vtime > 1800000)
{
if (vmode_pal)
{
printf(", using PAL mode");
v = &v_pal;
}
else
{
printf(", PAL mode cannot be used. Using predefined NTSC mode");
v = &v_ntsc;
adjust = 0;
}
}
else
{
if (vmode_ntsc)
{
printf(", using NTSC mode");
v = &v_ntsc;
}
else
{
printf(", NTSC mode cannot be used. Using predefined PAL mode");
v = &v_pal;
adjust = 0;
}
}
}
printf(".\033[0m\n");
double Fpix = 0;
if (adjust)
{
Fpix = 100 * (v->item[1] + v->item[2] + v->item[3] + v->item[4]) * (v->item[5] + v->item[6] + v->item[7] + v->item[8]);
Fpix /= vtime;
if (Fpix < 2.f || Fpix > 300.f)
{
printf("Estimated Fpix(%.4f MHz) is outside supported range. Canceling auto-adjust.\n", Fpix);
Fpix = 0;
}
}
set_video(v, Fpix);
user_io_send_buttons(1);
usleep(100000);
show_video_info(1);
}
}
static void fill_fb()
{
int pos = 0;
for (int y = 0; y < fb_height; y++)
{
pos = y * fb_stride + FB_HDRSZ;
int base_color = (y / 32) & 7;
for (int x = 0; x < fb_width; x++)
{
#if(FB_FMT == 2)
int gray = (256 * x) / fb_width;
uint32_t color = 0;
if (base_color & 1) color |= gray;
if (base_color & 2) color |= gray << 8;
if (base_color & 4) color |= gray << 16;
#else
int gray = (32 * x) / fb_width;
uint16_t color = 0;
if (base_color & 1) color |= gray;
if (base_color & 2) color |= gray << 5;
if (base_color & 4) color |= gray << 10;
#endif
fb_base[pos++] = color;
}
}
}
void video_fb_enable(int enable)
{
if (fb_base)
{
int res = spi_uio_cmd_cont(UIO_SET_FBUF);
if (res)
{
if (enable)
{
fb_width = (v_cur.item[1] >= 1440) ? v_cur.item[1] / 2 : v_cur.item[1];
fb_height = (v_cur.item[5] >= 1080) ? v_cur.item[5] / 2 : v_cur.item[5];
printf("Switch to HPS frame buffer\n");
spi_w(0x8000 | (FB_FMT & 3) << 12); // enable flag, format, fixed height
spi_w((uint16_t)FB_ADDR); // base address low word
spi_w(FB_ADDR >> 16); // base address high word
spi_w(fb_width-1); // frame width
spi_w(fb_height-1); // frame height
spi_w(0); // Aspect ratio X/Y (0 - full screen)
#if(FB_FMT == 2)
fb_stride = (((fb_width * 4 + 255) / 256) * 256)/4;
#else
fb_stride = (((fb_width * 2 + 255) / 256) * 256)/2;
#endif
printf("HPS frame buffer: %dx%d, stride = %d items\n", fb_width, fb_height, fb_stride);
fill_fb();
}
else
{
printf("Switch to core frame buffer\n");
spi_w(0); // enable flag
}
fb_enabled = enable;
}
else
{
printf("Core doesn't support HPS frame buffer\n");
}
DisableIO();
}
}
int video_fb_state()
{
return fb_enabled;
}

17
video.h Normal file
View File

@@ -0,0 +1,17 @@
#ifndef VIDEO_H
#define VIDEO_H
int video_get_scaler_flt();
void video_set_scaler_flt(int n);
char* video_get_scaler_coeff();
void video_set_scaler_coeff(char *name);
void video_mode_load();
void video_mode_adjust();
int hasAPI1_5();
void video_fb_enable(int enable);
int video_fb_state();
#endif // VIDEO_H