This commit is contained in:
David Haywood 2016-03-27 22:45:39 +01:00
commit b939d79892
7 changed files with 187 additions and 109 deletions

View File

@ -1303,7 +1303,7 @@ void layout_element::component::draw_beltreel(running_machine &machine, bitmap_a
//-------------------------------------------------
// load_bitmap - load a PNG file with artwork for
// load_bitmap - load a PNG/JPG file with artwork for
// a component
//-------------------------------------------------
@ -1317,6 +1317,10 @@ void layout_element::component::load_bitmap()
if (m_bitmap[0].valid() && !m_alphafile[0].empty())
render_load_png(m_bitmap[0], *m_file[0], m_dirname.c_str(), m_alphafile[0].c_str(), true);
// PNG failed, let's try JPG
if (!m_bitmap[0].valid())
render_load_jpeg(m_bitmap[0], *m_file[0], m_dirname.c_str(), m_imagefile[0].c_str());
// if we can't load the bitmap, allocate a dummy one and report an error
if (!m_bitmap[0].valid())
{

View File

@ -523,6 +523,96 @@ void render_line_to_quad(const render_bounds *bounds, float width, render_bounds
}
/*-------------------------------------------------
render_load_jpeg - load a JPG file into a
bitmap
-------------------------------------------------*/
void render_load_jpeg(bitmap_argb32 &bitmap, emu_file &file, const char *dirname, const char *filename)
{
// deallocate previous bitmap
bitmap.reset();
bitmap_format format = bitmap.format();
// define file's full name
std::string fname;
if (dirname == nullptr)
fname = filename;
else
fname.assign(dirname).append(PATH_SEPARATOR).append(filename);
osd_file::error filerr = file.open(fname.c_str());
if (filerr != osd_file::error::NONE)
return;
// define standard JPEG structures
jpeg_decompress_struct cinfo;
jpeg_error_mgr jerr;
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&cinfo);
// allocates a buffer for the image
UINT64 jpg_size = file.size();
unsigned char *jpg_buffer = global_alloc_array(unsigned char, jpg_size + 100);
// read data from the file and set them in the buffer
file.read(jpg_buffer, jpg_size);
jpeg_mem_src(&cinfo, jpg_buffer, jpg_size);
// read JPEG header and start decompression
jpeg_read_header(&cinfo, TRUE);
jpeg_start_decompress(&cinfo);
// allocates the destination bitmap
int w = cinfo.output_width;
int h = cinfo.output_height;
int s = cinfo.output_components;
bitmap.allocate(w, h);
// allocates a buffer to receive the information and copy them into the bitmap
int row_stride = cinfo.output_width * cinfo.output_components;
JSAMPARRAY buffer = (JSAMPARRAY)malloc(sizeof(JSAMPROW));
buffer[0] = (JSAMPROW)malloc(sizeof(JSAMPLE) * row_stride);
while ( cinfo.output_scanline < cinfo.output_height )
{
int j = cinfo.output_scanline;
jpeg_read_scanlines(&cinfo, buffer, 1);
if (s == 1)
for (int i = 0; i < w; ++i)
if (format == BITMAP_FORMAT_ARGB32)
bitmap.pix32(j, i) = rgb_t(0xFF, buffer[0][i], buffer[0][i], buffer[0][i]);
else
bitmap.pix32(j, i) = rgb_t(buffer[0][i], buffer[0][i], buffer[0][i]);
else if (s == 3)
for (int i = 0; i < w; ++i)
if (format == BITMAP_FORMAT_ARGB32)
bitmap.pix32(j, i) = rgb_t(0xFF, buffer[0][i * s], buffer[0][i * s + 1], buffer[0][i * s + 2]);
else
bitmap.pix32(j, i) = rgb_t(buffer[0][i * s], buffer[0][i * s + 1], buffer[0][i * s + 2]);
else
{
osd_printf_error("Cannot read JPEG data from %s file.\n", fname.c_str());
break;
}
}
// finish decompression and frees the memory
jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
file.close();
free(buffer[0]);
free(buffer);
global_free_array(jpg_buffer);
}
/*-------------------------------------------------
render_load_png - load a PNG file into a
bitmap

View File

@ -11,6 +11,7 @@
#define __RENDUTIL_H__
#include "render.h"
#include "libjpeg/jpeglib.h"
#include <math.h>
@ -25,6 +26,7 @@ void render_resample_argb_bitmap_hq(bitmap_argb32 &dest, bitmap_argb32 &source,
int render_clip_line(render_bounds *bounds, const render_bounds *clip);
int render_clip_quad(render_bounds *bounds, const render_bounds *clip, render_quad_texuv *texcoords);
void render_line_to_quad(const render_bounds *bounds, float width, render_bounds *bounds0, render_bounds *bounds1);
void render_load_jpeg(bitmap_argb32 &bitmap, emu_file &file, const char *dirname, const char *filename);
bool render_load_png(bitmap_argb32 &bitmap, emu_file &file, const char *dirname, const char *filename, bool load_as_alpha_to_existing = false);

View File

@ -14,8 +14,7 @@
#define __UI_UTILS_H__
#include "osdepend.h"
#include "render.h"
#include "libjpeg/jpeglib.h"
#include "rendutil.h"
#define MAX_CHAR_INFO 256
#define MAX_CUST_FILTER 8
@ -255,90 +254,5 @@ char* chartrimcarriage(char str[]);
const char* strensure(const char* s);
// jpeg loader
template <typename _T>
void render_load_jpeg(_T &bitmap, emu_file &file, const char *dirname, const char *filename)
{
// deallocate previous bitmap
bitmap.reset();
bitmap_format format = bitmap.format();
// define file's full name
std::string fname;
if (dirname == nullptr)
fname = filename;
else
fname.assign(dirname).append(PATH_SEPARATOR).append(filename);
osd_file::error filerr = file.open(fname.c_str());
if (filerr != osd_file::error::NONE)
return;
// define standard JPEG structures
jpeg_decompress_struct cinfo;
jpeg_error_mgr jerr;
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&cinfo);
// allocates a buffer for the image
UINT64 jpg_size = file.size();
unsigned char *jpg_buffer = global_alloc_array(unsigned char, jpg_size + 100);
// read data from the file and set them in the buffer
file.read(jpg_buffer, jpg_size);
jpeg_mem_src(&cinfo, jpg_buffer, jpg_size);
// read JPEG header and start decompression
jpeg_read_header(&cinfo, TRUE);
jpeg_start_decompress(&cinfo);
// allocates the destination bitmap
int w = cinfo.output_width;
int h = cinfo.output_height;
int s = cinfo.output_components;
bitmap.allocate(w, h);
// allocates a buffer to receive the information and copy them into the bitmap
int row_stride = cinfo.output_width * cinfo.output_components;
JSAMPARRAY buffer = (JSAMPARRAY)malloc(sizeof(JSAMPROW));
buffer[0] = (JSAMPROW)malloc(sizeof(JSAMPLE) * row_stride);
while ( cinfo.output_scanline < cinfo.output_height )
{
int j = cinfo.output_scanline;
jpeg_read_scanlines(&cinfo, buffer, 1);
if (s == 1)
for (int i = 0; i < w; ++i)
if (format == BITMAP_FORMAT_ARGB32)
bitmap.pix32(j, i) = rgb_t(0xFF, buffer[0][i], buffer[0][i], buffer[0][i]);
else
bitmap.pix32(j, i) = rgb_t(buffer[0][i], buffer[0][i], buffer[0][i]);
else if (s == 3)
for (int i = 0; i < w; ++i)
if (format == BITMAP_FORMAT_ARGB32)
bitmap.pix32(j, i) = rgb_t(0xFF, buffer[0][i * s], buffer[0][i * s + 1], buffer[0][i * s + 2]);
else
bitmap.pix32(j, i) = rgb_t(buffer[0][i * s], buffer[0][i * s + 1], buffer[0][i * s + 2]);
else
{
osd_printf_info("Error! Cannot read JPEG data from %s file.\n", fname.c_str());
break;
}
}
// finish decompression and frees the memory
jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
file.close();
free(buffer[0]);
free(buffer);
global_free_array(jpg_buffer);
}
#endif /* __UI_UTILS_H__ */

View File

@ -240,8 +240,8 @@ Notes:
24LC64 - Microchip 24LC64 64K I2C Serial EEPROM (SOIC8)
24LC024 - Microchip 24LC024 2K I2C Serial EEPROM (SOIC8)
M68AF127B - ST Microelectronics 1Mbit (128K x8), 5V Asynchronous SRAM (SOP32)
AN2131QC - Cypress AN2131 EZ-USB-Family 8051-based High-Speed USB IC's (QFP80)
AN2131SC / (QFP44)
AN2131QC - Cypress AN2131 EZ-USB-Family 8051-based High-Speed USB IC's (QFP80) firmware in IC11
AN2131SC / (QFP44) firmware in IC32
ADM3222 - Analog Devices ADM3222 High-Speed, +3.3V, 2-Channel RS232/V.28 Interface Device (SOIC20)
SN65240 - Texas Instruments SN65240 USB Port Transient Suppressor (SOIC8)
BA7623 - Rohm BA7623 75-Ohm driver IC with 3 internal circuits (SOIC8)
@ -572,7 +572,7 @@ static const struct {
UINT32 address;
UINT8 write_byte;
} modify[16];
} hacks[2] = { { "chihiro", { { 0x6a79f, 0x01 }, { 0x6a7a0, 0x00 }, { 0x6b575, 0x00 }, { 0x6b576, 0x00 }, { 0x6b5af, 0x75 }, { 0x6b78a, 0x75 }, { 0x6b7ca, 0x00 }, { 0x6b7b8, 0x00 }, { 0x8f5b2, 0x75 }, { 0x79a9e, 0x74 }, { 0x79b80, 0x74 }, { 0x79b97, 0x74 }, { 0, 0 } } },
} hacks[2] = { { "chihiro", { { 0x6a79f/*3f79f*/, 0x01 }, { 0x6a7a0/*3f7a0*/, 0x00 }, { 0x6b575/*40575*/, 0x00 }, { 0x6b576/*40576*/, 0x00 }, { 0x6b5af/*405af*/, 0x75 }, { 0x6b78a/*4078a*/, 0x75 }, { 0x6b7ca/*407ca*/, 0x00 }, { 0x6b7b8/*407b8*/, 0x00 }, { 0x8f5b2, 0x75 }, { 0x79a9e/*2ea9e*/, 0x74 }, { 0x79b80/*2eb80*/, 0x74 }, { 0x79b97/*2eb97*/, 0x74 }, { 0, 0 } } },
{ "outr2", { { 0x12e4cf, 0x01 }, { 0x12e4d0, 0x00 }, { 0x4793e, 0x01 }, { 0x4793f, 0x00 }, { 0x47aa3, 0x01 }, { 0x47aa4, 0x00 }, { 0x14f2b6, 0x84 }, { 0x14f2d1, 0x75 }, { 0x8732f, 0x7d }, { 0x87384, 0x7d }, { 0x87388, 0xeb }, { 0, 0 } } } };
void chihiro_state::hack_usb()

