Add support for parsing edid-decode text dumps
This commit is contained in:
@@ -48,6 +48,7 @@ add_executable(86Box
|
||||
nvr_at.c
|
||||
nvr_ps2.c
|
||||
machine_status.c
|
||||
edid_parse.cpp
|
||||
)
|
||||
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||
|
||||
120
src/edid_parse.cpp
Normal file
120
src/edid_parse.cpp
Normal file
@@ -0,0 +1,120 @@
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
|
||||
#include <regex>
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include <86box/86box.h>
|
||||
#include <86box/plat.h>
|
||||
|
||||
extern int ini_detect_bom(const char *fn);
|
||||
extern ssize_t local_getline(char **buf, size_t *bufsiz, FILE *fp);
|
||||
}
|
||||
|
||||
// https://stackoverflow.com/a/64886763
|
||||
static std::vector<std::string> split(const std::string str, const std::string regex_str)
|
||||
{
|
||||
std::regex regexz(regex_str);
|
||||
std::vector<std::string> list(std::sregex_token_iterator(str.begin(), str.end(), regexz, -1),
|
||||
std::sregex_token_iterator());
|
||||
return list;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
{
|
||||
bool parse_edid_decode_file(const char* path, uint8_t* out, ssize_t* size_out)
|
||||
{
|
||||
std::regex regexLib("^([a-f0-9]{32}|[a-f0-9 ]{47})$", std::regex_constants::egrep);
|
||||
FILE* file;
|
||||
pclog("Parse %s\n", path);
|
||||
try {
|
||||
bool bom = ini_detect_bom(path);
|
||||
{
|
||||
// First check for "edid-decode (hex)" string.
|
||||
file = plat_fopen(path, "rb");
|
||||
if (file) {
|
||||
std::string str;
|
||||
size_t size;
|
||||
if (!fseek(file, 0, SEEK_END)) {
|
||||
size = ftell(file);
|
||||
if (size != -1) {
|
||||
str.resize(size);
|
||||
}
|
||||
fseek(file, 0, SEEK_SET);
|
||||
auto read = fread((void*)str.data(), 1, size, file);
|
||||
str.resize(read);
|
||||
fclose(file);
|
||||
file = NULL;
|
||||
|
||||
if (str.size() == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (str.find("edid-decode") == std::string::npos) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
file = plat_fopen(path, "rb");
|
||||
if (file) {
|
||||
char* buf = NULL;
|
||||
size_t size = 0;
|
||||
std::string edid_decode_text;
|
||||
fseek(file, 0, SEEK_END);
|
||||
size = ftell(file);
|
||||
fseek(file, 0, SEEK_SET);
|
||||
if (bom) {
|
||||
fseek(file, 3, SEEK_SET);
|
||||
size -= 3;
|
||||
}
|
||||
edid_decode_text.resize(size);
|
||||
auto err = fread((void*)edid_decode_text.data(), size, 1, file);
|
||||
fclose(file);
|
||||
file = NULL;
|
||||
if (err == 0) {
|
||||
return false;
|
||||
}
|
||||
std::istringstream isstream(edid_decode_text);
|
||||
std::string line;
|
||||
std::string edid;
|
||||
while (std::getline(isstream, line)) {
|
||||
if (line[line.size() - 1] == '\r') {
|
||||
line.resize(line.size() - 1);
|
||||
}
|
||||
std::smatch matched;
|
||||
if (std::regex_match(line, matched, regexLib)) {
|
||||
edid.append(matched.str() + " ");
|
||||
}
|
||||
}
|
||||
if (edid.size() >= 3) {
|
||||
edid.resize(edid.size() - 1);
|
||||
auto vals = split(edid, "\\s+");
|
||||
if (vals.size()) {
|
||||
*size_out = vals.size();
|
||||
if (vals.size() > 256)
|
||||
return false;
|
||||
for (int i = 0; i < vals.size(); i++) {
|
||||
out[i] = (uint8_t)std::strtoul(&vals[i][0], nullptr, 16);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
} catch (std::bad_alloc&) {
|
||||
if (file) {
|
||||
fclose(file);
|
||||
file = NULL;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -46,7 +46,7 @@ SettingsDisplay::SettingsDisplay(QWidget *parent)
|
||||
for (uint8_t i = 0; i < GFXCARD_MAX; i ++)
|
||||
videoCard[i] = gfxcard[i];
|
||||
|
||||
ui->lineEdit->setFilter(tr("EDID") % util::DlgFilter({ "bin", "dat", "edid" }) % tr("All files") % util::DlgFilter({ "*" }, true));
|
||||
ui->lineEdit->setFilter(tr("EDID") % util::DlgFilter({ "bin", "dat", "edid", "txt" }) % tr("All files") % util::DlgFilter({ "*" }, true));
|
||||
|
||||
onCurrentMachineChanged(machine);
|
||||
}
|
||||
|
||||
@@ -316,7 +316,7 @@ ini_close(ini_t ini)
|
||||
free(list);
|
||||
}
|
||||
|
||||
static int
|
||||
int
|
||||
ini_detect_bom(const char *fn)
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
*
|
||||
* Copyright 2020 RichardG.
|
||||
*/
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
@@ -231,13 +232,36 @@ ddc_create_default_edid(ssize_t* size_out)
|
||||
return edid;
|
||||
}
|
||||
|
||||
extern bool parse_edid_decode_file(const char* path, uint8_t* out, ssize_t* size);
|
||||
|
||||
void *
|
||||
ddc_init(void *i2c)
|
||||
{
|
||||
ssize_t edid_size = 0;
|
||||
uint8_t* edid_bytes = NULL;
|
||||
if (monitor_edid == 1 && monitor_edid_path[0]) {
|
||||
FILE* file = plat_fopen(monitor_edid_path, "rb");
|
||||
FILE* file;
|
||||
{
|
||||
edid_bytes = calloc(1, 256);
|
||||
if (parse_edid_decode_file(monitor_edid_path, edid_bytes, &edid_size) == false) {
|
||||
if (edid_size > 256) {
|
||||
wchar_t errmsg[2048] = { 0 };
|
||||
wchar_t path[2048] = { 0 };
|
||||
|
||||
#ifdef _WIN32
|
||||
mbstoc16s(path, monitor_edid_path, sizeof_w(path));
|
||||
#else
|
||||
mbstowcs(path, monitor_edid_path, sizeof_w(path));
|
||||
#endif
|
||||
swprintf(errmsg, sizeof_w(errmsg), plat_get_string(STRING_EDID_TOO_LARGE), path);
|
||||
ui_msgbox_header(MBX_ERROR, L"EDID", errmsg);
|
||||
}
|
||||
free(edid_bytes);
|
||||
} else {
|
||||
goto calculate_cksum;
|
||||
}
|
||||
}
|
||||
file = plat_fopen(monitor_edid_path, "rb");
|
||||
|
||||
if (!file)
|
||||
goto default_init;
|
||||
@@ -282,6 +306,8 @@ ddc_init(void *i2c)
|
||||
goto default_init;
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
calculate_cksum:
|
||||
if (edid_size < 128) {
|
||||
edid_bytes = realloc(edid_bytes, 128);
|
||||
edid_size = 128;
|
||||
@@ -306,7 +332,6 @@ ddc_init(void *i2c)
|
||||
}
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
return i2c_eeprom_init(i2c, 0x50, edid_bytes, edid_size, 0);
|
||||
}
|
||||
default_init:
|
||||
|
||||
Reference in New Issue
Block a user