diff --git a/builds/genesis_plus_gx_libretro.dll b/builds/genesis_plus_gx_libretro.dll index 9f97450..ae66c7d 100644 Binary files a/builds/genesis_plus_gx_libretro.dll and b/builds/genesis_plus_gx_libretro.dll differ diff --git a/builds/genplus_cube.dol b/builds/genplus_cube.dol index 8fee7a2..86a3b2a 100644 Binary files a/builds/genplus_cube.dol and b/builds/genplus_cube.dol differ diff --git a/builds/genplus_wii.dol b/builds/genplus_wii.dol index cfdce4e..88023e4 100644 Binary files a/builds/genplus_wii.dol and b/builds/genplus_wii.dol differ diff --git a/core/cart_hw/md_cart.c b/core/cart_hw/md_cart.c index dc19bba..2456954 100644 --- a/core/cart_hw/md_cart.c +++ b/core/cart_hw/md_cart.c @@ -292,14 +292,6 @@ void md_cart_init(void) while (cart.romsize > size) size <<= 1; - /* total ROM size is not a factor of 2 */ - /* TODO: handle all possible ROM configurations using cartridge database */ - if ((size < MAXROMSIZE) && (cart.romsize < size)) - { - /* ROM is padded up to 2^k bytes */ - memset(cart.rom + cart.romsize, 0xff, size - cart.romsize); - } - /* Sonic & Knuckles */ if (strstr(rominfo.international,"SONIC & KNUCKLES")) { @@ -307,6 +299,22 @@ void md_cart_init(void) size = 0x400000; } + /* total ROM size is not a factor of 2 */ + /* TODO: handle all possible ROM configurations using cartridge database */ + if (cart.romsize < size) + { + if (size < MAXROMSIZE) + { + /* ROM is padded up to 2^k bytes */ + memset(cart.rom + cart.romsize, 0xff, size - cart.romsize); + } + else + { + /* ROM is padded up to max ROM size */ + memset(cart.rom + cart.romsize, 0xff, MAXROMSIZE - cart.romsize); + } + } + /* ROM is mirrored each 2^k bytes */ cart.mask = size - 1; diff --git a/core/cart_hw/sms_cart.c b/core/cart_hw/sms_cart.c index 47ebfec..6a2fecc 100644 --- a/core/cart_hw/sms_cart.c +++ b/core/cart_hw/sms_cart.c @@ -255,8 +255,8 @@ static const rominfo_t game_list[] = {0x41C948BF, 0, 0, SYSTEM_SPORTSPAD, MAPPER_SEGA, SYSTEM_SMS2, REGION_USA}, /* Sports Pad Soccer */ /* games requiring homemade multitap */ - {0xFAB6F52F, 0, 0, SYSTEM_MS4PLAY, MAPPER_NONE, SYSTEM_SMS2, REGION_USA}, /* BOom (v1.0) */ - {0x143AB50B, 0, 0, SYSTEM_MS4PLAY, MAPPER_NONE, SYSTEM_SMS2, REGION_USA}, /* BOom (v1.1) */ + {0xFAB6F52F, 0, 0, SYSTEM_MASTERTAP, MAPPER_NONE, SYSTEM_SMS2, REGION_USA}, /* BOom (v1.0) */ + {0x143AB50B, 0, 0, SYSTEM_MASTERTAP, MAPPER_NONE, SYSTEM_SMS2, REGION_USA}, /* BOom (v1.1) */ /* games supporting YM2413 FM */ {0x1C951F8E, 0, 1, SYSTEM_GAMEPAD, MAPPER_SEGA, SYSTEM_SMS2, REGION_USA}, /* After Burner */ diff --git a/core/input_hw/gamepad.c b/core/input_hw/gamepad.c index 7e6ec58..ebb1463 100644 --- a/core/input_hw/gamepad.c +++ b/core/input_hw/gamepad.c @@ -253,17 +253,17 @@ void jcart_write(unsigned int address, unsigned int data) /* Master System multitap ports handler (original design by Furrtek) */ /* cf. http://www.smspower.org/uploads/Homebrew/BOoM-SMS-sms4p_2.png */ /*--------------------------------------------------------------------------*/ -unsigned char ms4play_1_read(void) +unsigned char mastertap_1_read(void) { return gamepad_read(flipflop[0].Counter); } -unsigned char ms4play_2_read(void) +unsigned char mastertap_2_read(void) { return gamepad_read(flipflop[1].Counter + 4); } -void ms4play_1_write(unsigned char data, unsigned char mask) +void mastertap_1_write(unsigned char data, unsigned char mask) { /* update bits set as output only */ data = (flipflop[0].Latch & ~mask) | (data & mask); @@ -278,7 +278,7 @@ void ms4play_1_write(unsigned char data, unsigned char mask) flipflop[0].Latch = data; } -void ms4play_2_write(unsigned char data, unsigned char mask) +void mastertap_2_write(unsigned char data, unsigned char mask) { /* update bits set as output only */ data = (flipflop[1].Latch & ~mask) | (data & mask); diff --git a/core/input_hw/gamepad.h b/core/input_hw/gamepad.h index 9c75bde..f44d606 100644 --- a/core/input_hw/gamepad.h +++ b/core/input_hw/gamepad.h @@ -53,9 +53,9 @@ extern void wayplay_1_write(unsigned char data, unsigned char mask); extern void wayplay_2_write(unsigned char data, unsigned char mask); extern unsigned int jcart_read(unsigned int address); extern void jcart_write(unsigned int address, unsigned int data); -extern unsigned char ms4play_1_read(void); -extern unsigned char ms4play_2_read(void); -extern void ms4play_1_write(unsigned char data, unsigned char mask); -extern void ms4play_2_write(unsigned char data, unsigned char mask); +extern unsigned char mastertap_1_read(void); +extern unsigned char mastertap_2_read(void); +extern void mastertap_1_write(unsigned char data, unsigned char mask); +extern void mastertap_2_write(unsigned char data, unsigned char mask); #endif diff --git a/core/input_hw/input.c b/core/input_hw/input.c index 3ad7958..fd5c68e 100644 --- a/core/input_hw/input.c +++ b/core/input_hw/input.c @@ -170,7 +170,7 @@ void input_init(void) break; } - case SYSTEM_MS4PLAY: + case SYSTEM_MASTERTAP: { for (i=0; i<4; i++) { @@ -289,7 +289,7 @@ void input_init(void) break; } - case SYSTEM_MS4PLAY: + case SYSTEM_MASTERTAP: { for (i=4; i<8; i++) { diff --git a/core/input_hw/input.h b/core/input_hw/input.h index f6fdec0..db6ae04 100644 --- a/core/input_hw/input.h +++ b/core/input_hw/input.h @@ -54,7 +54,7 @@ #define SYSTEM_LIGHTPHASER (7) /* Sega Light Phaser (Master System) */ #define SYSTEM_PADDLE (8) /* Sega Paddle Control (Master System) */ #define SYSTEM_SPORTSPAD (9) /* Sega Sports Pad (Master System) */ -#define SYSTEM_MS4PLAY (10) /* Multi Tap -- Master System homemade */ +#define SYSTEM_MASTERTAP (10) /* Multi Tap -- Master System homemade */ #define SYSTEM_TEAMPLAYER (11) /* Multi Tap -- Sega TeamPlayer */ #define SYSTEM_WAYPLAY (12) /* Multi Tap -- EA 4-Way Play (use both ports) */ diff --git a/core/io_ctrl.c b/core/io_ctrl.c index 7dfcf3d..6232863 100644 --- a/core/io_ctrl.c +++ b/core/io_ctrl.c @@ -122,10 +122,10 @@ void io_init(void) break; } - case SYSTEM_MS4PLAY: + case SYSTEM_MASTERTAP: { - port[0].data_w = ms4play_1_write; - port[0].data_r = ms4play_1_read; + port[0].data_w = mastertap_1_write; + port[0].data_r = mastertap_1_read; break; } @@ -216,10 +216,10 @@ void io_init(void) break; } - case SYSTEM_MS4PLAY: + case SYSTEM_MASTERTAP: { - port[1].data_w = ms4play_2_write; - port[1].data_r = ms4play_2_read; + port[1].data_w = mastertap_2_write; + port[1].data_r = mastertap_2_read; break; } diff --git a/core/vdp_render.c b/core/vdp_render.c index 04b4288..67bdb08 100644 --- a/core/vdp_render.c +++ b/core/vdp_render.c @@ -3812,44 +3812,50 @@ void parse_satb_m5(int line) do { - /* Read Y position & size from internal SAT */ + /* Read Y position from internal SAT cache */ ypos = (q[link] >> im2_flag) & 0x1FF; - size = q[link + 1] >> 8; - /* Sprite height */ - height = 8 + ((size & 3) << 3); - - /* Y range */ - ypos = line - ypos; - - /* Sprite is visble on this line ? */ - if ((ypos >= 0) && (ypos < height)) + /* Check if sprite Y position has been reached */ + if (line >= ypos) { - /* Sprite overflow */ - if (count == max) + /* Read sprite size from internal SAT cache */ + size = q[link + 1] >> 8; + + /* Sprite height */ + height = 8 + ((size & 3) << 3); + + /* Y range */ + ypos = line - ypos; + + /* Check if sprite is visible on current line */ + if (ypos < height) { - status |= 0x40; - break; + /* Sprite overflow */ + if (count == max) + { + status |= 0x40; + break; + } + + /* Update sprite list (only name, attribute & xpos are parsed from VRAM) */ + object_info->attr = p[link + 2]; + object_info->xpos = p[link + 3] & 0x1ff; + object_info->ypos = ypos; + object_info->size = size & 0x0f; + + /* Increment Sprite count */ + ++count; + + /* Next sprite entry */ + object_info++; } - - /* Update sprite list (only name, attribute & xpos are parsed from VRAM) */ - object_info->attr = p[link + 2]; - object_info->xpos = p[link + 3] & 0x1ff; - object_info->ypos = ypos; - object_info->size = size & 0x0f; - - /* Increment Sprite count */ - ++count; - - /* Next sprite entry */ - object_info++; } - /* Read link data from internal SAT */ + /* Read link data from internal SAT cache */ link = (q[link + 1] & 0x7F) << 2; - /* Last sprite */ - if (link == 0) break; + /* Stop parsing if link data points to first entry (#0) or after the last entry (#64 in H32 mode, #80 in H40 mode) */ + if ((link == 0) || (link >= bitmap.viewport.w)) break; } while (--total); diff --git a/gx/gui/cheats.c b/gx/gui/cheats.c index 829044c..8c31d46 100644 --- a/gx/gui/cheats.c +++ b/gx/gui/cheats.c @@ -3,7 +3,7 @@ * * Cheats menu * - * Copyright Eke-Eke (2010-2012) + * Copyright Eke-Eke (2010-2014) * * Redistribution and use of this code or any derivative works are permitted * provided that the following conditions are met: @@ -46,7 +46,7 @@ #define BG_COLOR_1 {0x49,0x49,0x49,0xff} #define BG_COLOR_2 {0x66,0x66,0x66,0xff} -#define MAX_CHEATS (150) +#define MAX_CHEATS (350) #define MAX_DESC_LENGTH (63) #ifdef HW_RVL @@ -853,38 +853,52 @@ void CheatMenu(void) while (update != -1) { /* update arrows buttons */ - if (offset > 0) m->arrows[0]->state |= BUTTON_VISIBLE; - else m->arrows[0]->state &= ~BUTTON_VISIBLE; - if ((offset + 10) < (maxcheats + 1)) m->arrows[1]->state |= BUTTON_VISIBLE; - else m->arrows[1]->state &= ~BUTTON_VISIBLE; + if (offset > 0) + m->arrows[0]->state |= BUTTON_VISIBLE; + else + m->arrows[0]->state &= ~BUTTON_VISIBLE; + if (((offset + 10) < (maxcheats + 1)) && ((offset + 10) < MAX_CHEATS)) + m->arrows[1]->state |= BUTTON_VISIBLE; + else + m->arrows[1]->state &= ~BUTTON_VISIBLE; /* draw menu */ GUI_DrawMenu(m); - /* restore cheats offset */ - if (!(menu_cheats.bg_images[6].state & IMAGE_VISIBLE)) + /* check if browsing cheats list */ + if (!(m->bg_images[6].state & IMAGE_VISIBLE)) { + /* restore cheats list offset */ m->offset = offset; - m->max_items = maxcheats + 1; + m->max_items = (maxcheats < MAX_CHEATS) ? (maxcheats + 1) : MAX_CHEATS; m->max_buttons = 10; + m->helpers[1] = NULL; } /* update menu */ update = GUI_UpdateMenu(m); - /* update selected cheat */ - if ((m->selected < 10) && (selection != m->selected)) - { - selection = m->selected; - string_offset = 0; - } - - /* save offset then restore default */ + /* check if browsing cheats list */ if (!(m->bg_images[6].state & IMAGE_VISIBLE)) { - offset = m->offset; + /* update selected cheat */ + if ((m->selected < 10) && (selection != m->selected)) + { + selection = m->selected; + string_offset = 0; + } + + /* save cheats list offset */ + if (offset != m->offset) + { + offset = m->offset; + string_offset = 0; + } + + /* restore default GUI settings */ m->offset = 0; m->max_items = m->max_buttons = 30; + m->helpers[1] = &action_select; } @@ -1194,35 +1208,38 @@ void CheatMenu(void) /* Special inputs */ if (m_input.keys & PAD_TRIGGER_R) { - /* sort cheat list */ - for (i = offset + selection + 1; i < maxcheats; i++) + if (GUI_WaitConfirm("Warning","Delete Cheat Entry ?")) { - strcpy(cheatlist[i-1].text,cheatlist[i].text); - strcpy(cheatlist[i-1].code,cheatlist[i].code); - cheatlist[i-1].address = cheatlist[i].address; - cheatlist[i-1].data = cheatlist[i].data; - cheatlist[i-1].enable = cheatlist[i].enable; + /* sort cheat list */ + for (i = offset + selection + 1; i < maxcheats; i++) + { + strcpy(cheatlist[i-1].text,cheatlist[i].text); + strcpy(cheatlist[i-1].code,cheatlist[i].code); + cheatlist[i-1].address = cheatlist[i].address; + cheatlist[i-1].data = cheatlist[i].data; + cheatlist[i-1].enable = cheatlist[i].enable; + } + + /* clear last cheat */ + cheatlist[maxcheats-1].text[0] = 0; + cheatlist[maxcheats-1].code[0] = 0; + cheatlist[maxcheats-1].address = 0; + cheatlist[maxcheats-1].data = 0; + cheatlist[maxcheats-1].enable = 0; + + /* disable last button */ + if ((maxcheats - offset) < 10) + { + m->buttons[maxcheats - offset].state &= ~BUTTON_ACTIVE; + m->buttons[maxcheats - offset - 1].shift[1] = 0; + } + + /* decrease cheat count */ + maxcheats--; + + /* reset scrolling */ + string_offset = 0; } - - /* clear last cheat */ - cheatlist[maxcheats-1].text[0] = 0; - cheatlist[maxcheats-1].code[0] = 0; - cheatlist[maxcheats-1].address = 0; - cheatlist[maxcheats-1].data = 0; - cheatlist[maxcheats-1].enable = 0; - - /* disable last button */ - if ((maxcheats - offset) < 10) - { - m->buttons[maxcheats - offset].state &= ~BUTTON_ACTIVE; - m->buttons[maxcheats - offset - 1].shift[1] = 0; - } - - /* decrease cheat count */ - maxcheats--; - - /* reset scrolling */ - string_offset = 0; } else if (m_input.keys & PAD_TRIGGER_L) { diff --git a/gx/gui/cheats.h b/gx/gui/cheats.h index e6759a6..5a6f216 100644 --- a/gx/gui/cheats.h +++ b/gx/gui/cheats.h @@ -3,7 +3,7 @@ * * Cheats menu * - * Copyright Eke-Eke (2010-2012) + * Copyright Eke-Eke (2010-2014) * * Redistribution and use of this code or any derivative works are permitted * provided that the following conditions are met: diff --git a/gx/gui/gui.c b/gx/gui/gui.c index cccab34..0dbcb72 100644 --- a/gx/gui/gui.c +++ b/gx/gui/gui.c @@ -1770,8 +1770,17 @@ static void *MsgBox_Thread(gui_message *message_box) /* draw exit message */ if (message_box->buttonA) { - FONT_writeCenter("Press to continue.",18,166,166+message_box->window->width,248+22,(GXColor)WHITE); - gxDrawTexture(message_box->buttonA, 166+116, 248+4+(18-message_box->buttonA->height)/2,message_box->buttonA->width, message_box->buttonA->height,255); + if (message_box->buttonB) + { + FONT_writeCenter(" Confirm Cancel ",18,166,166+message_box->window->width,248+18+8,(GXColor)WHITE); + gxDrawTexture(message_box->buttonA, 166+56, 248+8+(18-message_box->buttonA->height)/2,message_box->buttonA->width, message_box->buttonA->height,255); + gxDrawTexture(message_box->buttonB, 166+166, 248+8+(18-message_box->buttonB->height)/2,message_box->buttonB->width, message_box->buttonB->height,255); + } + else + { + FONT_writeCenter("Press to continue.",18,166,166+message_box->window->width,248+18+4,(GXColor)WHITE); + gxDrawTexture(message_box->buttonA, 166+116, 248+4+(18-message_box->buttonA->height)/2,message_box->buttonA->width, message_box->buttonA->height,255); + } } /* update display */ @@ -1936,6 +1945,7 @@ void GUI_MsgBoxClose(void) gxTextureClose(&message_box.window); gxTextureClose(&message_box.top); gxTextureClose(&message_box.buttonA); + gxTextureClose(&message_box.buttonB); gxTextureClose(&message_box.throbber); } } @@ -1964,6 +1974,32 @@ void GUI_WaitPrompt(char *title, char *msg) GUI_MsgBoxClose(); } +int GUI_WaitConfirm(char *title, char *msg) +{ + /* clear unused texture */ + gxTextureClose(&message_box.throbber); + + /* open or update message box */ + GUI_MsgBoxOpen(title, msg, 0); + + /* allocate texture */ + message_box.buttonA = gxTextureOpenPNG(Key_A_png,0); + message_box.buttonB = gxTextureOpenPNG(Key_B_png,0); + + /* wait for button A or Button B*/ + while (m_input.keys & (PAD_BUTTON_A | PAD_BUTTON_B)) + VIDEO_WaitVSync(); + while (!(m_input.keys & (PAD_BUTTON_A | PAD_BUTTON_B))) + VIDEO_WaitVSync(); + + int ret = m_input.keys & PAD_BUTTON_A; + + /* always close message box */ + GUI_MsgBoxClose(); + + return ret; +} + /* Basic Fading */ void GUI_FadeOut() { diff --git a/gx/gui/gui.h b/gx/gui/gui.h index 57d8f58..4500f60 100644 --- a/gx/gui/gui.h +++ b/gx/gui/gui.h @@ -120,11 +120,11 @@ typedef struct typedef struct { char title[64]; /* menu title */ - s8 selected; /* index of selected item */ - s8 offset; /* items list offset */ - u8 max_items; /* total number of items */ - u8 max_buttons; /* total number of buttons */ - u8 max_images; /* total number of background images */ + int selected; /* index of selected item */ + int offset; /* items list offset */ + int max_items; /* total number of items */ + int max_buttons; /* total number of buttons */ + int max_images; /* total number of background images */ u8 screenshot; /* game screen background */ gui_item *items; /* menu items */ gui_butn *buttons; /* menu buttons */ @@ -144,6 +144,7 @@ typedef struct gx_texture *window; /* pointer to box texture */ gx_texture *top; /* pointer to box title texture */ gx_texture *buttonA; /* pointer to button A texture */ + gx_texture *buttonB; /* pointer to button A texture */ gx_texture *throbber; /* pointer to throbber texture */ } gui_message; @@ -238,6 +239,7 @@ extern void GUI_MsgBoxOpen(char *title, char *msg, bool throbber); extern void GUI_MsgBoxUpdate(char *title, char *msg); extern void GUI_MsgBoxClose(void); extern void GUI_WaitPrompt(char *title, char *msg); +extern int GUI_WaitConfirm(char *title, char *msg); extern void GUI_FadeOut(); extern GXColor *GUI_GetBgColor(void); extern void GUI_SetBgColor(u8 color); diff --git a/gx/gui/menu.c b/gx/gui/menu.c index 7e12fe1..a0557ee 100644 --- a/gx/gui/menu.c +++ b/gx/gui/menu.c @@ -108,7 +108,7 @@ extern const u8 Ctrl_paddle_png[]; extern const u8 Ctrl_sportspad_png[]; extern const u8 Ctrl_none_png[]; extern const u8 Ctrl_teamplayer_png[]; -extern const u8 Ctrl_ms4play_png[]; +extern const u8 Ctrl_mastertap_png[]; extern const u8 Ctrl_pad_auto_png[]; extern const u8 Ctrl_pad2b_png[]; extern const u8 Ctrl_pad3b_png[]; @@ -2062,7 +2062,7 @@ static void ctrlmenu(void) {NULL,Ctrl_lightphaser_png,"","Select Port 1 device", 89,109,88,92}, {NULL,Ctrl_paddle_png ,"","Select Port 1 device", 86,117,96,84}, {NULL,Ctrl_sportspad_png ,"","Select Port 1 device", 95,117,76,84}, - {NULL,Ctrl_ms4play_png ,"","Select Port 1 device", 94,100,80,100}, + {NULL,Ctrl_mastertap_png ,"","Select Port 1 device", 96,104,76,96}, {NULL,Ctrl_teamplayer_png ,"","Select Port 1 device", 94,109,80,92}, {NULL,Ctrl_4wayplay_png ,"","Select Port 1 device", 98,110,72,92} }, @@ -2077,7 +2077,7 @@ static void ctrlmenu(void) {NULL,Ctrl_lightphaser_png,"","Select Port 2 device", 89,279,88,92}, {NULL,Ctrl_paddle_png ,"","Select Port 2 device", 86,287,96,84}, {NULL,Ctrl_sportspad_png ,"","Select Port 2 device", 95,287,76,84}, - {NULL,Ctrl_ms4play_png ,"","Select Port 1 device", 94,270,80,100}, + {NULL,Ctrl_mastertap_png ,"","Select Port 1 device", 96,274,76,96}, {NULL,Ctrl_teamplayer_png ,"","Select Port 2 device", 94,279,80,92}, {NULL,Ctrl_4wayplay_png ,"","Select Port 2 device", 98,280,72,92} } @@ -2438,7 +2438,7 @@ static void ctrlmenu(void) case DEVICE_PAD3B: case DEVICE_PAD6B: { - if (input.system[index/4] == SYSTEM_MS4PLAY) + if (input.system[index/4] == SYSTEM_MASTERTAP) { /* force 2-buttons pad */ items = items_special[3]; @@ -3139,13 +3139,17 @@ static int savemenu(void) { if (slots[slot].valid) { - if (slot_delete(slot,config.s_device) >= 0) + if (GUI_WaitConfirm("Warning","Delete Save File ?")) { - /* hide screenshot */ - gxTextureClose(&bg_saves[0].texture); - bg_saves[0].state &= ~IMAGE_VISIBLE; - slots[slot].valid = 0; - update = -1; + if (slot_delete(slot,config.s_device) >= 0) + { + /* hide screenshot */ + gxTextureClose(&bg_saves[0].texture); + bg_saves[0].state &= ~IMAGE_VISIBLE; + bg_saves[1].state |= IMAGE_VISIBLE; + slots[slot].valid = 0; + update = -1; + } } } break; diff --git a/gx/gx_input.c b/gx/gx_input.c index 0ea17ed..91051ba 100644 --- a/gx/gx_input.c +++ b/gx/gx_input.c @@ -3,7 +3,7 @@ * * Genesis Plus GX input support * - * Copyright Eke-Eke (2007-2013) + * Copyright Eke-Eke (2007-2014) * * Redistribution and use of this code or any derivative works are permitted * provided that the following conditions are met: @@ -490,23 +490,29 @@ static int wpad_StickX(WPADData *data, u8 right) if (js) { - /* raw X value */ - int x = js->pos.x; - - /* value returned is sometime above calibrated limits */ - if (x > js->max.x) return 127; - if (x < js->min.x) return -128; + /* raw X position */ + int pos = js->pos.x; + + /* X range calibration */ + int min = js->min.x; + int max = js->max.x; + int center = js->center.x; + + /* value returned could be above calibration limits */ + if (pos > max) return 127; + if (pos < min) return -128; /* adjust against center position */ - x -= js->center.x; + pos -= center; /* return interpolated range [-128;127] */ - if (x > 0) + if (pos > 0) { - return (int)(127.0 * ((float)x / (float)(js->max.x - js->center.x))); + return (int)(127.0 * ((float)pos / (float)(max - center))); } + else { - return (int)(128.0 * ((float)x / (float)(js->center.x - js->min.x))); + return (int)(128.0 * ((float)pos / (float)(center - min))); } } @@ -533,23 +539,29 @@ static int wpad_StickY(WPADData *data, u8 right) if (js) { - /* raw Y value */ - int y = js->pos.y; - - /* value returned is sometime above calibrated limits */ - if (y > js->max.y) return 127; - if (y < js->min.y) return -128; + /* raw Y position */ + int pos = js->pos.y; + + /* Y range calibration */ + int min = js->min.y; + int max = js->max.y; + int center = js->center.y; + + /* value returned could be above calibration limits */ + if (pos > max) return 127; + if (pos < min) return -128; /* adjust against center position */ - y -= js->center.y; + pos -= center; /* return interpolated range [-128;127] */ - if (y > 0) + if (pos > 0) { - return (int)(127.0 * ((float)y / (float)(js->max.y - js->center.y))); + return (int)(127.0 * ((float)pos / (float)(max - center))); } + else { - return (int)(128.0 * ((float)y / (float)(js->center.y - js->min.y))); + return (int)(128.0 * ((float)pos / (float)(center - min))); } } @@ -1113,6 +1125,39 @@ int gx_input_FindDevices(void) if (wpad == (config.input[player].device - 1)) { found++; + + /* some 3rd party classic controllers return invalid factory calibration data */ + if (wpad == EXP_CLASSIC) + { + /* WPAD data */ + WPADData *data = WPAD_Data(config.input[player].port); + + /* Left analog stick */ + struct joystick_t* js = &data->exp.classic.ljs; + + /* Check acquired calibration data */ + if ((js->max.x <= js->center.x) || (js->min.x >= js->center.x) || + (js->max.y <= js->center.y) || (js->min.y >= js->center.y)) + { + /* Reset to default values */ + js->min.x = js->min.y = 0; + js->max.x = js->max.y = 64; + js->center.x = js->center.y = 32; + } + + /* Right analog stick */ + js = &data->exp.classic.rjs; + + /* Check acquired calibration data */ + if ((js->max.x <= js->center.x) || (js->min.x >= js->center.x) || + (js->max.y <= js->center.y) || (js->min.y >= js->center.y)) + { + /* Reset to default values */ + js->min.x = js->min.y = 0; + js->max.x = js->max.y = 32; + js->center.x = js->center.y = 16; + } + } } break; } @@ -1528,44 +1573,31 @@ void gx_input_UpdateMenu(void) } #ifdef HW_RVL - /* Wiimote direction keys */ + /* Wiimote & Classic Controller direction keys */ WPAD_IR(0, &m_input.ir); if (m_input.ir.valid) { /* Wiimote is handled vertically */ - if (pw & WPAD_BUTTON_UP) pp |= PAD_BUTTON_UP; - else if (pw & WPAD_BUTTON_DOWN) pp |= PAD_BUTTON_DOWN; - else if (pw & WPAD_BUTTON_LEFT) pp |= PAD_BUTTON_LEFT; - else if (pw & WPAD_BUTTON_RIGHT) pp |= PAD_BUTTON_RIGHT; + if (pw & (WPAD_BUTTON_UP|WPAD_CLASSIC_BUTTON_UP)) pp |= PAD_BUTTON_UP; + else if (pw & (WPAD_BUTTON_DOWN|WPAD_CLASSIC_BUTTON_DOWN)) pp |= PAD_BUTTON_DOWN; + else if (pw & (WPAD_BUTTON_LEFT|WPAD_CLASSIC_BUTTON_LEFT)) pp |= PAD_BUTTON_LEFT; + else if (pw & (WPAD_BUTTON_RIGHT|WPAD_CLASSIC_BUTTON_RIGHT)) pp |= PAD_BUTTON_RIGHT; } else { /* Wiimote is handled horizontally */ - if (pw & WPAD_BUTTON_UP) pp |= PAD_BUTTON_LEFT; - else if (pw & WPAD_BUTTON_DOWN) pp |= PAD_BUTTON_RIGHT; - else if (pw & WPAD_BUTTON_LEFT) pp |= PAD_BUTTON_DOWN; - else if (pw & WPAD_BUTTON_RIGHT) pp |= PAD_BUTTON_UP; + if (pw & (WPAD_BUTTON_UP|WPAD_CLASSIC_BUTTON_LEFT)) pp |= PAD_BUTTON_LEFT; + else if (pw & (WPAD_BUTTON_DOWN|WPAD_CLASSIC_BUTTON_RIGHT)) pp |= PAD_BUTTON_RIGHT; + else if (pw & (WPAD_BUTTON_LEFT|WPAD_CLASSIC_BUTTON_DOWN)) pp |= PAD_BUTTON_DOWN; + else if (pw & (WPAD_BUTTON_RIGHT|WPAD_CLASSIC_BUTTON_UP)) pp |= PAD_BUTTON_UP; } - /* Classic Controller direction keys */ - if (pw & WPAD_CLASSIC_BUTTON_UP) pp |= PAD_BUTTON_UP; - else if (pw & WPAD_CLASSIC_BUTTON_DOWN) pp |= PAD_BUTTON_DOWN; - else if (pw & WPAD_CLASSIC_BUTTON_LEFT) pp |= PAD_BUTTON_LEFT; - else if (pw & WPAD_CLASSIC_BUTTON_RIGHT) pp |= PAD_BUTTON_RIGHT; - - /* WPAD buttons */ - if (pw & WPAD_BUTTON_A) pp |= PAD_BUTTON_A; - if (pw & WPAD_BUTTON_B) pp |= PAD_BUTTON_B; - if (pw & WPAD_BUTTON_2) pp |= PAD_BUTTON_A; - if (pw & WPAD_BUTTON_1) pp |= PAD_BUTTON_B; - if (pw & WPAD_BUTTON_HOME) pp |= PAD_TRIGGER_Z; - if (pw & WPAD_BUTTON_PLUS) pp |= PAD_TRIGGER_L; - if (pw & WPAD_BUTTON_MINUS) pp |= PAD_TRIGGER_R; - if (pw & WPAD_CLASSIC_BUTTON_FULL_L) pp |= PAD_TRIGGER_L; - if (pw & WPAD_CLASSIC_BUTTON_FULL_R) pp |= PAD_TRIGGER_R; - if (pw & WPAD_CLASSIC_BUTTON_A) pp |= PAD_BUTTON_A; - if (pw & WPAD_CLASSIC_BUTTON_B) pp |= PAD_BUTTON_B; - if (pw & WPAD_CLASSIC_BUTTON_HOME) pp |= PAD_TRIGGER_Z; + /* WPAD button keys */ + if (pw & (WPAD_BUTTON_2|WPAD_BUTTON_A|WPAD_CLASSIC_BUTTON_A)) pp |= PAD_BUTTON_A; + if (pw & (WPAD_BUTTON_1|WPAD_BUTTON_B|WPAD_CLASSIC_BUTTON_B)) pp |= PAD_BUTTON_B; + if (pw & (WPAD_BUTTON_HOME|WPAD_CLASSIC_BUTTON_HOME)) pp |= PAD_TRIGGER_Z; + if (pw & (WPAD_BUTTON_PLUS|WPAD_CLASSIC_BUTTON_PLUS|WPAD_CLASSIC_BUTTON_FULL_L)) pp |= PAD_TRIGGER_L; + if (pw & (WPAD_BUTTON_MINUS|WPAD_CLASSIC_BUTTON_MINUS|WPAD_CLASSIC_BUTTON_FULL_L)) pp |= PAD_TRIGGER_R; #endif /* Update menu inputs */ diff --git a/gx/gx_input.h b/gx/gx_input.h index 77143b4..070cbf6 100644 --- a/gx/gx_input.h +++ b/gx/gx_input.h @@ -3,7 +3,7 @@ * * Genesis Plus GX input support * - * Copyright Eke-Eke (2007-2013) + * Copyright Eke-Eke (2007-2014) * * Redistribution and use of this code or any derivative works are permitted * provided that the following conditions are met: diff --git a/gx/gx_video.c b/gx/gx_video.c index bb3c765..62c0f5e 100644 --- a/gx/gx_video.c +++ b/gx/gx_video.c @@ -667,8 +667,8 @@ static void gxDrawCrosshair(gx_texture *texture, int x, int y) int ywidth = square[3] - square[7]; /* adjust texture coordinates to EFB */ - x = (((x + bitmap.viewport.x) * xwidth) / vwidth) + square[6] - w/2; - y = (((y + bitmap.viewport.y) * ywidth) / vheight) + square[7] - h/2; + x = (((x + bitmap.viewport.x) * xwidth) / (bitmap.viewport.w+2*bitmap.viewport.x)) + square[6] - w/2; + y = (((y + bitmap.viewport.y) * ywidth) / (bitmap.viewport.h+2*bitmap.viewport.y)) + square[7] - h/2; /* load texture object */ GXTexObj texObj; diff --git a/gx/images/Ctrl_mastertap.png b/gx/images/Ctrl_mastertap.png new file mode 100644 index 0000000..966fc8f Binary files /dev/null and b/gx/images/Ctrl_mastertap.png differ diff --git a/gx/images/Ctrl_ms4play.png b/gx/images/Ctrl_ms4play.png deleted file mode 100644 index 3a05924..0000000 Binary files a/gx/images/Ctrl_ms4play.png and /dev/null differ