View File

@ -261,7 +261,7 @@ class ohci_function_device {
public:
ohci_function_device(running_machine &machine);
void execute_reset();
int execute_transfer(int address, int endpoint, int pid, UINT8 *buffer, int size) ;
int execute_transfer(int address, int endpoint, int pid, UINT8 *buffer, int size);
protected:
virtual int handle_nonstandard_request(int endpoint, USBSetupPacket *setup) { return -1; };
virtual int handle_get_status_request(int endpoint, USBSetupPacket *setup) { return 0; };
@ -269,6 +269,8 @@ protected:
virtual int handle_set_feature_request(int endpoint, USBSetupPacket *setup) { return 0; };
virtual int handle_set_descriptor_request(int endpoint, USBSetupPacket *setup) { return 0; };
virtual int handle_synch_frame_request(int endpoint, USBSetupPacket *setup) { return 0; };
virtual void handle_status_stage(int endpoint) { return; };
virtual int handle_bulk_pid(int endpoint, int pid, UINT8 *buffer, int size) { return 0; };
void add_device_descriptor(const USBStandardDeviceDescriptor &descriptor);
void add_configuration_descriptor(const USBStandardConfigurationDescriptor &descriptor);
@ -297,6 +299,7 @@ protected:
int configurationvalue;
UINT8 *descriptors;
int descriptors_pos;
bool wantstatuscallback;
USBStandardDeviceDescriptor device_descriptor;
std::forward_list<usb_device_configuration *> configurations;
std::forward_list<usb_device_string *> device_strings;
@ -323,6 +326,8 @@ class ohci_hlean2131qc_device: public ohci_function_device
public:
ohci_hlean2131qc_device(running_machine &machine);
int handle_nonstandard_request(int endpoint, USBSetupPacket *setup) override;
int handle_bulk_pid(int endpoint, int pid, UINT8 *buffer, int size) override;
void set_region_base(UINT8 *data);
private:
static const USBStandardDeviceDescriptor devdesc;
static const USBStandardConfigurationDescriptor condesc;
@ -340,6 +345,8 @@ private:
static const UINT8 strdesc0[];
static const UINT8 strdesc1[];
static const UINT8 strdesc2[];
int maximum_send;
UINT8 *region;
};
class ohci_hlean2131sc_device : public ohci_function_device

