Skip to content

Commit

Permalink
Changed the Steel Battalion controller to not have an internal hub. R…
Browse files Browse the repository at this point in the history
…emoved the ability to mount XMUs to the Steel Battalion controller's internal hub as it no longer exists.
  • Loading branch information
faha223 committed Dec 28, 2023
1 parent 76b29ae commit 0699999
Show file tree
Hide file tree
Showing 2 changed files with 167 additions and 148 deletions.
46 changes: 31 additions & 15 deletions ui/xemu-input.c
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ static const char **peripheral_params_settings_map[4][2] = {
static int sdl_kbd_scancode_map[25];
static int sdl_sbc_kbd_scancode_map[56];

const char *get_bound_driver(int port) {
static const char *get_bound_driver(int port) {
assert(port >= 0 && port <= 3);
const char *driver = NULL;
switch(port) {
Expand Down Expand Up @@ -820,16 +820,22 @@ void xemu_input_bind(int index, ControllerState *state, int save)
bound_controllers[index]->bound = index;

char *tmp;

// Create controller's internal USB hub.
QDict *usbhub_qdict = qdict_new();
qdict_put_str(usbhub_qdict, "driver", "usb-hub");
tmp = g_strdup_printf("1.%d", port_map[index]);
qdict_put_str(usbhub_qdict, "port", tmp);
qdict_put_int(usbhub_qdict, "ports", 3);
QemuOpts *usbhub_opts = qemu_opts_from_qdict(qemu_find_opts("device"), usbhub_qdict, &error_abort);
DeviceState *usbhub_dev = qdev_device_add(usbhub_opts, &error_abort);
g_free(tmp);
QDict *usbhub_qdict = NULL;
DeviceState *usbhub_dev = NULL;

bool hasInternalHub = strcmp(bound_drivers[index], DRIVER_STEEL_BATTALION) != 0;

if(hasInternalHub) {
// Create controller's internal USB hub.
usbhub_qdict = qdict_new();
qdict_put_str(usbhub_qdict, "driver", "usb-hub");
tmp = g_strdup_printf("1.%d", port_map[index]);
qdict_put_str(usbhub_qdict, "port", tmp);
qdict_put_int(usbhub_qdict, "ports", 3);
QemuOpts *usbhub_opts = qemu_opts_from_qdict(qemu_find_opts("device"), usbhub_qdict, &error_abort);
usbhub_dev = qdev_device_add(usbhub_opts, &error_abort);
g_free(tmp);
}

// Create XID controller. This is connected to Port 1 of the controller's internal USB Hub
QDict *qdict = qdict_new();
Expand All @@ -845,7 +851,8 @@ void xemu_input_bind(int index, ControllerState *state, int save)

// Specify index/port
qdict_put_int(qdict, "index", index);
tmp = g_strdup_printf("1.%d.1", port_map[index]);
const char *fmt = hasInternalHub ? "1.%d.1" : "1.%d";
tmp = g_strdup_printf(fmt, port_map[index]);
qdict_put_str(qdict, "port", tmp);
g_free(tmp);

Expand All @@ -855,12 +862,14 @@ void xemu_input_bind(int index, ControllerState *state, int save)
assert(dev);

// Unref for eventual cleanup
qobject_unref(usbhub_qdict);
object_unref(OBJECT(usbhub_dev));
if(usbhub_qdict != NULL)
qobject_unref(usbhub_qdict);
if(usbhub_dev != NULL)
object_unref(OBJECT(usbhub_dev));
qobject_unref(qdict);
object_unref(OBJECT(dev));

state->device = usbhub_dev;
state->device = hasInternalHub ? usbhub_dev : dev;
}
}

Expand All @@ -870,6 +879,9 @@ bool xemu_input_bind_xmu(int player_index, int expansion_slot_index,
assert(player_index >= 0 && player_index < 4);
assert(expansion_slot_index >= 0 && expansion_slot_index < 2);

bool hasInternalHub = strcmp(bound_drivers[player_index], DRIVER_STEEL_BATTALION) != 0;
assert(hasInternalHub);

ControllerState *player = bound_controllers[player_index];
enum peripheral_type peripheral_type =
player->peripheral_types[expansion_slot_index];
Expand Down Expand Up @@ -992,6 +1004,10 @@ void xemu_input_unbind_xmu(int player_index, int expansion_slot_index)

void xemu_input_rebind_xmu(int port)
{
bool hasInternalHub = strcmp(bound_drivers[port], DRIVER_STEEL_BATTALION) != 0;
if(!hasInternalHub)
return;

// Try to bind peripherals back to controller
for (int i = 0; i < 2; i++) {
enum peripheral_type peripheral_type =
Expand Down
269 changes: 136 additions & 133 deletions ui/xui/main-menu.cc
Original file line number Diff line number Diff line change
Expand Up @@ -321,165 +321,168 @@ void MainMenuInputView::Draw()
ImGui::SetCursorPos(pos);

if (bound_state) {
SectionTitle("Expansion Slots");
// Begin a 2-column layout to render the expansion slots
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing,
g_viewport_mgr.Scale(ImVec2(0, 12)));
ImGui::Columns(2, "mixed", false);

xmu_fbo->Target();
id = (ImTextureID)(intptr_t)xmu_fbo->Texture();

const char *img_file_filters = ".img Files\0*.img\0All Files\0*.*\0";
const char *comboLabels[2] = { "###ExpansionSlotA",
"###ExpansionSlotB" };
for (int i = 0; i < 2; i++) {
// Display a combo box to allow the user to choose the type of
// peripheral they want to use
enum peripheral_type selected_type =
bound_state->peripheral_types[i];
const char *peripheral_type_names[2] = { "None", "Memory Unit" };
const char *selected_peripheral_type =
peripheral_type_names[selected_type];
ImGui::SetNextItemWidth(-FLT_MIN);
if (ImGui::BeginCombo(comboLabels[i], selected_peripheral_type,
ImGuiComboFlags_NoArrowButton)) {
// Handle all available peripheral types
for (int j = 0; j < 2; j++) {
bool is_selected = selected_type == j;
ImGui::PushID(j);
const char *selectable_label = peripheral_type_names[j];

if (ImGui::Selectable(selectable_label, is_selected)) {
// Free any existing peripheral
if (bound_state->peripherals[i] != NULL) {
if (bound_state->peripheral_types[i] ==
PERIPHERAL_XMU) {
// Another peripheral was already bound.
// Unplugging
xemu_input_unbind_xmu(active, i);
bool hasInternalHub = strcmp(bound_drivers[active], DRIVER_STEEL_BATTALION) != 0;
if(hasInternalHub) {
SectionTitle("Expansion Slots");
// Begin a 2-column layout to render the expansion slots
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing,
g_viewport_mgr.Scale(ImVec2(0, 12)));
ImGui::Columns(2, "mixed", false);

xmu_fbo->Target();
id = (ImTextureID)(intptr_t)xmu_fbo->Texture();

const char *img_file_filters = ".img Files\0*.img\0All Files\0*.*\0";
const char *comboLabels[2] = { "###ExpansionSlotA",
"###ExpansionSlotB" };
for (int i = 0; i < 2; i++) {
// Display a combo box to allow the user to choose the type of
// peripheral they want to use
enum peripheral_type selected_type =
bound_state->peripheral_types[i];
const char *peripheral_type_names[2] = { "None", "Memory Unit" };
const char *selected_peripheral_type =
peripheral_type_names[selected_type];
ImGui::SetNextItemWidth(-FLT_MIN);
if (ImGui::BeginCombo(comboLabels[i], selected_peripheral_type,
ImGuiComboFlags_NoArrowButton)) {
// Handle all available peripheral types
for (int j = 0; j < 2; j++) {
bool is_selected = selected_type == j;
ImGui::PushID(j);
const char *selectable_label = peripheral_type_names[j];

if (ImGui::Selectable(selectable_label, is_selected)) {
// Free any existing peripheral
if (bound_state->peripherals[i] != NULL) {
if (bound_state->peripheral_types[i] ==
PERIPHERAL_XMU) {
// Another peripheral was already bound.
// Unplugging
xemu_input_unbind_xmu(active, i);
}

// Free the existing state
g_free((void *)bound_state->peripherals[i]);
bound_state->peripherals[i] = NULL;
}

// Free the existing state
g_free((void *)bound_state->peripherals[i]);
bound_state->peripherals[i] = NULL;
}
// Change the peripheral type to the newly selected type
bound_state->peripheral_types[i] =
(enum peripheral_type)j;

// Change the peripheral type to the newly selected type
bound_state->peripheral_types[i] =
(enum peripheral_type)j;
// Allocate state for the new peripheral
if (j == PERIPHERAL_XMU) {
bound_state->peripherals[i] =
g_malloc(sizeof(XmuState));
memset(bound_state->peripherals[i], 0,
sizeof(XmuState));
}

// Allocate state for the new peripheral
if (j == PERIPHERAL_XMU) {
bound_state->peripherals[i] =
g_malloc(sizeof(XmuState));
memset(bound_state->peripherals[i], 0,
sizeof(XmuState));
xemu_save_peripheral_settings(
active, i, bound_state->peripheral_types[i], NULL);
}

xemu_save_peripheral_settings(
active, i, bound_state->peripheral_types[i], NULL);
}
if (is_selected) {
ImGui::SetItemDefaultFocus();
}

if (is_selected) {
ImGui::SetItemDefaultFocus();
ImGui::PopID();
}

ImGui::PopID();
ImGui::EndCombo();
}
DrawComboChevron();

ImGui::EndCombo();
}
DrawComboChevron();
// Set an X offset to center the image button within the column
ImGui::SetCursorPosX(
ImGui::GetCursorPosX() +
(int)((ImGui::GetColumnWidth() -
xmu_w * g_viewport_mgr.m_scale -
2 * port_padding * g_viewport_mgr.m_scale) /
2));

// Set an X offset to center the image button within the column
ImGui::SetCursorPosX(
ImGui::GetCursorPosX() +
(int)((ImGui::GetColumnWidth() -
xmu_w * g_viewport_mgr.m_scale -
2 * port_padding * g_viewport_mgr.m_scale) /
2));
selected_type = bound_state->peripheral_types[i];
if (selected_type == PERIPHERAL_XMU) {
float x = xmu_x + i * xmu_x_stride;
float y = xmu_y;

selected_type = bound_state->peripheral_types[i];
if (selected_type == PERIPHERAL_XMU) {
float x = xmu_x + i * xmu_x_stride;
float y = xmu_y;
XmuState *xmu = (XmuState *)bound_state->peripherals[i];
if (xmu->filename != NULL && strlen(xmu->filename) > 0) {
RenderXmu(x, y, 0x81dc8a00, 0x0f0f0f00);

XmuState *xmu = (XmuState *)bound_state->peripherals[i];
if (xmu->filename != NULL && strlen(xmu->filename) > 0) {
RenderXmu(x, y, 0x81dc8a00, 0x0f0f0f00);
} else {
RenderXmu(x, y, 0x1f1f1f00, 0x0f0f0f00);
}

} else {
RenderXmu(x, y, 0x1f1f1f00, 0x0f0f0f00);
}
ImVec2 xmu_display_size;
if (ImGui::GetContentRegionMax().x <
xmu_h * g_viewport_mgr.m_scale) {
xmu_display_size.x = ImGui::GetContentRegionMax().x / 2;
xmu_display_size.y = xmu_display_size.x * xmu_h / xmu_w;
} else {
xmu_display_size = ImVec2(xmu_w * g_viewport_mgr.m_scale,
xmu_h * g_viewport_mgr.m_scale);
}

ImVec2 xmu_display_size;
if (ImGui::GetContentRegionMax().x <
xmu_h * g_viewport_mgr.m_scale) {
xmu_display_size.x = ImGui::GetContentRegionMax().x / 2;
xmu_display_size.y = xmu_display_size.x * xmu_h / xmu_w;
} else {
xmu_display_size = ImVec2(xmu_w * g_viewport_mgr.m_scale,
xmu_h * g_viewport_mgr.m_scale);
}
ImGui::SetCursorPosX(
ImGui::GetCursorPosX() +
(int)((ImGui::GetColumnWidth() - xmu_display_size.x) /
2.0));

ImGui::Image(id, xmu_display_size, ImVec2(0.5f * i, 1),
ImVec2(0.5f * (i + 1), 0));
ImVec2 pos = ImGui::GetCursorPos();

ImGui::SetCursorPos(pos);

// Button to generate a new XMU
ImGui::PushID(i);
if (ImGui::Button("New Image", ImVec2(250, 0))) {
int flags = NOC_FILE_DIALOG_SAVE |
NOC_FILE_DIALOG_OVERWRITE_CONFIRMATION;
const char *new_path = PausedFileOpen(
flags, img_file_filters, NULL, "xmu.img");

if (new_path) {
if (create_fatx_image(new_path, DEFAULT_XMU_SIZE)) {
// XMU was created successfully. Bind it
xemu_input_bind_xmu(active, i, new_path, false);
} else {
// Show alert message
char *msg = g_strdup_printf(
"Unable to create XMU image at %s", new_path);
xemu_queue_error_message(msg);
g_free(msg);
}
}
}

ImGui::SetCursorPosX(
ImGui::GetCursorPosX() +
(int)((ImGui::GetColumnWidth() - xmu_display_size.x) /
2.0));

ImGui::Image(id, xmu_display_size, ImVec2(0.5f * i, 1),
ImVec2(0.5f * (i + 1), 0));
ImVec2 pos = ImGui::GetCursorPos();

ImGui::SetCursorPos(pos);

// Button to generate a new XMU
ImGui::PushID(i);
if (ImGui::Button("New Image", ImVec2(250, 0))) {
int flags = NOC_FILE_DIALOG_SAVE |
NOC_FILE_DIALOG_OVERWRITE_CONFIRMATION;
const char *new_path = PausedFileOpen(
flags, img_file_filters, NULL, "xmu.img");

if (new_path) {
if (create_fatx_image(new_path, DEFAULT_XMU_SIZE)) {
// XMU was created successfully. Bind it
xemu_input_bind_xmu(active, i, new_path, false);
const char *xmu_port_path = NULL;
if (xmu->filename == NULL)
xmu_port_path = g_strdup("");
else
xmu_port_path = g_strdup(xmu->filename);
if (FilePicker("Image", &xmu_port_path, img_file_filters)) {
if (strlen(xmu_port_path) == 0) {
xemu_input_unbind_xmu(active, i);
} else {
// Show alert message
char *msg = g_strdup_printf(
"Unable to create XMU image at %s", new_path);
xemu_queue_error_message(msg);
g_free(msg);
xemu_input_bind_xmu(active, i, xmu_port_path, false);
}
}
}
g_free((void *)xmu_port_path);

const char *xmu_port_path = NULL;
if (xmu->filename == NULL)
xmu_port_path = g_strdup("");
else
xmu_port_path = g_strdup(xmu->filename);
if (FilePicker("Image", &xmu_port_path, img_file_filters)) {
if (strlen(xmu_port_path) == 0) {
xemu_input_unbind_xmu(active, i);
} else {
xemu_input_bind_xmu(active, i, xmu_port_path, false);
}
ImGui::PopID();
}
g_free((void *)xmu_port_path);

ImGui::PopID();
ImGui::NextColumn();
}

ImGui::NextColumn();
}

xmu_fbo->Restore();
xmu_fbo->Restore();

ImGui::PopStyleVar(); // ItemSpacing
ImGui::Columns(1);
ImGui::PopStyleVar(); // ItemSpacing
ImGui::Columns(1);
}
}

SectionTitle("Options");
Expand Down

0 comments on commit 0699999

Please sign in to comment.