Merge remote-tracking branch 'origin/master' into cdrom_changes
This commit is contained in:
@@ -89,11 +89,7 @@ add_library(ui STATIC
|
||||
qt_hardwarerenderer.hpp
|
||||
qt_openglrenderer.cpp
|
||||
qt_openglrenderer.hpp
|
||||
qt_opengloptions.cpp
|
||||
qt_opengloptions.hpp
|
||||
qt_opengloptionsdialog.cpp
|
||||
qt_opengloptionsdialog.hpp
|
||||
qt_opengloptionsdialog.ui
|
||||
qt_glsl_parser.cpp
|
||||
|
||||
qt_settings.cpp
|
||||
qt_settings.hpp
|
||||
@@ -190,6 +186,14 @@ add_library(ui STATIC
|
||||
|
||||
../qt_resources.qrc
|
||||
./qdarkstyle/dark/darkstyle.qrc
|
||||
|
||||
qt_openglshadermanagerdialog.hpp
|
||||
qt_openglshadermanagerdialog.cpp
|
||||
qt_openglshadermanagerdialog.ui
|
||||
|
||||
qt_openglshaderconfig.hpp
|
||||
qt_openglshaderconfig.cpp
|
||||
qt_openglshaderconfig.ui
|
||||
)
|
||||
|
||||
if(RTMIDI)
|
||||
|
||||
@@ -682,10 +682,10 @@ msgid "Surface images"
|
||||
msgstr "Ảnh bề mặt"
|
||||
|
||||
msgid "Machine \"%hs\" is not available due to missing ROMs in the roms/machines directory. Switching to an available machine."
|
||||
msgstr "Mẫu máy \"%hs\" không giả lập được do thiếu file ROM tương ứng trong mục roms/machines. Hãy chọn mẫu máy khác."
|
||||
msgstr "Mẫu máy \"%hs\" không giả lập được do thiếu file ROM tương ứng trong thư mục roms/machines. Hãy chọn mẫu máy khác."
|
||||
|
||||
msgid "Video card \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card."
|
||||
msgstr "Card đồ họa \"%hs\" không giả lập được do thiếu file ROM tương ứng trong mục roms/video. Hãy chọn card đồ họa khác."
|
||||
msgstr "Card đồ họa \"%hs\" không giả lập được do thiếu file ROM tương ứng trong thư mục roms/video. Hãy chọn card đồ họa khác."
|
||||
|
||||
msgid "Video card #2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Disabling the second video card."
|
||||
msgstr "Card đồ họa 2 \"%hs\" không giả lập được do thiếu file ROM tương ứng trong mục roms/video. Vô hiệu hóa card đồ họa thứ hai."
|
||||
@@ -1219,7 +1219,7 @@ msgid "Development of the WinBox manager stopped in 2022 due to a lack of mainta
|
||||
msgstr "Trình quản lý phiên WinBox đã bị dừng phát triển năm 2022 do thiếu nhân sự duy trì. Vì những quyết định để cho 86Box trở nên tốt hơn, chúng tôi đã không còn hỗ trợ trình quản lý WinBox.\n\n Sẽ không có bản cập nhật mới cho WinBox nữa, và nếu bạn tiếp tục sử dụng với các bản 86Box mới hơn có thể gặp lỗi. Bất kì các bản bug report liên quan đến lỗi của WinBox sẽ bị coi là không hợp lệ và bị đóng.\n\nTruy cập 86Box.net để tìm qua các trình quản lý phiên/manager khác cho phù hợp."
|
||||
|
||||
msgid "Generate"
|
||||
msgstr "Phát ra"
|
||||
msgstr "Tạo"
|
||||
|
||||
msgid "Joystick configuration"
|
||||
msgstr "Cấu hình cần điều khiển"
|
||||
@@ -1240,7 +1240,7 @@ msgid "List of MCA devices:"
|
||||
msgstr "Danh sách các thiết bị MCA:"
|
||||
|
||||
msgid "Tablet tool"
|
||||
msgstr "Công cụ máy tính bảng"
|
||||
msgstr "Công cụ bảng nhập liệu"
|
||||
|
||||
msgid "Qt (OpenGL &ES)"
|
||||
msgstr "QT (OpenGL &ES)"
|
||||
@@ -1264,19 +1264,19 @@ msgid "Cursor/Puck"
|
||||
msgstr "Con trỏ/puck"
|
||||
|
||||
msgid "Pen"
|
||||
msgstr "Cái bút"
|
||||
msgstr "Bút"
|
||||
|
||||
msgid "Host CD/DVD Drive (%1:)"
|
||||
msgstr "Máy chủ CD/DVD ổ đĩa (%1 :)"
|
||||
|
||||
msgid "&Connected"
|
||||
msgstr "& Kết nối"
|
||||
msgstr "&Đã kết nối"
|
||||
|
||||
msgid "Clear image history"
|
||||
msgstr "Xóa lịch sử ảnh đĩa"
|
||||
|
||||
msgid "Create..."
|
||||
msgstr "Tạo nên..."
|
||||
msgstr "Tạo..."
|
||||
|
||||
msgid "previous image"
|
||||
msgstr "đĩa trước đó"
|
||||
@@ -1309,7 +1309,7 @@ msgid "OpenGL 3.0 renderer options"
|
||||
msgstr "Tùy chọn kết xuất OpenGL 3.0"
|
||||
|
||||
msgid "Render behavior"
|
||||
msgstr "Hiện ra hành vi"
|
||||
msgstr "Hành vi kết xuất"
|
||||
|
||||
msgid "Use target framerate:"
|
||||
msgstr "Dùng số khung hình mục tiêu:"
|
||||
@@ -1321,16 +1321,16 @@ msgid "VSync"
|
||||
msgstr "Vsync"
|
||||
|
||||
msgid "<html><head/><body><p>Render each frame immediately, in sync with the emulated display.</p><p><span style=" font-style:italic;">This is the recommended option if the shaders in use don't utilize frametime for animated effects.</span></p></body></html>"
|
||||
msgstr "<html><head/><body><p>Kết xuất mỗi khung ngay lập tức, đồng bộ với màn hình mô phỏng.</p><p><span style=" font-style:italic;">Đây là tùy chọn được đề xuất nếu các shader đang sử dụng không sử dụng hình chữ nhật cho các hiệu ứng hoạt hình.</span></p></body></html>"
|
||||
msgstr "<html><head/><body><p>Kết xuất mỗi khung ngay lập tức, đồng bộ với màn hình mô phỏng.</p><p><span style=" font-style:italic;">Đây là tùy chọn được đề xuất nếu các shader đang sử dụng không tối ưu frametime cho các hiệu ứng động.</span></p></body></html>"
|
||||
|
||||
msgid "Synchronize with video"
|
||||
msgstr "Đồng bộ hóa với video"
|
||||
msgstr "Đồng bộ với video"
|
||||
|
||||
msgid "Shaders"
|
||||
msgstr "Shaders"
|
||||
|
||||
msgid "Remove"
|
||||
msgstr "Di dời"
|
||||
msgstr "Loại bỏ"
|
||||
|
||||
msgid "No shader selected"
|
||||
msgstr "Không có shader được chọn"
|
||||
@@ -1363,19 +1363,19 @@ msgid "Error initializing OpenGL"
|
||||
msgstr "Lỗi khởi tạo OpenGL"
|
||||
|
||||
msgid "Falling back to software rendering.\n"
|
||||
msgstr "Rơi trở lại kết xuất phần mềm.\n"
|
||||
msgstr "Quay trở lại kết xuất phần mềm.\n"
|
||||
|
||||
msgid "Allocating memory for unpack buffer failed.\n"
|
||||
msgstr "Phân bổ bộ nhớ cho bộ đệm giải nén không thành công.\n"
|
||||
|
||||
msgid "<html><head/><body><p>When selecting media images (CD-ROM, floppy, etc.) the open dialog will start in the same directory as the 86Box configuration file. This setting will likely only make a difference on macOS.</p></body></html>"
|
||||
msgstr "<html><head/><body><p>Khi chọn hình ảnh phương tiện (CD-ROM, FLOPPY, v.v.), hộp thoại mở sẽ bắt đầu trong cùng thư mục với tệp cấu hình 86box. Cài đặt này có thể sẽ chỉ tạo ra sự khác biệt trên macOS.</p></body></html>"
|
||||
msgstr "<html><head/><body><p>Khi chọn hình ảnh phương tiện (CD-ROM, ổ mềm, v.v.), hộp thoại mở sẽ bắt đầu trong cùng thư mục với tệp cấu hình 86box. Cài đặt này có thể sẽ chỉ tạo ra sự khác biệt trên macOS.</p></body></html>"
|
||||
|
||||
msgid "This machine might have been moved or copied."
|
||||
msgstr "Máy này có thể đã được di chuyển hoặc sao chép."
|
||||
msgstr "Cấu hình máy này có thể đã được di chuyển hoặc sao chép."
|
||||
|
||||
msgid "In order to ensure proper networking functionality, 86Box needs to know if this machine was moved or copied.\n\nSelect \"I Copied It\" if you are not sure."
|
||||
msgstr "Để đảm bảo chức năng kết nối mạng thích hợp, 86box cần biết liệu máy này có được di chuyển hay sao chép không.\n\nNếu bạn không chắc chắn, chọn \"Tôi đã sao chép nó\"."
|
||||
msgstr "Để đảm bảo chức năng kết nối mạng thích hợp, 86Box cần biết liệu máy này có được di chuyển hay sao chép không.\n\nNếu bạn không chắc chắn, chọn \"Tôi đã sao chép nó\"."
|
||||
|
||||
msgid "I Moved It"
|
||||
msgstr "Tôi đã di chuyển nó"
|
||||
@@ -1390,7 +1390,7 @@ msgid "No MCA devices."
|
||||
msgstr "Không có thiết bị MCA."
|
||||
|
||||
msgid "MiB"
|
||||
msgstr "Mib"
|
||||
msgstr "MiB"
|
||||
|
||||
msgid "Network Card #1"
|
||||
msgstr "Thẻ mạng 1"
|
||||
@@ -1405,7 +1405,7 @@ msgid "Network Card #4"
|
||||
msgstr "Thẻ mạng 4"
|
||||
|
||||
msgid "Mode"
|
||||
msgstr "Cách thức"
|
||||
msgstr "Chế độ"
|
||||
|
||||
msgid "Interface"
|
||||
msgstr "Giao diện"
|
||||
@@ -1417,7 +1417,7 @@ msgid "VDE Socket"
|
||||
msgstr "Ổ cắm VDE"
|
||||
|
||||
msgid "86Box Unit Tester"
|
||||
msgstr "Người kiểm tra đơn vị 86box"
|
||||
msgstr "Trình kiểm tra đơn vị 86box"
|
||||
|
||||
msgid "Novell NetWare 2.x Key Card"
|
||||
msgstr "Thẻ khóa Novell Netware 2.x"
|
||||
@@ -1435,7 +1435,7 @@ msgid "Serial port passthrough 4"
|
||||
msgstr "Thông qua cổng serial 4"
|
||||
|
||||
msgid "Vision Systems LBA Enhancer"
|
||||
msgstr "Hệ thống tầm nhìn LBA Enhancer"
|
||||
msgstr "Vision Systems LBA Enhancer"
|
||||
|
||||
msgid "Renderer options..."
|
||||
msgstr "Tùy chọn kết xuất ..."
|
||||
@@ -1477,7 +1477,7 @@ msgid "Roland CM-32LN Emulation"
|
||||
msgstr "Mô phỏng Roland CM-32LN"
|
||||
|
||||
msgid "OPL4-ML Daughterboard"
|
||||
msgstr "Con gái OPL4-ML"
|
||||
msgstr "Bo mạch con OPL4-ML"
|
||||
|
||||
msgid "System MIDI"
|
||||
msgstr "MIDI của hệ thống"
|
||||
@@ -1489,7 +1489,7 @@ msgid "BIOS Address"
|
||||
msgstr "Địa chỉ BIOS"
|
||||
|
||||
msgid "Enable BIOS extension ROM Writes"
|
||||
msgstr "Bật ROM mở rộng BIOS"
|
||||
msgstr "Kích hoạt ghi ROM mở rộng BIOS"
|
||||
|
||||
msgid "Address"
|
||||
msgstr "Địa chỉ"
|
||||
@@ -1516,22 +1516,22 @@ msgid "BIOS size"
|
||||
msgstr "Kích thước BIOS"
|
||||
|
||||
msgid "Map C0000-C7FFF as UMB"
|
||||
msgstr "Bản đồ C0000-C7FFF dưới dạng UMB"
|
||||
msgstr "Map C0000-C7FFF dưới dạng UMB"
|
||||
|
||||
msgid "Map C8000-CFFFF as UMB"
|
||||
msgstr "Bản đồ C8000-CFFFF dưới dạng UMB"
|
||||
msgstr "Map C8000-CFFFF dưới dạng UMB"
|
||||
|
||||
msgid "Map D0000-D7FFF as UMB"
|
||||
msgstr "Bản đồ D0000-D7FFF dưới dạng UMB"
|
||||
msgstr "Map D0000-D7FFF dưới dạng UMB"
|
||||
|
||||
msgid "Map D8000-DFFFF as UMB"
|
||||
msgstr "Bản đồ D8000-Dffff dưới dạng UMB"
|
||||
msgstr "Map D8000-Dffff dưới dạng UMB"
|
||||
|
||||
msgid "Map E0000-E7FFF as UMB"
|
||||
msgstr "Bản đồ E0000-E7FFF dưới dạng UMB"
|
||||
msgstr "Map E0000-E7FFF dưới dạng UMB"
|
||||
|
||||
msgid "Map E8000-EFFFF as UMB"
|
||||
msgstr "Bản đồ e8000-effff dưới dạng umb"
|
||||
msgstr "Map e8000-effff dưới dạng umb"
|
||||
|
||||
msgid "JS9 Jumper (JIM)"
|
||||
msgstr "JS9 Jumper (Jim)"
|
||||
@@ -1546,13 +1546,13 @@ msgid "MIDI Thru"
|
||||
msgstr "Thông qua đầu vào MIDI"
|
||||
|
||||
msgid "MIDI Clockout"
|
||||
msgstr "MIDI đồng hồ"
|
||||
msgstr "MIDI Clockout"
|
||||
|
||||
msgid "SoundFont"
|
||||
msgstr "Soundfont"
|
||||
msgstr "Font âm thanh"
|
||||
|
||||
msgid "Output Gain"
|
||||
msgstr "Đầu ra tăng"
|
||||
msgstr "Tăng đầu ra"
|
||||
|
||||
msgid "Chorus"
|
||||
msgstr "Điệp khúc"
|
||||
@@ -1591,7 +1591,7 @@ msgid "Interpolation Method"
|
||||
msgstr "Phương pháp nội suy"
|
||||
|
||||
msgid "Reverb Output Gain"
|
||||
msgstr "Gợi ý đầu ra hồi âm"
|
||||
msgstr "Tăng đầu ra hồi âm"
|
||||
|
||||
msgid "Reversed stereo"
|
||||
msgstr "Đảo ngược âm thanh nổi"
|
||||
@@ -1612,10 +1612,10 @@ msgid "RTS toggle"
|
||||
msgstr "RT chuyển đổi"
|
||||
|
||||
msgid "Revision"
|
||||
msgstr "Ôn tập"
|
||||
msgstr "Bản sửa đổi"
|
||||
|
||||
msgid "Controller"
|
||||
msgstr "Người điều khiển"
|
||||
msgstr "Bộ điều khiển"
|
||||
|
||||
msgid "Show Crosshair"
|
||||
msgstr "Hiển thị hình chữ thập"
|
||||
@@ -1627,7 +1627,7 @@ msgid "MAC Address"
|
||||
msgstr "Địa chỉ MAC"
|
||||
|
||||
msgid "MAC Address OUI"
|
||||
msgstr " OUI địa chỉ MAC"
|
||||
msgstr "OUI địa chỉ MAC"
|
||||
|
||||
msgid "Enable BIOS"
|
||||
msgstr "Bật BIOS"
|
||||
@@ -1699,7 +1699,7 @@ msgid "Enable OPL"
|
||||
msgstr "Bật OPL"
|
||||
|
||||
msgid "Receive MIDI input (MPU-401)"
|
||||
msgstr "Nhận nhập MIDI (MPU-401)"
|
||||
msgstr "Nhận đầu vào MIDI (MPU-401)"
|
||||
|
||||
msgid "SB low DMA"
|
||||
msgstr "SB DMA thấp"
|
||||
@@ -1711,7 +1711,7 @@ msgid "Enable CMS"
|
||||
msgstr "Bật CMS"
|
||||
|
||||
msgid "Mixer"
|
||||
msgstr "Máy trộn"
|
||||
msgstr "Bộ trộn"
|
||||
|
||||
msgid "High DMA"
|
||||
msgstr "DMA cao"
|
||||
@@ -1747,13 +1747,13 @@ msgid "RGB type"
|
||||
msgstr "Loại RGB"
|
||||
|
||||
msgid "Line doubling type"
|
||||
msgstr "Dòng nhân đôi"
|
||||
msgstr "Loại dòng kép"
|
||||
|
||||
msgid "Snow emulation"
|
||||
msgstr "Đun tuyết"
|
||||
msgstr "Giả lập hiệu ứng tuyết"
|
||||
|
||||
msgid "Monitor type"
|
||||
msgstr "Loại giám sát"
|
||||
msgstr "Loại màn hình"
|
||||
|
||||
msgid "Character set"
|
||||
msgstr "Bộ ký tự"
|
||||
@@ -1762,13 +1762,13 @@ msgid "XGA type"
|
||||
msgstr "Loại XGA"
|
||||
|
||||
msgid "Instance"
|
||||
msgstr "Ví dụ"
|
||||
msgstr "Bản chạy"
|
||||
|
||||
msgid "MMIO Address"
|
||||
msgstr "Địa chỉ MMIO"
|
||||
|
||||
msgid "RAMDAC type"
|
||||
msgstr "Loại Ramdac"
|
||||
msgstr "Loại RAMDAC"
|
||||
|
||||
msgid "Blend"
|
||||
msgstr "Trộn"
|
||||
@@ -1792,13 +1792,13 @@ msgid "Texture memory size"
|
||||
msgstr "Kích thước bộ nhớ kết cấu"
|
||||
|
||||
msgid "Dither subtraction"
|
||||
msgstr "Phân biệt trừ"
|
||||
msgstr "Giảm ngân tán"
|
||||
|
||||
msgid "Screen Filter"
|
||||
msgstr "Bộ lọc màn hình"
|
||||
|
||||
msgid "Render threads"
|
||||
msgstr "Kết xuất chủ đề"
|
||||
msgstr "Luồng kết xuất"
|
||||
|
||||
msgid "SLI"
|
||||
msgstr "SLI"
|
||||
@@ -1813,13 +1813,13 @@ msgid "I/O Width"
|
||||
msgstr "Chiều rộng I/O"
|
||||
|
||||
msgid "Transfer Speed"
|
||||
msgstr "Tốc độ chuyển"
|
||||
msgstr "Tốc độ truyền tải"
|
||||
|
||||
msgid "EMS mode"
|
||||
msgstr "Chế độ EMS"
|
||||
|
||||
msgid "Address for > 2 MB"
|
||||
msgstr "Địa chỉ cho> 2 MB"
|
||||
msgstr "Địa chỉ cho > 2 MB"
|
||||
|
||||
msgid "Frame Address"
|
||||
msgstr "Địa chỉ khung"
|
||||
@@ -1834,7 +1834,7 @@ msgid "Always at selected speed"
|
||||
msgstr "Luôn ở tốc độ đã chọn"
|
||||
|
||||
msgid "BIOS setting + Hotkeys (off during POST)"
|
||||
msgstr "Cài đặt BIOS + phím nóng (TẮT trong bài đăng)"
|
||||
msgstr "Cài đặt BIOS + phím nóng (TẮT trong POST)"
|
||||
|
||||
msgid "64 kB starting from F0000"
|
||||
msgstr "64 kb bắt đầu từ f0000"
|
||||
@@ -1861,7 +1861,7 @@ msgid "Non-timed (original)"
|
||||
msgstr "Không đúng lúc (bản gốc)"
|
||||
|
||||
msgid "45 Hz (JMP2 not populated)"
|
||||
msgstr "45 Hz (JMP2 không dân cư)"
|
||||
msgstr "45 Hz (JMP2 không phổ cập)"
|
||||
|
||||
msgid "Two"
|
||||
msgstr "Hai"
|
||||
@@ -1870,10 +1870,10 @@ msgid "Three"
|
||||
msgstr "Ba"
|
||||
|
||||
msgid "Wheel"
|
||||
msgstr "Bánh xe"
|
||||
msgstr "Con lăn"
|
||||
|
||||
msgid "Five + Wheel"
|
||||
msgstr "Năm + bánh xe"
|
||||
msgstr "Năm + con lăn"
|
||||
|
||||
msgid "A3 - SMT2 Serial / SMT3(R)V"
|
||||
msgstr "A3 - SMT2 Serial / SMT3(R)V"
|
||||
@@ -2008,7 +2008,7 @@ msgid "Color"
|
||||
msgstr "Màu sắc"
|
||||
|
||||
msgid "U.S. English"
|
||||
msgstr "Tiếng Anh Hoa Kỳ"
|
||||
msgstr "Tiếng Anh Mỹ"
|
||||
|
||||
msgid "Scandinavian"
|
||||
msgstr "Scandinavia"
|
||||
@@ -2020,13 +2020,13 @@ msgid "Bochs latest"
|
||||
msgstr "Bochs mới nhất"
|
||||
|
||||
msgid "Mono Non-Interlaced"
|
||||
msgstr "Đơn sắc không được xen kẽ"
|
||||
msgstr "Đơn sắc không xen kẽ"
|
||||
|
||||
msgid "Color Interlaced"
|
||||
msgstr "Màu sắc xen kẽ"
|
||||
|
||||
msgid "Color Non-Interlaced"
|
||||
msgstr "Màu sắc không được xen kẽ"
|
||||
msgstr "Màu sắc không xen kẽ"
|
||||
|
||||
msgid "3Dfx Voodoo Graphics"
|
||||
msgstr "Đồ họa 3Dfx Voodoo"
|
||||
@@ -2074,7 +2074,7 @@ msgid "Parallel Line Internet Protocol"
|
||||
msgstr "Parallel Line Internet Protocol"
|
||||
|
||||
msgid "Protection Dongle for Savage Quest"
|
||||
msgstr "Bảo vệ dongle cho Savage Quest"
|
||||
msgstr "Dongle bảo vệ cho Savage Quest"
|
||||
|
||||
msgid "Serial Passthrough Device"
|
||||
msgstr "Thiết bị thông qua cổng serial"
|
||||
@@ -2086,7 +2086,7 @@ msgid "Host Serial Device"
|
||||
msgstr "Thiết bị serial máy chủ"
|
||||
|
||||
msgid "Name of pipe"
|
||||
msgstr "Tên của đường ống"
|
||||
msgstr "Tên đường ống"
|
||||
|
||||
msgid "Data bits"
|
||||
msgstr "Bit dữ liệu"
|
||||
@@ -2095,10 +2095,10 @@ msgid "Stop bits"
|
||||
msgstr "Dừng bit"
|
||||
|
||||
msgid "Baud Rate of Passthrough"
|
||||
msgstr "Tốc độ baud của qua đường"
|
||||
msgstr "Tốc độ baud của đường thông"
|
||||
|
||||
msgid "Named Pipe (Server)"
|
||||
msgstr "Đường ống được đặt tên (máy chủ)"
|
||||
msgstr "Đường ống có tên (máy chủ)"
|
||||
|
||||
msgid "Host Serial Passthrough"
|
||||
msgstr "Thông qua cổng serial của máy chủ"
|
||||
@@ -2107,19 +2107,19 @@ msgid "Eject %s"
|
||||
msgstr "Đẩy đĩa ra %s"
|
||||
|
||||
msgid "&Unmute"
|
||||
msgstr "&Không quay được"
|
||||
msgstr "&Mở tiếng"
|
||||
|
||||
msgid "Softfloat FPU"
|
||||
msgstr "Softfloat FPU"
|
||||
|
||||
msgid "High performance impact"
|
||||
msgstr "Tác động cao đến hiệu suất"
|
||||
msgstr "Ảnh hưởng lớn đến hiệu suất"
|
||||
|
||||
msgid "RAM Disk (max. speed)"
|
||||
msgstr "Đĩa RAM (Tối đa. Tốc độ)"
|
||||
msgstr "Đĩa RAM (tốc độ tối đa)"
|
||||
|
||||
msgid "IBM 8514/A clone (ISA)"
|
||||
msgstr "IBM 8514/A dòng vô tính (ISA)"
|
||||
msgstr "IBM 8514/A bản nhái (ISA)"
|
||||
|
||||
msgid "Vendor"
|
||||
msgstr "Nhà sản xuất"
|
||||
|
||||
@@ -54,6 +54,8 @@ plat_vidapi(const char *api)
|
||||
return 4;
|
||||
} else if (!strcasecmp(api, "vnc")) {
|
||||
return 5;
|
||||
} else if (!strcasecmp(api, "qt_opengl3_pcem")) {
|
||||
return 6;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -83,6 +85,9 @@ plat_vidapi_name(int api)
|
||||
case 5:
|
||||
name = "vnc";
|
||||
break;
|
||||
case 6:
|
||||
name = "qt_opengl3_pcem";
|
||||
break;
|
||||
default:
|
||||
fatal("Unknown renderer: %i\n", api);
|
||||
break;
|
||||
|
||||
@@ -123,7 +123,7 @@ DeviceConfig::ProcessConfig(void *dc, const void *c, const bool is_dep)
|
||||
if (config == NULL)
|
||||
return;
|
||||
|
||||
while (config->type != -1) {
|
||||
while (config->type != CONFIG_END) {
|
||||
const int config_type = config->type & CONFIG_TYPE_MASK;
|
||||
|
||||
/* Ignore options of the wrong class. */
|
||||
@@ -242,8 +242,12 @@ DeviceConfig::ProcessConfig(void *dc, const void *c, const bool is_dep)
|
||||
int currentIndex = -1;
|
||||
|
||||
q = 0;
|
||||
for (auto *bios = config->bios; (bios != nullptr) && (bios->name != nullptr) &&
|
||||
(strlen(bios->name) > 0); ++bios) {
|
||||
for (auto *bios = config->bios; (bios != nullptr) &&
|
||||
(bios->name != nullptr) &&
|
||||
(bios->internal_name != nullptr) &&
|
||||
(strlen(bios->name) > 0) &&
|
||||
(strlen(bios->internal_name) > 0) &&
|
||||
(bios->files_no > 0); ++bios) {
|
||||
p = 0;
|
||||
for (int d = 0; d < bios->files_no; d++)
|
||||
p += !!rom_present(const_cast<char *>(bios->files[d]));
|
||||
@@ -372,7 +376,7 @@ DeviceConfig::ConfigureDevice(const _device_ *device, int instance, Settings *se
|
||||
return;
|
||||
|
||||
config = device->config;
|
||||
while (config->type != -1) {
|
||||
while (config->type != CONFIG_END) {
|
||||
switch (config->type) {
|
||||
default:
|
||||
break;
|
||||
|
||||
384
src/qt/qt_glsl_parser.cpp
Normal file
384
src/qt/qt_glsl_parser.cpp
Normal file
@@ -0,0 +1,384 @@
|
||||
#include "qt_mainwindow.hpp"
|
||||
#include <QMessageBox>
|
||||
#include <QWindow>
|
||||
#include <QCoreApplication>
|
||||
|
||||
extern MainWindow* main_window;
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <stdint.h>
|
||||
extern "C"
|
||||
{
|
||||
#include <86box/86box.h>
|
||||
#include <86box/ini.h>
|
||||
#include <86box/config.h>
|
||||
#include <86box/qt-glslp-parser.h>
|
||||
#include <86box/path.h>
|
||||
|
||||
extern void startblit();
|
||||
extern void endblit();
|
||||
}
|
||||
|
||||
#define safe_strncpy(a, b, n) \
|
||||
do { \
|
||||
strncpy((a), (b), (n)-1); \
|
||||
(a)[(n)-1] = 0; \
|
||||
} while (0)
|
||||
|
||||
|
||||
|
||||
static inline void *wx_config_load(const char *path) { ini_t ini = ini_read(path); if (ini) ini_strip_quotes(ini); return (void*)ini; }
|
||||
|
||||
static inline int wx_config_get_string(void *config, const char *name, char *dst, int size, const char *defVal) {
|
||||
int res = ini_has_entry(ini_find_or_create_section((ini_t)config, ""), name);
|
||||
char* str = ini_get_string((ini_t)config, "", name, (char*)defVal);
|
||||
if (size == 0)
|
||||
return res;
|
||||
if (str != NULL)
|
||||
strncpy(dst, str, size - 1);
|
||||
else
|
||||
dst[0] = 0;
|
||||
return res;
|
||||
}
|
||||
|
||||
static inline int wx_config_get_int(void *config, const char *name, int *dst, int defVal) {
|
||||
int res = ini_has_entry(ini_find_or_create_section((ini_t)config, ""), name);
|
||||
*dst = ini_get_int((ini_t)config, "", name, defVal);
|
||||
return res;
|
||||
}
|
||||
|
||||
static inline int wx_config_get_float(void *config, const char *name, float *dst, float defVal) {
|
||||
int res = ini_has_entry(ini_find_or_create_section((ini_t)config, ""), name);
|
||||
*dst = (float)ini_get_double((ini_t)config, "", name, defVal);
|
||||
return res;
|
||||
}
|
||||
|
||||
static inline int wx_config_get_bool(void *config, const char *name, int *dst, int defVal) {
|
||||
int res = ini_has_entry(ini_find_or_create_section((ini_t)config, ""), name);
|
||||
*dst = !!ini_get_int((ini_t)config, "", name, defVal);
|
||||
return res;
|
||||
}
|
||||
|
||||
static inline int wx_config_has_entry(void *config, const char *name) { return ini_has_entry(ini_find_or_create_section((ini_t)config, ""), name); }
|
||||
static inline void wx_config_free(void *config) { ini_close(config); };
|
||||
|
||||
static int endswith(const char *str, const char *ext) {
|
||||
int i;
|
||||
const char *p;
|
||||
int elen = strlen(ext);
|
||||
int slen = strlen(str);
|
||||
if (slen >= elen) {
|
||||
p = &str[slen - elen];
|
||||
for (i = 0; i < elen; ++i) {
|
||||
if (tolower(p[i]) != tolower(ext[i]))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *load_file(const char *fn) {
|
||||
FILE *f = fopen(fn, "rb");
|
||||
if (!f)
|
||||
return 0;
|
||||
fseek(f, 0, SEEK_END);
|
||||
long fsize = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
|
||||
char *data = (char*)malloc(fsize + 1);
|
||||
|
||||
fread(data, fsize, 1, f);
|
||||
fclose(f);
|
||||
|
||||
data[fsize] = 0;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static void strip_lines(const char *program, const char *starts_with) {
|
||||
/* strip parameters */
|
||||
char *ptr = strstr(program, starts_with);
|
||||
while (ptr) {
|
||||
while (*ptr != '\n' && *ptr != '\0')
|
||||
*ptr++ = ' ';
|
||||
ptr = strstr(program, starts_with);
|
||||
}
|
||||
}
|
||||
|
||||
static void strip_parameters(const char *program) {
|
||||
/* strip parameters */
|
||||
strip_lines(program, "#pragma parameter");
|
||||
}
|
||||
|
||||
static void strip_defines(const char *program) {
|
||||
/* strip texture define */
|
||||
strip_lines(program, "#define texture");
|
||||
}
|
||||
|
||||
static int has_parameter(glslp_t *glsl, char *id) {
|
||||
int i;
|
||||
for (i = 0; i < glsl->num_parameters; ++i)
|
||||
if (!strcmp(glsl->parameters[i].id, id))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_parameters(glslp_t *glsl) {
|
||||
int i;
|
||||
struct parameter p;
|
||||
for (i = 0; i < glsl->num_shaders; ++i) {
|
||||
struct shader *shader = &glsl->shaders[i];
|
||||
FILE *f = fopen(shader->shader_fn, "rb");
|
||||
if (!f)
|
||||
return 0;
|
||||
|
||||
char line[1024];
|
||||
while (fgets(line, sizeof(line) - 1, f) && glsl->num_parameters < MAX_PARAMETERS) {
|
||||
int num = sscanf(line, "#pragma parameter %63s \"%63[^\"]\" %f %f %f %f", p.id, p.description,
|
||||
&p.default_value, &p.min, &p.max, &p.step);
|
||||
if (num < 5)
|
||||
continue;
|
||||
p.id[63] = 0;
|
||||
p.description[63] = 0;
|
||||
|
||||
if (num == 5)
|
||||
p.step = 0.1f * (p.max - p.min);
|
||||
|
||||
p.value = p.default_value;
|
||||
|
||||
if (!has_parameter(glsl, p.id)) {
|
||||
memcpy(&glsl->parameters[glsl->num_parameters++], &p, sizeof(struct parameter));
|
||||
pclog("Read parameter: %s (%s) %f, %f -> %f (%f)\n", p.id, p.description, p.default_value, p.min,
|
||||
p.max, p.step);
|
||||
}
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct parameter *get_parameter(glslp_t *glslp, const char *id) {
|
||||
int i;
|
||||
for (i = 0; i < glslp->num_parameters; ++i) {
|
||||
if (!strcmp(glslp->parameters[i].id, id)) {
|
||||
return &glslp->parameters[i];
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static glslp_t *glsl_parse(const char *f) {
|
||||
glslp_t *glslp = (glslp_t*)malloc(sizeof(glslp_t));
|
||||
memset(glslp, 0, sizeof(glslp_t));
|
||||
glslp->num_shaders = 1;
|
||||
struct shader *shader = &glslp->shaders[0];
|
||||
strcpy(shader->shader_fn, f);
|
||||
shader->shader_program = load_file(f);
|
||||
if (!shader->shader_program) {
|
||||
QMessageBox::critical((QWidget *) qApp->findChild<QWindow *>(), QObject::tr("GLSL error"), QObject::tr("Could not load shader %1").arg(shader->shader_fn));
|
||||
//wx_simple_messagebox("GLSL error", "Could not load shader %s\n", shader->shader_fn);
|
||||
glslp_free(glslp);
|
||||
return 0;
|
||||
}
|
||||
strip_parameters(shader->shader_program);
|
||||
strip_defines(shader->shader_program);
|
||||
shader->scale_x = shader->scale_y = 1.0f;
|
||||
strcpy(shader->scale_type_x, "source");
|
||||
strcpy(shader->scale_type_y, "source");
|
||||
get_parameters(glslp);
|
||||
return glslp;
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
void get_glslp_name(const char *f, char *s, int size) { safe_strncpy(s, path_get_filename((char *)f), size); }
|
||||
|
||||
glslp_t *glslp_parse(const char *f) {
|
||||
int i, j, len, sublen;
|
||||
char s[513], t[513], z[540];
|
||||
|
||||
memset(s, 0, sizeof(s));
|
||||
if (endswith(f, ".glsl"))
|
||||
return glsl_parse(f);
|
||||
|
||||
void *cfg = wx_config_load(f);
|
||||
|
||||
if (!cfg) {
|
||||
fprintf(stderr, "GLSLP Error: Could not load GLSLP-file %s\n", f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
glslp_t *glslp = (glslp_t*)malloc(sizeof(glslp_t));
|
||||
memset(glslp, 0, sizeof(glslp_t));
|
||||
|
||||
get_glslp_name(f, glslp->name, sizeof(glslp->name));
|
||||
|
||||
wx_config_get_int(cfg, "shaders", &glslp->num_shaders, 0);
|
||||
|
||||
wx_config_get_bool(cfg, "filter_linear0", &glslp->input_filter_linear, -1);
|
||||
|
||||
for (i = 0; i < glslp->num_shaders; ++i) {
|
||||
struct shader *shader = &glslp->shaders[i];
|
||||
|
||||
snprintf(s, sizeof(s) - 1, "shader%d", i);
|
||||
if (!wx_config_get_string(cfg, s, t, sizeof(t), 0)) {
|
||||
/* shader doesn't exist, lets break here */
|
||||
glslp->num_shaders = i;
|
||||
break;
|
||||
}
|
||||
strcpy(s, f);
|
||||
*path_get_filename(s) = 0;
|
||||
snprintf(shader->shader_fn, sizeof(shader->shader_fn) - 1, "%s%s", s, t);
|
||||
shader->shader_program = load_file(shader->shader_fn);
|
||||
if (!shader->shader_program) {
|
||||
fprintf(stderr, "GLSLP Error: Could not load shader %s\n", shader->shader_fn);
|
||||
glslp_free(glslp);
|
||||
return 0;
|
||||
}
|
||||
strip_parameters(shader->shader_program);
|
||||
strip_defines(shader->shader_program);
|
||||
|
||||
snprintf(s, sizeof(s) - 1, "alias%d", i);
|
||||
wx_config_get_string(cfg, s, shader->alias, sizeof(shader->alias), 0);
|
||||
|
||||
snprintf(s, sizeof(s) - 1, "filter_linear%d", i + 1);
|
||||
wx_config_get_bool(cfg, s, &shader->filter_linear, 0);
|
||||
|
||||
snprintf(s, sizeof(s) - 1, "wrap_mode%d", i);
|
||||
wx_config_get_string(cfg, s, shader->wrap_mode, sizeof(shader->wrap_mode), 0);
|
||||
|
||||
snprintf(s, sizeof(s) - 1, "float_framebuffer%d", i);
|
||||
wx_config_get_bool(cfg, s, &shader->float_framebuffer, 0);
|
||||
snprintf(s, sizeof(s) - 1, "srgb_framebuffer%d", i);
|
||||
wx_config_get_bool(cfg, s, &shader->srgb_framebuffer, 0);
|
||||
|
||||
snprintf(s, sizeof(s) - 1, "mipmap_input%d", i);
|
||||
wx_config_get_bool(cfg, s, &shader->mipmap_input, 0);
|
||||
|
||||
strcpy(shader->scale_type_x, "source");
|
||||
snprintf(s, sizeof(s) - 1, "scale_type_x%d", i);
|
||||
wx_config_get_string(cfg, s, shader->scale_type_x, sizeof(shader->scale_type_x), 0);
|
||||
strcpy(shader->scale_type_y, "source");
|
||||
snprintf(s, sizeof(s) - 1, "scale_type_y%d", i);
|
||||
wx_config_get_string(cfg, s, shader->scale_type_y, sizeof(shader->scale_type_y), 0);
|
||||
snprintf(s, sizeof(s) - 1, "scale_type%d", i);
|
||||
if (wx_config_has_entry(cfg, s)) {
|
||||
wx_config_get_string(cfg, s, shader->scale_type_x, sizeof(shader->scale_type_x), 0);
|
||||
wx_config_get_string(cfg, s, shader->scale_type_y, sizeof(shader->scale_type_y), 0);
|
||||
}
|
||||
|
||||
snprintf(s, sizeof(s) - 1, "scale_x%d", i);
|
||||
wx_config_get_float(cfg, s, &shader->scale_x, 1.0f);
|
||||
snprintf(s, sizeof(s) - 1, "scale_y%d", i);
|
||||
wx_config_get_float(cfg, s, &shader->scale_y, 1.0f);
|
||||
snprintf(s, sizeof(s) - 1, "scale%d", i);
|
||||
if (wx_config_has_entry(cfg, s)) {
|
||||
wx_config_get_float(cfg, s, &shader->scale_x, 1.0f);
|
||||
wx_config_get_float(cfg, s, &shader->scale_y, 1.0f);
|
||||
}
|
||||
|
||||
snprintf(s, sizeof(s) - 1, "frame_count_mod%d", i);
|
||||
wx_config_get_int(cfg, s, &shader->frame_count_mod, 0);
|
||||
}
|
||||
|
||||
/* textures */
|
||||
glslp->num_textures = 0;
|
||||
wx_config_get_string(cfg, "textures", t, sizeof(t), 0);
|
||||
|
||||
len = strlen(t);
|
||||
j = 0;
|
||||
sublen = 0;
|
||||
for (i = 0; i < len; ++i) {
|
||||
if (t[i] == ';' || i == len - 1) {
|
||||
sublen = (i - j) + ((i == len - 1) ? 1 : 0) + 1;
|
||||
safe_strncpy(s, t + j, sublen);
|
||||
s[511 < sublen ? 511 : sublen] = 0;
|
||||
|
||||
if (s[strlen(s) - 1] == ';') s[strlen(s) - 1] = 0;
|
||||
|
||||
struct texture *tex = &glslp->textures[glslp->num_textures++];
|
||||
|
||||
strcpy(tex->name, s);
|
||||
wx_config_get_string(cfg, s, tex->path, sizeof(tex->path), 0);
|
||||
|
||||
snprintf(z, sizeof(z) - 1, "%s_linear", s);
|
||||
wx_config_get_bool(cfg, z, &tex->linear, 0);
|
||||
|
||||
snprintf(z, sizeof(z) - 1, "%s_mipmap", s);
|
||||
wx_config_get_bool(cfg, z, &tex->mipmap, 0);
|
||||
|
||||
snprintf(z, sizeof(z) - 1, "%s_wrap_mode", s);
|
||||
wx_config_get_string(cfg, z, tex->wrap_mode, sizeof(tex->wrap_mode), 0);
|
||||
|
||||
j = i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* parameters */
|
||||
get_parameters(glslp);
|
||||
|
||||
wx_config_get_string(cfg, "parameters", t, sizeof(t), 0);
|
||||
|
||||
len = strlen(t);
|
||||
j = 0;
|
||||
sublen = 0;
|
||||
for (i = 0; i < len; ++i) {
|
||||
if (t[i] == ';' || i == len - 1) {
|
||||
sublen = (i - j) + ((i == len - 1) ? 1 : 0) + 1;
|
||||
safe_strncpy(s, t + j, sublen);
|
||||
s[511 < sublen ? 511 : sublen] = 0;
|
||||
|
||||
struct parameter *p = get_parameter(glslp, s);
|
||||
|
||||
if (p)
|
||||
wx_config_get_float(cfg, s, &p->default_value, 0);
|
||||
|
||||
j = i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
wx_config_free(cfg);
|
||||
|
||||
return glslp;
|
||||
}
|
||||
|
||||
void glslp_free(glslp_t *p) {
|
||||
int i;
|
||||
for (i = 0; i < p->num_shaders; ++i)
|
||||
if (p->shaders[i].shader_program)
|
||||
free(p->shaders[i].shader_program);
|
||||
free(p);
|
||||
}
|
||||
|
||||
void glslp_read_shader_config(glslp_t *shader) {
|
||||
char s[512];
|
||||
int i;
|
||||
char *name = shader->name;
|
||||
sprintf(s, "GL3 Shaders - %s", name);
|
||||
for (i = 0; i < shader->num_parameters; ++i) {
|
||||
struct parameter *param = &shader->parameters[i];
|
||||
param->value = config_get_double(s, param->id, param->default_value);
|
||||
}
|
||||
}
|
||||
|
||||
void glslp_write_shader_config(glslp_t *shader) {
|
||||
char s[512];
|
||||
int i;
|
||||
char *name = shader->name;
|
||||
|
||||
startblit();
|
||||
sprintf(s, "GL3 Shaders - %s", name);
|
||||
for (i = 0; i < shader->num_parameters; ++i) {
|
||||
struct parameter *param = &shader->parameters[i];
|
||||
config_set_double(s, param->id, param->value);
|
||||
}
|
||||
endblit();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -90,6 +90,8 @@ extern "C" {
|
||||
#include <86box/timer.h>
|
||||
#include <86box/nvr.h>
|
||||
extern int qt_nvr_save(void);
|
||||
|
||||
bool cpu_thread_running = false;
|
||||
}
|
||||
|
||||
void qt_set_sequence_auto_mnemonic(bool b);
|
||||
@@ -389,6 +391,7 @@ main_thread_fn()
|
||||
// title_update = 1;
|
||||
uint64_t old_time = elapsed_timer.elapsed();
|
||||
int drawits = frames = 0;
|
||||
is_cpu_thread = 1;
|
||||
while (!is_quit && cpu_thread_run) {
|
||||
/* See if it is time to run a frame of code. */
|
||||
const uint64_t new_time = elapsed_timer.elapsed();
|
||||
@@ -443,6 +446,7 @@ main_thread_fn()
|
||||
}
|
||||
}
|
||||
|
||||
cpu_thread_running = false;
|
||||
is_quit = 1;
|
||||
for (uint8_t i = 1; i < GFXCARD_MAX; i ++) {
|
||||
if (gfxcard[i]) {
|
||||
@@ -735,6 +739,7 @@ main(int argc, char *argv[])
|
||||
#endif
|
||||
plat_pause(0);
|
||||
|
||||
cpu_thread_running = true;
|
||||
main_thread = new std::thread(main_thread_fn);
|
||||
});
|
||||
|
||||
|
||||
@@ -62,6 +62,8 @@ extern int qt_nvr_save(void);
|
||||
#ifdef MTR_ENABLED
|
||||
# include <minitrace/minitrace.h>
|
||||
#endif
|
||||
|
||||
extern bool cpu_thread_running;
|
||||
};
|
||||
|
||||
#include <QGuiApplication>
|
||||
@@ -452,6 +454,9 @@ MainWindow::MainWindow(QWidget *parent)
|
||||
endblit();
|
||||
}
|
||||
#endif
|
||||
case 6:
|
||||
newVidApi = RendererStack::Renderer::OpenGL3PCem;
|
||||
break;
|
||||
}
|
||||
ui->stackedWidget->switchRenderer(newVidApi);
|
||||
if (!show_second_monitors)
|
||||
@@ -779,6 +784,14 @@ MainWindow::closeEvent(QCloseEvent *event)
|
||||
ui->stackedWidget->mouse_exit_func();
|
||||
|
||||
ui->stackedWidget->switchRenderer(RendererStack::Renderer::Software);
|
||||
for (int i = 1; i < MONITORS_NUM; i++) {
|
||||
if (renderers[i] && renderers[i]->isHidden()) {
|
||||
renderers[i]->show();
|
||||
QApplication::processEvents();
|
||||
renderers[i]->switchRenderer(RendererStack::Renderer::Software);
|
||||
QApplication::processEvents();
|
||||
}
|
||||
}
|
||||
|
||||
qt_nvr_save();
|
||||
config_save();
|
||||
@@ -1253,7 +1266,7 @@ MainWindow::eventFilter(QObject *receiver, QEvent *event)
|
||||
static auto curdopause = dopause;
|
||||
if (event->type() == QEvent::WindowBlocked) {
|
||||
curdopause = dopause;
|
||||
plat_pause(1);
|
||||
plat_pause(isShowMessage ? 2 : 1);
|
||||
emit setMouseCapture(false);
|
||||
} else if (event->type() == QEvent::WindowUnblocked) {
|
||||
plat_pause(curdopause);
|
||||
@@ -1267,6 +1280,7 @@ void
|
||||
MainWindow::refreshMediaMenu()
|
||||
{
|
||||
mm->refresh(ui->menuMedia);
|
||||
status->setSoundGainAction(ui->actionSound_gain);
|
||||
status->refresh(ui->statusbar);
|
||||
ui->actionMCA_devices->setVisible(machine_has_bus(machine, MACHINE_BUS_MCA));
|
||||
ui->actionACPI_Shutdown->setEnabled(!!acpi_enabled);
|
||||
@@ -1276,7 +1290,11 @@ void
|
||||
MainWindow::showMessage(int flags, const QString &header, const QString &message)
|
||||
{
|
||||
if (QThread::currentThread() == this->thread()) {
|
||||
showMessage_(flags, header, message);
|
||||
if (!cpu_thread_running) {
|
||||
showMessageForNonQtThread(flags, header, message, nullptr);
|
||||
}
|
||||
else
|
||||
showMessage_(flags, header, message);
|
||||
} else {
|
||||
std::atomic_bool done = false;
|
||||
emit showMessageForNonQtThread(flags, header, message, &done);
|
||||
@@ -1292,6 +1310,7 @@ MainWindow::showMessage_(int flags, const QString &header, const QString &messag
|
||||
if (done) {
|
||||
*done = false;
|
||||
}
|
||||
isShowMessage = true;
|
||||
QMessageBox box(QMessageBox::Warning, header, message, QMessageBox::NoButton, this);
|
||||
if (flags & (MBX_FATAL)) {
|
||||
box.setIcon(QMessageBox::Critical);
|
||||
@@ -1303,6 +1322,7 @@ MainWindow::showMessage_(int flags, const QString &header, const QString &messag
|
||||
if (done) {
|
||||
*done = true;
|
||||
}
|
||||
isShowMessage = false;
|
||||
if (cpu_thread_run == 0)
|
||||
QApplication::exit(-1);
|
||||
}
|
||||
@@ -1979,15 +1999,40 @@ MainWindow::changeEvent(QEvent *event)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MainWindow::reloadAllRenderers()
|
||||
{
|
||||
reload_renderers = true;
|
||||
}
|
||||
|
||||
void
|
||||
MainWindow::on_actionRenderer_options_triggered()
|
||||
{
|
||||
if (const auto dlg = ui->stackedWidget->getOptions(this)) {
|
||||
if (dlg->exec() == QDialog::Accepted) {
|
||||
for (int i = 1; i < MONITORS_NUM; i++) {
|
||||
if (ui->stackedWidget->reloadRendererOption()) {
|
||||
ui->stackedWidget->switchRenderer(static_cast<RendererStack::Renderer>(vid_api));
|
||||
if (show_second_monitors) {
|
||||
for (int i = 1; i < MONITORS_NUM; i++) {
|
||||
if (renderers[i] && renderers[i]->reloadRendererOption() && renderers[i]->hasOptions()) {
|
||||
ui->stackedWidget->switchRenderer(static_cast<RendererStack::Renderer>(vid_api));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else for (int i = 1; i < MONITORS_NUM; i++) {
|
||||
if (renderers[i] && renderers[i]->hasOptions())
|
||||
renderers[i]->reloadOptions();
|
||||
}
|
||||
} else if (reload_renderers && ui->stackedWidget->reloadRendererOption()) {
|
||||
reload_renderers = false;
|
||||
ui->stackedWidget->switchRenderer(static_cast<RendererStack::Renderer>(vid_api));
|
||||
if (show_second_monitors) {
|
||||
for (int i = 1; i < MONITORS_NUM; i++) {
|
||||
if (renderers[i] && renderers[i]->reloadRendererOption() && renderers[i]->hasOptions()) {
|
||||
ui->stackedWidget->switchRenderer(static_cast<RendererStack::Renderer>(vid_api));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ public:
|
||||
QSize getRenderWidgetSize();
|
||||
void setSendKeyboardInput(bool enabled);
|
||||
void checkFullscreenHotkey();
|
||||
void reloadAllRenderers();
|
||||
|
||||
std::array<std::unique_ptr<RendererStack>, 8> renderers;
|
||||
signals:
|
||||
@@ -173,11 +174,17 @@ private:
|
||||
bool fs_on_signal = false;
|
||||
bool fs_off_signal = false;
|
||||
|
||||
/* Reload the renderers after closing renderer options dialog. */
|
||||
bool reload_renderers = false;
|
||||
|
||||
friend class SpecifyDimensions;
|
||||
friend class ProgSettings;
|
||||
friend class RendererCommon;
|
||||
friend class RendererStack; // For UI variable access by non-primary renderer windows.
|
||||
friend class WindowsRawInputFilter; // Needed to reload renderers on style sheet changes.
|
||||
|
||||
|
||||
bool isShowMessage = false;
|
||||
};
|
||||
|
||||
#endif // QT_MAINWINDOW_HPP
|
||||
|
||||
@@ -1,196 +0,0 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* OpenGL renderer options for Qt
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: Teemu Korhonen
|
||||
*
|
||||
* Copyright 2022 Teemu Korhonen
|
||||
*/
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QFile>
|
||||
#include <QRegularExpression>
|
||||
#include <QStringBuilder>
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include "qt_opengloptions.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include <86box/86box.h>
|
||||
}
|
||||
|
||||
/* Default vertex shader. */
|
||||
static const GLchar *vertex_shader = "\
|
||||
in vec2 VertexCoord;\n\
|
||||
in vec2 TexCoord;\n\
|
||||
out vec2 tex;\n\
|
||||
void main(){\n\
|
||||
gl_Position = vec4(VertexCoord, 0.0, 1.0);\n\
|
||||
tex = TexCoord;\n\
|
||||
}\n";
|
||||
|
||||
/* Default fragment shader. */
|
||||
static const GLchar *fragment_shader = "\
|
||||
in vec2 tex;\n\
|
||||
uniform sampler2D texsampler;\n\
|
||||
out vec4 color;\n\
|
||||
void main() {\n\
|
||||
color = texture(texsampler, tex);\n\
|
||||
}\n";
|
||||
|
||||
OpenGLOptions::OpenGLOptions(QObject *parent, bool loadConfig, const QString &glslVersion)
|
||||
: QObject(parent)
|
||||
, m_glslVersion(glslVersion)
|
||||
{
|
||||
m_filter = video_filter_method == 0
|
||||
? FilterType::Nearest
|
||||
: FilterType::Linear;
|
||||
|
||||
if (!loadConfig)
|
||||
return;
|
||||
|
||||
/* Initialize with config. */
|
||||
m_vsync = video_vsync != 0;
|
||||
m_framerate = video_framerate;
|
||||
|
||||
m_renderBehavior = video_framerate == -1
|
||||
? RenderBehaviorType::SyncWithVideo
|
||||
: RenderBehaviorType::TargetFramerate;
|
||||
|
||||
QString shaderPath(video_shader);
|
||||
|
||||
if (shaderPath.isEmpty()) {
|
||||
addDefaultShader();
|
||||
} else {
|
||||
try {
|
||||
addShader(shaderPath);
|
||||
} catch (const std::runtime_error &) {
|
||||
/* Fallback to default shader */
|
||||
addDefaultShader();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
OpenGLOptions::save() const
|
||||
{
|
||||
video_vsync = m_vsync ? 1 : 0;
|
||||
video_framerate = m_renderBehavior == RenderBehaviorType::SyncWithVideo ? -1 : m_framerate;
|
||||
video_filter_method = m_filter == FilterType::Nearest ? 0 : 1;
|
||||
|
||||
/* TODO: multiple shaders */
|
||||
auto path = m_shaders.first().path().toLocal8Bit();
|
||||
|
||||
if (!path.isEmpty())
|
||||
qstrncpy(video_shader, path.constData(), sizeof(video_shader));
|
||||
else
|
||||
video_shader[0] = '\0';
|
||||
}
|
||||
|
||||
OpenGLOptions::FilterType
|
||||
OpenGLOptions::filter() const
|
||||
{
|
||||
/* Filter method is controlled externally */
|
||||
return video_filter_method == 0
|
||||
? FilterType::Nearest
|
||||
: FilterType::Linear;
|
||||
}
|
||||
|
||||
void
|
||||
OpenGLOptions::setRenderBehavior(RenderBehaviorType value)
|
||||
{
|
||||
m_renderBehavior = value;
|
||||
}
|
||||
|
||||
void
|
||||
OpenGLOptions::setFrameRate(int value)
|
||||
{
|
||||
m_framerate = value;
|
||||
}
|
||||
|
||||
void
|
||||
OpenGLOptions::setVSync(bool value)
|
||||
{
|
||||
m_vsync = value;
|
||||
}
|
||||
|
||||
void
|
||||
OpenGLOptions::setFilter(FilterType value)
|
||||
{
|
||||
m_filter = value;
|
||||
}
|
||||
|
||||
void
|
||||
OpenGLOptions::addShader(const QString &path)
|
||||
{
|
||||
QFile shader_file(path);
|
||||
|
||||
if (!shader_file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
throw std::runtime_error(
|
||||
QString(tr("Error opening \"%1\": %2"))
|
||||
.arg(path)
|
||||
.arg(shader_file.errorString())
|
||||
.toStdString());
|
||||
}
|
||||
|
||||
auto shader_text = QString(shader_file.readAll());
|
||||
|
||||
shader_file.close();
|
||||
|
||||
/* Remove parameter lines */
|
||||
shader_text.remove(QRegularExpression("^\\s*#pragma parameter.*?\\n", QRegularExpression::MultilineOption));
|
||||
|
||||
QRegularExpression version("^\\s*(#version\\s+\\w+)", QRegularExpression::MultilineOption);
|
||||
|
||||
auto match = version.match(shader_text);
|
||||
|
||||
QString version_line(m_glslVersion);
|
||||
|
||||
if (match.hasMatch()) {
|
||||
/* Extract existing version and remove it. */
|
||||
version_line = match.captured(1);
|
||||
shader_text.remove(version);
|
||||
}
|
||||
|
||||
auto shader = new QOpenGLShaderProgram(this);
|
||||
|
||||
auto throw_shader_error = [path, shader](const QString &what) {
|
||||
throw std::runtime_error(
|
||||
QString(what % ":\n\n %2")
|
||||
.arg(path)
|
||||
.arg(shader->log())
|
||||
.toStdString());
|
||||
};
|
||||
|
||||
static const char *extension = "\n#extension GL_ARB_shading_language_420pack : enable\n";
|
||||
|
||||
if (!shader->addShaderFromSourceCode(QOpenGLShader::Vertex, version_line % extension % "\n#define VERTEX\n#line 1\n" % shader_text))
|
||||
throw_shader_error(tr("Error compiling vertex shader in file \"%1\""));
|
||||
|
||||
if (!shader->addShaderFromSourceCode(QOpenGLShader::Fragment, version_line % extension % "\n#define FRAGMENT\n#line 1\n" % shader_text))
|
||||
throw_shader_error(tr("Error compiling fragment shader in file \"%1\""));
|
||||
|
||||
if (!shader->link())
|
||||
throw_shader_error(tr("Error linking shader program in file \"%1\""));
|
||||
|
||||
m_shaders << OpenGLShaderPass(shader, path);
|
||||
}
|
||||
|
||||
void
|
||||
OpenGLOptions::addDefaultShader()
|
||||
{
|
||||
auto shader = new QOpenGLShaderProgram(this);
|
||||
shader->addShaderFromSourceCode(QOpenGLShader::Vertex, m_glslVersion % "\n" % vertex_shader);
|
||||
shader->addShaderFromSourceCode(QOpenGLShader::Fragment, m_glslVersion % "\n" % fragment_shader);
|
||||
shader->link();
|
||||
m_shaders << OpenGLShaderPass(shader, QString());
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Header for OpenGL renderer options
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: Teemu Korhonen
|
||||
*
|
||||
* Copyright 2022 Teemu Korhonen
|
||||
*/
|
||||
|
||||
#ifndef QT_OPENGLOPTIONS_HPP
|
||||
#define QT_OPENGLOPTIONS_HPP
|
||||
|
||||
#include <QList>
|
||||
#include <QObject>
|
||||
#include <QOpenGLContext>
|
||||
#include <QOpenGLShaderProgram>
|
||||
|
||||
class OpenGLShaderPass {
|
||||
public:
|
||||
OpenGLShaderPass(QOpenGLShaderProgram *shader, const QString &path)
|
||||
: m_shader(shader)
|
||||
, m_path(path)
|
||||
, m_vertex_coord(shader->attributeLocation("VertexCoord"))
|
||||
, m_tex_coord(shader->attributeLocation("TexCoord"))
|
||||
, m_color(shader->attributeLocation("Color"))
|
||||
, m_mvp_matrix(shader->uniformLocation("MVPMatrix"))
|
||||
, m_input_size(shader->uniformLocation("InputSize"))
|
||||
, m_output_size(shader->uniformLocation("OutputSize"))
|
||||
, m_texture_size(shader->uniformLocation("TextureSize"))
|
||||
, m_frame_count(shader->uniformLocation("FrameCount"))
|
||||
{
|
||||
}
|
||||
|
||||
bool bind() const { return m_shader->bind(); }
|
||||
const QString &path() const { return m_path; }
|
||||
const GLint &vertex_coord() const { return m_vertex_coord; }
|
||||
const GLint &tex_coord() const { return m_tex_coord; }
|
||||
const GLint &color() const { return m_color; }
|
||||
const GLint &mvp_matrix() const { return m_mvp_matrix; }
|
||||
const GLint &input_size() const { return m_input_size; }
|
||||
const GLint &output_size() const { return m_output_size; }
|
||||
const GLint &texture_size() const { return m_texture_size; }
|
||||
const GLint &frame_count() const { return m_frame_count; }
|
||||
|
||||
private:
|
||||
QOpenGLShaderProgram *m_shader;
|
||||
QString m_path;
|
||||
GLint m_vertex_coord;
|
||||
GLint m_tex_coord;
|
||||
GLint m_color;
|
||||
GLint m_mvp_matrix;
|
||||
GLint m_input_size;
|
||||
GLint m_output_size;
|
||||
GLint m_texture_size;
|
||||
GLint m_frame_count;
|
||||
};
|
||||
|
||||
class OpenGLOptions : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum RenderBehaviorType { SyncWithVideo,
|
||||
TargetFramerate };
|
||||
|
||||
enum FilterType { Nearest,
|
||||
Linear };
|
||||
|
||||
OpenGLOptions(QObject *parent, bool loadConfig, const QString &glslVersion);
|
||||
|
||||
RenderBehaviorType renderBehavior() const { return m_renderBehavior; }
|
||||
int framerate() const { return m_framerate; }
|
||||
bool vSync() const { return m_vsync; }
|
||||
FilterType filter() const;
|
||||
|
||||
const QList<OpenGLShaderPass> &shaders() const { return m_shaders; }
|
||||
|
||||
void setRenderBehavior(RenderBehaviorType value);
|
||||
void setFrameRate(int value);
|
||||
void setVSync(bool value);
|
||||
void setFilter(FilterType value);
|
||||
void addShader(const QString &path);
|
||||
void addDefaultShader();
|
||||
void save() const;
|
||||
|
||||
private:
|
||||
RenderBehaviorType m_renderBehavior = SyncWithVideo;
|
||||
int m_framerate = -1;
|
||||
bool m_vsync = false;
|
||||
FilterType m_filter = Nearest;
|
||||
QList<OpenGLShaderPass> m_shaders;
|
||||
QString m_glslVersion;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,116 +0,0 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* OpenGL renderer options dialog for Qt
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: Teemu Korhonen
|
||||
*
|
||||
* Copyright 2022 Teemu Korhonen
|
||||
*/
|
||||
|
||||
#include <QFileDialog>
|
||||
#include <QMessageBox>
|
||||
#include <QStringBuilder>
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include "qt_opengloptionsdialog.hpp"
|
||||
#include "qt_util.hpp"
|
||||
#include "ui_qt_opengloptionsdialog.h"
|
||||
|
||||
OpenGLOptionsDialog::OpenGLOptionsDialog(QWidget *parent, const OpenGLOptions &options, std::function<OpenGLOptions *()> optionsFactory)
|
||||
: QDialog(parent)
|
||||
, ui(new Ui::OpenGLOptionsDialog)
|
||||
, createOptions(optionsFactory)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
if (options.renderBehavior() == OpenGLOptions::SyncWithVideo)
|
||||
ui->syncWithVideo->setChecked(true);
|
||||
else {
|
||||
ui->syncToFramerate->setChecked(true);
|
||||
ui->targetFps->setValue(options.framerate());
|
||||
}
|
||||
|
||||
ui->vsync->setChecked(options.vSync());
|
||||
|
||||
if (!options.shaders().isEmpty()) {
|
||||
auto path = options.shaders().first().path();
|
||||
if (!path.isEmpty())
|
||||
ui->shader->setPlainText(path);
|
||||
}
|
||||
}
|
||||
|
||||
OpenGLOptionsDialog::~OpenGLOptionsDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void
|
||||
OpenGLOptionsDialog::accept()
|
||||
{
|
||||
auto options = createOptions();
|
||||
|
||||
options->setRenderBehavior(
|
||||
ui->syncWithVideo->isChecked()
|
||||
? OpenGLOptions::SyncWithVideo
|
||||
: OpenGLOptions::TargetFramerate);
|
||||
|
||||
options->setFrameRate(ui->targetFps->value());
|
||||
|
||||
options->setVSync(ui->vsync->isChecked());
|
||||
|
||||
auto shader = ui->shader->toPlainText();
|
||||
|
||||
try {
|
||||
|
||||
if (!shader.isEmpty())
|
||||
options->addShader(shader);
|
||||
else
|
||||
options->addDefaultShader();
|
||||
|
||||
} catch (const std::runtime_error &e) {
|
||||
delete options;
|
||||
|
||||
QMessageBox msgBox(this);
|
||||
msgBox.setWindowTitle(tr("Shader error"));
|
||||
msgBox.setText(tr("Could not load shaders."));
|
||||
msgBox.setInformativeText(tr("More information in details."));
|
||||
msgBox.setDetailedText(e.what());
|
||||
msgBox.setIcon(QMessageBox::Critical);
|
||||
msgBox.setStandardButtons(QMessageBox::Close);
|
||||
msgBox.setDefaultButton(QMessageBox::Close);
|
||||
msgBox.setStyleSheet("QTextEdit { min-width: 45em; }");
|
||||
msgBox.exec();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
options->save();
|
||||
|
||||
emit optionsChanged(options);
|
||||
|
||||
QDialog::accept();
|
||||
}
|
||||
|
||||
void
|
||||
OpenGLOptionsDialog::on_addShader_clicked()
|
||||
{
|
||||
auto shader = QFileDialog::getOpenFileName(
|
||||
this,
|
||||
QString(),
|
||||
QString(),
|
||||
tr("OpenGL Shaders") % util::DlgFilter({ "glsl" }, true));
|
||||
|
||||
if (shader.isNull())
|
||||
return;
|
||||
|
||||
ui->shader->setPlainText(shader);
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Header for OpenGL renderer options dialog
|
||||
*
|
||||
* Authors: Teemu Korhonen
|
||||
*
|
||||
* Copyright 2022 Teemu Korhonen
|
||||
*/
|
||||
|
||||
#ifndef QT_OPENGLOPTIONSDIALOG_H
|
||||
#define QT_OPENGLOPTIONSDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include "qt_opengloptions.hpp"
|
||||
|
||||
namespace Ui {
|
||||
class OpenGLOptionsDialog;
|
||||
}
|
||||
|
||||
class OpenGLOptionsDialog : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit OpenGLOptionsDialog(QWidget *parent, const OpenGLOptions &options, std::function<OpenGLOptions *()> optionsFactory);
|
||||
~OpenGLOptionsDialog();
|
||||
|
||||
signals:
|
||||
void optionsChanged(OpenGLOptions *options);
|
||||
|
||||
public slots:
|
||||
void accept() override;
|
||||
|
||||
private:
|
||||
Ui::OpenGLOptionsDialog *ui;
|
||||
|
||||
std::function<OpenGLOptions *()> createOptions;
|
||||
|
||||
private slots:
|
||||
void on_addShader_clicked();
|
||||
};
|
||||
|
||||
#endif // QT_OPENGLOPTIONSDIALOG_H
|
||||
@@ -1,280 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>OpenGLOptionsDialog</class>
|
||||
<widget class="QDialog" name="OpenGLOptionsDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>320</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>OpenGL 3.0 renderer options</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Render behavior</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2" columnstretch="3,1">
|
||||
<item row="1" column="0">
|
||||
<widget class="QRadioButton" name="syncToFramerate">
|
||||
<property name="text">
|
||||
<string>Use target framerate:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QSpinBox" name="targetFps">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string> fps</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>15</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>240</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>60</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QCheckBox" name="vsync">
|
||||
<property name="text">
|
||||
<string>VSync</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QRadioButton" name="syncWithVideo">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Render each frame immediately, in sync with the emulated display.</p><p><span style=" font-style:italic;">This is the recommended option if the shaders in use don't utilize frametime for animated effects.</span></p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Synchronize with video</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QSlider" name="fpsSlider">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>15</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>240</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>60</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="invertedAppearance">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="tickPosition">
|
||||
<enum>QSlider::NoTicks</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>Shaders</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout" columnstretch="3,1">
|
||||
<item row="2" column="1">
|
||||
<widget class="QPushButton" name="removeShader">
|
||||
<property name="text">
|
||||
<string>Remove</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="0" rowspan="3">
|
||||
<widget class="QTextEdit" name="shader">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="placeholderText">
|
||||
<string>No shader selected</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" alignment="Qt::AlignTop">
|
||||
<widget class="QPushButton" name="addShader">
|
||||
<property name="text">
|
||||
<string>Browse...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>syncWithVideo</tabstop>
|
||||
<tabstop>syncToFramerate</tabstop>
|
||||
<tabstop>fpsSlider</tabstop>
|
||||
<tabstop>targetFps</tabstop>
|
||||
<tabstop>vsync</tabstop>
|
||||
<tabstop>shader</tabstop>
|
||||
<tabstop>addShader</tabstop>
|
||||
<tabstop>removeShader</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>OpenGLOptionsDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>257</x>
|
||||
<y>310</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>OpenGLOptionsDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>325</x>
|
||||
<y>310</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>syncToFramerate</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>targetFps</receiver>
|
||||
<slot>setEnabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>140</x>
|
||||
<y>71</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>380</x>
|
||||
<y>98</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>syncToFramerate</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>fpsSlider</receiver>
|
||||
<slot>setEnabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>158</x>
|
||||
<y>66</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>168</x>
|
||||
<y>87</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>fpsSlider</sender>
|
||||
<signal>valueChanged(int)</signal>
|
||||
<receiver>targetFps</receiver>
|
||||
<slot>setValue(int)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>252</x>
|
||||
<y>90</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>308</x>
|
||||
<y>89</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>targetFps</sender>
|
||||
<signal>valueChanged(int)</signal>
|
||||
<receiver>fpsSlider</receiver>
|
||||
<slot>setValue(int)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>364</x>
|
||||
<y>93</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>134</x>
|
||||
<y>93</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>removeShader</sender>
|
||||
<signal>clicked()</signal>
|
||||
<receiver>shader</receiver>
|
||||
<slot>clear()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>333</x>
|
||||
<y>201</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>235</x>
|
||||
<y>208</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -11,12 +11,14 @@
|
||||
*
|
||||
*
|
||||
* Authors: Teemu Korhonen
|
||||
* Cacodemon345
|
||||
*
|
||||
* Copyright 2022 Teemu Korhonen
|
||||
* Copyright 2025 Cacodemon345
|
||||
*/
|
||||
|
||||
#ifndef QT_OPENGLRENDERER_HPP
|
||||
#define QT_OPENGLRENDERER_HPP
|
||||
#ifndef QT_OpenGLRenderer_HPP
|
||||
#define QT_OpenGLRenderer_HPP
|
||||
|
||||
#if defined Q_OS_MACOS || __arm__
|
||||
# define NO_BUFFER_STORAGE
|
||||
@@ -37,12 +39,24 @@
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
#include "qt_opengloptions.hpp"
|
||||
#include "qt_renderercommon.hpp"
|
||||
|
||||
typedef void(QOPENGLF_APIENTRYP PFNGLBUFFERSTORAGEEXTPROC_LOCAL)(GLenum target, GLsizeiptr size, const void *data, GLbitfield flags);
|
||||
extern "C"
|
||||
{
|
||||
#include <86box/qt-glslp-parser.h>
|
||||
}
|
||||
|
||||
class OpenGLRenderer : public QWindow, protected QOpenGLExtraFunctions, public RendererCommon {
|
||||
struct render_data {
|
||||
int pass;
|
||||
struct glsl_shader *shader;
|
||||
struct shader_pass *shader_pass;
|
||||
GLfloat *output_size;
|
||||
struct shader_pass *orig_pass;
|
||||
GLint texture;
|
||||
int frame_count;
|
||||
};
|
||||
|
||||
class OpenGLRenderer : public QWindow, public RendererCommon {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
@@ -56,7 +70,7 @@ public:
|
||||
void finalize() override final;
|
||||
bool hasOptions() const override { return true; }
|
||||
QDialog *getOptions(QWidget *parent) override;
|
||||
void reloadOptions() override;
|
||||
bool reloadRendererOption() { return true; }
|
||||
|
||||
signals:
|
||||
void initialized();
|
||||
@@ -71,47 +85,64 @@ protected:
|
||||
bool event(QEvent *event) override;
|
||||
|
||||
private:
|
||||
static constexpr int INIT_WIDTH = 640;
|
||||
static constexpr int INIT_HEIGHT = 400;
|
||||
static constexpr int ROW_LENGTH = 2048;
|
||||
static constexpr int BUFFERPIXELS = 4194304;
|
||||
static constexpr int BUFFERBYTES = 16777216; /* Pixel is 4 bytes. */
|
||||
static constexpr int BUFFERCOUNT = 3; /* How many buffers to use for pixel transfer (2-3 is commonly recommended). */
|
||||
|
||||
std::array<std::unique_ptr<uint8_t>, 2> imagebufs;
|
||||
|
||||
QTimer *renderTimer;
|
||||
OpenGLOptions *options;
|
||||
|
||||
QString glslVersion;
|
||||
QString glslVersion = "";
|
||||
|
||||
bool isInitialized = false;
|
||||
bool isFinalized = false;
|
||||
|
||||
GLuint unpackBufferID = 0;
|
||||
GLuint vertexArrayID = 0;
|
||||
GLuint vertexBufferID = 0;
|
||||
GLuint textureID = 0;
|
||||
int frameCounter = 0;
|
||||
int max_texture_size = 65536;
|
||||
int frameCounter = 0;
|
||||
|
||||
OpenGLOptions::FilterType currentFilter;
|
||||
QOpenGLExtraFunctions glw;
|
||||
struct shader_texture scene_texture;
|
||||
glsl_t *active_shader;
|
||||
|
||||
void *unpackBuffer = nullptr;
|
||||
|
||||
int glsl_version[2] = { 0, 0 };
|
||||
|
||||
void initialize();
|
||||
void initializeExtensions();
|
||||
void initializeBuffers();
|
||||
void applyOptions();
|
||||
void applyShader(const OpenGLShaderPass &shader);
|
||||
bool notReady() const { return !isInitialized || isFinalized; }
|
||||
|
||||
void create_scene_shader();
|
||||
void create_texture(struct shader_texture *tex);
|
||||
void create_fbo(struct shader_fbo *fbo);
|
||||
void recreate_fbo(struct shader_fbo *fbo, int width, int height);
|
||||
void setup_fbo(struct shader *shader, struct shader_fbo *fbo);
|
||||
|
||||
/* GL_ARB_buffer_storage */
|
||||
bool hasBufferStorage = false;
|
||||
#ifndef NO_BUFFER_STORAGE
|
||||
PFNGLBUFFERSTORAGEEXTPROC_LOCAL glBufferStorage = nullptr;
|
||||
#endif
|
||||
bool notReady() const { return !isInitialized || isFinalized; }
|
||||
glsl_t* load_glslp(glsl_t *glsl, int num_shader, const char *f);
|
||||
glsl_t* load_shaders(int num, char shaders[MAX_USER_SHADERS][512]);
|
||||
int compile_shader(GLenum shader_type, const char *prepend, const char *program, int *dst);
|
||||
int create_default_shader_tex(struct shader_pass *pass);
|
||||
int create_default_shader_color(struct shader_pass *pass);
|
||||
int create_program(struct shader_program *program);
|
||||
|
||||
GLuint get_uniform(GLuint program, const char *name);
|
||||
GLuint get_attrib(GLuint program, const char *name);
|
||||
|
||||
void find_uniforms(struct glsl_shader *glsl, int num_pass);
|
||||
void delete_texture(struct shader_texture *tex);
|
||||
void delete_fbo(struct shader_fbo *fbo);
|
||||
void delete_program(struct shader_program *program);
|
||||
void delete_vbo(struct shader_vbo *vbo);
|
||||
void delete_pass(struct shader_pass *pass);
|
||||
void delete_prev(struct shader_prev *prev);
|
||||
void delete_shader(struct glsl_shader *glsl);
|
||||
void delete_glsl(glsl_t *glsl);
|
||||
void read_shader_config();
|
||||
|
||||
void render_pass(struct render_data *data);
|
||||
|
||||
private slots:
|
||||
void render();
|
||||
void updateOptions(OpenGLOptions *newOptions);
|
||||
};
|
||||
|
||||
class opengl_init_error : public std::runtime_error {
|
||||
|
||||
85
src/qt/qt_openglshaderconfig.cpp
Normal file
85
src/qt/qt_openglshaderconfig.cpp
Normal file
@@ -0,0 +1,85 @@
|
||||
#include "qt_openglshaderconfig.hpp"
|
||||
#include "ui_qt_openglshaderconfig.h"
|
||||
|
||||
#include "qt_mainwindow.hpp"
|
||||
|
||||
extern MainWindow* main_window;
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include <86box/86box.h>
|
||||
#include <86box/plat.h>
|
||||
#include <86box/config.h>
|
||||
}
|
||||
|
||||
OpenGLShaderConfig::OpenGLShaderConfig(QWidget *parent, glslp_t* shader)
|
||||
: QDialog(parent)
|
||||
, ui(new Ui::OpenGLShaderConfig)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
currentShader = shader;
|
||||
|
||||
connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
|
||||
connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||
|
||||
glslp_read_shader_config(currentShader);
|
||||
|
||||
for (int i = 0; i < currentShader->num_parameters; i++) {
|
||||
auto spinBox = new QDoubleSpinBox;
|
||||
spinBox->setObjectName(currentShader->parameters[i].id);
|
||||
spinBox->setRange(currentShader->parameters[i].min, currentShader->parameters[i].max);
|
||||
spinBox->setValue(currentShader->parameters[i].value);
|
||||
spinBox->setSingleStep(currentShader->parameters[i].step);
|
||||
QFormLayout* layout = (QFormLayout*)ui->scrollAreaWidgetContents->layout();
|
||||
layout->addRow(currentShader->parameters[i].description, spinBox);
|
||||
}
|
||||
}
|
||||
|
||||
OpenGLShaderConfig::~OpenGLShaderConfig()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void OpenGLShaderConfig::on_buttonBox_clicked(QAbstractButton *button)
|
||||
{
|
||||
if (ui->buttonBox->buttonRole(button) == QDialogButtonBox::ResetRole) {
|
||||
for (int i = 0; i < currentShader->num_parameters; i++) {
|
||||
QDoubleSpinBox* box = this->findChild<QDoubleSpinBox*>(QString(currentShader->parameters[i].id));
|
||||
if (box) {
|
||||
box->setValue(currentShader->parameters[i].default_value);
|
||||
}
|
||||
}
|
||||
} else if (ui->buttonBox->buttonRole(button) == QDialogButtonBox::ApplyRole) {
|
||||
startblit();
|
||||
for (int i = 0; i < currentShader->num_parameters; i++) {
|
||||
QDoubleSpinBox* box = this->findChild<QDoubleSpinBox*>(QString(currentShader->parameters[i].id));
|
||||
if (box) {
|
||||
float val = (float)box->value();
|
||||
currentShader->parameters[i].value = val;
|
||||
}
|
||||
}
|
||||
glslp_write_shader_config(currentShader);
|
||||
config_save();
|
||||
endblit();
|
||||
main_window->reloadAllRenderers();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void OpenGLShaderConfig::on_OpenGLShaderConfig_accepted()
|
||||
{
|
||||
startblit();
|
||||
for (int i = 0; i < currentShader->num_parameters; i++) {
|
||||
QDoubleSpinBox* box = (QDoubleSpinBox*)this->findChild<QDoubleSpinBox*>(QString(currentShader->parameters[i].id));
|
||||
if (box) {
|
||||
float val = (float)box->value();
|
||||
currentShader->parameters[i].value = val;
|
||||
}
|
||||
}
|
||||
glslp_write_shader_config(currentShader);
|
||||
config_save();
|
||||
endblit();
|
||||
main_window->reloadAllRenderers();
|
||||
}
|
||||
|
||||
40
src/qt/qt_openglshaderconfig.hpp
Normal file
40
src/qt/qt_openglshaderconfig.hpp
Normal file
@@ -0,0 +1,40 @@
|
||||
#ifndef QT_OPENGLSHADERCONFIG_HPP
|
||||
#define QT_OPENGLSHADERCONFIG_HPP
|
||||
|
||||
#include <QDialog>
|
||||
#include <QLabel>
|
||||
#include <QDoubleSpinBox>
|
||||
#include <QAbstractButton>
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include <86box/qt-glslp-parser.h>
|
||||
}
|
||||
|
||||
namespace Ui {
|
||||
class OpenGLShaderConfig;
|
||||
}
|
||||
|
||||
class OpenGLShaderConfig : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit OpenGLShaderConfig(QWidget *parent = nullptr, glslp_t* shader = nullptr);
|
||||
~OpenGLShaderConfig();
|
||||
|
||||
private slots:
|
||||
void on_buttonBox_clicked(QAbstractButton *button);
|
||||
|
||||
void on_OpenGLShaderConfig_accepted();
|
||||
|
||||
private:
|
||||
Ui::OpenGLShaderConfig *ui;
|
||||
glslp_t* currentShader;
|
||||
|
||||
std::map<std::string, double> defaultValues;
|
||||
};
|
||||
|
||||
#endif // QT_OPENGLSHADERCONFIG_HPP
|
||||
92
src/qt/qt_openglshaderconfig.ui
Normal file
92
src/qt/qt_openglshaderconfig.ui
Normal file
@@ -0,0 +1,92 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>OpenGLShaderConfig</class>
|
||||
<widget class="QDialog" name="OpenGLShaderConfig">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Shader Configuration</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SizeConstraint::SetMinAndMaxSize</enum>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QScrollArea" name="scrollArea">
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="scrollAreaWidgetContents">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>380</width>
|
||||
<height>250</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_2">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SizeConstraint::SetMaximumSize</enum>
|
||||
</property>
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::FieldGrowthPolicy::AllNonFixedFieldsGrow</enum>
|
||||
</property>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::StandardButton::Apply|QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok|QDialogButtonBox::StandardButton::Reset</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>OpenGLShaderConfig</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>OpenGLShaderConfig</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
260
src/qt/qt_openglshadermanagerdialog.cpp
Normal file
260
src/qt/qt_openglshadermanagerdialog.cpp
Normal file
@@ -0,0 +1,260 @@
|
||||
#include "qt_openglshadermanagerdialog.hpp"
|
||||
#include "ui_qt_openglshadermanagerdialog.h"
|
||||
|
||||
#include "qt_mainwindow.hpp"
|
||||
extern MainWindow* main_window;
|
||||
|
||||
#include "qt_openglshaderconfig.hpp"
|
||||
|
||||
#include <QListWidgetItem>
|
||||
#include <QFileDialog>
|
||||
#include <QMessageBox>
|
||||
|
||||
extern "C" {
|
||||
#include <86box/86box.h>
|
||||
#include <86box/plat.h>
|
||||
#include <86box/video.h>
|
||||
#include <86box/path.h>
|
||||
#include <86box/ini.h>
|
||||
#include <86box/config.h>
|
||||
#include <86box/qt-glslp-parser.h>
|
||||
|
||||
extern char gl3_shader_file[MAX_USER_SHADERS][512];
|
||||
}
|
||||
|
||||
OpenGLShaderManagerDialog::OpenGLShaderManagerDialog(QWidget *parent)
|
||||
: QDialog(parent)
|
||||
, ui(new Ui::OpenGLShaderManagerDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
ui->checkBoxVSync->setChecked(!!video_vsync);
|
||||
ui->radioButtonVideoSync->setChecked(video_framerate == -1);
|
||||
ui->radioButtonTargetFramerate->setChecked(video_framerate != -1);
|
||||
if (video_framerate != -1) {
|
||||
ui->targetFrameRate->setValue(video_framerate);
|
||||
} else {
|
||||
ui->targetFrameRate->setDisabled(true);
|
||||
}
|
||||
|
||||
for (int i = 0; i < MAX_USER_SHADERS; i++) {
|
||||
if (gl3_shader_file[i][0] != 0) {
|
||||
char* filename = path_get_filename(gl3_shader_file[i]);
|
||||
if (filename[0] != 0) {
|
||||
glslp_t* shaderfile = glslp_parse(gl3_shader_file[i]);
|
||||
if (shaderfile) {
|
||||
QListWidgetItem* item = new QListWidgetItem(ui->shaderListWidget);
|
||||
item->setText(filename);
|
||||
item->setData(Qt::UserRole + 1, QString(gl3_shader_file[i]));
|
||||
item->setData(Qt::UserRole + 2, (uintptr_t)shaderfile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ui->shaderListWidget->count()) {
|
||||
ui->shaderListWidget->setCurrentRow(ui->shaderListWidget->count() - 1);
|
||||
auto current = ui->shaderListWidget->currentItem();
|
||||
if (current) {
|
||||
glslp_t* shader = (glslp_t*)current->data(Qt::UserRole + 2).toULongLong();
|
||||
if (shader->num_parameters > 0)
|
||||
ui->buttonConfigure->setEnabled(true);
|
||||
else
|
||||
ui->buttonConfigure->setEnabled(false);
|
||||
} else {
|
||||
ui->buttonConfigure->setEnabled(false);
|
||||
}
|
||||
} else {
|
||||
ui->buttonRemove->setDisabled(true);
|
||||
ui->buttonMoveUp->setDisabled(true);
|
||||
ui->buttonMoveDown->setDisabled(true);
|
||||
ui->buttonConfigure->setDisabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
OpenGLShaderManagerDialog::~OpenGLShaderManagerDialog()
|
||||
{
|
||||
for (int i = 0; i < ui->shaderListWidget->count(); i++) {
|
||||
if (ui->shaderListWidget->item(i) && ui->shaderListWidget->item(i)->data(Qt::UserRole + 2).toULongLong()) {
|
||||
glslp_free((glslp_t*)ui->shaderListWidget->item(i)->data(Qt::UserRole + 2).toULongLong());
|
||||
}
|
||||
}
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void OpenGLShaderManagerDialog::on_buttonBox_clicked(QAbstractButton *button)
|
||||
{
|
||||
if (ui->buttonBox->buttonRole(button) == QDialogButtonBox::AcceptRole) {
|
||||
accept();
|
||||
} else if (ui->buttonBox->buttonRole(button) == QDialogButtonBox::RejectRole) {
|
||||
reject();
|
||||
} else if (ui->buttonBox->buttonRole(button) == QDialogButtonBox::ApplyRole) {
|
||||
on_OpenGLShaderManagerDialog_accepted();
|
||||
main_window->reloadAllRenderers();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void OpenGLShaderManagerDialog::on_buttonMoveUp_clicked()
|
||||
{
|
||||
if (ui->shaderListWidget->currentRow() == 0)
|
||||
return;
|
||||
|
||||
int row = ui->shaderListWidget->currentRow();
|
||||
auto item = ui->shaderListWidget->takeItem(row);
|
||||
ui->shaderListWidget->insertItem(row - 1, item);
|
||||
ui->shaderListWidget->setCurrentItem(item);
|
||||
}
|
||||
|
||||
|
||||
void OpenGLShaderManagerDialog::on_shaderListWidget_currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous)
|
||||
{
|
||||
if (current == nullptr) {
|
||||
ui->buttonRemove->setDisabled(true);
|
||||
ui->buttonMoveUp->setDisabled(true);
|
||||
ui->buttonMoveDown->setDisabled(true);
|
||||
ui->buttonConfigure->setDisabled(true);
|
||||
return;
|
||||
} else {
|
||||
ui->buttonRemove->setDisabled(false);
|
||||
ui->buttonConfigure->setDisabled(true);
|
||||
if (current) {
|
||||
glslp_t* shader = (glslp_t*)current->data(Qt::UserRole + 2).toULongLong();
|
||||
if (shader->num_parameters > 0)
|
||||
ui->buttonConfigure->setEnabled(true);
|
||||
}
|
||||
}
|
||||
ui->buttonMoveUp->setDisabled(ui->shaderListWidget->currentRow() == 0);
|
||||
ui->buttonMoveDown->setDisabled(ui->shaderListWidget->currentRow() == (ui->shaderListWidget->count() - 1));
|
||||
}
|
||||
|
||||
|
||||
void OpenGLShaderManagerDialog::on_shaderListWidget_currentRowChanged(int currentRow)
|
||||
{
|
||||
auto current = ui->shaderListWidget->currentItem();
|
||||
if (current == nullptr) {
|
||||
ui->buttonRemove->setDisabled(true);
|
||||
ui->buttonMoveUp->setDisabled(true);
|
||||
ui->buttonMoveDown->setDisabled(true);
|
||||
ui->buttonConfigure->setDisabled(true);
|
||||
return;
|
||||
} else {
|
||||
ui->buttonRemove->setDisabled(false);
|
||||
ui->buttonConfigure->setDisabled(true);
|
||||
if (current) {
|
||||
glslp_t* shader = (glslp_t*)current->data(Qt::UserRole + 2).toULongLong();
|
||||
if (shader->num_parameters > 0)
|
||||
ui->buttonConfigure->setEnabled(true);
|
||||
}
|
||||
}
|
||||
ui->buttonMoveUp->setDisabled(ui->shaderListWidget->currentRow() == 0);
|
||||
ui->buttonMoveDown->setDisabled(ui->shaderListWidget->currentRow() == (ui->shaderListWidget->count() - 1));
|
||||
}
|
||||
|
||||
|
||||
void OpenGLShaderManagerDialog::on_buttonMoveDown_clicked()
|
||||
{
|
||||
if (ui->shaderListWidget->currentRow() == (ui->shaderListWidget->count() - 1))
|
||||
return;
|
||||
|
||||
int row = ui->shaderListWidget->currentRow();
|
||||
auto item = ui->shaderListWidget->takeItem(row);
|
||||
ui->shaderListWidget->insertItem(row + 1, item);
|
||||
ui->shaderListWidget->setCurrentItem(item);
|
||||
}
|
||||
|
||||
|
||||
void OpenGLShaderManagerDialog::on_buttonAdd_clicked()
|
||||
{
|
||||
auto res = QFileDialog::getOpenFileName(this, QString(), QString(), "GLSL Shaders (*.glslp *.glsl);;All files (*.*)");
|
||||
if (!res.isEmpty()) {
|
||||
auto glslp_file = res.toUtf8();
|
||||
glslp_t* shaderfile = glslp_parse(glslp_file.data());
|
||||
if (shaderfile) {
|
||||
auto filename = path_get_filename(glslp_file.data());
|
||||
QListWidgetItem* item = new QListWidgetItem(ui->shaderListWidget);
|
||||
item->setText(filename);
|
||||
item->setData(Qt::UserRole + 1, res);
|
||||
item->setData(Qt::UserRole + 2, (uintptr_t)shaderfile);
|
||||
if (ui->shaderListWidget->count()) {
|
||||
ui->shaderListWidget->setCurrentRow(ui->shaderListWidget->count() - 1);
|
||||
}
|
||||
} else {
|
||||
QMessageBox::critical(this, tr("GLSL error"), tr("Could not load filename %1").arg(res));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void OpenGLShaderManagerDialog::on_buttonRemove_clicked()
|
||||
{
|
||||
if (ui->shaderListWidget->currentItem()) {
|
||||
auto item = ui->shaderListWidget->takeItem(ui->shaderListWidget->currentRow());
|
||||
|
||||
if (item->data(Qt::UserRole + 2).toULongLong()) {
|
||||
glslp_free((glslp_t*)item->data(Qt::UserRole + 2).toULongLong());
|
||||
}
|
||||
delete item;
|
||||
|
||||
on_shaderListWidget_currentRowChanged(ui->shaderListWidget->currentRow());
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLShaderManagerDialog::on_OpenGLShaderManagerDialog_accepted()
|
||||
{
|
||||
memset(gl3_shader_file, 0, sizeof(gl3_shader_file));
|
||||
for (int i = 0; i < ui->shaderListWidget->count(); i++) {
|
||||
strncpy(gl3_shader_file[i], ui->shaderListWidget->item(i)->data(Qt::UserRole + 1).toString().toUtf8(), 512);
|
||||
}
|
||||
startblit();
|
||||
video_vsync = ui->checkBoxVSync->isChecked();
|
||||
if (ui->radioButtonTargetFramerate->isChecked()) {
|
||||
video_framerate = ui->horizontalSliderFramerate->value();
|
||||
} else {
|
||||
video_framerate = -1;
|
||||
}
|
||||
config_save();
|
||||
endblit();
|
||||
}
|
||||
|
||||
|
||||
void OpenGLShaderManagerDialog::on_buttonConfigure_clicked()
|
||||
{
|
||||
auto item = ui->shaderListWidget->currentItem();
|
||||
if (item) {
|
||||
glslp_t* shader = (glslp_t*)item->data(Qt::UserRole + 2).toULongLong();
|
||||
|
||||
auto configDialog = new OpenGLShaderConfig(this, shader);
|
||||
configDialog->exec();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void OpenGLShaderManagerDialog::on_radioButtonVideoSync_clicked()
|
||||
{
|
||||
ui->targetFrameRate->setDisabled(true);
|
||||
}
|
||||
|
||||
|
||||
void OpenGLShaderManagerDialog::on_radioButtonTargetFramerate_clicked()
|
||||
{
|
||||
ui->targetFrameRate->setDisabled(false);
|
||||
}
|
||||
|
||||
|
||||
void OpenGLShaderManagerDialog::on_horizontalSliderFramerate_sliderMoved(int position)
|
||||
{
|
||||
(void)position;
|
||||
|
||||
if (ui->horizontalSliderFramerate->value() != ui->targetFrameRate->value())
|
||||
ui->targetFrameRate->setValue(ui->horizontalSliderFramerate->value());
|
||||
}
|
||||
|
||||
|
||||
void OpenGLShaderManagerDialog::on_targetFrameRate_valueChanged(int arg1)
|
||||
{
|
||||
(void)arg1;
|
||||
|
||||
if (ui->horizontalSliderFramerate->value() != ui->targetFrameRate->value())
|
||||
ui->horizontalSliderFramerate->setValue(ui->targetFrameRate->value());
|
||||
}
|
||||
|
||||
50
src/qt/qt_openglshadermanagerdialog.hpp
Normal file
50
src/qt/qt_openglshadermanagerdialog.hpp
Normal file
@@ -0,0 +1,50 @@
|
||||
#ifndef QT_OPENGLSHADERMANAGERDIALOG_H
|
||||
#define QT_OPENGLSHADERMANAGERDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <QAbstractButton>
|
||||
#include <QListWidgetItem>
|
||||
|
||||
namespace Ui {
|
||||
class OpenGLShaderManagerDialog;
|
||||
}
|
||||
|
||||
class OpenGLShaderManagerDialog : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit OpenGLShaderManagerDialog(QWidget *parent = nullptr);
|
||||
~OpenGLShaderManagerDialog();
|
||||
|
||||
private slots:
|
||||
void on_buttonBox_clicked(QAbstractButton *button);
|
||||
|
||||
void on_buttonMoveUp_clicked();
|
||||
|
||||
void on_shaderListWidget_currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous);
|
||||
|
||||
void on_shaderListWidget_currentRowChanged(int currentRow);
|
||||
|
||||
void on_buttonMoveDown_clicked();
|
||||
|
||||
void on_buttonAdd_clicked();
|
||||
|
||||
void on_buttonRemove_clicked();
|
||||
|
||||
void on_OpenGLShaderManagerDialog_accepted();
|
||||
|
||||
void on_buttonConfigure_clicked();
|
||||
|
||||
void on_radioButtonVideoSync_clicked();
|
||||
|
||||
void on_radioButtonTargetFramerate_clicked();
|
||||
|
||||
void on_horizontalSliderFramerate_sliderMoved(int position);
|
||||
|
||||
void on_targetFrameRate_valueChanged(int arg1);
|
||||
|
||||
private:
|
||||
Ui::OpenGLShaderManagerDialog *ui;
|
||||
};
|
||||
|
||||
#endif // QT_OPENGLSHADERMANAGERDIALOG_H
|
||||
204
src/qt/qt_openglshadermanagerdialog.ui
Normal file
204
src/qt/qt_openglshadermanagerdialog.ui
Normal file
@@ -0,0 +1,204 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>OpenGLShaderManagerDialog</class>
|
||||
<widget class="QDialog" name="OpenGLShaderManagerDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>465</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Shader Manager</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SizeConstraint::SetFixedSize</enum>
|
||||
</property>
|
||||
<item row="1" column="0">
|
||||
<widget class="QGroupBox" name="groupBoxShaders">
|
||||
<property name="title">
|
||||
<string>Shaders</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SizeConstraint::SetFixedSize</enum>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QListWidget" name="shaderListWidget">
|
||||
<property name="dragDropMode">
|
||||
<enum>QAbstractItemView::DragDropMode::InternalMove</enum>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectionBehavior::SelectItems</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SizeConstraint::SetFixedSize</enum>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="buttonAdd">
|
||||
<property name="text">
|
||||
<string>Add</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="buttonRemove">
|
||||
<property name="text">
|
||||
<string>Remove</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="buttonConfigure">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Configure</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="buttonMoveUp">
|
||||
<property name="text">
|
||||
<string>Move up</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="buttonMoveDown">
|
||||
<property name="text">
|
||||
<string>Move down</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::StandardButton::Apply|QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok</set>
|
||||
</property>
|
||||
<property name="centerButtons">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Render behavior</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SizeConstraint::SetDefaultConstraint</enum>
|
||||
</property>
|
||||
<item row="1" column="0">
|
||||
<widget class="QRadioButton" name="radioButtonTargetFramerate">
|
||||
<property name="text">
|
||||
<string>Use target framerate:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QSlider" name="horizontalSliderFramerate">
|
||||
<property name="minimum">
|
||||
<number>15</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>240</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>60</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="invertedAppearance">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="invertedControls">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QRadioButton" name="radioButtonVideoSync">
|
||||
<property name="text">
|
||||
<string>Synchronize with video</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QCheckBox" name="checkBoxVSync">
|
||||
<property name="text">
|
||||
<string>VSync</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QSpinBox" name="targetFrameRate">
|
||||
<property name="suffix">
|
||||
<string> fps</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>15</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>240</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>60</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -385,6 +385,7 @@ plat_munmap(void *ptr, size_t size)
|
||||
#endif
|
||||
}
|
||||
|
||||
extern bool cpu_thread_running;
|
||||
void
|
||||
plat_pause(int p)
|
||||
{
|
||||
@@ -392,6 +393,10 @@ plat_pause(int p)
|
||||
wchar_t title[1024];
|
||||
wchar_t paused_msg[512];
|
||||
|
||||
if (!cpu_thread_running && p == 1) {
|
||||
p = 2;
|
||||
}
|
||||
|
||||
if ((!!p) == dopause) {
|
||||
#ifdef Q_OS_WINDOWS
|
||||
if (source_hwnd)
|
||||
|
||||
@@ -34,6 +34,8 @@ public:
|
||||
virtual QDialog *getOptions(QWidget *parent) { return nullptr; }
|
||||
/* Reloads options of renderer */
|
||||
virtual void reloadOptions() { }
|
||||
/* Make the renderer reload itself */
|
||||
virtual bool reloadRendererOption() { return false; }
|
||||
|
||||
int r_monitor_index = 0;
|
||||
|
||||
|
||||
@@ -337,6 +337,26 @@ RendererStack::createRenderer(Renderer renderer)
|
||||
current.reset(this->createWindowContainer(hw, this));
|
||||
break;
|
||||
}
|
||||
case Renderer::OpenGL3PCem:
|
||||
{
|
||||
this->createWinId();
|
||||
auto hw = new OpenGLRenderer(this);
|
||||
rendererWindow = hw;
|
||||
connect(this, &RendererStack::blitToRenderer, hw, &OpenGLRenderer::onBlit, Qt::QueuedConnection);
|
||||
connect(hw, &OpenGLRenderer::initialized, [=]() {
|
||||
/* Buffers are available only after initialization. */
|
||||
imagebufs = rendererWindow->getBuffers();
|
||||
endblit();
|
||||
emit rendererChanged();
|
||||
});
|
||||
connect(hw, &OpenGLRenderer::errorInitializing, [=]() {
|
||||
/* Renderer not could initialize, fallback to software. */
|
||||
imagebufs = {};
|
||||
QTimer::singleShot(0, this, [this]() { switchRenderer(Renderer::Software); });
|
||||
});
|
||||
current.reset(this->createWindowContainer(hw, this));
|
||||
break;
|
||||
}
|
||||
case Renderer::OpenGL3:
|
||||
{
|
||||
this->createWinId();
|
||||
@@ -406,7 +426,7 @@ RendererStack::createRenderer(Renderer renderer)
|
||||
|
||||
currentBuf = 0;
|
||||
|
||||
if (renderer != Renderer::OpenGL3 && renderer != Renderer::Vulkan) {
|
||||
if (renderer != Renderer::OpenGL3 && renderer != Renderer::Vulkan && renderer != Renderer::OpenGL3PCem) {
|
||||
imagebufs = rendererWindow->getBuffers();
|
||||
endblit();
|
||||
emit rendererChanged();
|
||||
|
||||
@@ -59,6 +59,7 @@ public:
|
||||
OpenGLES,
|
||||
OpenGL3,
|
||||
Vulkan,
|
||||
OpenGL3PCem = 6,
|
||||
None = -1
|
||||
};
|
||||
void switchRenderer(Renderer renderer);
|
||||
@@ -69,6 +70,8 @@ public:
|
||||
void reloadOptions() const { return rendererWindow->reloadOptions(); }
|
||||
/* Returns options dialog for current renderer */
|
||||
QDialog *getOptions(QWidget *parent) { return rendererWindow ? rendererWindow->getOptions(parent) : nullptr; }
|
||||
/* Reload the renderer itself */
|
||||
bool reloadRendererOption() { return rendererWindow ? rendererWindow->reloadRendererOption() : false; }
|
||||
|
||||
void setFocusRenderer();
|
||||
void onResize(int width, int height);
|
||||
|
||||
@@ -50,13 +50,15 @@ void
|
||||
SettingsSound::save()
|
||||
{
|
||||
for (uint8_t i = 0; i < SOUND_CARD_MAX; ++i) {
|
||||
auto *cbox = findChild<QComboBox *>(QString("comboBoxSoundCard%1").arg(i + 1));
|
||||
sound_card_current[i] = cbox->currentData().toInt();
|
||||
QComboBox *cbox = findChild<QComboBox *>(QString("comboBoxSoundCard%1").arg(i + 1));
|
||||
sound_card_current[i] = cbox->currentData().toInt();
|
||||
}
|
||||
|
||||
midi_output_device_current = ui->comboBoxMidiOut->currentData().toInt();
|
||||
midi_input_device_current = ui->comboBoxMidiIn->currentData().toInt();
|
||||
mpu401_standalone_enable = ui->checkBoxMPU401->isChecked() ? 1 : 0;
|
||||
|
||||
midi_input_device_current = ui->comboBoxMidiIn->currentData().toInt();
|
||||
|
||||
mpu401_standalone_enable = ui->checkBoxMPU401->isChecked() ? 1 : 0;
|
||||
|
||||
sound_is_float = ui->checkBoxFloat32->isChecked() ? 1 : 0;
|
||||
|
||||
@@ -74,12 +76,13 @@ SettingsSound::onCurrentMachineChanged(const int machineId)
|
||||
int c;
|
||||
int selectedRow;
|
||||
|
||||
// Sound Card
|
||||
for (uint8_t i = 0; i < SOUND_CARD_MAX; ++i) {
|
||||
auto * cbox = findChild<QComboBox *>(QString("comboBoxSoundCard%1").arg(i + 1));
|
||||
auto * model = cbox->model();
|
||||
const auto removeRows = model->rowCount();
|
||||
c = 0;
|
||||
selectedRow = 0;
|
||||
QComboBox *cbox = findChild<QComboBox *>(QString("comboBoxSoundCard%1").arg(i + 1));
|
||||
c = 0;
|
||||
auto model = cbox->model();
|
||||
auto removeRows = model->rowCount();
|
||||
selectedRow = 0;
|
||||
|
||||
while (true) {
|
||||
/* Skip "internal" if machine doesn't have it or this is not the primary card. */
|
||||
@@ -88,17 +91,21 @@ SettingsSound::onCurrentMachineChanged(const int machineId)
|
||||
continue;
|
||||
}
|
||||
|
||||
auto name = DeviceConfig::DeviceName(sound_card_getdevice(c), sound_card_get_internal_name(c), 1);
|
||||
const QString name = DeviceConfig::DeviceName(sound_card_getdevice(c), sound_card_get_internal_name(c), 1);
|
||||
if (name.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (sound_card_available(c) && device_is_valid(sound_card_getdevice(c), machineId)) {
|
||||
int row = Models::AddEntry(model, name, c);
|
||||
if (c == sound_card_current[i]) {
|
||||
selectedRow = row - removeRows;
|
||||
if (sound_card_available(c)) {
|
||||
const device_t *sound_dev = sound_card_getdevice(c);
|
||||
if (device_is_valid(sound_dev, machineId)) {
|
||||
int row = Models::AddEntry(model, name, c);
|
||||
if (c == sound_card_current[i]) {
|
||||
selectedRow = row - removeRows;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
c++;
|
||||
}
|
||||
|
||||
@@ -108,12 +115,14 @@ SettingsSound::onCurrentMachineChanged(const int machineId)
|
||||
cbox->setCurrentIndex(selectedRow);
|
||||
}
|
||||
|
||||
auto model = ui->comboBoxMidiOut->model();
|
||||
auto removeRows = model->rowCount();
|
||||
c = 0;
|
||||
selectedRow = 0;
|
||||
// Midi Out
|
||||
c = 0;
|
||||
auto model = ui->comboBoxMidiOut->model();
|
||||
auto removeRows = model->rowCount();
|
||||
selectedRow = 0;
|
||||
|
||||
while (true) {
|
||||
QString name = DeviceConfig::DeviceName(midi_out_device_getdevice(c), midi_out_device_get_internal_name(c), 0);
|
||||
const QString name = DeviceConfig::DeviceName(midi_out_device_getdevice(c), midi_out_device_get_internal_name(c), 0);
|
||||
if (name.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
@@ -124,19 +133,23 @@ SettingsSound::onCurrentMachineChanged(const int machineId)
|
||||
selectedRow = row - removeRows;
|
||||
}
|
||||
}
|
||||
|
||||
c++;
|
||||
}
|
||||
|
||||
model->removeRows(0, removeRows);
|
||||
ui->comboBoxMidiOut->setEnabled(model->rowCount() > 0);
|
||||
ui->comboBoxMidiOut->setCurrentIndex(-1);
|
||||
ui->comboBoxMidiOut->setCurrentIndex(selectedRow);
|
||||
|
||||
// Midi In
|
||||
c = 0;
|
||||
model = ui->comboBoxMidiIn->model();
|
||||
removeRows = model->rowCount();
|
||||
c = 0;
|
||||
selectedRow = 0;
|
||||
|
||||
while (true) {
|
||||
QString name = DeviceConfig::DeviceName(midi_in_device_getdevice(c), midi_in_device_get_internal_name(c), 0);
|
||||
const QString name = DeviceConfig::DeviceName(midi_in_device_getdevice(c), midi_in_device_get_internal_name(c), 0);
|
||||
if (name.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
@@ -150,14 +163,19 @@ SettingsSound::onCurrentMachineChanged(const int machineId)
|
||||
|
||||
c++;
|
||||
}
|
||||
|
||||
model->removeRows(0, removeRows);
|
||||
ui->comboBoxMidiIn->setEnabled(model->rowCount() > 0);
|
||||
ui->comboBoxMidiIn->setCurrentIndex(-1);
|
||||
ui->comboBoxMidiIn->setCurrentIndex(selectedRow);
|
||||
|
||||
// Standalone MPU401
|
||||
ui->checkBoxMPU401->setChecked(mpu401_standalone_enable > 0);
|
||||
|
||||
// Float32 Sound
|
||||
ui->checkBoxFloat32->setChecked(sound_is_float > 0);
|
||||
|
||||
// FM Driver
|
||||
switch (fm_driver) {
|
||||
case FM_DRV_YMFM:
|
||||
ui->radioButtonYMFM->setChecked(true);
|
||||
@@ -193,6 +211,7 @@ SettingsSound::on_comboBoxSoundCard1_currentIndexChanged(int index)
|
||||
return;
|
||||
}
|
||||
int sndCard = ui->comboBoxSoundCard1->currentData().toInt();
|
||||
|
||||
if (sndCard == SOUND_INTERNAL)
|
||||
ui->pushButtonConfigureSoundCard1->setEnabled(machine_has_flags(machineId, MACHINE_SOUND) &&
|
||||
device_has_config(machine_get_snd_device(machineId)));
|
||||
@@ -203,8 +222,9 @@ SettingsSound::on_comboBoxSoundCard1_currentIndexChanged(int index)
|
||||
void
|
||||
SettingsSound::on_pushButtonConfigureSoundCard1_clicked()
|
||||
{
|
||||
int sndCard = ui->comboBoxSoundCard1->currentData().toInt();
|
||||
auto *device = sound_card_getdevice(sndCard);
|
||||
int sndCard = ui->comboBoxSoundCard1->currentData().toInt();
|
||||
auto *device = sound_card_getdevice(sndCard);
|
||||
|
||||
if (sndCard == SOUND_INTERNAL)
|
||||
device = machine_get_snd_device(machineId);
|
||||
DeviceConfig::ConfigureDevice(device, 1, qobject_cast<Settings *>(Settings::settings));
|
||||
@@ -216,15 +236,17 @@ SettingsSound::on_comboBoxSoundCard2_currentIndexChanged(int index)
|
||||
if (index < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
int sndCard = ui->comboBoxSoundCard2->currentData().toInt();
|
||||
|
||||
ui->pushButtonConfigureSoundCard2->setEnabled(sound_card_has_config(sndCard));
|
||||
}
|
||||
|
||||
void
|
||||
SettingsSound::on_pushButtonConfigureSoundCard2_clicked()
|
||||
{
|
||||
int sndCard = ui->comboBoxSoundCard2->currentData().toInt();
|
||||
auto *device = sound_card_getdevice(sndCard);
|
||||
int sndCard = ui->comboBoxSoundCard2->currentData().toInt();
|
||||
const device_t *device = sound_card_getdevice(sndCard);
|
||||
DeviceConfig::ConfigureDevice(device, 2, qobject_cast<Settings *>(Settings::settings));
|
||||
}
|
||||
|
||||
@@ -234,15 +256,18 @@ SettingsSound::on_comboBoxSoundCard3_currentIndexChanged(int index)
|
||||
if (index < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
int sndCard = ui->comboBoxSoundCard3->currentData().toInt();
|
||||
|
||||
ui->pushButtonConfigureSoundCard3->setEnabled(sound_card_has_config(sndCard));
|
||||
}
|
||||
|
||||
void
|
||||
SettingsSound::on_pushButtonConfigureSoundCard3_clicked()
|
||||
{
|
||||
int sndCard = ui->comboBoxSoundCard3->currentData().toInt();
|
||||
auto *device = sound_card_getdevice(sndCard);
|
||||
int sndCard = ui->comboBoxSoundCard3->currentData().toInt();
|
||||
const device_t *device = sound_card_getdevice(sndCard);
|
||||
|
||||
DeviceConfig::ConfigureDevice(device, 3, qobject_cast<Settings *>(Settings::settings));
|
||||
}
|
||||
|
||||
@@ -252,15 +277,18 @@ SettingsSound::on_comboBoxSoundCard4_currentIndexChanged(int index)
|
||||
if (index < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
int sndCard = ui->comboBoxSoundCard4->currentData().toInt();
|
||||
|
||||
ui->pushButtonConfigureSoundCard4->setEnabled(sound_card_has_config(sndCard));
|
||||
}
|
||||
|
||||
void
|
||||
SettingsSound::on_pushButtonConfigureSoundCard4_clicked()
|
||||
{
|
||||
int sndCard = ui->comboBoxSoundCard4->currentData().toInt();
|
||||
auto *device = sound_card_getdevice(sndCard);
|
||||
int sndCard = ui->comboBoxSoundCard4->currentData().toInt();
|
||||
const device_t *device = sound_card_getdevice(sndCard);
|
||||
|
||||
DeviceConfig::ConfigureDevice(device, 4, qobject_cast<Settings *>(Settings::settings));
|
||||
}
|
||||
|
||||
@@ -270,6 +298,7 @@ SettingsSound::on_comboBoxMidiOut_currentIndexChanged(int index)
|
||||
if (index < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
ui->pushButtonConfigureMidiOut->setEnabled(midi_out_device_has_config(ui->comboBoxMidiOut->currentData().toInt()));
|
||||
ui->checkBoxMPU401->setEnabled(allowMpu401(ui) && (machine_has_bus(machineId, MACHINE_BUS_ISA) || machine_has_bus(machineId, MACHINE_BUS_MCA)));
|
||||
ui->pushButtonConfigureMPU401->setEnabled(allowMpu401(ui) && ui->checkBoxMPU401->isChecked());
|
||||
@@ -288,6 +317,7 @@ SettingsSound::on_comboBoxMidiIn_currentIndexChanged(int index)
|
||||
if (index < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
ui->pushButtonConfigureMidiIn->setEnabled(midi_in_device_has_config(ui->comboBoxMidiIn->currentData().toInt()));
|
||||
ui->checkBoxMPU401->setEnabled(allowMpu401(ui) && (machine_has_bus(machineId, MACHINE_BUS_ISA) || machine_has_bus(machineId, MACHINE_BUS_MCA)));
|
||||
ui->pushButtonConfigureMPU401->setEnabled(allowMpu401(ui) && ui->checkBoxMPU401->isChecked());
|
||||
|
||||
@@ -52,8 +52,8 @@ void
|
||||
SettingsStorageControllers::save()
|
||||
{
|
||||
/* Storage devices category */
|
||||
for (int i = 0; i < SCSI_CARD_MAX; ++i) {
|
||||
auto *cbox = findChild<QComboBox *>(QString("comboBoxSCSI%1").arg(i + 1));
|
||||
for (uint8_t i = 0; i < SCSI_CARD_MAX; ++i) {
|
||||
QComboBox *cbox = findChild<QComboBox *>(QString("comboBoxSCSI%1").arg(i + 1));
|
||||
scsi_card_current[i] = cbox->currentData().toInt();
|
||||
}
|
||||
hdc_current[0] = ui->comboBoxHD->currentData().toInt();
|
||||
@@ -71,10 +71,11 @@ SettingsStorageControllers::onCurrentMachineChanged(int machineId)
|
||||
this->machineId = machineId;
|
||||
|
||||
/*HD controller config*/
|
||||
int c = 0;
|
||||
auto *model = ui->comboBoxHD->model();
|
||||
auto removeRows = model->rowCount();
|
||||
int c = 0;
|
||||
int selectedRow = 0;
|
||||
|
||||
while (true) {
|
||||
/* Skip "internal" if machine doesn't have it. */
|
||||
if ((c == 1) && (machine_has_flags(machineId, MACHINE_HDC) == 0)) {
|
||||
@@ -88,7 +89,7 @@ SettingsStorageControllers::onCurrentMachineChanged(int machineId)
|
||||
}
|
||||
|
||||
if (hdc_available(c)) {
|
||||
auto *hdc_dev = hdc_get_device(c);
|
||||
const device_t *hdc_dev = hdc_get_device(c);
|
||||
|
||||
if (device_is_valid(hdc_dev, machineId)) {
|
||||
int row = Models::AddEntry(model, name, c);
|
||||
@@ -124,7 +125,7 @@ SettingsStorageControllers::onCurrentMachineChanged(int machineId)
|
||||
}
|
||||
|
||||
if (fdc_card_available(c)) {
|
||||
auto *fdc_dev = fdc_card_getdevice(c);
|
||||
const device_t *fdc_dev = fdc_card_getdevice(c);
|
||||
|
||||
if (device_is_valid(fdc_dev, machineId)) {
|
||||
int row = Models::AddEntry(model, name, c);
|
||||
@@ -141,10 +142,11 @@ SettingsStorageControllers::onCurrentMachineChanged(int machineId)
|
||||
ui->comboBoxFD->setCurrentIndex(selectedRow);
|
||||
|
||||
/*CD interface controller config*/
|
||||
model = ui->comboBoxCDInterface->model();
|
||||
removeRows = model->rowCount();
|
||||
c = 0;
|
||||
c = 0;
|
||||
model = ui->comboBoxCDInterface->model();
|
||||
removeRows = model->rowCount();
|
||||
selectedRow = 0;
|
||||
|
||||
while (true) {
|
||||
/* Skip "internal" if machine doesn't have it. */
|
||||
QString name = DeviceConfig::DeviceName(cdrom_interface_get_device(c), cdrom_interface_get_internal_name(c), 1);
|
||||
@@ -153,7 +155,7 @@ SettingsStorageControllers::onCurrentMachineChanged(int machineId)
|
||||
}
|
||||
|
||||
if (cdrom_interface_available(c)) {
|
||||
auto *cdrom_interface_dev = cdrom_interface_get_device(c);
|
||||
const device_t *cdrom_interface_dev = cdrom_interface_get_device(c);
|
||||
|
||||
if (device_is_valid(cdrom_interface_dev, machineId)) {
|
||||
int row = Models::AddEntry(model, name, c);
|
||||
@@ -169,21 +171,21 @@ SettingsStorageControllers::onCurrentMachineChanged(int machineId)
|
||||
ui->comboBoxCDInterface->setCurrentIndex(-1);
|
||||
ui->comboBoxCDInterface->setCurrentIndex(selectedRow);
|
||||
|
||||
for (int i = 0; i < SCSI_CARD_MAX; ++i) {
|
||||
auto *cbox = findChild<QComboBox *>(QString("comboBoxSCSI%1").arg(i + 1));
|
||||
model = cbox->model();
|
||||
removeRows = model->rowCount();
|
||||
c = 0;
|
||||
selectedRow = 0;
|
||||
for (uint8_t i = 0; i < SCSI_CARD_MAX; ++i) {
|
||||
QComboBox *cbox = findChild<QComboBox *>(QString("comboBoxSCSI%1").arg(i + 1));
|
||||
c = 0;
|
||||
model = cbox->model();
|
||||
removeRows = model->rowCount();
|
||||
selectedRow = 0;
|
||||
|
||||
while (true) {
|
||||
auto name = DeviceConfig::DeviceName(scsi_card_getdevice(c), scsi_card_get_internal_name(c), 1);
|
||||
QString name = DeviceConfig::DeviceName(scsi_card_getdevice(c), scsi_card_get_internal_name(c), 1);
|
||||
if (name.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (scsi_card_available(c)) {
|
||||
auto *scsi_dev = scsi_card_getdevice(c);
|
||||
const device_t *scsi_dev = scsi_card_getdevice(c);
|
||||
if (device_is_valid(scsi_dev, machineId)) {
|
||||
int row = Models::AddEntry(model, name, c);
|
||||
if (c == scsi_card_current[i]) {
|
||||
@@ -236,7 +238,8 @@ SettingsStorageControllers::on_comboBoxFD_currentIndexChanged(int index)
|
||||
ui->pushButtonFD->setEnabled(hdc_has_config(ui->comboBoxFD->currentData().toInt()) > 0);
|
||||
}
|
||||
|
||||
void SettingsStorageControllers::on_comboBoxCDInterface_currentIndexChanged(int index)
|
||||
void
|
||||
SettingsStorageControllers::on_comboBoxCDInterface_currentIndexChanged(int index)
|
||||
{
|
||||
if (index < 0) {
|
||||
return;
|
||||
@@ -346,14 +349,14 @@ SettingsStorageControllers::on_pushButtonSCSI4_clicked()
|
||||
DeviceConfig::ConfigureDevice(scsi_card_getdevice(ui->comboBoxSCSI4->currentData().toInt()), 4, qobject_cast<Settings *>(Settings::settings));
|
||||
}
|
||||
|
||||
void SettingsStorageControllers::on_checkBoxLbaEnhancer_stateChanged(int arg1)
|
||||
void
|
||||
SettingsStorageControllers::on_checkBoxLbaEnhancer_stateChanged(int arg1)
|
||||
{
|
||||
ui->pushButtonConfigureLbaEnhancer->setEnabled(arg1 != 0);
|
||||
}
|
||||
|
||||
|
||||
void SettingsStorageControllers::on_pushButtonConfigureLbaEnhancer_clicked()
|
||||
void
|
||||
SettingsStorageControllers::on_pushButtonConfigureLbaEnhancer_clicked()
|
||||
{
|
||||
DeviceConfig::ConfigureDevice(&lba_enhancer_device);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user