View File

@ -984,6 +984,7 @@ ohci_function_device::ohci_function_device(running_machine &machine)
endpoints[e].position = nullptr;
}
endpoints[0].type = ControlEndpoint;
wantstatuscallback = false;
settingaddress = false;
configurationvalue = 0;
selected_configuration = nullptr;
@ -1253,13 +1254,22 @@ int ohci_function_device::execute_transfer(int address, int endpoint, int pid, U
if (pid == SetupPid) {
USBSetupPacket *p=(USBSetupPacket *)buffer;
// control transfers are done in 3 stages: first the setup stage, then an optional data stage, then a status stage
// so there are 3 cases:
// 1- control transfer with a data stage where the host sends data to the device
// in this case the sequence of pids transferred is control pid, data out pid, data in pid
// 2- control transfer with a data stage where the host receives data from the device
// in this case the sequence of pids transferred is control pid, data in pid, data out pid
// 3- control transfer without a data stage
// in this case the sequence of pids transferred is control pid, data in pid
// define direction 0:host->device 1:device->host
// case == 1, IN data stage and OUT status stage
// case == 0, OUT data stage and IN status stage
// data stage is optional, IN status stage
// direction == 1 -> IN data stage and OUT status stage
// direction == 0 -> OUT data stage and IN status stage
// data stage not present -> IN status stage
endpoints[endpoint].controldirection = (p->bmRequestType & 128) >> 7;
endpoints[endpoint].controltype = (p->bmRequestType & 0x60) >> 5;
endpoints[endpoint].controlrecipient = p->bmRequestType & 0x1f;
wantstatuscallback = false;
if (endpoint == 0) {
endpoints[endpoint].position = nullptr;
// number of byte to transfer in data stage (0 no data stage)
@ -1341,23 +1351,26 @@ int ohci_function_device::execute_transfer(int address, int endpoint, int pid, U
return handle_nonstandard_request(endpoint, p);
}
else if (pid == InPid) {
if (endpoint == 0) {
if (endpoints[endpoint].type == ControlEndpoint) { //if (endpoint == 0) {
// if no data has been transferred (except for the setup stage)
// and the lenght of this IN transaction is 0
// assume this is the status stage
if ((size == 0) && (endpoints[endpoint].remain == 0)) {
if (settingaddress == true)
if ((endpoints[endpoint].remain == 0) && (size == 0)) {
if ((endpoint == 0) && (settingaddress == true))
{
// set of address is active at end of status stage
address = newaddress;
settingaddress = false;
state = AddressState;
}
if (wantstatuscallback == true)
handle_status_stage(endpoint);
wantstatuscallback = false;
return 0;
}
// case ==1, give data
// case ==0, nothing
// if device->host
// if device->host, since InPid then this is data stage
if (endpoints[endpoint].controldirection == DeviceToHost) {
// data stage
if (size > endpoints[endpoint].remain)
@ -1367,15 +1380,22 @@ int ohci_function_device::execute_transfer(int address, int endpoint, int pid, U
endpoints[endpoint].position = endpoints[endpoint].position + size;
endpoints[endpoint].remain = endpoints[endpoint].remain - size;
}
else {
if (wantstatuscallback == true)
handle_status_stage(endpoint);
wantstatuscallback = false;
}
}
else if (endpoints[endpoint].type == BulkEndpoint)
return handle_bulk_pid(endpoint, pid, buffer, size);
else
return -1;
}
else if (pid == OutPid) {
if (endpoint == 0) {
if (endpoints[endpoint].type == ControlEndpoint) { //if (endpoint == 0) {
// case ==1, nothing
// case ==0, give data
// if host->device
// if host->device, since OutPid then this is data stage
if (endpoints[endpoint].controldirection == HostToDevice) {
// data stage
if (size > endpoints[endpoint].remain)
@ -1385,7 +1405,14 @@ int ohci_function_device::execute_transfer(int address, int endpoint, int pid, U
endpoints[endpoint].position = endpoints[endpoint].position + size;
endpoints[endpoint].remain = endpoints[endpoint].remain - size;
}
else {
if (wantstatuscallback == true)
handle_status_stage(endpoint);
wantstatuscallback = false;
}
}
else if (endpoints[endpoint].type == BulkEndpoint)
return handle_bulk_pid(endpoint, pid, buffer, size);
else
return -1;
}
@ -1454,25 +1481,43 @@ ohci_hlean2131qc_device::ohci_hlean2131qc_device(running_machine &machine) :
add_device_descriptor(devdesc);
add_configuration_descriptor(condesc);
add_interface_descriptor(intdesc);
add_endpoint_descriptor(enddesc81);
add_endpoint_descriptor(enddesc82);
add_endpoint_descriptor(enddesc83);
add_endpoint_descriptor(enddesc84);
add_endpoint_descriptor(enddesc85);
// it is important to add the endpoints in the same order they are found in the device firmware
add_endpoint_descriptor(enddesc01);
add_endpoint_descriptor(enddesc02);
add_endpoint_descriptor(enddesc03);
add_endpoint_descriptor(enddesc04);
add_endpoint_descriptor(enddesc05);
add_endpoint_descriptor(enddesc81);
add_endpoint_descriptor(enddesc82);
add_endpoint_descriptor(enddesc83);
add_endpoint_descriptor(enddesc84);
add_endpoint_descriptor(enddesc85);
add_string_descriptor(strdesc0);
add_string_descriptor(strdesc1);
add_string_descriptor(strdesc2);
maximum_send = 0;
region = nullptr;
}
void ohci_hlean2131qc_device::set_region_base(UINT8 *data)
{
region = data;
}
int ohci_hlean2131qc_device::handle_nonstandard_request(int endpoint, USBSetupPacket *setup)
{
if (endpoint != 0)
return -1;
printf("Control request: %x %x %x %x %x %x %x\n\r", endpoint, endpoints[endpoint].controldirection, setup->bmRequestType, setup->bRequest, setup->wValue, setup->wIndex, setup->wLength);
//if ((setup->bRequest == 0x18) && (setup->wValue == 0x8000))
if (setup->bRequest == 0x17)
{
maximum_send = setup->wIndex;
if (maximum_send > 0x40)
maximum_send = 0x40;
endpoints[2].remain = maximum_send;
endpoints[2].position = region + 0x2000 + setup->wValue;
}
for (int n = 0; n < setup->wLength; n++)
endpoints[endpoint].buffer[n] = 0xa0 ^ n;
endpoints[endpoint].buffer[0] = 0;
@ -1481,6 +1526,20 @@ int ohci_hlean2131qc_device::handle_nonstandard_request(int endpoint, USBSetupPa
return 0;
}
int ohci_hlean2131qc_device::handle_bulk_pid(int endpoint, int pid, UINT8 *buffer, int size)
{
printf("Bulk request: %x %d %x\n\r", endpoint, pid, size);
if ((endpoint == 2) && (pid == InPid))
{
if (size > endpoints[2].remain)
size = endpoints[2].remain;
memcpy(buffer, endpoints[2].position, size);
endpoints[2].position = endpoints[3].position + size;
endpoints[2].remain = endpoints[3].remain - size;
}
return size;
}
//pc20
const USBStandardDeviceDescriptor ohci_hlean2131sc_device::devdesc = { 0x12,0x01,0x0100,0x60,0x01,0x00,0x40,0x0CA3,0x0003,0x0110,0x01,0x02,0x00,0x01 };
const USBStandardConfigurationDescriptor ohci_hlean2131sc_device::condesc = { 0x09,0x02,0x003C,0x01,0x01,0x00,0x80,0x96 };
@ -1501,12 +1560,13 @@ ohci_hlean2131sc_device::ohci_hlean2131sc_device(running_machine &machine) :
add_device_descriptor(devdesc);
add_configuration_descriptor(condesc);
add_interface_descriptor(intdesc);
add_endpoint_descriptor(enddesc81);
add_endpoint_descriptor(enddesc82);
add_endpoint_descriptor(enddesc83);
// it is important to add the endpoints in the same order they are found in the device firmware
add_endpoint_descriptor(enddesc01);
add_endpoint_descriptor(enddesc02);
add_endpoint_descriptor(enddesc03);
add_endpoint_descriptor(enddesc81);
add_endpoint_descriptor(enddesc82);
add_endpoint_descriptor(enddesc83);
add_string_descriptor(strdesc0);
add_string_descriptor(strdesc1);
add_string_descriptor(strdesc2);
@ -2221,6 +2281,7 @@ void xbox_base_state::machine_start()
ohcist.timer->enable(false);
//usb_device = new ohci_game_controller_device(machine());
usb_device = new ohci_hlean2131qc_device(machine());
usb_device->set_region_base(memregion(":others")->base()); // temporary, should be in chihiro
//usb_device = new ohci_hlean2131sc_device(machine());
usb_ohci_plug(1, usb_device); // test connect
#endif