diff --git a/rpcs3/Emu/Io/KeyboardHandler.h b/rpcs3/Emu/Io/KeyboardHandler.h index 44bd2bdfcf..463ae9516a 100644 --- a/rpcs3/Emu/Io/KeyboardHandler.h +++ b/rpcs3/Emu/Io/KeyboardHandler.h @@ -16,8 +16,17 @@ enum CellKbReadMode enum CellKbCodeType { - CELL_KB_CODETYPE_RAW = 0, - CELL_KB_CODETYPE_ASCII = 1, + CELL_KB_CODETYPE_RAW = 0, + CELL_KB_CODETYPE_ASCII = 1, +}; + +enum KbLedCodes +{ + CELL_KB_LED_NUM_LOCK = 0x00000001, + CELL_KB_LED_CAPS_LOCK = 0x00000002, + CELL_KB_LED_SCROLL_LOCK = 0x00000004, + CELL_KB_LED_COMPOSE = 0x00000008, + CELL_KB_LED_KANA = 0x00000016, }; enum KbMetaKeys @@ -203,7 +212,7 @@ struct CellKbData : led(0) , mkey(0) , len(0) - { + { // (TODO: Set initial state of led) } }; @@ -226,11 +235,9 @@ struct KbButton u32 m_keyCode; u32 m_outKeyCode; bool m_pressed; - //bool m_flush; KbButton(u32 keyCode, u32 outKeyCode) : m_pressed(false) - //, m_flush(false) , m_keyCode(keyCode) , m_outKeyCode(outKeyCode) { @@ -276,17 +283,40 @@ public: if (pressed) { - u16 kcode; - if (config.code_type == CELL_KB_CODETYPE_RAW) - { - kcode = button.m_outKeyCode; + + if (code == 308 || code == 307 || code == 306 || + code == 393 || code == 396 || code == 394) + { // Meta Keys + data.mkey |= button.m_outKeyCode; } - else //config.code_type == CELL_KB_CODETYPE_ASCII + else { - kcode = cellKbCnvRawCode(config.arrange, data.mkey, data.led, button.m_outKeyCode); + // Led Keys + if (code == 364) data.led ^= CELL_KB_LED_NUM_LOCK; + if (code == 311) data.led ^= CELL_KB_LED_CAPS_LOCK; + if (code == 365) data.led ^= CELL_KB_LED_SCROLL_LOCK; + + u16 kcode; + if (config.code_type == CELL_KB_CODETYPE_RAW) + { + kcode = button.m_outKeyCode; + } + else //config.code_type == CELL_KB_CODETYPE_ASCII + { + kcode = cellKbCnvRawCode(config.arrange, data.mkey, data.led, button.m_outKeyCode); + } + data.keycode[data.len % CELL_KB_MAX_KEYCODES] = kcode; + data.len++; + } + } + + if (!pressed) + { + if (code == 308 || code == 307 || code == 306 || + code == 393 || code == 396 || code == 394) + { // Meta Keys + data.mkey &= ~button.m_outKeyCode; } - data.keycode[data.len % CELL_KB_MAX_KEYCODES] = kcode; - data.len++; } } diff --git a/rpcs3/Emu/Io/Null/NullKeyboardHandler.h b/rpcs3/Emu/Io/Null/NullKeyboardHandler.h index d5693a78cc..4a9598a71e 100644 --- a/rpcs3/Emu/Io/Null/NullKeyboardHandler.h +++ b/rpcs3/Emu/Io/Null/NullKeyboardHandler.h @@ -14,6 +14,10 @@ public: memset(&m_info, 0, sizeof(KbInfo)); m_info.max_connect = max_connect; m_keyboards.Clear(); + for(u32 i=0; i> 7; - current_info.SColorResolution = (packedField >> 4) & 7; + current_info.SColorResolution = ((packedField >> 4) & 7)+1; current_info.SSortFlag = (packedField >> 3) & 1; - current_info.SSizeOfGlobalColorTable = packedField & 7; + current_info.SSizeOfGlobalColorTable = (packedField & 7)+1; current_info.SBackGroundColor = Memory.Read8(buffer+11); current_info.SPixelAspectRatio = Memory.Read8(buffer+12); @@ -171,6 +171,9 @@ int cellGifDecDecodeData(u32 mainHandle, u32 subHandle, u32 data_addr, u32 dataC } Memory.Free(buffer); + //The output data is an image (dataOutInfo.recordType = 1) + Memory.Write32(dataOutInfo_addr, 1); + return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/Modules/cellJpgDec.cpp b/rpcs3/Emu/SysCalls/Modules/cellJpgDec.cpp index d8bac54859..05eeaf7f04 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellJpgDec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellJpgDec.cpp @@ -21,6 +21,19 @@ enum CELL_JPGDEC_ERROR_CB_PARAM = 0x80611109, }; +enum CellJpgDecColorSpace +{ + CELL_JPG_UNKNOWN = 0, + CELL_JPG_GRAYSCALE = 1, + CELL_JPG_RGB = 2, + CELL_JPG_YCbCr = 3, + CELL_JPG_RGBA = 10, + CELL_JPG_UPSAMPLE_ONLY = 11, + CELL_JPG_ARGB = 20, + CELL_JPG_GRAYSCALE_TO_ALPHA_RGBA = 40, + CELL_JPG_GRAYSCALE_TO_ALPHA_ARGB = 41, +}; + struct CellJpgDecInfo { u32 imageWidth; @@ -40,6 +53,36 @@ struct CellJpgDecSrc u32 spuThreadEnable; // CellJpgDecSpuThreadEna }; +struct CellJpgDecInParam +{ + u32 *commandPtr; + u32 downScale; + u32 method; // CellJpgDecMethod + u32 outputMode; // CellJpgDecOutputMode + u32 outputColorSpace; // CellJpgDecColorSpace + u8 outputColorAlpha; + u8 reserved[3]; +}; + +struct CellJpgDecOutParam +{ + u64 outputWidthByte; + u32 outputWidth; + u32 outputHeight; + u32 outputComponents; + u32 outputMode; // CellJpgDecOutputMode + u32 outputColorSpace; // CellJpgDecColorSpace + u32 downScale; + u32 useMemorySpace; +}; + +struct CellJpgDecSubHandle //Custom struct +{ + u32 fd; + u64 fileSize; + CellJpgDecInParam inParam; +}; + CellJpgDecInfo current_info; CellJpgDecSrc current_src; @@ -72,30 +115,39 @@ int cellJpgDecOpen(u32 mainHandle, u32 subHandle_addr, u32 src_addr, u32 openInf //current_src.streamSize = Memory.Read32(src_addr+20); //current_src.spuThreadEnable = Memory.Read32(src_addr+24); - u32& fd_addr = subHandle_addr; // Set file descriptor as sub handler of the decoder + CellJpgDecSubHandle *subHandle = new CellJpgDecSubHandle; + + // Get file descriptor + u32 fd_addr = Memory.Alloc(sizeof(u32), 1); int ret = cellFsOpen(current_src.fileName, 0, fd_addr, NULL, 0); + subHandle->fd = Memory.Read32(fd_addr); + Memory.Free(fd_addr); if(ret != 0) return CELL_JPGDEC_ERROR_OPEN_FILE; + // Get size of file + u32 sb_addr = Memory.Alloc(52,1); // Alloc a CellFsStat struct + cellFsFstat(subHandle->fd, sb_addr); + subHandle->fileSize = Memory.Read64(sb_addr+36); // Get CellFsStat.st_size + Memory.Free(sb_addr); + + // From now, every u32 subHandle argument is a pointer to a CellPngDecSubHandle struct. + Memory.Write32(subHandle_addr, (u32)subHandle); + return CELL_OK; } int cellJpgDecClose(u32 mainHandle, u32 subHandle) { - u32& fd = subHandle; - cellFsClose(fd); + cellFsClose( ((CellJpgDecSubHandle*)subHandle)->fd ); + delete (CellJpgDecSubHandle*)subHandle; return CELL_OK; } int cellJpgDecReadHeader(u32 mainHandle, u32 subHandle, u32 info_addr) { - u32& fd = subHandle; - - //Get size of file - u32 sb_addr = Memory.Alloc(52,1); // Alloc a CellFsStat struct - cellFsFstat(fd, sb_addr); - u64 fileSize = Memory.Read64(sb_addr+36); // Get CellFsStat.st_size - Memory.Free(sb_addr); + const u32& fd = ((CellJpgDecSubHandle*)subHandle)->fd; + const u64& fileSize = ((CellJpgDecSubHandle*)subHandle)->fileSize; //Copy the JPG file to a buffer u32 buffer = Memory.Alloc(fileSize,1); @@ -134,7 +186,7 @@ int cellJpgDecReadHeader(u32 mainHandle, u32 subHandle, u32 info_addr) current_info.imageWidth = Memory.Read8(buffer+i+7)*256 + Memory.Read8(buffer+i+8); current_info.imageHeight = Memory.Read8(buffer+i+5)*256 + Memory.Read8(buffer+i+6); current_info.numComponents = 0; // Unimplemented - current_info.colorSpace = 0; // Unimplemented + current_info.colorSpace = 3; // Unimplemented mem_class_t info(info_addr); info += current_info.imageWidth; @@ -148,13 +200,9 @@ int cellJpgDecReadHeader(u32 mainHandle, u32 subHandle, u32 info_addr) int cellJpgDecDecodeData(u32 mainHandle, u32 subHandle, u32 data_addr, u32 dataCtrlParam_addr, u32 dataOutInfo_addr) { - u32& fd = subHandle; - - //Get size of file - u32 sb_addr = Memory.Alloc(52,1); // Alloc a CellFsStat struct - cellFsFstat(fd, sb_addr); - u64 fileSize = Memory.Read64(sb_addr+36); // Get CellFsStat.st_size - Memory.Free(sb_addr); + const u32& fd = ((CellJpgDecSubHandle*)subHandle)->fd; + const u64& fileSize = ((CellJpgDecSubHandle*)subHandle)->fileSize; + const CellJpgDecInParam& inParam = ((CellJpgDecSubHandle*)subHandle)->inParam; // (TODO: We should use the outParam) //Copy the JPG file to a buffer u32 buffer = Memory.Alloc(fileSize,1); @@ -177,20 +225,34 @@ int cellJpgDecDecodeData(u32 mainHandle, u32 subHandle, u32 data_addr, u32 dataC return CELL_JPGDEC_ERROR_STREAM_FORMAT; } u32 image_size = width * height * 4; - for(u32 i = 0; i < image_size; i+=4){ - Memory.Write8(data_addr+i+0, image[i+3]); - Memory.Write8(data_addr+i+1, image[i+0]); - Memory.Write8(data_addr+i+2, image[i+1]); - Memory.Write8(data_addr+i+3, image[i+2]); + if (inParam.outputColorSpace == CELL_JPG_RGBA){ + for(u32 i = 0; i < image_size; i+=4){ + Memory.Write8(data_addr+i+0, image[i+0]); + Memory.Write8(data_addr+i+1, image[i+1]); + Memory.Write8(data_addr+i+2, image[i+2]); + Memory.Write8(data_addr+i+3, image[i+3]); + } + } + else if (inParam.outputColorSpace == CELL_JPG_ARGB){ + for(u32 i = 0; i < image_size; i+=4){ + Memory.Write8(data_addr+i+0, image[i+3]); + Memory.Write8(data_addr+i+1, image[i+0]); + Memory.Write8(data_addr+i+2, image[i+1]); + Memory.Write8(data_addr+i+3, image[i+2]); + } } Memory.Free(buffer); return CELL_OK; } -int cellJpgDecSetParameter(u32 mainHandle, u32 subHandle, u32 inParam, u32 outParam) +int cellJpgDecSetParameter(u32 mainHandle, u32 subHandle, u32 inParam_addr, u32 outParam_addr) { - UNIMPLEMENTED_FUNC(cellJpgDec); + CellJpgDecInParam& inParam = ((CellJpgDecSubHandle*)subHandle)->inParam; + inParam.outputColorSpace = Memory.Read32(inParam_addr+16); + + // (TODO) + return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/Modules/cellPngDec.cpp b/rpcs3/Emu/SysCalls/Modules/cellPngDec.cpp index 70659c9fed..d260312d8f 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellPngDec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellPngDec.cpp @@ -22,6 +22,16 @@ enum CELL_PNGDEC_ERROR_CB_PARAM = 0x8061120a, }; +enum CellPngDecColorSpace +{ + CELL_PNGDEC_GRAYSCALE = 1, + CELL_PNGDEC_RGB = 2, + CELL_PNGDEC_PALETTE = 4, + CELL_PNGDEC_GRAYSCALE_ALPHA = 9, + CELL_PNGDEC_RGBA = 10, + CELL_PNGDEC_ARGB = 20, +}; + struct CellPngDecInfo { u32 imageWidth; @@ -44,6 +54,36 @@ struct CellPngDecSrc u32 spuThreadEnable; // CellPngDecSpuThreadEna }; +struct CellPngDecInParam +{ + u32 *commandPtr; + u32 outputMode; // CellPngDecOutputMode + u32 outputColorSpace; // CellPngDecColorSpace + u32 outputBitDepth; + u32 outputPackFlag; // CellPngDecPackFlag + u32 outputAlphaSelect; // CellPngDecAlphaSelect + u32 outputColorAlpha; +}; + +struct CellPngDecOutParam +{ + u64 outputWidthByte; + u32 outputWidth; + u32 outputHeight; + u32 outputComponents; + u32 outputBitDepth; + u32 outputMode; // CellPngDecOutputMode + u32 outputColorSpace; // CellPngDecColorSpace + u32 useMemorySpace; +}; + +struct CellPngDecSubHandle //Custom struct +{ + u32 fd; + u64 fileSize; + CellPngDecInParam inParam; +}; + CellPngDecInfo current_info; CellPngDecSrc current_src; @@ -70,30 +110,41 @@ int cellPngDecOpen(u32 mainHandle, u32 subHandle_addr, u32 src_addr, u32 openInf //current_src.streamSize = Memory.Read32(src_addr+20); //current_src.spuThreadEnable = Memory.Read32(src_addr+24); - u32& fd_addr = subHandle_addr; // Set file descriptor as sub handler of the decoder + CellPngDecSubHandle *subHandle = new CellPngDecSubHandle; + + // Get file descriptor + u32 fd_addr = Memory.Alloc(sizeof(u32), 1); int ret = cellFsOpen(current_src.fileName, 0, fd_addr, NULL, 0); + subHandle->fd = Memory.Read32(fd_addr); + Memory.Free(fd_addr); if(ret != 0) return CELL_PNGDEC_ERROR_OPEN_FILE; + // Get size of file + u32 sb_addr = Memory.Alloc(52,1); // Alloc a CellFsStat struct + cellFsFstat(subHandle->fd, sb_addr); + subHandle->fileSize = Memory.Read64(sb_addr+36); // Get CellFsStat.st_size + Memory.Free(sb_addr); + + // From now, every u32 subHandle argument is a pointer to a CellPngDecSubHandle struct. + Memory.Write32(subHandle_addr, (u32)subHandle); + return CELL_OK; } int cellPngDecClose(u32 mainHandle, u32 subHandle) { - u32& fd = subHandle; - cellFsClose(fd); + cellFsClose( ((CellPngDecSubHandle*)subHandle)->fd ); + delete (CellPngDecSubHandle*)subHandle; return CELL_OK; } int cellPngDecReadHeader(u32 mainHandle, u32 subHandle, u32 info_addr) { - u32& fd = subHandle; + const u32& fd = ((CellPngDecSubHandle*)subHandle)->fd; + const u64& fileSize = ((CellPngDecSubHandle*)subHandle)->fileSize; //Check size of file - u32 sb_addr = Memory.Alloc(52,1); // Alloc a CellFsStat struct - cellFsFstat(fd, sb_addr); - u64 fileSize = Memory.Read64(sb_addr+36); // Get CellFsStat.st_size - Memory.Free(sb_addr); if(fileSize < 29) return CELL_PNGDEC_ERROR_HEADER; // Error: The file is smaller than the length of a PNG header //Write the header to buffer @@ -134,17 +185,13 @@ int cellPngDecReadHeader(u32 mainHandle, u32 subHandle, u32 info_addr) int cellPngDecDecodeData(u32 mainHandle, u32 subHandle, u32 data_addr, u32 dataCtrlParam_addr, u32 dataOutInfo_addr) { - u32& fd = subHandle; - - //Get size of file - u32 sb_addr = Memory.Alloc(52,1); // Alloc a CellFsStat struct - cellFsFstat(fd, sb_addr); - u64 fileSize = Memory.Read64(sb_addr+36); // Get CellFsStat.st_size - Memory.Free(sb_addr); + const u32& fd = ((CellPngDecSubHandle*)subHandle)->fd; + const u64& fileSize = ((CellPngDecSubHandle*)subHandle)->fileSize; + const CellPngDecInParam& inParam = ((CellPngDecSubHandle*)subHandle)->inParam; // (TODO: We should use the outParam) //Copy the PNG file to a buffer u32 buffer = Memory.Alloc(fileSize,1); - u32 pos_addr = Memory.Alloc(8,1); + u32 pos_addr = Memory.Alloc(sizeof(u64),1); cellFsLseek(fd, 0, 0, pos_addr); cellFsRead(fd, buffer, fileSize, NULL); Memory.Free(pos_addr); @@ -163,20 +210,34 @@ int cellPngDecDecodeData(u32 mainHandle, u32 subHandle, u32 data_addr, u32 dataC return CELL_PNGDEC_ERROR_STREAM_FORMAT; } u32 image_size = width * height * 4; - for(u32 i = 0; i < image_size; i+=4){ - Memory.Write8(data_addr+i+0, image[i+3]); - Memory.Write8(data_addr+i+1, image[i+0]); - Memory.Write8(data_addr+i+2, image[i+1]); - Memory.Write8(data_addr+i+3, image[i+2]); + if (inParam.outputColorSpace == CELL_PNGDEC_RGBA){ + for(u32 i = 0; i < image_size; i+=4){ + Memory.Write8(data_addr+i+0, image[i+0]); + Memory.Write8(data_addr+i+1, image[i+1]); + Memory.Write8(data_addr+i+2, image[i+2]); + Memory.Write8(data_addr+i+3, image[i+3]); + } + } + else if (inParam.outputColorSpace == CELL_PNGDEC_ARGB){ + for(u32 i = 0; i < image_size; i+=4){ + Memory.Write8(data_addr+i+0, image[i+3]); + Memory.Write8(data_addr+i+1, image[i+0]); + Memory.Write8(data_addr+i+2, image[i+1]); + Memory.Write8(data_addr+i+3, image[i+2]); + } } Memory.Free(buffer); return CELL_OK; } -int cellPngDecSetParameter(u32 mainHandle, u32 subHandle, u32 inParam, u32 outParam) +int cellPngDecSetParameter(u32 mainHandle, u32 subHandle, u32 inParam_addr, u32 outParam_addr) { - UNIMPLEMENTED_FUNC(cellPngDec); + CellPngDecInParam& inParam = ((CellPngDecSubHandle*)subHandle)->inParam; + inParam.outputColorSpace = Memory.Read32(inParam_addr+8); + + // (TODO) + return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Keyboard.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Keyboard.cpp index 90073fe946..f01e368e91 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Keyboard.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Keyboard.cpp @@ -68,7 +68,14 @@ u16 cellKbCnvRawCode(u32 arrange, u32 mkey, u32 led, u16 rawcode) if (rawcode == 0x58) return 0x0A | 0x4000; // '\n' // ASCII - if (rawcode >= 0x04 && rawcode <= 0x1D) return rawcode + 0x3D; // 'A' - 'Z' + if (rawcode >= 0x04 && rawcode <= 0x1D) // 'A' - 'Z' + { + rawcode -= + (mkey&(CELL_KB_MKEY_L_SHIFT|CELL_KB_MKEY_R_SHIFT)) ? + ((led&(CELL_KB_LED_CAPS_LOCK)) ? 0 : 0x20) : + ((led&(CELL_KB_LED_CAPS_LOCK)) ? 0x20 : 0); + return rawcode + 0x5D; + } if (rawcode >= 0x1E && rawcode <= 0x26) return rawcode + 0x13; // '1' - '9' if (rawcode == 0x27) return 0x30; // '0' if (rawcode == 0x28) return 0x0A; // '\n' @@ -76,6 +83,10 @@ u16 cellKbCnvRawCode(u32 arrange, u32 mkey, u32 led, u16 rawcode) if (rawcode == 0x2C) return 0x20; // ' ' if (rawcode == 0x2D) return 0x2D; // '-' if (rawcode == 0x2E) return 0x3D; // '=' + if (rawcode == 0x36) return 0x2C; // ',' + if (rawcode == 0x37) return 0x2E; // '.' + if (rawcode == 0x38) return 0x2F; // '/' + if (rawcode == 0x87) return 0x5C; // '\' // (TODO: Add more cases) diff --git a/rpcs3/Gui/MainFrame.cpp b/rpcs3/Gui/MainFrame.cpp index 063681289a..ad555891f6 100644 --- a/rpcs3/Gui/MainFrame.cpp +++ b/rpcs3/Gui/MainFrame.cpp @@ -274,7 +274,9 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event)) wxDialog diag(this, wxID_ANY, "Settings", wxDefaultPosition); - wxBoxSizer* s_panel(new wxBoxSizer(wxVERTICAL)); + wxBoxSizer* s_panel(new wxBoxSizer(wxHORIZONTAL)); + wxBoxSizer* s_subpanel1(new wxBoxSizer(wxVERTICAL)); + wxBoxSizer* s_subpanel2(new wxBoxSizer(wxVERTICAL)); wxStaticBoxSizer* s_round_cpu( new wxStaticBoxSizer( wxVERTICAL, &diag, _("CPU") ) ); wxStaticBoxSizer* s_round_cpu_decoder( new wxStaticBoxSizer( wxVERTICAL, &diag, _("Decoder") ) ); @@ -284,7 +286,7 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event)) wxStaticBoxSizer* s_round_gs_res( new wxStaticBoxSizer( wxVERTICAL, &diag, _("Default resolution") ) ); wxStaticBoxSizer* s_round_gs_aspect( new wxStaticBoxSizer( wxVERTICAL, &diag, _("Default aspect ratio") ) ); - wxStaticBoxSizer* s_round_pad( new wxStaticBoxSizer( wxVERTICAL, &diag, _("IO") ) ); + wxStaticBoxSizer* s_round_io( new wxStaticBoxSizer( wxVERTICAL, &diag, _("IO") ) ); wxStaticBoxSizer* s_round_pad_handler( new wxStaticBoxSizer( wxVERTICAL, &diag, _("Pad Handler") ) ); wxStaticBoxSizer* s_round_keyboard_handler( new wxStaticBoxSizer( wxVERTICAL, &diag, _("Keyboard Handler") ) ); @@ -343,8 +345,8 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event)) s_round_pad_handler->Add(cbox_pad_handler, wxSizerFlags().Border(wxALL, 5).Expand()); s_round_keyboard_handler->Add(cbox_keyboard_handler, wxSizerFlags().Border(wxALL, 5).Expand()); - s_round_pad->Add(s_round_pad_handler, wxSizerFlags().Border(wxALL, 5).Expand()); - s_round_pad->Add(s_round_keyboard_handler, wxSizerFlags().Border(wxALL, 5).Expand()); + s_round_io->Add(s_round_pad_handler, wxSizerFlags().Border(wxALL, 5).Expand()); + s_round_io->Add(s_round_keyboard_handler, wxSizerFlags().Border(wxALL, 5).Expand()); wxBoxSizer* s_b_panel(new wxBoxSizer(wxHORIZONTAL)); @@ -353,10 +355,14 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event)) //wxBoxSizer* s_conf_panel(new wxBoxSizer(wxHORIZONTAL)); - s_panel->Add(s_round_cpu, wxSizerFlags().Border(wxALL, 5).Expand()); - s_panel->Add(s_round_gs, wxSizerFlags().Border(wxALL, 5).Expand()); - s_panel->Add(s_round_pad, wxSizerFlags().Border(wxALL, 5).Expand()); - s_panel->Add(s_b_panel, wxSizerFlags().Border(wxALL, 8).Expand()); + s_subpanel1->Add(s_round_cpu, wxSizerFlags().Border(wxALL, 5).Expand()); + s_subpanel1->Add(s_round_gs, wxSizerFlags().Border(wxALL, 5).Expand()); + s_subpanel2->Add(s_round_io, wxSizerFlags().Border(wxALL, 5).Expand()); + s_subpanel1->Add(s_b_panel, wxSizerFlags().Border(wxALL, 8).Expand()); + + s_subpanel2->AddSpacer(200); + s_panel->Add(s_subpanel1, wxSizerFlags().Border(wxALL, 5).Expand()); + s_panel->Add(s_subpanel2, wxSizerFlags().Border(wxALL, 5).Expand()); diag.SetSizerAndFit( s_panel );