summaryrefslogtreecommitdiffstatshomepage
path: root/src/osd/modules
diff options
context:
space:
mode:
Diffstat (limited to 'src/osd/modules')
-rw-r--r--src/osd/modules/debugger/debug_module.h13
-rw-r--r--src/osd/modules/debugger/debuggdbstub.cpp204
-rw-r--r--src/osd/modules/debugger/debugimgui.cpp179
-rw-r--r--src/osd/modules/debugger/debugosx.mm23
-rw-r--r--src/osd/modules/debugger/debugqt.cpp369
-rw-r--r--src/osd/modules/debugger/debugwin.cpp278
-rw-r--r--src/osd/modules/debugger/none.cpp18
-rw-r--r--src/osd/modules/debugger/osx/debugcommandhistory.h5
-rw-r--r--src/osd/modules/debugger/osx/debugcommandhistory.mm32
-rw-r--r--src/osd/modules/debugger/osx/debugconsole.mm65
-rw-r--r--src/osd/modules/debugger/osx/debugosx.h35
-rw-r--r--src/osd/modules/debugger/osx/debugview.mm77
-rw-r--r--src/osd/modules/debugger/osx/debugwindowhandler.h13
-rw-r--r--src/osd/modules/debugger/osx/debugwindowhandler.mm38
-rw-r--r--src/osd/modules/debugger/osx/deviceinfoviewer.mm23
-rw-r--r--src/osd/modules/debugger/osx/devicesviewer.mm10
-rw-r--r--src/osd/modules/debugger/osx/disassemblyview.mm8
-rw-r--r--src/osd/modules/debugger/osx/disassemblyviewer.mm18
-rw-r--r--src/osd/modules/debugger/osx/errorlogviewer.mm12
-rw-r--r--src/osd/modules/debugger/osx/memoryview.mm18
-rw-r--r--src/osd/modules/debugger/osx/memoryviewer.mm16
-rw-r--r--src/osd/modules/debugger/osx/pointsviewer.mm32
-rw-r--r--src/osd/modules/debugger/qt/breakpointswindow.cpp96
-rw-r--r--src/osd/modules/debugger/qt/breakpointswindow.h33
-rw-r--r--src/osd/modules/debugger/qt/dasmwindow.cpp205
-rw-r--r--src/osd/modules/debugger/qt/dasmwindow.h43
-rw-r--r--src/osd/modules/debugger/qt/debuggerview.cpp60
-rw-r--r--src/osd/modules/debugger/qt/debuggerview.h19
-rw-r--r--src/osd/modules/debugger/qt/deviceinformationwindow.cpp68
-rw-r--r--src/osd/modules/debugger/qt/deviceinformationwindow.h38
-rw-r--r--src/osd/modules/debugger/qt/deviceswindow.cpp42
-rw-r--r--src/osd/modules/debugger/qt/deviceswindow.h32
-rw-r--r--src/osd/modules/debugger/qt/logwindow.cpp37
-rw-r--r--src/osd/modules/debugger/qt/logwindow.h32
-rw-r--r--src/osd/modules/debugger/qt/mainwindow.cpp264
-rw-r--r--src/osd/modules/debugger/qt/mainwindow.h57
-rw-r--r--src/osd/modules/debugger/qt/memorywindow.cpp446
-rw-r--r--src/osd/modules/debugger/qt/memorywindow.h54
-rw-r--r--src/osd/modules/debugger/qt/windowqt.cpp193
-rw-r--r--src/osd/modules/debugger/qt/windowqt.h107
-rw-r--r--src/osd/modules/debugger/win/consolewininfo.cpp163
-rw-r--r--src/osd/modules/debugger/win/consolewininfo.h7
-rw-r--r--src/osd/modules/debugger/win/debugbaseinfo.cpp4
-rw-r--r--src/osd/modules/debugger/win/debugbaseinfo.h6
-rw-r--r--src/osd/modules/debugger/win/debugviewinfo.cpp93
-rw-r--r--src/osd/modules/debugger/win/debugviewinfo.h10
-rw-r--r--src/osd/modules/debugger/win/debugwin.h13
-rw-r--r--src/osd/modules/debugger/win/debugwininfo.cpp129
-rw-r--r--src/osd/modules/debugger/win/debugwininfo.h25
-rw-r--r--src/osd/modules/debugger/win/disasmbasewininfo.cpp28
-rw-r--r--src/osd/modules/debugger/win/disasmbasewininfo.h6
-rw-r--r--src/osd/modules/debugger/win/disasmviewinfo.cpp32
-rw-r--r--src/osd/modules/debugger/win/disasmviewinfo.h8
-rw-r--r--src/osd/modules/debugger/win/disasmwininfo.cpp44
-rw-r--r--src/osd/modules/debugger/win/disasmwininfo.h9
-rw-r--r--src/osd/modules/debugger/win/editwininfo.cpp51
-rw-r--r--src/osd/modules/debugger/win/editwininfo.h10
-rw-r--r--src/osd/modules/debugger/win/logviewinfo.cpp6
-rw-r--r--src/osd/modules/debugger/win/logviewinfo.h4
-rw-r--r--src/osd/modules/debugger/win/logwininfo.cpp23
-rw-r--r--src/osd/modules/debugger/win/logwininfo.h7
-rw-r--r--src/osd/modules/debugger/win/memoryviewinfo.cpp61
-rw-r--r--src/osd/modules/debugger/win/memoryviewinfo.h8
-rw-r--r--src/osd/modules/debugger/win/memorywininfo.cpp46
-rw-r--r--src/osd/modules/debugger/win/memorywininfo.h8
-rw-r--r--src/osd/modules/debugger/win/pointswininfo.cpp57
-rw-r--r--src/osd/modules/debugger/win/pointswininfo.h8
-rw-r--r--src/osd/modules/debugger/win/uimetrics.cpp93
-rw-r--r--src/osd/modules/debugger/win/uimetrics.h41
-rw-r--r--src/osd/modules/debugger/xmlconfig.cpp53
-rw-r--r--src/osd/modules/debugger/xmlconfig.h71
-rw-r--r--src/osd/modules/diagnostics/diagnostics_win32.cpp86
-rw-r--r--src/osd/modules/file/posixdir.cpp2
-rw-r--r--src/osd/modules/file/posixfile.cpp2
-rw-r--r--src/osd/modules/file/winfile.cpp94
-rw-r--r--src/osd/modules/file/winfile.h2
-rw-r--r--src/osd/modules/file/winptty.cpp10
-rw-r--r--src/osd/modules/file/winrtfile.cpp6
-rw-r--r--src/osd/modules/font/font_dwrite.cpp38
-rw-r--r--src/osd/modules/font/font_module.h2
-rw-r--r--src/osd/modules/font/font_none.cpp16
-rw-r--r--src/osd/modules/font/font_osx.cpp3
-rw-r--r--src/osd/modules/font/font_sdl.cpp12
-rw-r--r--src/osd/modules/font/font_windows.cpp19
-rw-r--r--src/osd/modules/input/assignmenthelper.cpp592
-rw-r--r--src/osd/modules/input/assignmenthelper.h118
-rw-r--r--src/osd/modules/input/input_common.cpp404
-rw-r--r--src/osd/modules/input/input_common.h428
-rw-r--r--src/osd/modules/input/input_dinput.cpp1399
-rw-r--r--src/osd/modules/input/input_dinput.h282
-rw-r--r--src/osd/modules/input/input_mac.cpp7
-rw-r--r--src/osd/modules/input/input_module.h13
-rw-r--r--src/osd/modules/input/input_none.cpp60
-rw-r--r--src/osd/modules/input/input_rawinput.cpp536
-rw-r--r--src/osd/modules/input/input_sdl.cpp2441
-rw-r--r--src/osd/modules/input/input_sdlcommon.cpp337
-rw-r--r--src/osd/modules/input/input_sdlcommon.h142
-rw-r--r--src/osd/modules/input/input_win32.cpp477
-rw-r--r--src/osd/modules/input/input_wincommon.h39
-rw-r--r--src/osd/modules/input/input_windows.cpp85
-rw-r--r--src/osd/modules/input/input_windows.h56
-rw-r--r--src/osd/modules/input/input_winhybrid.cpp299
-rw-r--r--src/osd/modules/input/input_x11.cpp625
-rw-r--r--src/osd/modules/input/input_xinput.cpp3200
-rw-r--r--src/osd/modules/input/input_xinput.h66
-rw-r--r--src/osd/modules/lib/osdlib.h59
-rw-r--r--src/osd/modules/lib/osdlib_macosx.cpp93
-rw-r--r--src/osd/modules/lib/osdlib_unix.cpp58
-rw-r--r--src/osd/modules/lib/osdlib_win32.cpp95
-rw-r--r--src/osd/modules/lib/osdobj_common.cpp518
-rw-r--r--src/osd/modules/lib/osdobj_common.h82
-rw-r--r--src/osd/modules/midi/midi_module.h25
-rw-r--r--src/osd/modules/midi/none.cpp85
-rw-r--r--src/osd/modules/midi/portmidi.cpp370
-rw-r--r--src/osd/modules/monitor/monitor_common.cpp2
-rw-r--r--src/osd/modules/monitor/monitor_common.h34
-rw-r--r--src/osd/modules/monitor/monitor_module.h3
-rw-r--r--src/osd/modules/monitor/monitor_sdl.cpp11
-rw-r--r--src/osd/modules/netdev/netdev_module.h14
-rw-r--r--src/osd/modules/netdev/none.cpp18
-rw-r--r--src/osd/modules/netdev/pcap.cpp64
-rw-r--r--src/osd/modules/netdev/taptun.cpp73
-rw-r--r--src/osd/modules/opengl/gl_shader_mgr.cpp374
-rw-r--r--src/osd/modules/opengl/gl_shader_mgr.h84
-rw-r--r--src/osd/modules/opengl/gl_shader_tool.cpp647
-rw-r--r--src/osd/modules/opengl/gl_shader_tool.h218
-rw-r--r--src/osd/modules/opengl/osd_opengl.h154
-rw-r--r--src/osd/modules/osdmodule.cpp78
-rw-r--r--src/osd/modules/osdmodule.h42
-rw-r--r--src/osd/modules/osdwindow.cpp110
-rw-r--r--src/osd/modules/osdwindow.h150
-rw-r--r--src/osd/modules/output/console.cpp18
-rw-r--r--src/osd/modules/output/network.cpp308
-rw-r--r--src/osd/modules/output/none.cpp16
-rw-r--r--src/osd/modules/output/output_module.h24
-rw-r--r--src/osd/modules/output/win32_output.cpp48
-rw-r--r--src/osd/modules/output/win32_output.h12
-rw-r--r--src/osd/modules/render/aviwrite.cpp6
-rw-r--r--src/osd/modules/render/aviwrite.h17
-rw-r--r--src/osd/modules/render/bgfx/blendreader.cpp11
-rw-r--r--src/osd/modules/render/bgfx/chain.cpp42
-rw-r--r--src/osd/modules/render/bgfx/chain.h17
-rw-r--r--src/osd/modules/render/bgfx/chainentry.cpp97
-rw-r--r--src/osd/modules/render/bgfx/chainentry.h14
-rw-r--r--src/osd/modules/render/bgfx/chainentryreader.cpp48
-rw-r--r--src/osd/modules/render/bgfx/chainentryreader.h12
-rw-r--r--src/osd/modules/render/bgfx/chainmanager.cpp463
-rw-r--r--src/osd/modules/render/bgfx/chainmanager.h97
-rw-r--r--src/osd/modules/render/bgfx/chainreader.cpp58
-rw-r--r--src/osd/modules/render/bgfx/chainreader.h15
-rw-r--r--src/osd/modules/render/bgfx/clearreader.cpp22
-rw-r--r--src/osd/modules/render/bgfx/clearreader.h14
-rw-r--r--src/osd/modules/render/bgfx/depthreader.cpp8
-rw-r--r--src/osd/modules/render/bgfx/depthreader.h10
-rw-r--r--src/osd/modules/render/bgfx/effect.cpp40
-rw-r--r--src/osd/modules/render/bgfx/effect.h23
-rw-r--r--src/osd/modules/render/bgfx/effectmanager.cpp74
-rw-r--r--src/osd/modules/render/bgfx/effectmanager.h29
-rw-r--r--src/osd/modules/render/bgfx/effectreader.cpp107
-rw-r--r--src/osd/modules/render/bgfx/effectreader.h24
-rw-r--r--src/osd/modules/render/bgfx/entryuniform.h12
-rw-r--r--src/osd/modules/render/bgfx/entryuniformreader.cpp12
-rw-r--r--src/osd/modules/render/bgfx/entryuniformreader.h14
-rw-r--r--src/osd/modules/render/bgfx/frameparameter.cpp8
-rw-r--r--src/osd/modules/render/bgfx/frameparameter.h16
-rw-r--r--src/osd/modules/render/bgfx/inputpair.cpp40
-rw-r--r--src/osd/modules/render/bgfx/parameter.h15
-rw-r--r--src/osd/modules/render/bgfx/paramreader.cpp32
-rw-r--r--src/osd/modules/render/bgfx/paramreader.h14
-rw-r--r--src/osd/modules/render/bgfx/paramuniform.h8
-rw-r--r--src/osd/modules/render/bgfx/paramuniformreader.cpp10
-rw-r--r--src/osd/modules/render/bgfx/paramuniformreader.h16
-rw-r--r--src/osd/modules/render/bgfx/shadermanager.cpp23
-rw-r--r--src/osd/modules/render/bgfx/shadermanager.h24
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/blurs/fs_smart-blur.sc32
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/blurs/vs_smart-blur.sc4
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/crt-geom/crt-geom_common.sc214
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_crt-geom-deluxe.sc14
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_crt-geom.sc120
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_gaussx.sc38
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_gaussy.sc38
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_lowpass.sc2
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_mipmap8.sc24
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_phosphor_apply.sc10
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_crt-geom.sc102
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_gaussx.sc16
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_gaussy.sc16
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_lowpass.sc72
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_mipmap8.sc11
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_phosphor_apply.sc11
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_phosphor_update.sc11
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/crt/vs_crt-caligari.sc4
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/default/vs_blit.sc5
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/eagle/fs_eagle.sc14
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/eagle/vs_eagle.sc4
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_defocus.sc2
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_distortion.sc4
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_scanline.sc27
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_chroma.sc5
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_color.sc5
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_deconverge.sc4
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_defocus.sc5
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_distortion.sc5
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_ntsc_decode.sc5
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_ntsc_encode.sc5
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_phosphor.sc5
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_post.sc5
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_prescale.sc5
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_scanline.sc5
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/hqx/fs_hq2x.sc4
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/hqx/fs_hq3x.sc4
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/hqx/fs_hq4x.sc4
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/hqx/vs_hq2x.sc4
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/hqx/vs_hq3x.sc4
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/hqx/vs_hq4x.sc4
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/lcd-grid/fs_lcd-grid.sc116
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/lcd-grid/fs_persistence.sc6
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/lcd-grid/vs_lcd-grid.sc5
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/lcd-grid/vs_persistence.sc5
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/misc/fs_deposterize-pass0.sc2
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/misc/fs_deposterize-pass1.sc2
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/misc/vs_blit.sc5
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/misc/vs_bob-and-ghost-deinterlace.sc5
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/misc/vs_deposterize-pass0.sc4
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/misc/vs_deposterize-pass1.sc4
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/misc/vs_lut.sc5
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/misc/vs_resize_blit.sc21
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/misc/vs_saturation.sc5
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/pillarbox_left_horizontal/vs_gaussian.sc5
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/pillarbox_left_horizontal/vs_offset_sat.sc9
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/pillarbox_left_vertical/vs_gaussian.sc5
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/pillarbox_left_vertical/vs_offset_sat.sc9
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/pillarbox_right_horizontal/vs_gaussian.sc5
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/pillarbox_right_horizontal/vs_offset_sat.sc9
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/pillarbox_right_vertical/vs_gaussian.sc5
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/pillarbox_right_vertical/vs_offset_sat.sc9
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/unfiltered/vs_blit.sc5
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/warp/vs_dilation-horizontal-fast.sc6
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/fs_custom-jinc2-sharper.sc14
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/fs_super-2xbr-3d-pass0.sc14
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_custom-jinc2-sharper.sc5
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-2xbr-3d-pass0.sc5
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-2xbr-3d-pass1.sc5
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-2xbr-3d-pass2.sc4
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-4xbr-3d-pass0.sc5
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-4xbr-3d-pass1.sc5
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-4xbr-3d-pass1f.sc4
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-4xbr-3d-pass2.sc5
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-4xbr-3d-pass3.sc5
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-4xbr-3d-pass3f.sc4
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-fast-pass0.sc5
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-fast-pass1.sc5
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-fast-pass2.sc5
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-pass0.sc4
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-pass1.sc5
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-pass2.sc4
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-pass3.sc4
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv1-noblend.sc4
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv2-3d.sc4
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv2-fast.sc4
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv2-noblend.sc4
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv2.sc4
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv3-noblend.sc4
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv3.sc4
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-sharp.sc4
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-v2-gamma.sc4
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-v2.sc4
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-v4-gamma.sc4
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-v4.sc4
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-v4b.sc4
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-v5-gamma.sc4
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid.sc4
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-a-pass0.sc4
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-accuracy-pass0.sc4
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-accuracy-pass1.sc4
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-b-pass0.sc4
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-c-pass0.sc4
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-d-pass0.sc4
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-noblend-pass1.sc4
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-pass1.sc4
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv3-multipass/fs_xbr-lv3-pass0.sc2
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv3-multipass/vs_xbr-lv3-pass0.sc4
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv3-multipass/vs_xbr-lv3-pass1.sc4
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-mlv4-multipass/fs_xbr-mlv4-pass4.sc2
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-mlv4-multipass/vs_xbr-mlv4-pass1.sc4
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-mlv4-multipass/vs_xbr-mlv4-pass2.sc4
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-mlv4-multipass/vs_xbr-mlv4-pass3.sc4
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-mlv4-multipass/vs_xbr-mlv4-pass4.sc4
-rw-r--r--src/osd/modules/render/bgfx/shaders/vs_gui.sc5
-rw-r--r--src/osd/modules/render/bgfx/shaders/vs_screen.sc5
-rw-r--r--src/osd/modules/render/bgfx/slider.cpp6
-rw-r--r--src/osd/modules/render/bgfx/slider.h16
-rw-r--r--src/osd/modules/render/bgfx/sliderreader.cpp77
-rw-r--r--src/osd/modules/render/bgfx/sliderreader.h16
-rw-r--r--src/osd/modules/render/bgfx/slideruniform.cpp9
-rw-r--r--src/osd/modules/render/bgfx/slideruniform.h10
-rw-r--r--src/osd/modules/render/bgfx/slideruniformreader.cpp16
-rw-r--r--src/osd/modules/render/bgfx/slideruniformreader.h16
-rw-r--r--src/osd/modules/render/bgfx/statereader.cpp27
-rw-r--r--src/osd/modules/render/bgfx/statereader.h23
-rw-r--r--src/osd/modules/render/bgfx/suppressor.cpp6
-rw-r--r--src/osd/modules/render/bgfx/suppressor.h10
-rw-r--r--src/osd/modules/render/bgfx/suppressorreader.cpp23
-rw-r--r--src/osd/modules/render/bgfx/suppressorreader.h12
-rw-r--r--src/osd/modules/render/bgfx/target.cpp11
-rw-r--r--src/osd/modules/render/bgfx/target.h14
-rw-r--r--src/osd/modules/render/bgfx/targetmanager.cpp132
-rw-r--r--src/osd/modules/render/bgfx/targetmanager.h37
-rw-r--r--src/osd/modules/render/bgfx/targetreader.cpp60
-rw-r--r--src/osd/modules/render/bgfx/targetreader.h14
-rw-r--r--src/osd/modules/render/bgfx/texture.cpp9
-rw-r--r--src/osd/modules/render/bgfx/texture.h8
-rw-r--r--src/osd/modules/render/bgfx/texturehandleprovider.h11
-rw-r--r--src/osd/modules/render/bgfx/texturemanager.cpp141
-rw-r--r--src/osd/modules/render/bgfx/texturemanager.h37
-rw-r--r--src/osd/modules/render/bgfx/timeparameter.cpp6
-rw-r--r--src/osd/modules/render/bgfx/timeparameter.h15
-rw-r--r--src/osd/modules/render/bgfx/uniform.cpp6
-rw-r--r--src/osd/modules/render/bgfx/uniform.h12
-rw-r--r--src/osd/modules/render/bgfx/uniformreader.cpp32
-rw-r--r--src/osd/modules/render/bgfx/uniformreader.h16
-rw-r--r--src/osd/modules/render/bgfx/valueuniform.cpp10
-rw-r--r--src/osd/modules/render/bgfx/valueuniform.h10
-rw-r--r--src/osd/modules/render/bgfx/valueuniformreader.cpp8
-rw-r--r--src/osd/modules/render/bgfx/valueuniformreader.h15
-rw-r--r--src/osd/modules/render/bgfx/view.cpp4
-rw-r--r--src/osd/modules/render/bgfx/view.h6
-rw-r--r--src/osd/modules/render/bgfx/windowparameter.h16
-rw-r--r--src/osd/modules/render/bgfxutil.cpp34
-rw-r--r--src/osd/modules/render/bgfxutil.h3
-rw-r--r--src/osd/modules/render/binpacker.h36
-rw-r--r--src/osd/modules/render/blit13.ipp (renamed from src/osd/modules/render/blit13.h)0
-rw-r--r--src/osd/modules/render/d3d/d3dcomm.h103
-rw-r--r--src/osd/modules/render/d3d/d3dhlsl.cpp912
-rw-r--r--src/osd/modules/render/d3d/d3dhlsl.h98
-rw-r--r--src/osd/modules/render/draw13.cpp753
-rw-r--r--src/osd/modules/render/draw13.h216
-rw-r--r--src/osd/modules/render/drawbgfx.cpp997
-rw-r--r--src/osd/modules/render/drawbgfx.h87
-rw-r--r--src/osd/modules/render/drawd3d.cpp851
-rw-r--r--src/osd/modules/render/drawd3d.h57
-rw-r--r--src/osd/modules/render/drawgdi.cpp119
-rw-r--r--src/osd/modules/render/drawgdi.h55
-rw-r--r--src/osd/modules/render/drawnone.cpp79
-rw-r--r--src/osd/modules/render/drawnone.h33
-rw-r--r--src/osd/modules/render/drawogl.cpp1109
-rw-r--r--src/osd/modules/render/drawogl.h244
-rw-r--r--src/osd/modules/render/drawsdl.cpp337
-rw-r--r--src/osd/modules/render/drawsdl.h88
-rw-r--r--src/osd/modules/render/render_module.h38
-rw-r--r--src/osd/modules/render/sdlglcontext.h55
-rw-r--r--src/osd/modules/render/winglcontext.h201
-rw-r--r--src/osd/modules/sound/coreaudio_sound.cpp67
-rw-r--r--src/osd/modules/sound/direct_sound.cpp56
-rw-r--r--src/osd/modules/sound/js_sound.cpp34
-rw-r--r--src/osd/modules/sound/js_sound.js7
-rw-r--r--src/osd/modules/sound/none.cpp20
-rw-r--r--src/osd/modules/sound/pa_sound.cpp56
-rw-r--r--src/osd/modules/sound/pulse_sound.cpp16
-rw-r--r--src/osd/modules/sound/sdl_sound.cpp64
-rw-r--r--src/osd/modules/sound/sound_module.h16
-rw-r--r--src/osd/modules/sound/xaudio2_sound.cpp143
362 files changed, 19580 insertions, 11376 deletions
diff --git a/src/osd/modules/debugger/debug_module.h b/src/osd/modules/debugger/debug_module.h
index fb659a1b312..1c5b1973c8e 100644
--- a/src/osd/modules/debugger/debug_module.h
+++ b/src/osd/modules/debugger/debug_module.h
@@ -4,13 +4,15 @@
* debug_module.h
*
*/
+#ifndef MAME_OSD_DEBUGGER_DEBUG_MODULE_H
+#define MAME_OSD_DEBUGGER_DEBUG_MODULE_H
-#ifndef DEBUG_MODULE_H_
-#define DEBUG_MODULE_H_
+#pragma once
#include "osdepend.h"
#include "modules/osdmodule.h"
+
//============================================================
// CONSTANTS
//============================================================
@@ -20,14 +22,11 @@
class debug_module
{
public:
-
- virtual ~debug_module() { }
+ virtual ~debug_module() = default;
virtual void init_debugger(running_machine &machine) = 0;
virtual void wait_for_debugger(device_t &device, bool firststop) = 0;
virtual void debugger_update() = 0;
};
-
-
-#endif /* DEBUG_MODULE_H_ */
+#endif // MAME_OSD_DEBUGGER_DEBUG_MODULE_H
diff --git a/src/osd/modules/debugger/debuggdbstub.cpp b/src/osd/modules/debugger/debuggdbstub.cpp
index eaeb1df4cca..e5092c71548 100644
--- a/src/osd/modules/debugger/debuggdbstub.cpp
+++ b/src/osd/modules/debugger/debuggdbstub.cpp
@@ -7,17 +7,26 @@
//============================================================
#include "emu.h"
+#include "debug_module.h"
+
#include "debug/debugcon.h"
#include "debug/debugcpu.h"
#include "debug/points.h"
#include "debug/textbuf.h"
-#include "debug_module.h"
#include "debugger.h"
-#include "fileio.h"
+
#include "modules/lib/osdobj_common.h"
#include "modules/osdmodule.h"
+#include "fileio.h"
+
#include <cinttypes>
+#include <string_view>
+
+
+namespace osd {
+
+namespace {
//-------------------------------------------------------------------------
#define MAX_PACKET_SIZE 16384
@@ -245,9 +254,9 @@ static const gdb_register_map gdb_register_map_m68020pmmu =
{ "A4", "a4", false, TYPE_INT },
{ "A5", "a5", false, TYPE_INT },
{ "A6", "fp", true, TYPE_INT },
- { "A7", "sp", true, TYPE_INT },
+ { "SP", "sp", true, TYPE_INT },
{ "SR", "ps", false, TYPE_INT }, // NOTE GDB named it ps, but it's actually sr
- { "PC", "pc", true, TYPE_CODE_POINTER },
+ { "CURPC","pc", true, TYPE_CODE_POINTER },
}
};
@@ -272,9 +281,9 @@ static const gdb_register_map gdb_register_map_m68000 =
{ "A4", "a4", false, TYPE_INT },
{ "A5", "a5", false, TYPE_INT },
{ "A6", "fp", true, TYPE_INT },
- { "A7", "sp", true, TYPE_INT },
+ { "SP", "sp", true, TYPE_INT },
{ "SR", "ps", false, TYPE_INT }, // NOTE GDB named it ps, but it's actually sr
- { "PC", "pc", true, TYPE_CODE_POINTER },
+ { "CURPC","pc", true, TYPE_CODE_POINTER },
//NOTE m68-elf-gdb complains about fpcontrol register not present but 68000 doesn't have floating point so...
}
};
@@ -401,6 +410,65 @@ static const gdb_register_map gdb_register_map_score7 =
}
};
+
+//-------------------------------------------------------------------------
+static const gdb_register_map gdb_register_map_nios2 =
+{
+ "nios2",
+ "org.gnu.gdb.nios2.cpu",
+ {
+ { "zero", "zero", false, TYPE_INT },
+ { "at", "at", false, TYPE_INT },
+ { "r2", "r2", false, TYPE_INT },
+ { "r3", "r3", false, TYPE_INT },
+ { "r4", "r4", false, TYPE_INT },
+ { "r5", "r5", false, TYPE_INT },
+ { "r6", "r6", false, TYPE_INT },
+ { "r7", "r7", false, TYPE_INT },
+ { "r8", "r8", false, TYPE_INT },
+ { "r9", "r9", false, TYPE_INT },
+ { "r10", "r10", false, TYPE_INT },
+ { "r11", "r11", false, TYPE_INT },
+ { "r12", "r12", false, TYPE_INT },
+ { "r13", "r13", false, TYPE_INT },
+ { "r14", "r14", false, TYPE_INT },
+ { "r15", "r15", false, TYPE_INT },
+ { "r16", "r16", false, TYPE_INT },
+ { "r17", "r17", false, TYPE_INT },
+ { "r18", "r18", false, TYPE_INT },
+ { "r19", "r19", false, TYPE_INT },
+ { "r20", "r20", false, TYPE_INT },
+ { "r21", "r21", false, TYPE_INT },
+ { "r22", "r22", false, TYPE_INT },
+ { "r23", "r23", false, TYPE_INT },
+ { "et", "et", false, TYPE_INT },
+ { "bt", "bt", false, TYPE_INT },
+ { "gp", "gp", false, TYPE_DATA_POINTER },
+ { "sp", "sp", true, TYPE_DATA_POINTER },
+ { "fp", "fp", false, TYPE_DATA_POINTER },
+ { "ea", "ea", false, TYPE_CODE_POINTER },
+ { "ba", "sstatus", false, TYPE_INT }, // this is Altera's fault
+ { "ra", "ra", false, TYPE_CODE_POINTER },
+ { "status", "status", false, TYPE_INT },
+ { "estatus", "estatus", false, TYPE_INT },
+ { "bstatus", "bstatus", false, TYPE_INT },
+ { "ienable", "ienable", false, TYPE_INT },
+ { "ipending", "ipending", false, TYPE_INT },
+ { "cpuid", "cpuid", false, TYPE_INT },
+ { "ctl6", "ctl6", false, TYPE_INT },
+ { "exception","exception",false, TYPE_INT },
+ { "pteaddr", "pteaddr", false, TYPE_INT },
+ { "tlbacc", "tlbacc", false, TYPE_INT },
+ { "tlbmisc", "tlbmisc", false, TYPE_INT },
+ { "eccinj", "eccinj", false, TYPE_INT },
+ { "badaddr", "badaddr", false, TYPE_INT },
+ { "config", "config", false, TYPE_INT },
+ { "mpubase", "mpubase", false, TYPE_INT },
+ { "mpuacc", "mpuacc", false, TYPE_INT },
+ { "PC", "pc", true, TYPE_CODE_POINTER },
+ }
+};
+
//-------------------------------------------------------------------------
static const std::map<std::string, const gdb_register_map &> gdb_register_maps = {
{ "i486", gdb_register_map_i486 },
@@ -410,10 +478,17 @@ static const std::map<std::string, const gdb_register_map &> gdb_register_maps =
{ "m68020pmmu", gdb_register_map_m68020pmmu },
{ "m68000", gdb_register_map_m68000 },
{ "z80", gdb_register_map_z80 },
+ { "z84c015", gdb_register_map_z80 },
{ "m6502", gdb_register_map_m6502 },
- { "n2a03", gdb_register_map_m6502 },
+ { "m6507", gdb_register_map_m6502 },
+ { "m6510", gdb_register_map_m6502 },
+ { "m65c02", gdb_register_map_m6502 },
+ { "m65ce02", gdb_register_map_m6502 },
+ { "rp2a03", gdb_register_map_m6502 },
+ { "w65c02s", gdb_register_map_m6502 },
{ "m6809", gdb_register_map_m6809 },
{ "score7", gdb_register_map_score7 },
+ { "nios2", gdb_register_map_nios2 },
};
//-------------------------------------------------------------------------
@@ -450,7 +525,7 @@ public:
virtual ~debug_gdbstub() { }
- virtual int init(const osd_options &options) override;
+ virtual int init(osd_interface &osd, const osd_options &options) override;
virtual void exit() override;
virtual void init_debugger(running_machine &machine) override;
@@ -495,6 +570,7 @@ public:
cmd_reply handle_P(const char *buf);
cmd_reply handle_q(const char *buf);
cmd_reply handle_s(const char *buf);
+ cmd_reply handle_T(const char *buf);
cmd_reply handle_z(const char *buf);
cmd_reply handle_Z(const char *buf);
@@ -512,7 +588,7 @@ public:
int readchar();
- void send_reply(const char *str);
+ void send_reply(std::string_view str);
void send_stop_packet();
private:
@@ -563,7 +639,7 @@ private:
};
//-------------------------------------------------------------------------
-int debug_gdbstub::init(const osd_options &options)
+int debug_gdbstub::init(osd_interface &osd, const osd_options &options)
{
m_debugger_port = options.debugger_port();
return 0;
@@ -601,11 +677,11 @@ int debug_gdbstub::readchar()
}
//-------------------------------------------------------------------------
-static std::string escape_packet(const std::string src)
+static std::string escape_packet(std::string_view src)
{
std::string result;
result.reserve(src.length());
- for ( char ch: src )
+ for ( char ch : src )
{
if ( ch == '#' || ch == '$' || ch == '}' )
{
@@ -626,10 +702,10 @@ void debug_gdbstub::generate_target_xml()
target_xml += "<?xml version=\"1.0\"?>\n";
target_xml += "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">\n";
target_xml += "<target version=\"1.0\">\n";
- target_xml += string_format("<architecture>%s</architecture>\n", m_gdb_arch.c_str());
- target_xml += string_format(" <feature name=\"%s\">\n", m_gdb_feature.c_str());
+ target_xml += string_format("<architecture>%s</architecture>\n", m_gdb_arch);
+ target_xml += string_format(" <feature name=\"%s\">\n", m_gdb_feature);
for ( const auto &reg: m_gdb_registers )
- target_xml += string_format(" <reg name=\"%s\" bitsize=\"%d\" type=\"%s\"/>\n", reg.gdb_name.c_str(), reg.gdb_bitsize, gdb_register_type_str[reg.gdb_type]);
+ target_xml += string_format(" <reg name=\"%s\" bitsize=\"%d\" type=\"%s\"/>\n", reg.gdb_name, reg.gdb_bitsize, gdb_register_type_str[reg.gdb_type]);
target_xml += " </feature>\n";
target_xml += "</target>\n";
m_target_xml = escape_packet(target_xml);
@@ -644,7 +720,7 @@ void debug_gdbstub::wait_for_debugger(device_t &device, bool firststop)
if ( firststop && !m_initialized )
{
// find the "main" CPU, which is the first CPU (gdbstub doesn't have any notion of switching CPUs)
- m_maincpu = device_type_enumerator<cpu_device>(m_machine->root_device()).first();
+ m_maincpu = device_interface_enumerator<cpu_device>(m_machine->root_device()).first();
if (!m_maincpu)
fatalerror("gdbstub: cannot find any CPUs\n");
@@ -762,26 +838,24 @@ void debug_gdbstub::debugger_update()
//-------------------------------------------------------------------------
void debug_gdbstub::send_nack()
{
- m_socket.puts("-");
+ m_socket.write("-", 1);
}
//-------------------------------------------------------------------------
void debug_gdbstub::send_ack()
{
- m_socket.puts("+");
+ m_socket.write("+", 1);
}
//-------------------------------------------------------------------------
-void debug_gdbstub::send_reply(const char *str)
+void debug_gdbstub::send_reply(std::string_view str)
{
- size_t length = strlen(str);
-
uint8_t checksum = 0;
- for ( size_t i = 0; i < length; i++ )
- checksum += str[i];
+ for ( char ch : str )
+ checksum += ch;
std::string reply = string_format("$%s#%02x", str, checksum);
- m_socket.puts(reply);
+ m_socket.write(reply.c_str(), reply.length());
}
@@ -839,7 +913,7 @@ debug_gdbstub::cmd_reply debug_gdbstub::handle_g(const char *buf)
std::string reply;
for ( const auto &reg: m_gdb_registers )
reply += get_register_string(reg.gdb_regnum);
- send_reply(reply.c_str());
+ send_reply(reply);
return REPLY_NONE;
}
@@ -894,7 +968,8 @@ debug_gdbstub::cmd_reply debug_gdbstub::handle_m(const char *buf)
return REPLY_ENN;
offs_t offset = address;
- if ( !m_memory->translate(m_address_space->spacenum(), TRANSLATE_READ_DEBUG, offset) )
+ address_space *tspace;
+ if ( !m_memory->translate(m_address_space->spacenum(), device_memory_interface::TR_READ, offset, tspace) )
return REPLY_ENN;
// Disable side effects while reading memory.
@@ -904,10 +979,10 @@ debug_gdbstub::cmd_reply debug_gdbstub::handle_m(const char *buf)
reply.reserve(length * 2);
for ( int i = 0; i < length; i++ )
{
- uint8_t value = m_address_space->read_byte(offset + i);
+ uint8_t value = tspace->read_byte(offset + i);
reply += string_format("%02x", value);
}
- send_reply(reply.c_str());
+ send_reply(reply);
return REPLY_NONE;
}
@@ -939,7 +1014,8 @@ debug_gdbstub::cmd_reply debug_gdbstub::handle_M(const char *buf)
return REPLY_ENN;
offs_t offset = address;
- if ( !m_memory->translate(m_address_space->spacenum(), TRANSLATE_READ_DEBUG, offset) )
+ address_space *tspace;
+ if ( !m_memory->translate(m_address_space->spacenum(), device_memory_interface::TR_READ, offset, tspace) )
return REPLY_ENN;
std::vector<uint8_t> data;
@@ -947,7 +1023,7 @@ debug_gdbstub::cmd_reply debug_gdbstub::handle_M(const char *buf)
return REPLY_ENN;
for ( int i = 0; i < length; i++ )
- m_address_space->write_byte(offset + i, data[i]);
+ tspace->write_byte(offset + i, data[i]);
return REPLY_OK;
}
@@ -962,7 +1038,7 @@ debug_gdbstub::cmd_reply debug_gdbstub::handle_p(const char *buf)
if ( sscanf(buf, "%x", &gdb_regnum) != 1 || gdb_regnum >= m_gdb_registers.size() )
return REPLY_ENN;
std::string reply = get_register_string(gdb_regnum);
- send_reply(reply.c_str());
+ send_reply(reply);
return REPLY_NONE;
}
@@ -1029,7 +1105,7 @@ debug_gdbstub::cmd_reply debug_gdbstub::handle_q(const char *buf)
reply += string_format("%02x", *line++);
reply += "0A";
}
- send_reply(reply.c_str());
+ send_reply(reply);
return REPLY_NONE;
}
@@ -1046,7 +1122,7 @@ debug_gdbstub::cmd_reply debug_gdbstub::handle_q(const char *buf)
{
std::string reply = string_format("PacketSize=%x", MAX_PACKET_SIZE);
reply += ";qXfer:features:read+";
- send_reply(reply.c_str());
+ send_reply(reply);
return REPLY_NONE;
}
else if ( name == "Xfer" )
@@ -1067,7 +1143,7 @@ debug_gdbstub::cmd_reply debug_gdbstub::handle_q(const char *buf)
else
reply += 'l';
reply += m_target_xml.substr(offset, length);
- send_reply(reply.c_str());
+ send_reply(reply);
m_target_xml_sent = true;
return REPLY_NONE;
}
@@ -1101,6 +1177,17 @@ debug_gdbstub::cmd_reply debug_gdbstub::handle_s(const char *buf)
}
//-------------------------------------------------------------------------
+// Find out if the thread XX is alive.
+debug_gdbstub::cmd_reply debug_gdbstub::handle_T(const char *buf)
+{
+ if ( is_thread_id_ok(buf) )
+ return REPLY_OK;
+
+ // thread is dead
+ return REPLY_ENN;
+}
+
+//-------------------------------------------------------------------------
static bool remove_breakpoint(device_debug *debug, uint64_t address, int /*kind*/)
{
const debug_breakpoint *bp = debug->breakpoint_find(address);
@@ -1140,9 +1227,10 @@ debug_gdbstub::cmd_reply debug_gdbstub::handle_z(const char *buf)
// watchpoints
offs_t offset = address;
+ address_space *tspace;
if ( type == 2 || type == 3 || type == 4 )
{
- if ( !m_memory->translate(m_address_space->spacenum(), TRANSLATE_READ_DEBUG, offset) )
+ if ( !m_memory->translate(m_address_space->spacenum(), device_memory_interface::TR_READ, offset, tspace) )
return REPLY_ENN;
m_address_map.erase(offset);
}
@@ -1181,9 +1269,10 @@ debug_gdbstub::cmd_reply debug_gdbstub::handle_Z(const char *buf)
// watchpoints
offs_t offset = address;
+ address_space *tspace;
if ( type == 2 || type == 3 || type == 4 )
{
- if ( !m_memory->translate(m_address_space->spacenum(), TRANSLATE_READ_DEBUG, offset) )
+ if ( !m_memory->translate(m_address_space->spacenum(), device_memory_interface::TR_READ, offset, tspace) )
return REPLY_ENN;
m_address_map[offset] = address;
}
@@ -1199,15 +1288,15 @@ debug_gdbstub::cmd_reply debug_gdbstub::handle_Z(const char *buf)
return REPLY_OK;
case 2:
// write watchpoint
- debug->watchpoint_set(*m_address_space, read_or_write::WRITE, offset, kind, nullptr, nullptr);
+ debug->watchpoint_set(*m_address_space, read_or_write::WRITE, offset, kind);
return REPLY_OK;
case 3:
// read watchpoint
- debug->watchpoint_set(*m_address_space, read_or_write::READ, offset, kind, nullptr, nullptr);
+ debug->watchpoint_set(*m_address_space, read_or_write::READ, offset, kind);
return REPLY_OK;
case 4:
// access watchpoint
- debug->watchpoint_set(*m_address_space, read_or_write::READWRITE, offset, kind, nullptr, nullptr);
+ debug->watchpoint_set(*m_address_space, read_or_write::READWRITE, offset, kind);
return REPLY_OK;
}
@@ -1241,7 +1330,7 @@ void debug_gdbstub::send_stop_packet()
if ( m_target_xml_sent )
for ( const auto &gdb_regnum: m_stop_reply_registers )
reply += string_format("%02x:%s;", gdb_regnum, get_register_string(gdb_regnum));
- send_reply(reply.c_str());
+ send_reply(reply);
}
//-------------------------------------------------------------------------
@@ -1270,6 +1359,7 @@ void debug_gdbstub::handle_packet()
case 'P': reply = handle_P(buf); break;
case 'q': reply = handle_q(buf); break;
case 's': reply = handle_s(buf); break;
+ case 'T': reply = handle_T(buf); break;
case 'z': reply = handle_z(buf); break;
case 'Z': reply = handle_Z(buf); break;
}
@@ -1282,22 +1372,6 @@ void debug_gdbstub::handle_packet()
}
//-------------------------------------------------------------------------
-#define BYTESWAP_64(x) ((((x) << 56) & 0xFF00000000000000) \
- | (((x) << 40) & 0x00FF000000000000) \
- | (((x) << 24) & 0x0000FF0000000000) \
- | (((x) << 8) & 0x000000FF00000000) \
- | (((x) >> 8) & 0x00000000FF000000) \
- | (((x) >> 24) & 0x0000000000FF0000) \
- | (((x) >> 40) & 0x000000000000FF00) \
- | (((x) >> 56) & 0x00000000000000FF))
-#define BYTESWAP_32(x) ((((x) << 24) & 0xFF000000) \
- | (((x) << 8) & 0x00FF0000) \
- | (((x) >> 8) & 0x0000FF00) \
- | (((x) >> 24) & 0x000000FF))
-#define BYTESWAP_16(x) ((((x) << 8) & 0xFF00) \
- | (((x) >> 8) & 0x00FF))
-
-//-------------------------------------------------------------------------
std::string debug_gdbstub::get_register_string(int gdb_regnum)
{
const gdb_register &reg = m_gdb_registers[gdb_regnum];
@@ -1310,9 +1384,9 @@ std::string debug_gdbstub::get_register_string(int gdb_regnum)
value &= (1ULL << reg.gdb_bitsize) - 1;
if ( !m_is_be )
{
- value = (reg.gdb_bitsize == 64) ? BYTESWAP_64(value)
- : (reg.gdb_bitsize == 32) ? BYTESWAP_32(value)
- : (reg.gdb_bitsize == 16) ? BYTESWAP_16(value)
+ value = (reg.gdb_bitsize == 64) ? swapendian_int64(value)
+ : (reg.gdb_bitsize == 32) ? swapendian_int32(value)
+ : (reg.gdb_bitsize == 16) ? swapendian_int16(value)
: value;
}
return string_format(fmt, value);
@@ -1331,9 +1405,9 @@ bool debug_gdbstub::parse_register_string(uint64_t *pvalue, const char *buf, int
return false;
if ( !m_is_be )
{
- value = (reg.gdb_bitsize == 64) ? BYTESWAP_64(value)
- : (reg.gdb_bitsize == 32) ? BYTESWAP_32(value)
- : (reg.gdb_bitsize == 16) ? BYTESWAP_16(value)
+ value = (reg.gdb_bitsize == 64) ? swapendian_int64(value)
+ : (reg.gdb_bitsize == 32) ? swapendian_int32(value)
+ : (reg.gdb_bitsize == 16) ? swapendian_int16(value)
: value;
}
*pvalue = value;
@@ -1430,5 +1504,9 @@ void debug_gdbstub::handle_character(char ch)
}
}
+} // anonymous namespace
+
+} // namespace osd
+
//-------------------------------------------------------------------------
-MODULE_DEFINITION(DEBUG_GDBSTUB, debug_gdbstub)
+MODULE_DEFINITION(DEBUG_GDBSTUB, osd::debug_gdbstub)
diff --git a/src/osd/modules/debugger/debugimgui.cpp b/src/osd/modules/debugger/debugimgui.cpp
index 944ed203b79..4ae514f857f 100644
--- a/src/osd/modules/debugger/debugimgui.cpp
+++ b/src/osd/modules/debugger/debugimgui.cpp
@@ -3,9 +3,11 @@
// ImGui based debugger
#include "emu.h"
+#include "debug_module.h"
+
#include "imgui/imgui.h"
-#include "render.h"
-#include "uiinput.h"
+
+#include "imagedev/floppy.h"
#include "debug/debugvw.h"
#include "debug/dvdisasm.h"
@@ -14,14 +16,20 @@
#include "debug/dvwpoints.h"
#include "debug/debugcon.h"
#include "debug/debugcpu.h"
+#include "debugger.h"
+#include "render.h"
+#include "uiinput.h"
+
+#include "formats/flopimg.h"
#include "config.h"
-#include "debugger.h"
#include "modules/lib/osdobj_common.h"
-#include "debug_module.h"
#include "modules/osdmodule.h"
#include "zippath.h"
-#include "imagedev/floppy.h"
+
+namespace osd {
+
+namespace {
class debug_area
{
@@ -118,7 +126,7 @@ public:
virtual ~debug_imgui() { }
- virtual int init(const osd_options &options) override { return 0; }
+ virtual int init(osd_interface &osd, const osd_options &options) override { return 0; }
virtual void exit() override {};
virtual void init_debugger(running_machine &machine) override;
@@ -199,6 +207,7 @@ private:
file_entry* m_selected_file;
int m_format_sel;
char m_path[1024]; // path text field buffer
+ std::unordered_map<input_item_id,ImGuiKey> m_mapping;
};
// globals
@@ -346,10 +355,11 @@ void debug_imgui::handle_keys()
for(input_item_id id = ITEM_ID_A; id <= ITEM_ID_CANCEL; ++id)
{
- if(m_machine->input().code_pressed(input_code(DEVICE_CLASS_KEYBOARD, 0, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, id)))
- io.KeysDown[id] = true;
- else
- io.KeysDown[id] = false;
+ if(m_machine->input().code_pressed(input_code(DEVICE_CLASS_KEYBOARD, 0, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, id))) {
+ if (m_mapping.count(id)) io.AddKeyEvent(m_mapping[id], true);
+ } else {
+ if (m_mapping.count(id)) io.AddKeyEvent(m_mapping[id], false);
+ }
}
m_key_char = 0;
@@ -368,9 +378,9 @@ void debug_imgui::handle_keys()
}
// global keys
- if(ImGui::IsKeyPressed(ITEM_ID_F3,false))
+ if(ImGui::IsKeyPressed(ImGuiKey_F3,false))
{
- if(ImGui::IsKeyDown(ITEM_ID_LSHIFT))
+ if(ImGui::IsKeyDown(ImGuiKey_LeftShift))
m_machine->schedule_hard_reset();
else
{
@@ -379,44 +389,44 @@ void debug_imgui::handle_keys()
}
}
- if(ImGui::IsKeyPressed(ITEM_ID_F5,false))
+ if(ImGui::IsKeyPressed(ImGuiKey_F5,false))
{
m_machine->debugger().console().get_visible_cpu()->debug()->go();
m_running = true;
}
- if(ImGui::IsKeyPressed(ITEM_ID_F6,false))
+ if(ImGui::IsKeyPressed(ImGuiKey_F6,false))
{
m_machine->debugger().console().get_visible_cpu()->debug()->go_next_device();
m_running = true;
}
- if(ImGui::IsKeyPressed(ITEM_ID_F7,false))
+ if(ImGui::IsKeyPressed(ImGuiKey_F7,false))
{
m_machine->debugger().console().get_visible_cpu()->debug()->go_interrupt();
m_running = true;
}
- if(ImGui::IsKeyPressed(ITEM_ID_F8,false))
+ if(ImGui::IsKeyPressed(ImGuiKey_F8,false))
m_machine->debugger().console().get_visible_cpu()->debug()->go_vblank();
- if(ImGui::IsKeyPressed(ITEM_ID_F9,false))
+ if(ImGui::IsKeyPressed(ImGuiKey_F9,false))
m_machine->debugger().console().get_visible_cpu()->debug()->single_step_out();
- if(ImGui::IsKeyPressed(ITEM_ID_F10,false))
+ if(ImGui::IsKeyPressed(ImGuiKey_F10,false))
m_machine->debugger().console().get_visible_cpu()->debug()->single_step_over();
- if(ImGui::IsKeyPressed(ITEM_ID_F11,false))
+ if(ImGui::IsKeyPressed(ImGuiKey_F11,false))
m_machine->debugger().console().get_visible_cpu()->debug()->single_step();
- if(ImGui::IsKeyPressed(ITEM_ID_F12,false))
+ if(ImGui::IsKeyPressed(ImGuiKey_F12,false))
{
m_machine->debugger().console().get_visible_cpu()->debug()->go();
m_hide = true;
}
- if(ImGui::IsKeyPressed(ITEM_ID_D,false) && ImGui::IsKeyDown(ITEM_ID_LCONTROL))
+ if(ImGui::IsKeyPressed(ImGuiKey_D,false) && io.KeyCtrl)
add_disasm(++m_win_count);
- if(ImGui::IsKeyPressed(ITEM_ID_M,false) && ImGui::IsKeyDown(ITEM_ID_LCONTROL))
+ if(ImGui::IsKeyPressed(ImGuiKey_M,false) && io.KeyCtrl)
add_memory(++m_win_count);
- if(ImGui::IsKeyPressed(ITEM_ID_B,false) && ImGui::IsKeyDown(ITEM_ID_LCONTROL))
+ if(ImGui::IsKeyPressed(ImGuiKey_B,false) && io.KeyCtrl)
add_bpoints(++m_win_count);
- if(ImGui::IsKeyPressed(ITEM_ID_W,false) && ImGui::IsKeyDown(ITEM_ID_LCONTROL))
+ if(ImGui::IsKeyPressed(ImGuiKey_W,false) && io.KeyCtrl)
add_wpoints(++m_win_count);
- if(ImGui::IsKeyPressed(ITEM_ID_L,false) && ImGui::IsKeyDown(ITEM_ID_LCONTROL))
+ if(ImGui::IsKeyPressed(ImGuiKey_L,false) && io.KeyCtrl)
add_log(++m_win_count);
}
@@ -439,38 +449,38 @@ void debug_imgui::handle_keys_views()
return;
// pass keypresses to debug view with focus
- if(ImGui::IsKeyPressed(ITEM_ID_UP))
+ if(ImGui::IsKeyPressed(ImGuiKey_UpArrow))
focus_view->view->process_char(DCH_UP);
- if(ImGui::IsKeyPressed(ITEM_ID_DOWN))
+ if(ImGui::IsKeyPressed(ImGuiKey_DownArrow))
focus_view->view->process_char(DCH_DOWN);
- if(ImGui::IsKeyPressed(ITEM_ID_LEFT))
+ if(ImGui::IsKeyPressed(ImGuiKey_LeftArrow))
{
- if(ImGui::IsKeyDown(ITEM_ID_LCONTROL))
+ if(ImGui::IsKeyDown(ImGuiKey_LeftCtrl))
focus_view->view->process_char(DCH_CTRLLEFT);
else
focus_view->view->process_char(DCH_LEFT);
}
- if(ImGui::IsKeyPressed(ITEM_ID_RIGHT))
+ if(ImGui::IsKeyPressed(ImGuiKey_RightArrow))
{
- if(ImGui::IsKeyDown(ITEM_ID_LCONTROL))
+ if(ImGui::IsKeyDown(ImGuiKey_LeftCtrl))
focus_view->view->process_char(DCH_CTRLRIGHT);
else
focus_view->view->process_char(DCH_RIGHT);
}
- if(ImGui::IsKeyPressed(ITEM_ID_PGUP))
+ if(ImGui::IsKeyPressed(ImGuiKey_PageUp))
focus_view->view->process_char(DCH_PUP);
- if(ImGui::IsKeyPressed(ITEM_ID_PGDN))
+ if(ImGui::IsKeyPressed(ImGuiKey_PageDown))
focus_view->view->process_char(DCH_PDOWN);
- if(ImGui::IsKeyPressed(ITEM_ID_HOME))
+ if(ImGui::IsKeyPressed(ImGuiKey_Home))
{
- if(ImGui::IsKeyDown(ITEM_ID_LCONTROL))
+ if(ImGui::IsKeyDown(ImGuiKey_LeftCtrl))
focus_view->view->process_char(DCH_CTRLHOME);
else
focus_view->view->process_char(DCH_HOME);
}
- if(ImGui::IsKeyPressed(ITEM_ID_END))
+ if(ImGui::IsKeyPressed(ImGuiKey_End))
{
- if(ImGui::IsKeyDown(ITEM_ID_LCONTROL))
+ if(ImGui::IsKeyDown(ImGuiKey_LeftCtrl))
focus_view->view->process_char(DCH_CTRLEND);
else
focus_view->view->process_char(DCH_END);
@@ -547,6 +557,8 @@ int debug_imgui::history_set(ImGuiInputTextCallbackData* data)
if(history_pos < view_main_console->console_history.size())
history_pos++;
break;
+ default:
+ break;
}
if(history_pos == view_main_console->console_history.size())
@@ -606,7 +618,10 @@ void debug_imgui::draw_view(debug_area* view_ptr, bool exp_change)
// temporarily set cursor to the last line, this will set the scroll bar range
if(view_ptr->type != DVT_MEMORY) // no scroll bars in memory views
+ {
ImGui::SetCursorPosY((totalsize.y) * fsize.y);
+ ImGui::Dummy(ImVec2(0,0)); // some object is required for validation
+ }
// set the visible area to be displayed
vsize.x = view_ptr->view_width / fsize.x;
@@ -985,18 +1000,18 @@ void debug_imgui::mount_image()
void debug_imgui::create_image()
{
- image_init_result res;
+ std::pair<std::error_condition, std::string> res;
auto *fd = dynamic_cast<floppy_image_device *>(m_dialog_image);
if(fd != nullptr)
{
res = fd->create(m_path,nullptr,nullptr);
- if(res == image_init_result::PASS)
+ if(!res.first)
fd->setup_write(m_typelist.at(m_format_sel).format);
}
else
res = m_dialog_image->create(m_path,nullptr,nullptr);
- if(res == image_init_result::PASS)
+ if(!res.first)
ImGui::CloseCurrentPopup();
// TODO: add a messagebox to display on an error
}
@@ -1013,7 +1028,6 @@ void debug_imgui::refresh_filelist()
std::error_condition const err = util::zippath_directory::open(m_path,dir);
if(!err)
{
- int x = 0;
// add drives
for(std::string const &volume_name : osd_get_volume_names())
{
@@ -1022,19 +1036,18 @@ void debug_imgui::refresh_filelist()
temp.basename = volume_name;
temp.fullpath = volume_name;
m_filelist.emplace_back(std::move(temp));
- x++;
}
first = m_filelist.size();
- const osd::directory::entry *dirent;
+ const directory::entry *dirent;
while((dirent = dir->readdir()) != nullptr)
{
file_entry temp;
switch(dirent->type)
{
- case osd::directory::entry::entry_type::FILE:
+ case directory::entry::entry_type::FILE:
temp.type = file_entry_type::FILE;
break;
- case osd::directory::entry::entry_type::DIR:
+ case directory::entry::entry_type::DIR:
temp.type = file_entry_type::DIRECTORY;
break;
default:
@@ -1190,10 +1203,10 @@ void debug_imgui::draw_create_dialog(const char* label)
if(ImGui::InputText("##createfilename",m_path,1024,ImGuiInputTextFlags_EnterReturnsTrue))
{
auto entry = osd_stat(m_path);
- auto file_type = (entry != nullptr) ? entry->type : osd::directory::entry::entry_type::NONE;
- if(file_type == osd::directory::entry::entry_type::NONE)
+ auto file_type = (entry != nullptr) ? entry->type : directory::entry::entry_type::NONE;
+ if(file_type == directory::entry::entry_type::NONE)
create_image();
- if(file_type == osd::directory::entry::entry_type::FILE)
+ if(file_type == directory::entry::entry_type::FILE)
m_create_confirm_wait = true;
// cannot overwrite a directory, so nothing will be none in that case.
}
@@ -1240,10 +1253,10 @@ void debug_imgui::draw_create_dialog(const char* label)
if(ImGui::Button("OK##mount"))
{
auto entry = osd_stat(m_path);
- auto file_type = (entry != nullptr) ? entry->type : osd::directory::entry::entry_type::NONE;
- if(file_type == osd::directory::entry::entry_type::NONE)
+ auto file_type = (entry != nullptr) ? entry->type : directory::entry::entry_type::NONE;
+ if(file_type == directory::entry::entry_type::NONE)
create_image();
- if(file_type == osd::directory::entry::entry_type::FILE)
+ if(file_type == directory::entry::entry_type::FILE)
m_create_confirm_wait = true;
// cannot overwrite a directory, so nothing will be none in that case.
m_create_open = false;
@@ -1393,7 +1406,6 @@ void debug_imgui::update()
//debug_area* view_ptr = view_list;
std::vector<debug_area*>::iterator view_ptr;
bool opened;
- int count = 0;
ImGui::PushStyleColor(ImGuiCol_WindowBg,ImVec4(1.0f,1.0f,1.0f,0.9f));
ImGui::PushStyleColor(ImGuiCol_Text,ImVec4(0.0f,0.0f,0.0f,1.0f));
ImGui::PushStyleColor(ImGuiCol_TextDisabled,ImVec4(0.0f,0.0f,1.0f,1.0f));
@@ -1438,7 +1450,6 @@ void debug_imgui::update()
break;
}
++view_ptr;
- count++;
}
// check for a closed window
if(to_delete != nullptr)
@@ -1464,26 +1475,39 @@ void debug_imgui::init_debugger(running_machine &machine)
m_has_images = true;
// map keys to ImGui inputs
- io.KeyMap[ImGuiKey_A] = ITEM_ID_A;
- io.KeyMap[ImGuiKey_C] = ITEM_ID_C;
- io.KeyMap[ImGuiKey_V] = ITEM_ID_V;
- io.KeyMap[ImGuiKey_X] = ITEM_ID_X;
- io.KeyMap[ImGuiKey_C] = ITEM_ID_C;
- io.KeyMap[ImGuiKey_Y] = ITEM_ID_Y;
- io.KeyMap[ImGuiKey_Z] = ITEM_ID_Z;
- io.KeyMap[ImGuiKey_Backspace] = ITEM_ID_BACKSPACE;
- io.KeyMap[ImGuiKey_Delete] = ITEM_ID_DEL;
- io.KeyMap[ImGuiKey_Tab] = ITEM_ID_TAB;
- io.KeyMap[ImGuiKey_PageUp] = ITEM_ID_PGUP;
- io.KeyMap[ImGuiKey_PageDown] = ITEM_ID_PGDN;
- io.KeyMap[ImGuiKey_Home] = ITEM_ID_HOME;
- io.KeyMap[ImGuiKey_End] = ITEM_ID_END;
- io.KeyMap[ImGuiKey_Escape] = ITEM_ID_ESC;
- io.KeyMap[ImGuiKey_Enter] = ITEM_ID_ENTER;
- io.KeyMap[ImGuiKey_LeftArrow] = ITEM_ID_LEFT;
- io.KeyMap[ImGuiKey_RightArrow] = ITEM_ID_RIGHT;
- io.KeyMap[ImGuiKey_UpArrow] = ITEM_ID_UP;
- io.KeyMap[ImGuiKey_DownArrow] = ITEM_ID_DOWN;
+ m_mapping[ITEM_ID_A] = ImGuiKey_A;
+ m_mapping[ITEM_ID_C] = ImGuiKey_C;
+ m_mapping[ITEM_ID_V] = ImGuiKey_V;
+ m_mapping[ITEM_ID_X] = ImGuiKey_X;
+ m_mapping[ITEM_ID_Y] = ImGuiKey_Y;
+ m_mapping[ITEM_ID_Z] = ImGuiKey_Z;
+ m_mapping[ITEM_ID_D] = ImGuiKey_D;
+ m_mapping[ITEM_ID_M] = ImGuiKey_M;
+ m_mapping[ITEM_ID_B] = ImGuiKey_B;
+ m_mapping[ITEM_ID_W] = ImGuiKey_W;
+ m_mapping[ITEM_ID_L] = ImGuiKey_L;
+ m_mapping[ITEM_ID_BACKSPACE] = ImGuiKey_Backspace;
+ m_mapping[ITEM_ID_DEL] = ImGuiKey_Delete;
+ m_mapping[ITEM_ID_TAB] = ImGuiKey_Tab;
+ m_mapping[ITEM_ID_PGUP] = ImGuiKey_PageUp;
+ m_mapping[ITEM_ID_PGDN] = ImGuiKey_PageDown;
+ m_mapping[ITEM_ID_HOME] = ImGuiKey_Home;
+ m_mapping[ITEM_ID_END] = ImGuiKey_End;
+ m_mapping[ITEM_ID_ESC] = ImGuiKey_Escape;
+ m_mapping[ITEM_ID_ENTER] = ImGuiKey_Enter;
+ m_mapping[ITEM_ID_LEFT] = ImGuiKey_LeftArrow;
+ m_mapping[ITEM_ID_RIGHT] = ImGuiKey_RightArrow;
+ m_mapping[ITEM_ID_UP] = ImGuiKey_UpArrow;
+ m_mapping[ITEM_ID_DOWN] = ImGuiKey_DownArrow;
+ m_mapping[ITEM_ID_F3] = ImGuiKey_F3;
+ m_mapping[ITEM_ID_F5] = ImGuiKey_F5;
+ m_mapping[ITEM_ID_F6] = ImGuiKey_F6;
+ m_mapping[ITEM_ID_F7] = ImGuiKey_F7;
+ m_mapping[ITEM_ID_F8] = ImGuiKey_F8;
+ m_mapping[ITEM_ID_F9] = ImGuiKey_F9;
+ m_mapping[ITEM_ID_F10] = ImGuiKey_F10;
+ m_mapping[ITEM_ID_F11] = ImGuiKey_F11;
+ m_mapping[ITEM_ID_F12] = ImGuiKey_F12;
// set key delay and repeat rates
io.KeyRepeatDelay = 0.400f;
@@ -1534,7 +1558,7 @@ void debug_imgui::wait_for_debugger(device_t &device, bool firststop)
m_running = false;
}
m_hide = false;
- //m_machine->ui_input().frame_update();
+ m_machine->osd().input_update(true);
handle_mouse();
handle_keys();
handle_console(m_machine);
@@ -1559,6 +1583,7 @@ void debug_imgui::debugger_update()
{
uint32_t width = m_machine->render().ui_target().width();
uint32_t height = m_machine->render().ui_target().height();
+ m_machine->osd().input_update(true);
handle_mouse();
handle_keys();
imguiBeginFrame(m_mouse_x,m_mouse_y,m_mouse_button ? IMGUI_MBUT_LEFT : 0, 0, width, height, m_key_char);
@@ -1567,4 +1592,8 @@ void debug_imgui::debugger_update()
}
}
-MODULE_DEFINITION(DEBUG_IMGUI, debug_imgui)
+} // anonymous namespace
+
+} // namespace osd
+
+MODULE_DEFINITION(DEBUG_IMGUI, osd::debug_imgui)
diff --git a/src/osd/modules/debugger/debugosx.mm b/src/osd/modules/debugger/debugosx.mm
index 66797e38453..a4721e4d292 100644
--- a/src/osd/modules/debugger/debugosx.mm
+++ b/src/osd/modules/debugger/debugosx.mm
@@ -24,11 +24,6 @@
// MAMEOS headers
#include "modules/lib/osdobj_common.h"
#include "osx/debugosx.h"
-#ifdef OSD_MAC
-#include "osdmac.h"
-#else
-#include "osdsdl.h"
-#endif
#include "debug_module.h"
#import "osx/debugconsole.h"
@@ -61,12 +56,12 @@ public:
[m_console release];
}
- virtual int init(const osd_options &options);
- virtual void exit();
+ virtual int init(osd_interface &osd, const osd_options &options) override;
+ virtual void exit() override;
- virtual void init_debugger(running_machine &machine);
- virtual void wait_for_debugger(device_t &device, bool firststop);
- virtual void debugger_update();
+ virtual void init_debugger(running_machine &machine) override;
+ virtual void wait_for_debugger(device_t &device, bool firststop) override;
+ virtual void debugger_update() override;
private:
void create_console();
@@ -91,7 +86,7 @@ std::atomic_bool debugger_osx::s_added_menus(false);
// initialise debugger module
//============================================================
-int debugger_osx::init(const osd_options &options)
+int debugger_osx::init(osd_interface &osd, const osd_options &options)
{
return 0;
}
@@ -165,7 +160,7 @@ void debugger_osx::wait_for_debugger(device_t &device, bool firststop)
}
// get and process messages
- NSEvent *ev = [NSApp nextEventMatchingMask:NSAnyEventMask
+ NSEvent *ev = [NSApp nextEventMatchingMask:NSEventMaskAny
untilDate:[NSDate distantFuture]
inMode:NSDefaultRunLoopMode
dequeue:YES];
@@ -241,7 +236,7 @@ void debugger_osx::build_menus()
[[debugMenu addItemWithTitle:@"Hard Reset"
action:@selector(debugHardReset:)
keyEquivalent:[NSString stringWithFormat:@"%C", (short)NSF3FunctionKey]]
- setKeyEquivalentModifierMask:NSShiftKeyMask];
+ setKeyEquivalentModifierMask:NSEventModifierFlagShift];
NSMenu *const runMenu = [[NSMenu alloc] initWithTitle:@"Run"];
item = [[NSApp mainMenu] insertItemWithTitle:@"Run"
@@ -295,7 +290,7 @@ void debugger_osx::build_menus()
[[runMenu addItemWithTitle:@"Step Out"
action:@selector(debugStepOut:)
keyEquivalent:[NSString stringWithFormat:@"%C", (short)NSF10FunctionKey]]
- setKeyEquivalentModifierMask:NSShiftKeyMask];
+ setKeyEquivalentModifierMask:NSEventModifierFlagShift];
}
}
diff --git a/src/osd/modules/debugger/debugqt.cpp b/src/osd/modules/debugger/debugqt.cpp
index a48f419a6a3..cdf3fb014bc 100644
--- a/src/osd/modules/debugger/debugqt.cpp
+++ b/src/osd/modules/debugger/debugqt.cpp
@@ -32,34 +32,64 @@
#include "qt/deviceswindow.h"
#include "qt/deviceinformationwindow.h"
-class debug_qt : public osd_module, public debug_module
+#include "util/xmlfile.h"
+
+
+#if defined(SDLMAME_UNIX) || defined(SDLMAME_WIN32)
+extern int sdl_entered_debugger;
+#elif defined(_WIN32)
+void winwindow_update_cursor_state(running_machine &machine);
+bool winwindow_qt_filter(void *message);
+#endif
+
+
+namespace osd {
+
+namespace {
+
+class debug_qt : public osd_module, public debug_module, protected debugger::qt::DebuggerQt
#if defined(_WIN32) && !defined(SDLMAME_WIN32)
, public QAbstractNativeEventFilter
#endif
{
public:
- debug_qt() : osd_module(OSD_DEBUG_PROVIDER, "qt"), debug_module(), m_machine(nullptr)
+ debug_qt() :
+ osd_module(OSD_DEBUG_PROVIDER, "qt"),
+ debug_module(),
+ m_machine(nullptr),
+ m_mainwindow(nullptr)
{
}
virtual ~debug_qt() { }
- virtual int init(const osd_options &options) { return 0; }
- virtual void exit() { }
+ virtual int init(osd_interface &osd, const osd_options &options) override { return 0; }
+ virtual void exit() override;
- virtual void init_debugger(running_machine &machine);
- virtual void wait_for_debugger(device_t &device, bool firststop);
- virtual void debugger_update();
+ virtual void init_debugger(running_machine &machine) override;
+ virtual void wait_for_debugger(device_t &device, bool firststop) override;
+ virtual void debugger_update() override;
#if defined(_WIN32) && !defined(SDLMAME_WIN32)
- virtual bool nativeEventFilter(const QByteArray &eventType, void *message, long *) Q_DECL_OVERRIDE;
+ virtual bool nativeEventFilter(const QByteArray &eventType, void *message, long *) override
+ {
+ winwindow_qt_filter(message);
+ return false;
+ }
#endif
+
+ virtual running_machine &machine() const override { return *m_machine; }
+
private:
+ void configuration_load(config_type which_type, config_level level, util::xml::data_node const *parentnode);
+ void configuration_save(config_type which_type, util::xml::data_node *parentnode);
+ void load_window_configurations(util::xml::data_node const &parentnode);
+
running_machine *m_machine;
+ debugger::qt::MainWindow *m_mainwindow;
+ util::xml::file::ptr m_config;
};
-namespace {
-
//============================================================
// "Global" variables to make QT happy
//============================================================
@@ -68,177 +98,18 @@ int qtArgc = 1;
char qtArg0[] = "mame";
char *qtArgv[] = { qtArg0, nullptr };
-bool oneShot = true;
-MainWindow *mainQtWindow = nullptr;
-
-//============================================================
-// XML configuration save/load
-//============================================================
-
-// Global variable used to feed the xml configuration callbacks
-std::vector<std::unique_ptr<WindowQtConfig> > xmlConfigurations;
-
-
-void xml_configuration_load(running_machine &machine, config_type cfg_type, config_level cfg_level, util::xml::data_node const *parentnode)
-{
- // We only care about system configuration files
- if ((cfg_type != config_type::SYSTEM) || !parentnode)
- return;
-
- xmlConfigurations.clear();
-
- // Configuration load
- util::xml::data_node const *wnode = nullptr;
- for (wnode = parentnode->get_child("window"); wnode; wnode = wnode->get_next_sibling("window"))
- {
- WindowQtConfig::WindowType type = (WindowQtConfig::WindowType)wnode->get_attribute_int("type", WindowQtConfig::WIN_TYPE_UNKNOWN);
- switch (type)
- {
- case WindowQtConfig::WIN_TYPE_MAIN: xmlConfigurations.push_back(std::make_unique<MainWindowQtConfig>()); break;
- case WindowQtConfig::WIN_TYPE_MEMORY: xmlConfigurations.push_back(std::make_unique<MemoryWindowQtConfig>()); break;
- case WindowQtConfig::WIN_TYPE_DASM: xmlConfigurations.push_back(std::make_unique<DasmWindowQtConfig>()); break;
- case WindowQtConfig::WIN_TYPE_LOG: xmlConfigurations.push_back(std::make_unique<LogWindowQtConfig>()); break;
- case WindowQtConfig::WIN_TYPE_BREAK_POINTS: xmlConfigurations.push_back(std::make_unique<BreakpointsWindowQtConfig>()); break;
- case WindowQtConfig::WIN_TYPE_DEVICES: xmlConfigurations.push_back(std::make_unique<DevicesWindowQtConfig>()); break;
- case WindowQtConfig::WIN_TYPE_DEVICE_INFORMATION: xmlConfigurations.push_back(std::make_unique<DeviceInformationWindowQtConfig>()); break;
- default: continue;
- }
- xmlConfigurations.back()->recoverFromXmlNode(*wnode);
- }
-}
-
-
-void xml_configuration_save(running_machine &machine, config_type cfg_type, util::xml::data_node *parentnode)
-{
- // We only save system configuration
- if (cfg_type != config_type::SYSTEM)
- return;
-
- for (int i = 0; i < xmlConfigurations.size(); i++)
- {
- WindowQtConfig &config = *xmlConfigurations[i];
-
- // Create an xml node
- util::xml::data_node *const debugger_node = parentnode->add_child("window", nullptr);
-
- // Insert the appropriate information
- if (debugger_node)
- config.addToXmlDataNode(*debugger_node);
- }
-}
-
-
-void gather_save_configurations()
-{
- xmlConfigurations.clear();
-
- // Loop over all the open windows
- foreach (QWidget *widget, QApplication::topLevelWidgets())
- {
- if (!widget->isVisible())
- continue;
-
- if (!widget->isWindow() || widget->windowType() != Qt::Window)
- continue;
-
- // Figure out its type
- if (dynamic_cast<MainWindow *>(widget))
- xmlConfigurations.push_back(std::make_unique<MainWindowQtConfig>());
- else if (dynamic_cast<MemoryWindow *>(widget))
- xmlConfigurations.push_back(std::make_unique<MemoryWindowQtConfig>());
- else if (dynamic_cast<DasmWindow *>(widget))
- xmlConfigurations.push_back(std::make_unique<DasmWindowQtConfig>());
- else if (dynamic_cast<LogWindow *>(widget))
- xmlConfigurations.push_back(std::make_unique<LogWindowQtConfig>());
- else if (dynamic_cast<BreakpointsWindow *>(widget))
- xmlConfigurations.push_back(std::make_unique<BreakpointsWindowQtConfig>());
- else if (dynamic_cast<DevicesWindow *>(widget))
- xmlConfigurations.push_back(std::make_unique<DevicesWindowQtConfig>());
- else if (dynamic_cast<DeviceInformationWindow *>(widget))
- xmlConfigurations.push_back(std::make_unique<DeviceInformationWindowQtConfig>());
-
- xmlConfigurations.back()->buildFromQWidget(widget);
- }
-}
-
-
-//============================================================
-// Utilities
-//============================================================
-
-void load_and_clear_main_window_config(std::vector<std::unique_ptr<WindowQtConfig> > &configList)
-{
- for (int i = 0; i < configList.size(); i++)
- {
- WindowQtConfig &config = *configList[i];
- if (config.m_type == WindowQtConfig::WIN_TYPE_MAIN)
- {
- config.applyToQWidget(mainQtWindow);
- configList.erase(configList.begin() + i);
- break;
- }
- }
-}
-
-
-void setup_additional_startup_windows(running_machine &machine, std::vector<std::unique_ptr<WindowQtConfig> > &configList)
-{
- for (int i = 0; i < configList.size(); i++)
- {
- WindowQtConfig &config = *configList[i];
-
- WindowQt *foo = nullptr;
- switch (config.m_type)
- {
- case WindowQtConfig::WIN_TYPE_MEMORY:
- foo = new MemoryWindow(machine); break;
- case WindowQtConfig::WIN_TYPE_DASM:
- foo = new DasmWindow(machine); break;
- case WindowQtConfig::WIN_TYPE_LOG:
- foo = new LogWindow(machine); break;
- case WindowQtConfig::WIN_TYPE_BREAK_POINTS:
- foo = new BreakpointsWindow(machine); break;
- case WindowQtConfig::WIN_TYPE_DEVICES:
- foo = new DevicesWindow(machine); break;
- case WindowQtConfig::WIN_TYPE_DEVICE_INFORMATION:
- foo = new DeviceInformationWindow(machine); break;
- default:
- break;
- }
- config.applyToQWidget(foo);
- foo->show();
- }
-}
-
-
-void bring_main_window_to_front()
-{
- foreach (QWidget *widget, QApplication::topLevelWidgets())
- {
- if (dynamic_cast<MainWindow *>(widget))
- {
- widget->activateWindow();
- widget->raise();
- }
- }
-}
-
-} // anonymous namespace
-
//============================================================
// Core functionality
//============================================================
-#if defined(_WIN32) && !defined(SDLMAME_WIN32)
-bool winwindow_qt_filter(void *message);
-
-bool debug_qt::nativeEventFilter(const QByteArray &eventType, void *message, long *)
+void debug_qt::exit()
{
- winwindow_qt_filter(message);
- return false;
+ // If you've done a hard reset, clear out existing widgets
+ emit exitDebugger();
+ m_mainwindow = nullptr;
}
-#endif
+
void debug_qt::init_debugger(running_machine &machine)
{
@@ -250,23 +121,13 @@ void debug_qt::init_debugger(running_machine &machine)
QAbstractEventDispatcher::instance()->installNativeEventFilter(this);
#endif
}
- else
- {
- // If you've done a hard reset, clear out existing widgets & get ready for re-init
- foreach (QWidget *widget, QApplication::topLevelWidgets())
- {
- if (!widget->isWindow() || widget->windowType() != Qt::Window)
- continue;
- delete widget;
- }
- oneShot = true;
- }
m_machine = &machine;
+
// Setup the configuration XML saving and loading
machine.configuration().config_register("debugger",
- configuration_manager::load_delegate(&xml_configuration_load, &machine),
- configuration_manager::save_delegate(&xml_configuration_save, &machine));
+ configuration_manager::load_delegate(&debug_qt::configuration_load, this),
+ configuration_manager::save_delegate(&debug_qt::configuration_save, this));
}
@@ -274,12 +135,6 @@ void debug_qt::init_debugger(running_machine &machine)
// Core functionality
//============================================================
-#if defined(SDLMAME_UNIX) || defined(SDLMAME_WIN32)
-extern int sdl_entered_debugger;
-#elif defined(_WIN32)
-void winwindow_update_cursor_state(running_machine &machine);
-#endif
-
void debug_qt::wait_for_debugger(device_t &device, bool firststop)
{
#if defined(SDLMAME_UNIX) || defined(SDLMAME_WIN32)
@@ -287,62 +142,33 @@ void debug_qt::wait_for_debugger(device_t &device, bool firststop)
#endif
// Dialog initialization
- if (oneShot)
+ if (!m_mainwindow)
{
- mainQtWindow = new MainWindow(*m_machine);
- load_and_clear_main_window_config(xmlConfigurations);
- setup_additional_startup_windows(*m_machine, xmlConfigurations);
- mainQtWindow->show();
- oneShot = false;
+ m_mainwindow = new debugger::qt::MainWindow(*this);
+ if (m_config)
+ {
+ load_window_configurations(*m_config->get_first_child());
+ m_config.reset();
+ }
+ m_mainwindow->show();
}
// Ensure all top level widgets are visible & bring main window to front
- foreach (QWidget *widget, QApplication::topLevelWidgets())
- {
- if (!widget->isWindow() || widget->windowType() != Qt::Window)
- continue;
- widget->show();
- }
+ emit showAllWindows();
if (firststop)
- bring_main_window_to_front();
+ {
+ m_mainwindow->activateWindow();
+ m_mainwindow->raise();
+ }
- // Set the main window to display the proper cpu
- mainQtWindow->setProcessor(&device);
+ // Set the main window to display the proper CPU
+ m_mainwindow->setProcessor(&device);
// Run our own QT event loop
osd_sleep(osd_ticks_per_second() / 1000 * 50);
qApp->processEvents(QEventLoop::AllEvents, 1);
- // Refresh everyone if requested
- if (mainQtWindow->wantsRefresh())
- {
- QWidgetList allWidgets = qApp->allWidgets();
- for (int i = 0; i < allWidgets.length(); i++)
- allWidgets[i]->update();
- mainQtWindow->clearRefreshFlag();
- }
-
- // Hide all top level widgets if requested
- if (mainQtWindow->wantsHide())
- {
- foreach (QWidget *widget, QApplication::topLevelWidgets())
- {
- if (!widget->isWindow() || widget->windowType() != Qt::Window)
- continue;
- widget->hide();
- }
- mainQtWindow->clearHideFlag();
- }
-
- // Exit if the machine has been instructed to do so (scheduled event == exit || hard_reset)
- if (m_machine->scheduled_event_pending())
- {
- // Keep a list of windows we want to save.
- // We need to do this here because by the time xml_configuration_save gets called
- // all the QT windows are already gone.
- gather_save_configurations();
- }
#if defined(_WIN32) && !defined(SDLMAME_WIN32)
winwindow_update_cursor_state(*m_machine); // make sure the cursor isn't hidden while in debugger
#endif
@@ -358,10 +184,75 @@ void debug_qt::debugger_update()
qApp->processEvents(QEventLoop::AllEvents, 1);
}
+
+void debug_qt::configuration_load(config_type which_type, config_level level, util::xml::data_node const *parentnode)
+{
+ // We only care about system configuration files for now
+ if ((config_type::SYSTEM == which_type) && parentnode)
+ {
+ if (m_mainwindow)
+ {
+ load_window_configurations(*parentnode);
+ }
+ else
+ {
+ m_config = util::xml::file::create();
+ parentnode->copy_into(*m_config);
+ }
+ }
+}
+
+
+void debug_qt::configuration_save(config_type which_type, util::xml::data_node *parentnode)
+{
+ // We only save system configuration for now
+ if ((config_type::SYSTEM == which_type) && parentnode)
+ emit saveConfiguration(*parentnode);
+}
+
+
+void debug_qt::load_window_configurations(util::xml::data_node const &parentnode)
+{
+ for (util::xml::data_node const *wnode = parentnode.get_child(debugger::NODE_WINDOW); wnode; wnode = wnode->get_next_sibling(debugger::NODE_WINDOW))
+ {
+ debugger::qt::WindowQt *win = nullptr;
+ switch (wnode->get_attribute_int(debugger::ATTR_WINDOW_TYPE, -1))
+ {
+ case debugger::WINDOW_TYPE_CONSOLE:
+ win = m_mainwindow;
+ break;
+ case debugger::WINDOW_TYPE_MEMORY_VIEWER:
+ win = new debugger::qt::MemoryWindow(*this);
+ break;
+ case debugger::WINDOW_TYPE_DISASSEMBLY_VIEWER:
+ win = new debugger::qt::DasmWindow(*this);
+ break;
+ case debugger::WINDOW_TYPE_ERROR_LOG_VIEWER:
+ win = new debugger::qt::LogWindow(*this);
+ break;
+ case debugger::WINDOW_TYPE_POINTS_VIEWER:
+ win = new debugger::qt::BreakpointsWindow(*this);
+ break;
+ case debugger::WINDOW_TYPE_DEVICES_VIEWER:
+ win = new debugger::qt::DevicesWindow(*this);
+ break;
+ case debugger::WINDOW_TYPE_DEVICE_INFO_VIEWER:
+ win = new debugger::qt::DeviceInformationWindow(*this);
+ break;
+ }
+ if (win)
+ win->restoreConfiguration(*wnode);
+ }
+}
+
+} // anonymous namespace
+
+} // namespace osd
+
#else // USE_QTDEBUG
-MODULE_NOT_SUPPORTED(debug_qt, OSD_DEBUG_PROVIDER, "qt")
+namespace osd { namespace { MODULE_NOT_SUPPORTED(debug_qt, OSD_DEBUG_PROVIDER, "qt") } }
#endif
-MODULE_DEFINITION(DEBUG_QT, debug_qt)
+MODULE_DEFINITION(DEBUG_QT, osd::debug_qt)
diff --git a/src/osd/modules/debugger/debugwin.cpp b/src/osd/modules/debugger/debugwin.cpp
index 18bbc07dd70..43d20ae371d 100644
--- a/src/osd/modules/debugger/debugwin.cpp
+++ b/src/osd/modules/debugger/debugwin.cpp
@@ -2,13 +2,12 @@
// copyright-holders:Aaron Giles, Vas Crabb
//============================================================
//
-// debugwin.c - Win32 debug window handling
+// debugwin.cpp - Win32 debug window handling
//
//============================================================
#include "emu.h"
#include "debug_module.h"
-#include "modules/osdmodule.h"
#if defined(OSD_WINDOWS) /*|| defined(SDLMAME_WIN32)*/
@@ -22,31 +21,48 @@
#include "win/pointswininfo.h"
#include "win/uimetrics.h"
+// emu
+#include "config.h"
#include "debugger.h"
#include "debug/debugcpu.h"
+#include "util/xmlfile.h"
+
+// osd/windows
#include "window.h"
-#include "../input/input_common.h"
-#include "../input/input_windows.h"
+#include "winmain.h"
+
+#include "../input/input_windows.h" // for the keyboard translation table
+
+namespace osd {
-class debugger_windows : public osd_module, public debug_module, protected debugger_windows_interface
+namespace {
+
+class debugger_windows :
+ public osd_module,
+ public debug_module,
+ protected debugger::win::debugger_windows_interface
{
public:
debugger_windows() :
osd_module(OSD_DEBUG_PROVIDER, "windows"),
debug_module(),
+ m_osd(nullptr),
m_machine(nullptr),
m_metrics(),
m_waiting_for_debugger(false),
m_window_list(),
- m_main_console(nullptr)
+ m_main_console(nullptr),
+ m_next_window_pos{ 0, 0 },
+ m_config(),
+ m_save_windows(true)
{
}
virtual ~debugger_windows() { }
- virtual int init(const osd_options &options) override { return 0; }
+ virtual int init(osd_interface &osd, osd_options const &options) override;
virtual void exit() override;
virtual void init_debugger(running_machine &machine) override;
@@ -56,31 +72,58 @@ public:
protected:
virtual running_machine &machine() const override { return *m_machine; }
- virtual ui_metrics &metrics() const override { return *m_metrics; }
+ virtual debugger::win::ui_metrics &metrics() const override { return *m_metrics; }
+ virtual void set_color_theme(int index) override;
+ virtual bool get_save_window_arrangement() const override { return m_save_windows; }
+ virtual void set_save_window_arrangement(bool save) override { m_save_windows = save; }
virtual bool const &waiting_for_debugger() const override { return m_waiting_for_debugger; }
virtual bool seq_pressed() const override;
- virtual void create_memory_window() override { create_window<memorywin_info>(); }
- virtual void create_disasm_window() override { create_window<disasmwin_info>(); }
- virtual void create_log_window() override { create_window<logwin_info>(); }
- virtual void create_points_window() override { create_window<pointswin_info>(); }
- virtual void remove_window(debugwin_info &info) override;
+ virtual void create_memory_window() override { create_window<debugger::win::memorywin_info>(); }
+ virtual void create_disasm_window() override { create_window<debugger::win::disasmwin_info>(); }
+ virtual void create_log_window() override { create_window<debugger::win::logwin_info>(); }
+ virtual void create_points_window() override { create_window<debugger::win::pointswin_info>(); }
+ virtual void remove_window(debugger::win::debugwin_info &info) override;
virtual void show_all() override;
virtual void hide_all() override;
+ virtual void stagger_window(HWND window, int width, int height) override;
+
private:
template <typename T> T *create_window();
- running_machine *m_machine;
- std::unique_ptr<ui_metrics> m_metrics;
- bool m_waiting_for_debugger;
- std::vector<std::unique_ptr<debugwin_info>> m_window_list;
- consolewin_info *m_main_console;
+ void config_load(config_type cfgtype, config_level cfglevel, util::xml::data_node const *parentnode);
+ void config_save(config_type cfgtype, util::xml::data_node *parentnode);
+
+ void load_configuration(util::xml::data_node const &parentnode);
+
+ windows_osd_interface *m_osd;
+ running_machine *m_machine;
+ std::unique_ptr<debugger::win::ui_metrics> m_metrics;
+ bool m_waiting_for_debugger;
+ std::vector<std::unique_ptr<debugger::win::debugwin_info> > m_window_list;
+ debugger::win::consolewin_info *m_main_console;
+
+ POINT m_next_window_pos;
+ LONG m_window_start_x;
+
+ util::xml::file::ptr m_config;
+ bool m_save_windows;
};
+int debugger_windows::init(osd_interface &osd, osd_options const &options)
+{
+ m_osd = dynamic_cast<windows_osd_interface *>(&osd);
+ if (!m_osd)
+ return -1;
+
+ return 0;
+}
+
+
void debugger_windows::exit()
{
// loop over windows and free them
@@ -96,23 +139,52 @@ void debugger_windows::exit()
void debugger_windows::init_debugger(running_machine &machine)
{
m_machine = &machine;
- m_metrics = std::make_unique<ui_metrics>(downcast<osd_options &>(m_machine->options()));
+ m_metrics = std::make_unique<debugger::win::ui_metrics>(downcast<osd_options &>(m_machine->options()));
+ machine.configuration().config_register(
+ "debugger",
+ configuration_manager::load_delegate(&debugger_windows::config_load, this),
+ configuration_manager::save_delegate(&debugger_windows::config_save, this));
}
void debugger_windows::wait_for_debugger(device_t &device, bool firststop)
{
// create a console window
- if (m_main_console == nullptr)
- m_main_console = create_window<consolewin_info>();
+ if (!m_main_console)
+ {
+ m_main_console = create_window<debugger::win::consolewin_info>();
+
+ // set the starting position for new auxiliary windows
+ HMONITOR const nearest_monitor = MonitorFromWindow(
+ dynamic_cast<win_window_info &>(*osd_common_t::window_list().front()).platform_window(),
+ MONITOR_DEFAULTTONEAREST);
+ if (nearest_monitor)
+ {
+ MONITORINFO info;
+ std::memset(&info, 0, sizeof(info));
+ info.cbSize = sizeof(info);
+ if (GetMonitorInfo(nearest_monitor, &info))
+ {
+ m_next_window_pos.x = info.rcWork.left + 100;
+ m_next_window_pos.y = info.rcWork.top + 100;
+ m_window_start_x = m_next_window_pos.x;
+ }
+ }
+ }
// update the views in the console to reflect the current CPU
- if (m_main_console != nullptr)
+ if (m_main_console)
m_main_console->set_cpu(device);
// when we are first stopped, adjust focus to us
- if (firststop && (m_main_console != nullptr))
+ if (firststop && m_main_console)
{
+ if (m_config)
+ {
+ for (util::xml::data_node const *node = m_config->get_first_child(); node; node = node->get_next_sibling())
+ load_configuration(*node);
+ m_config.reset();
+ }
m_main_console->set_foreground();
if (winwindow_has_focus())
m_main_console->set_default_focus();
@@ -123,7 +195,7 @@ void debugger_windows::wait_for_debugger(device_t &device, bool firststop)
show_all();
// run input polling to ensure that our status is in sync
- downcast<windows_osd_interface&>(machine().osd()).poll_input(*m_machine);
+ downcast<windows_osd_interface&>(machine().osd()).poll_input_modules(false);
// get and process messages
MSG message;
@@ -171,6 +243,14 @@ void debugger_windows::debugger_update()
}
+void debugger_windows::set_color_theme(int index)
+{
+ m_metrics->set_color_theme(index);
+ for (auto const &window : m_window_list)
+ window->redraw();
+}
+
+
bool debugger_windows::seq_pressed() const
{
input_seq const &seq = m_machine->ioport().type_seq(IPT_UI_DEBUG_BREAK);
@@ -222,7 +302,7 @@ bool debugger_windows::seq_pressed() const
}
-void debugger_windows::remove_window(debugwin_info &info)
+void debugger_windows::remove_window(debugger::win::debugwin_info &info)
{
for (auto it = m_window_list.begin(); it != m_window_list.end(); ++it)
if (it->get() == &info) {
@@ -241,28 +321,162 @@ void debugger_windows::show_all()
void debugger_windows::hide_all()
{
- SetForegroundWindow(std::static_pointer_cast<win_window_info>(osd_common_t::s_window_list.front())->platform_window());
+ SetForegroundWindow(dynamic_cast<win_window_info &>(*osd_common_t::window_list().front()).platform_window());
for (auto &info : m_window_list)
info->hide();
}
-template <typename T> T *debugger_windows::create_window()
+void debugger_windows::stagger_window(HWND window, int width, int height)
+{
+ // get width/height for client size
+ RECT target;
+ target.left = 0;
+ target.top = 0;
+ target.right = width;
+ target.bottom = height;
+ if (!AdjustWindowRectEx(&target, GetWindowLong(window, GWL_STYLE), GetMenu(window) ? TRUE : FALSE,GetWindowLong(window, GWL_EXSTYLE)))
+ {
+ // really shouldn't end up here, but have to do something
+ SetWindowPos(window, HWND_TOP, m_next_window_pos.x, m_next_window_pos.y, width, height, SWP_SHOWWINDOW);
+ return;
+ }
+ target.right -= target.left;
+ target.bottom -= target.top;
+ target.left = target.top = 0;
+
+ // get the work area for the nearest monitor to the target position
+ HMONITOR const mon = MonitorFromPoint(m_next_window_pos, MONITOR_DEFAULTTONEAREST);
+ if (mon)
+ {
+ MONITORINFO info;
+ std::memset(&info, 0, sizeof(info));
+ info.cbSize = sizeof(info);
+ if (GetMonitorInfo(mon, &info))
+ {
+ // restart cascade if necessary
+ if (((m_next_window_pos.x + target.right) > info.rcWork.right) || ((m_next_window_pos.y + target.bottom) > info.rcWork.bottom))
+ {
+ m_next_window_pos.x = m_window_start_x += 16;
+ m_next_window_pos.y = info.rcWork.top + 100;
+ if ((m_next_window_pos.x + target.right) > info.rcWork.right)
+ m_next_window_pos.x = m_window_start_x = info.rcWork.left + 100;
+ }
+ }
+ }
+
+ // move the window and adjust the next position
+ MoveWindow(window, m_next_window_pos.x, m_next_window_pos.y, target.right, target.bottom, FALSE);
+ SetWindowPos(window, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);
+ m_next_window_pos.x += 16;
+ m_next_window_pos.y += 16;
+}
+
+
+template <typename T>
+T *debugger_windows::create_window()
{
// allocate memory
std::unique_ptr<T> info = std::make_unique<T>(static_cast<debugger_windows_interface &>(*this));
if (info->is_valid())
{
+ T &result(*info);
m_window_list.push_back(std::move(info));
- T *ptr = dynamic_cast<T*>(m_window_list.back().get());
- return ptr;
+ return &result;
}
return nullptr;
}
-#else /* not windows */
-MODULE_NOT_SUPPORTED(debugger_windows, OSD_DEBUG_PROVIDER, "windows")
+void debugger_windows::config_load(config_type cfgtype, config_level cfglevel, util::xml::data_node const *parentnode)
+{
+ if (parentnode)
+ {
+ if (config_type::DEFAULT == cfgtype)
+ {
+ m_save_windows = 0 != parentnode->get_attribute_int(debugger::ATTR_DEBUGGER_SAVE_WINDOWS, m_save_windows ? 1 : 0);
+ util::xml::data_node const *const colors = parentnode->get_child(debugger::NODE_COLORS);
+ if (colors)
+ m_metrics->set_color_theme(colors->get_attribute_int(debugger::ATTR_COLORS_THEME, m_metrics->get_color_theme()));
+ }
+ else if (config_type::SYSTEM == cfgtype)
+ {
+ if (m_main_console)
+ {
+ load_configuration(*parentnode);
+ }
+ else
+ {
+ if (!m_config)
+ m_config = util::xml::file::create();
+ parentnode->copy_into(*m_config);
+ }
+ }
+ }
+}
+
+
+void debugger_windows::config_save(config_type cfgtype, util::xml::data_node *parentnode)
+{
+ if (config_type::DEFAULT == cfgtype)
+ {
+ parentnode->set_attribute_int(debugger::ATTR_DEBUGGER_SAVE_WINDOWS, m_save_windows ? 1 : 0);
+ util::xml::data_node *const colors = parentnode->add_child(debugger::NODE_COLORS, nullptr);
+ if (colors)
+ colors->set_attribute_int(debugger::ATTR_COLORS_THEME, m_metrics->get_color_theme());
+ }
+ else if (m_save_windows && (config_type::SYSTEM == cfgtype))
+ {
+ for (auto &info : m_window_list)
+ info->save_configuration(*parentnode);
+ }
+}
+
+
+void debugger_windows::load_configuration(util::xml::data_node const &parentnode)
+{
+ for (util::xml::data_node const *node = parentnode.get_child(debugger::NODE_WINDOW); node; node = node->get_next_sibling(debugger::NODE_WINDOW))
+ {
+ debugger::win::debugwin_info *win = nullptr;
+ switch (node->get_attribute_int(debugger::ATTR_WINDOW_TYPE, -1))
+ {
+ case debugger::WINDOW_TYPE_CONSOLE:
+ m_main_console->restore_configuration_from_node(*node);
+ break;
+ case debugger::WINDOW_TYPE_MEMORY_VIEWER:
+ win = create_window<debugger::win::memorywin_info>();
+ break;
+ case debugger::WINDOW_TYPE_DISASSEMBLY_VIEWER:
+ win = create_window<debugger::win::disasmwin_info>();
+ break;
+ case debugger::WINDOW_TYPE_ERROR_LOG_VIEWER:
+ win = create_window<debugger::win::logwin_info>();
+ break;
+ case debugger::WINDOW_TYPE_POINTS_VIEWER:
+ win = create_window<debugger::win::pointswin_info>();
+ break;
+ case debugger::WINDOW_TYPE_DEVICES_VIEWER:
+ // not supported
+ break;
+ case debugger::WINDOW_TYPE_DEVICE_INFO_VIEWER:
+ // not supported
+ break;
+ default:
+ break;
+ }
+ if (win)
+ win->restore_configuration_from_node(*node);
+ }
+}
+
+} // anonymous namespace
+
+} // namespace osd
+
+#else // not Windows
+
+namespace osd { namespace { MODULE_NOT_SUPPORTED(debugger_windows, OSD_DEBUG_PROVIDER, "windows") } }
+
#endif
-MODULE_DEFINITION(DEBUG_WINDOWS, debugger_windows)
+MODULE_DEFINITION(DEBUG_WINDOWS, osd::debugger_windows)
diff --git a/src/osd/modules/debugger/none.cpp b/src/osd/modules/debugger/none.cpp
index ef23fe04089..61bd1bbbd3e 100644
--- a/src/osd/modules/debugger/none.cpp
+++ b/src/osd/modules/debugger/none.cpp
@@ -8,24 +8,28 @@
#include "emu.h"
#include "debug_module.h"
-#include "modules/osdmodule.h"
#include "debug/debugcon.h"
#include "debug/debugcpu.h"
#include "debugger.h"
+
+namespace osd {
+
+namespace {
+
class debug_none : public osd_module, public debug_module
{
public:
- debug_none()
- : osd_module(OSD_DEBUG_PROVIDER, "none"), debug_module(),
+ debug_none() :
+ osd_module(OSD_DEBUG_PROVIDER, "none"), debug_module(),
m_machine(nullptr)
{
}
virtual ~debug_none() { }
- virtual int init(const osd_options &options) override { return 0; }
+ virtual int init(osd_interface &osd, const osd_options &options) override { return 0; }
virtual void exit() override { }
virtual void init_debugger(running_machine &machine) override;
@@ -50,4 +54,8 @@ void debug_none::debugger_update()
{
}
-MODULE_DEFINITION(DEBUG_NONE, debug_none)
+} // anonymous namespace
+
+} // namespace osd
+
+MODULE_DEFINITION(DEBUG_NONE, osd::debug_none)
diff --git a/src/osd/modules/debugger/osx/debugcommandhistory.h b/src/osd/modules/debugger/osx/debugcommandhistory.h
index f99767cb4be..e505aa4435c 100644
--- a/src/osd/modules/debugger/osx/debugcommandhistory.h
+++ b/src/osd/modules/debugger/osx/debugcommandhistory.h
@@ -8,6 +8,8 @@
#import "debugosx.h"
+#include "util/utilfwd.h"
+
#import <Cocoa/Cocoa.h>
@@ -32,4 +34,7 @@
- (void)reset;
- (void)clear;
+- (void)saveConfigurationToNode:(util::xml::data_node *)node;
+- (void)restoreConfigurationFromNode:(util::xml::data_node const *)node;
+
@end
diff --git a/src/osd/modules/debugger/osx/debugcommandhistory.mm b/src/osd/modules/debugger/osx/debugcommandhistory.mm
index 74a34904ae7..e2292f973b0 100644
--- a/src/osd/modules/debugger/osx/debugcommandhistory.mm
+++ b/src/osd/modules/debugger/osx/debugcommandhistory.mm
@@ -12,6 +12,8 @@
#import "debugcommandhistory.h"
+#include "util/xmlfile.h"
+
@implementation MAMEDebugCommandHistory
@@ -54,9 +56,9 @@
- (void)add:(NSString *)entry {
if (([history count] == 0) || ![[history objectAtIndex:0] isEqualToString:entry]) {
- [history insertObject:entry atIndex:0];
- while ([history count] > length)
+ while ([history count] >= length)
[history removeLastObject];
+ [history insertObject:entry atIndex:0];
}
position = 0;
}
@@ -110,4 +112,30 @@
[history removeAllObjects];
}
+
+- (void)saveConfigurationToNode:(util::xml::data_node *)node {
+ util::xml::data_node *const hist = node->add_child(osd::debugger::NODE_WINDOW_HISTORY, nullptr);
+ if (hist) {
+ for (NSInteger i = [history count]; 0 < i; --i)
+ hist->add_child(osd::debugger::NODE_HISTORY_ITEM, [[history objectAtIndex:(i - 1)] UTF8String]);
+ }
+}
+
+
+- (void)restoreConfigurationFromNode:(util::xml::data_node const *)node {
+ [self clear];
+ util::xml::data_node const *const hist = node->get_child(osd::debugger::NODE_WINDOW_HISTORY);
+ if (hist) {
+ util::xml::data_node const *item = hist->get_child(osd::debugger::NODE_HISTORY_ITEM);
+ while (item) {
+ if (item->get_value() && *item->get_value()) {
+ while ([history count] >= length)
+ [history removeLastObject];
+ [history insertObject:[NSString stringWithUTF8String:item->get_value()] atIndex:0];
+ }
+ item = item->get_next_sibling(osd::debugger::NODE_HISTORY_ITEM);
+ }
+ }
+}
+
@end
diff --git a/src/osd/modules/debugger/osx/debugconsole.mm b/src/osd/modules/debugger/osx/debugconsole.mm
index c1689a8b855..9673dc852ab 100644
--- a/src/osd/modules/debugger/osx/debugconsole.mm
+++ b/src/osd/modules/debugger/osx/debugconsole.mm
@@ -142,19 +142,25 @@
NSRect const available = [[NSScreen mainScreen] visibleFrame];
NSSize const regCurrent = [regScroll frame].size;
NSSize const regSize = [NSScrollView frameSizeForContentSize:[regView maximumFrameSize]
- hasHorizontalScroller:YES
- hasVerticalScroller:YES
- borderType:[regScroll borderType]];
+ horizontalScrollerClass:[NSScroller class]
+ verticalScrollerClass:[NSScroller class]
+ borderType:[regScroll borderType]
+ controlSize:NSControlSizeRegular
+ scrollerStyle:NSScrollerStyleOverlay];
NSSize const dasmCurrent = [dasmScroll frame].size;
NSSize const dasmSize = [NSScrollView frameSizeForContentSize:[dasmView maximumFrameSize]
- hasHorizontalScroller:YES
- hasVerticalScroller:YES
- borderType:[dasmScroll borderType]];
+ horizontalScrollerClass:[NSScroller class]
+ verticalScrollerClass:[NSScroller class]
+ borderType:[dasmScroll borderType]
+ controlSize:NSControlSizeRegular
+ scrollerStyle:NSScrollerStyleOverlay];
NSSize const consoleCurrent = [consoleContainer frame].size;
NSSize consoleSize = [NSScrollView frameSizeForContentSize:[consoleView maximumFrameSize]
- hasHorizontalScroller:YES
- hasVerticalScroller:YES
- borderType:[consoleScroll borderType]];
+ horizontalScrollerClass:[NSScroller class]
+ verticalScrollerClass:[NSScroller class]
+ borderType:[consoleScroll borderType]
+ controlSize:NSControlSizeRegular
+ scrollerStyle:NSScrollerStyleOverlay];
NSRect windowFrame = [window frame];
NSSize adjustment;
@@ -380,32 +386,35 @@
- (void)loadConfiguration:(util::xml::data_node const *)parentnode {
util::xml::data_node const *node = nullptr;
- for (node = parentnode->get_child("window"); node; node = node->get_next_sibling("window"))
+ for (node = parentnode->get_child(osd::debugger::NODE_WINDOW); node; node = node->get_next_sibling(osd::debugger::NODE_WINDOW))
{
MAMEDebugWindowHandler *win = nil;
- switch (node->get_attribute_int("type", -1))
+ switch (node->get_attribute_int(osd::debugger::ATTR_WINDOW_TYPE, -1))
{
- case MAME_DEBUGGER_WINDOW_TYPE_CONSOLE:
+ case osd::debugger::WINDOW_TYPE_CONSOLE:
[self restoreConfigurationFromNode:node];
break;
- case MAME_DEBUGGER_WINDOW_TYPE_MEMORY_VIEWER:
+ case osd::debugger::WINDOW_TYPE_MEMORY_VIEWER:
win = [[MAMEMemoryViewer alloc] initWithMachine:*machine console:self];
break;
- case MAME_DEBUGGER_WINDOW_TYPE_DISASSEMBLY_VIEWER:
+ case osd::debugger::WINDOW_TYPE_DISASSEMBLY_VIEWER:
win = [[MAMEDisassemblyViewer alloc] initWithMachine:*machine console:self];
break;
- case MAME_DEBUGGER_WINDOW_TYPE_ERROR_LOG_VIEWER:
+ case osd::debugger::WINDOW_TYPE_ERROR_LOG_VIEWER:
win = [[MAMEErrorLogViewer alloc] initWithMachine:*machine console:self];
break;
- case MAME_DEBUGGER_WINDOW_TYPE_POINTS_VIEWER:
+ case osd::debugger::WINDOW_TYPE_POINTS_VIEWER:
win = [[MAMEPointsViewer alloc] initWithMachine:*machine console:self];
break;
- case MAME_DEBUGGER_WINDOW_TYPE_DEVICES_VIEWER:
+ case osd::debugger::WINDOW_TYPE_DEVICES_VIEWER:
win = [[MAMEDevicesViewer alloc] initWithMachine:*machine console:self];
break;
- case MAME_DEBUGGER_WINDOW_TYPE_DEVICE_INFO_VIEWER:
- // FIXME: needs device info on init, make another variant
- //win = [[MAMEDeviceInfoViewer alloc] initWithMachine:*machine console:self];
+ case osd::debugger::WINDOW_TYPE_DEVICE_INFO_VIEWER:
+ {
+ // FIXME: feels like a leaky abstraction, but device is needed for init
+ device_t *const device = machine->root_device().subdevice(node->get_attribute_string(osd::debugger::ATTR_WINDOW_DEVICE_TAG, ":"));
+ win = [[MAMEDeviceInfoViewer alloc] initWithDevice:(device ? *device : machine->root_device()) machine:*machine console:self];
+ }
break;
default:
break;
@@ -423,34 +432,36 @@
- (void)saveConfigurationToNode:(util::xml::data_node *)node {
[super saveConfigurationToNode:node];
- node->set_attribute_int("type", MAME_DEBUGGER_WINDOW_TYPE_CONSOLE);
- util::xml::data_node *const splits = node->add_child("splits", nullptr);
+ node->set_attribute_int(osd::debugger::ATTR_WINDOW_TYPE, osd::debugger::WINDOW_TYPE_CONSOLE);
+ util::xml::data_node *const splits = node->add_child(osd::debugger::NODE_WINDOW_SPLITS, nullptr);
if (splits)
{
- splits->set_attribute_float("state",
+ splits->set_attribute_float(osd::debugger::ATTR_SPLITS_CONSOLE_STATE,
[regSplit isSubviewCollapsed:[[regSplit subviews] objectAtIndex:0]]
? 0.0
: NSMaxX([[[regSplit subviews] objectAtIndex:0] frame]));
- splits->set_attribute_float("disassembly",
+ splits->set_attribute_float(osd::debugger::ATTR_SPLITS_CONSOLE_DISASSEMBLY,
[dasmSplit isSubviewCollapsed:[[dasmSplit subviews] objectAtIndex:0]]
? 0.0
: NSMaxY([[[dasmSplit subviews] objectAtIndex:0] frame]));
}
[dasmView saveConfigurationToNode:node];
+ [history saveConfigurationToNode:node];
}
- (void)restoreConfigurationFromNode:(util::xml::data_node const *)node {
[super restoreConfigurationFromNode:node];
- util::xml::data_node const *const splits = node->get_child("splits");
+ util::xml::data_node const *const splits = node->get_child(osd::debugger::NODE_WINDOW_SPLITS);
if (splits)
{
- [regSplit setPosition:splits->get_attribute_float("state", NSMaxX([[[regSplit subviews] objectAtIndex:0] frame]))
+ [regSplit setPosition:splits->get_attribute_float(osd::debugger::ATTR_SPLITS_CONSOLE_STATE, NSMaxX([[[regSplit subviews] objectAtIndex:0] frame]))
ofDividerAtIndex:0];
- [dasmSplit setPosition:splits->get_attribute_float("disassembly", NSMaxY([[[dasmSplit subviews] objectAtIndex:0] frame]))
+ [dasmSplit setPosition:splits->get_attribute_float(osd::debugger::ATTR_SPLITS_CONSOLE_DISASSEMBLY, NSMaxY([[[dasmSplit subviews] objectAtIndex:0] frame]))
ofDividerAtIndex:0];
}
[dasmView restoreConfigurationFromNode:node];
+ [history restoreConfigurationFromNode:node];
}
diff --git a/src/osd/modules/debugger/osx/debugosx.h b/src/osd/modules/debugger/osx/debugosx.h
index 9d48402c032..6e0a47089d9 100644
--- a/src/osd/modules/debugger/osx/debugosx.h
+++ b/src/osd/modules/debugger/osx/debugosx.h
@@ -6,8 +6,13 @@
//
//============================================================
-#ifndef __SDL_DEBUGOSX__
-#define __SDL_DEBUGOSX__
+#ifndef MAME_OSD_DEBUGGER_OSX_DEBUGOSX_H
+#define MAME_OSD_DEBUGGER_OSX_DEBUGOSX_H
+
+#pragma once
+
+#include "../xmlconfig.h"
+
#define __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES 0
@@ -20,30 +25,6 @@
// standard Cocoa headers
#import <Cocoa/Cocoa.h>
-// workarounds for 10.6 warnings
-#ifdef MAC_OS_X_VERSION_MAX_ALLOWED
-
-#if MAC_OS_X_VERSION_MAX_ALLOWED < 1060
-
-@protocol NSWindowDelegate <NSObject>
-@end
-
-@protocol NSSplitViewDelegate <NSObject>
-@end
-
-@protocol NSControlTextEditingDelegate <NSObject>
-@end
-
-@protocol NSTextFieldDelegate <NSControlTextEditingDelegate>
-@end
-
-@protocol NSOutlineViewDataSource <NSObject>
-@end
-
-#endif // MAC_OS_X_VERSION_MAX_ALLOWED < 1060
-
-#endif // MAC_OS_X_VERSION_MAX_ALLOWED
-
#endif // __OBJC__
-#endif // __SDL_DEBUGOSX__
+#endif // MAME_OSD_DEBUGGER_OSX_DEBUGOSX_H
diff --git a/src/osd/modules/debugger/osx/debugview.mm b/src/osd/modules/debugger/osx/debugview.mm
index 8853be80622..ebf4ce257d5 100644
--- a/src/osd/modules/debugger/osx/debugview.mm
+++ b/src/osd/modules/debugger/osx/debugview.mm
@@ -51,6 +51,26 @@ static void debugwin_view_update(debug_view &view, void *osdprivate)
@implementation MAMEDebugView
+ (void)initialize {
+ // 10.15 and better get full adaptive Dark Mode support
+#if defined(MAC_OS_X_VERSION_10_15) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_15
+ DefaultForeground = [[NSColor textColor] retain];
+ ChangedForeground = [[NSColor systemRedColor] retain];
+ CommentForeground = [[NSColor systemGreenColor] retain];
+ // DCA_INVALID and DCA_DISABLED currently are not set by the core, so these 4 are unused
+ InvalidForeground = [[NSColor colorWithCalibratedRed:0.0 green:0.0 blue:1.0 alpha:1.0] retain];
+ DisabledChangedForeground = [[NSColor colorWithCalibratedRed:0.5 green:0.125 blue:0.125 alpha:1.0] retain];
+ DisabledInvalidForeground = [[NSColor colorWithCalibratedRed:0.0 green:0.0 blue:0.5 alpha:1.0] retain];
+ DisabledCommentForeground = [[NSColor colorWithCalibratedRed:0.0 green:0.25 blue:0.0 alpha:1.0] retain];
+
+ DefaultBackground = [[NSColor textBackgroundColor] retain];
+ VisitedBackground = [[NSColor systemTealColor] retain];
+ AncillaryBackground = [[NSColor unemphasizedSelectedContentBackgroundColor] retain];
+ SelectedBackground = [[NSColor selectedContentBackgroundColor] retain];
+ CurrentBackground = [[NSColor selectedControlColor] retain];
+ SelectedCurrentBackground = [[NSColor unemphasizedSelectedContentBackgroundColor] retain];
+ InactiveSelectedBackground = [[NSColor unemphasizedSelectedContentBackgroundColor] retain];
+ InactiveSelectedCurrentBackground = [[NSColor systemGrayColor] retain];
+#else
DefaultForeground = [[NSColor colorWithCalibratedWhite:0.0 alpha:1.0] retain];
ChangedForeground = [[NSColor colorWithCalibratedRed:0.875 green:0.0 blue:0.0 alpha:1.0] retain];
InvalidForeground = [[NSColor colorWithCalibratedRed:0.0 green:0.0 blue:1.0 alpha:1.0] retain];
@@ -67,6 +87,7 @@ static void debugwin_view_update(debug_view &view, void *osdprivate)
SelectedCurrentBackground = [[NSColor colorWithCalibratedRed:0.875 green:0.625 blue:0.875 alpha:1.0] retain];
InactiveSelectedBackground = [[NSColor colorWithCalibratedWhite:0.875 alpha:1.0] retain];
InactiveSelectedCurrentBackground = [[NSColor colorWithCalibratedRed:0.875 green:0.5 blue:0.625 alpha:1.0] retain];
+#endif
NonWhiteCharacters = [[[NSCharacterSet whitespaceAndNewlineCharacterSet] invertedSet] retain];
}
@@ -493,22 +514,22 @@ static void debugwin_view_update(debug_view &view, void *osdprivate)
- (void)saveConfigurationToNode:(util::xml::data_node *)node {
if (view->cursor_supported())
{
- util::xml::data_node *const selection = node->add_child("selection", nullptr);
+ util::xml::data_node *const selection = node->add_child(osd::debugger::NODE_WINDOW_SELECTION, nullptr);
if (selection)
{
debug_view_xy const pos = view->cursor_position();
- selection->set_attribute_int("visible", view->cursor_visible() ? 1 : 0);
- selection->set_attribute_int("start_x", pos.x);
- selection->set_attribute_int("start_y", pos.y);
+ selection->set_attribute_int(osd::debugger::ATTR_SELECTION_CURSOR_VISIBLE, view->cursor_visible() ? 1 : 0);
+ selection->set_attribute_int(osd::debugger::ATTR_SELECTION_CURSOR_X, pos.x);
+ selection->set_attribute_int(osd::debugger::ATTR_SELECTION_CURSOR_Y, pos.y);
}
}
- util::xml::data_node *const scroll = node->add_child("scroll", nullptr);
+ util::xml::data_node *const scroll = node->add_child(osd::debugger::NODE_WINDOW_SCROLL, nullptr);
if (scroll)
{
NSRect const visible = [self visibleRect];
- scroll->set_attribute_float("position_x", visible.origin.x);
- scroll->set_attribute_float("position_y", visible.origin.y);
+ scroll->set_attribute_float(osd::debugger::ATTR_SCROLL_ORIGIN_X, visible.origin.x);
+ scroll->set_attribute_float(osd::debugger::ATTR_SCROLL_ORIGIN_Y, visible.origin.y);
}
}
@@ -516,23 +537,23 @@ static void debugwin_view_update(debug_view &view, void *osdprivate)
- (void)restoreConfigurationFromNode:(util::xml::data_node const *)node {
if (view->cursor_supported())
{
- util::xml::data_node const *const selection = node->get_child("selection");
+ util::xml::data_node const *const selection = node->get_child(osd::debugger::NODE_WINDOW_SELECTION);
if (selection)
{
debug_view_xy pos = view->cursor_position();
- view->set_cursor_visible(0 != selection->get_attribute_int("visible", view->cursor_visible() ? 1 : 0));
- pos.x = selection->get_attribute_int("start_x", pos.x);
- pos.y = selection->get_attribute_int("start_y", pos.y);
+ view->set_cursor_visible(0 != selection->get_attribute_int(osd::debugger::ATTR_SELECTION_CURSOR_VISIBLE, view->cursor_visible() ? 1 : 0));
+ pos.x = selection->get_attribute_int(osd::debugger::ATTR_SELECTION_CURSOR_X, pos.x);
+ pos.y = selection->get_attribute_int(osd::debugger::ATTR_SELECTION_CURSOR_Y, pos.y);
view->set_cursor_position(pos);
}
}
- util::xml::data_node const *const scroll = node->get_child("scroll");
+ util::xml::data_node const *const scroll = node->get_child(osd::debugger::NODE_WINDOW_SCROLL);
if (scroll)
{
NSRect visible = [self visibleRect];
- visible.origin.x = scroll->get_attribute_float("position_x", visible.origin.x);
- visible.origin.y = scroll->get_attribute_float("position_y", visible.origin.y);
+ visible.origin.x = scroll->get_attribute_float(osd::debugger::ATTR_SCROLL_ORIGIN_X, visible.origin.x);
+ visible.origin.y = scroll->get_attribute_float(osd::debugger::ATTR_SCROLL_ORIGIN_Y, visible.origin.y);
[self scrollRectToVisible:visible];
}
}
@@ -743,8 +764,8 @@ static void debugwin_view_update(debug_view &view, void *osdprivate)
- (void)mouseDown:(NSEvent *)event {
NSPoint const location = [self convertPoint:[event locationInWindow] fromView:nil];
NSUInteger const modifiers = [event modifierFlags];
- view->process_click(((modifiers & NSCommandKeyMask) && [[self window] isMainWindow]) ? DCK_RIGHT_CLICK
- : (modifiers & NSAlternateKeyMask) ? DCK_MIDDLE_CLICK
+ view->process_click(((modifiers & NSEventModifierFlagCommand) && [[self window] isMainWindow]) ? DCK_RIGHT_CLICK
+ : (modifiers & NSEventModifierFlagOption) ? DCK_MIDDLE_CLICK
: DCK_LEFT_CLICK,
[self convertLocation:location]);
}
@@ -755,8 +776,8 @@ static void debugwin_view_update(debug_view &view, void *osdprivate)
NSPoint const location = [self convertPoint:[event locationInWindow] fromView:nil];
NSUInteger const modifiers = [event modifierFlags];
if (view->cursor_supported()
- && !(modifiers & NSAlternateKeyMask)
- && (!(modifiers & NSCommandKeyMask) || ![[self window] isMainWindow]))
+ && !(modifiers & NSEventModifierFlagOption)
+ && (!(modifiers & NSEventModifierFlagCommand) || ![[self window] isMainWindow]))
{
view->set_cursor_position([self convertLocation:location]);
view->set_cursor_visible(true);
@@ -783,34 +804,34 @@ static void debugwin_view_update(debug_view &view, void *osdprivate)
if ([str length] == 1)
{
- if (modifiers & NSNumericPadKeyMask)
+ if (modifiers & NSEventModifierFlagNumericPad)
{
switch ([str characterAtIndex:0])
{
case NSUpArrowFunctionKey:
- if (modifiers & NSCommandKeyMask)
+ if (modifiers & NSEventModifierFlagCommand)
view->process_char(DCH_CTRLHOME);
else
view->process_char(DCH_UP);
return;
case NSDownArrowFunctionKey:
- if (modifiers & NSCommandKeyMask)
+ if (modifiers & NSEventModifierFlagCommand)
view->process_char(DCH_CTRLEND);
else
view->process_char(DCH_DOWN);
return;
case NSLeftArrowFunctionKey:
- if (modifiers & NSCommandKeyMask)
+ if (modifiers & NSEventModifierFlagCommand)
[self typeCharacterAndScrollToCursor:DCH_HOME];
- else if (modifiers & NSAlternateKeyMask)
+ else if (modifiers & NSEventModifierFlagOption)
[self typeCharacterAndScrollToCursor:DCH_CTRLLEFT];
else
[self typeCharacterAndScrollToCursor:DCH_LEFT];
return;
case NSRightArrowFunctionKey:
- if (modifiers & NSCommandKeyMask)
+ if (modifiers & NSEventModifierFlagCommand)
[self typeCharacterAndScrollToCursor:DCH_END];
- else if (modifiers & NSAlternateKeyMask)
+ else if (modifiers & NSEventModifierFlagOption)
[self typeCharacterAndScrollToCursor:DCH_CTRLRIGHT];
else
[self typeCharacterAndScrollToCursor:DCH_RIGHT];
@@ -820,18 +841,18 @@ static void debugwin_view_update(debug_view &view, void *osdprivate)
return;
}
}
- else if (modifiers & NSFunctionKeyMask)
+ else if (modifiers & NSEventModifierFlagFunction)
{
switch ([str characterAtIndex:0])
{
case NSPageUpFunctionKey:
- if (modifiers & NSAlternateKeyMask)
+ if (modifiers & NSEventModifierFlagOption)
{
view->process_char(DCH_PUP);
return;
}
case NSPageDownFunctionKey:
- if (modifiers & NSAlternateKeyMask)
+ if (modifiers & NSEventModifierFlagOption)
{
view->process_char(DCH_PDOWN);
return;
diff --git a/src/osd/modules/debugger/osx/debugwindowhandler.h b/src/osd/modules/debugger/osx/debugwindowhandler.h
index c48bbb031b2..00c7327f2ba 100644
--- a/src/osd/modules/debugger/osx/debugwindowhandler.h
+++ b/src/osd/modules/debugger/osx/debugwindowhandler.h
@@ -23,19 +23,6 @@ extern NSString *const MAMEAuxiliaryDebugWindowWillCloseNotification;
extern NSString *const MAMESaveDebuggerConfigurationNotification;
-// for compatibility with the Qt debugger
-enum
-{
- MAME_DEBUGGER_WINDOW_TYPE_CONSOLE = 1,
- MAME_DEBUGGER_WINDOW_TYPE_MEMORY_VIEWER,
- MAME_DEBUGGER_WINDOW_TYPE_DISASSEMBLY_VIEWER,
- MAME_DEBUGGER_WINDOW_TYPE_ERROR_LOG_VIEWER,
- MAME_DEBUGGER_WINDOW_TYPE_POINTS_VIEWER,
- MAME_DEBUGGER_WINDOW_TYPE_DEVICES_VIEWER,
- MAME_DEBUGGER_WINDOW_TYPE_DEVICE_INFO_VIEWER
-};
-
-
@interface MAMEDebugWindowHandler : NSObject <NSWindowDelegate>
{
NSWindow *window;
diff --git a/src/osd/modules/debugger/osx/debugwindowhandler.mm b/src/osd/modules/debugger/osx/debugwindowhandler.mm
index ec79887e308..1341f420ed9 100644
--- a/src/osd/modules/debugger/osx/debugwindowhandler.mm
+++ b/src/osd/modules/debugger/osx/debugwindowhandler.mm
@@ -79,7 +79,7 @@ NSString *const MAMESaveDebuggerConfigurationNotification = @"MAMESaveDebuggerCo
[[stepMenu addItemWithTitle:@"Out"
action:@selector(debugStepOut:)
keyEquivalent:[NSString stringWithFormat:@"%C", (short)NSF10FunctionKey]]
- setKeyEquivalentModifierMask:NSShiftKeyMask];
+ setKeyEquivalentModifierMask:NSEventModifierFlagShift];
NSMenuItem *resetParentItem = [menu addItemWithTitle:@"Reset" action:NULL keyEquivalent:@""];
NSMenu *resetMenu = [[NSMenu alloc] initWithTitle:@"Reset"];
@@ -92,7 +92,7 @@ NSString *const MAMESaveDebuggerConfigurationNotification = @"MAMESaveDebuggerCo
[[resetMenu addItemWithTitle:@"Hard"
action:@selector(debugHardReset:)
keyEquivalent:[NSString stringWithFormat:@"%C", (short)NSF3FunctionKey]]
- setKeyEquivalentModifierMask:NSShiftKeyMask];
+ setKeyEquivalentModifierMask:NSEventModifierFlagShift];
[menu addItem:[NSMenuItem separatorItem]];
@@ -127,7 +127,7 @@ NSString *const MAMESaveDebuggerConfigurationNotification = @"MAMESaveDebuggerCo
NSPopUpButton *actionButton = [[NSPopUpButton alloc] initWithFrame:frame pullsDown:YES];
[actionButton setTitle:@""];
[actionButton addItemWithTitle:@""];
- [actionButton setBezelStyle:NSShadowlessSquareBezelStyle];
+ [actionButton setBezelStyle:NSBezelStyleShadowlessSquare];
[actionButton setFocusRingType:NSFocusRingTypeNone];
[[actionButton cell] setArrowPosition:NSPopUpArrowAtCenter];
[[self class] addCommonActionItems:[actionButton menu]];
@@ -140,10 +140,10 @@ NSString *const MAMESaveDebuggerConfigurationNotification = @"MAMESaveDebuggerCo
return nil;
window = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 320, 240)
- styleMask:(NSTitledWindowMask |
- NSClosableWindowMask |
- NSMiniaturizableWindowMask |
- NSResizableWindowMask)
+ styleMask:(NSWindowStyleMaskTitled |
+ NSWindowStyleMaskClosable |
+ NSWindowStyleMaskMiniaturizable |
+ NSWindowStyleMaskResizable)
backing:NSBackingStoreBuffered
defer:YES];
[window setReleasedWhenClosed:NO];
@@ -276,7 +276,7 @@ NSString *const MAMESaveDebuggerConfigurationNotification = @"MAMESaveDebuggerCo
if (m == machine)
{
util::xml::data_node *parentnode = (util::xml::data_node *)[[[notification userInfo] objectForKey:@"MAMEDebugParentNode"] pointerValue];
- util::xml::data_node *node = parentnode->add_child("window", nullptr);
+ util::xml::data_node *node = parentnode->add_child(osd::debugger::NODE_WINDOW, nullptr);
if (node)
[self saveConfigurationToNode:node];
}
@@ -285,19 +285,19 @@ NSString *const MAMESaveDebuggerConfigurationNotification = @"MAMESaveDebuggerCo
- (void)saveConfigurationToNode:(util::xml::data_node *)node {
NSRect frame = [window frame];
- node->set_attribute_float("position_x", frame.origin.x);
- node->set_attribute_float("position_y", frame.origin.y);
- node->set_attribute_float("size_x", frame.size.width);
- node->set_attribute_float("size_y", frame.size.height);
+ node->set_attribute_float(osd::debugger::ATTR_WINDOW_POSITION_X, frame.origin.x);
+ node->set_attribute_float(osd::debugger::ATTR_WINDOW_POSITION_Y, frame.origin.y);
+ node->set_attribute_float(osd::debugger::ATTR_WINDOW_WIDTH, frame.size.width);
+ node->set_attribute_float(osd::debugger::ATTR_WINDOW_HEIGHT, frame.size.height);
}
- (void)restoreConfigurationFromNode:(util::xml::data_node const *)node {
NSRect frame = [window frame];
- frame.origin.x = node->get_attribute_float("position_x", frame.origin.x);
- frame.origin.y = node->get_attribute_float("position_y", frame.origin.y);
- frame.size.width = node->get_attribute_float("size_x", frame.size.width);
- frame.size.height = node->get_attribute_float("size_y", frame.size.height);
+ frame.origin.x = node->get_attribute_float(osd::debugger::ATTR_WINDOW_POSITION_X, frame.origin.x);
+ frame.origin.y = node->get_attribute_float(osd::debugger::ATTR_WINDOW_POSITION_Y, frame.origin.y);
+ frame.size.width = node->get_attribute_float(osd::debugger::ATTR_WINDOW_WIDTH, frame.size.width);
+ frame.size.height = node->get_attribute_float(osd::debugger::ATTR_WINDOW_HEIGHT, frame.size.height);
NSSize min = [window minSize];
frame.size.width = std::max(frame.size.width, min.width);
@@ -493,15 +493,17 @@ NSString *const MAMESaveDebuggerConfigurationNotification = @"MAMESaveDebuggerCo
- (void)saveConfigurationToNode:(util::xml::data_node *)node {
[super saveConfigurationToNode:node];
- node->add_child("expression", [[self expression] UTF8String]);
+ node->add_child(osd::debugger::NODE_WINDOW_EXPRESSION, [[self expression] UTF8String]);
+ [history saveConfigurationToNode:node];
}
- (void)restoreConfigurationFromNode:(util::xml::data_node const *)node {
[super restoreConfigurationFromNode:node];
- util::xml::data_node const *const expr = node->get_child("expression");
+ util::xml::data_node const *const expr = node->get_child(osd::debugger::NODE_WINDOW_EXPRESSION);
if (expr && expr->get_value())
[self setExpression:[NSString stringWithUTF8String:expr->get_value()]];
+ [history restoreConfigurationFromNode:node];
}
@end
diff --git a/src/osd/modules/debugger/osx/deviceinfoviewer.mm b/src/osd/modules/debugger/osx/deviceinfoviewer.mm
index 61fdd8c8613..12f1ea1957a 100644
--- a/src/osd/modules/debugger/osx/deviceinfoviewer.mm
+++ b/src/osd/modules/debugger/osx/deviceinfoviewer.mm
@@ -54,14 +54,14 @@
- (NSTextField *)makeLabel:(NSString *)text {
NSTextField *const result = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 100, 14)];
[result setAutoresizingMask:(NSViewMaxYMargin | NSViewMaxXMargin)];
- [[result cell] setControlSize:NSSmallControlSize];
+ [[result cell] setControlSize:NSControlSizeSmall];
[result setEditable:NO];
[result setSelectable:NO];
[result setBezeled:NO];
[result setBordered:NO];
[result setDrawsBackground:NO];
- [result setAlignment:NSRightTextAlignment];
- [result setFont:[NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSSmallControlSize]]];
+ [result setAlignment:NSTextAlignmentRight];
+ [result setFont:[NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSControlSizeSmall]]];
[result setStringValue:text];
[result sizeToFit];
return result;
@@ -71,14 +71,14 @@
- (NSTextField *)makeField:(NSString *)text {
NSTextField *const result = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 100, 14)];
[result setAutoresizingMask:(NSViewWidthSizable | NSViewMaxYMargin)];
- [[result cell] setControlSize:NSSmallControlSize];
+ [[result cell] setControlSize:NSControlSizeSmall];
[result setEditable:NO];
[result setSelectable:YES];
[result setBezeled:NO];
[result setBordered:NO];
[result setDrawsBackground:NO];
- [result setAlignment:NSLeftTextAlignment];
- [result setFont:[NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSSmallControlSize]]];
+ [result setAlignment:NSTextAlignmentLeft];
+ [result setFont:[NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSControlSizeSmall]]];
[result setStringValue:text];
[result sizeToFit];
return result;
@@ -210,9 +210,11 @@
// create a scroll view for holding everything
NSSize desired = [NSScrollView frameSizeForContentSize:[contentView frame].size
- hasHorizontalScroller:YES
- hasVerticalScroller:YES
- borderType:NSNoBorder];
+ horizontalScrollerClass:[NSScroller class]
+ verticalScrollerClass:[NSScroller class]
+ borderType:NSNoBorder
+ controlSize:NSControlSizeRegular
+ scrollerStyle:NSScrollerStyleOverlay];
[window setContentSize:desired];
contentScroll = [[NSScrollView alloc] initWithFrame:[[window contentView] bounds]];
[contentScroll setDrawsBackground:NO];
@@ -237,7 +239,8 @@
- (void)saveConfigurationToNode:(util::xml::data_node *)node {
[super saveConfigurationToNode:node];
- node->set_attribute_int("type", MAME_DEBUGGER_WINDOW_TYPE_DEVICE_INFO_VIEWER);
+ node->set_attribute_int(osd::debugger::ATTR_WINDOW_TYPE, osd::debugger::WINDOW_TYPE_DEVICE_INFO_VIEWER);
+ node->set_attribute(osd::debugger::ATTR_WINDOW_DEVICE_TAG, device->tag());
}
@end
diff --git a/src/osd/modules/debugger/osx/devicesviewer.mm b/src/osd/modules/debugger/osx/devicesviewer.mm
index 23dba724b9d..02f63a41a6b 100644
--- a/src/osd/modules/debugger/osx/devicesviewer.mm
+++ b/src/osd/modules/debugger/osx/devicesviewer.mm
@@ -161,9 +161,11 @@
// calculate the optimal size for everything
NSSize const desired = [NSScrollView frameSizeForContentSize:NSMakeSize(480, 320)
- hasHorizontalScroller:YES
- hasVerticalScroller:YES
- borderType:[devicesScroll borderType]];
+ horizontalScrollerClass:[NSScroller class]
+ verticalScrollerClass:[NSScroller class]
+ borderType:[devicesScroll borderType]
+ controlSize:NSControlSizeRegular
+ scrollerStyle:NSScrollerStyleOverlay];
[self cascadeWindowWithDesiredSize:desired forView:devicesScroll];
// don't forget the result
@@ -185,7 +187,7 @@
- (void)saveConfigurationToNode:(util::xml::data_node *)node {
[super saveConfigurationToNode:node];
- node->set_attribute_int("type", MAME_DEBUGGER_WINDOW_TYPE_DEVICES_VIEWER);
+ node->set_attribute_int(osd::debugger::ATTR_WINDOW_TYPE, osd::debugger::WINDOW_TYPE_DEVICES_VIEWER);
}
diff --git a/src/osd/modules/debugger/osx/disassemblyview.mm b/src/osd/modules/debugger/osx/disassemblyview.mm
index 2e230c27e1c..c501d17230a 100644
--- a/src/osd/modules/debugger/osx/disassemblyview.mm
+++ b/src/osd/modules/debugger/osx/disassemblyview.mm
@@ -75,7 +75,7 @@
item = [menu addItemWithTitle:@"Disable Breakpoint"
action:@selector(debugToggleBreakpointEnable:)
keyEquivalent:[NSString stringWithFormat:@"%C", (short)NSF9FunctionKey]];
- [item setKeyEquivalentModifierMask:NSShiftKeyMask];
+ [item setKeyEquivalentModifierMask:NSEventModifierFlagShift];
[menu addItem:[NSMenuItem separatorItem]];
@@ -214,7 +214,7 @@
action:@selector(debugToggleBreakpointEnable:)
keyEquivalent:[NSString stringWithFormat:@"%C", (short)NSF9FunctionKey]
atIndex:index++];
- [disableItem setKeyEquivalentModifierMask:NSShiftKeyMask];
+ [disableItem setKeyEquivalentModifierMask:NSEventModifierFlagShift];
NSMenu *runMenu = [[menu itemWithTitle:@"Run"] submenu];
NSMenuItem *runItem;
@@ -274,14 +274,14 @@
- (void)saveConfigurationToNode:(util::xml::data_node *)node {
[super saveConfigurationToNode:node];
debug_view_disasm *const dasmView = downcast<debug_view_disasm *>(view);
- node->set_attribute_int("rightbar", dasmView->right_column());
+ node->set_attribute_int(osd::debugger::ATTR_WINDOW_DISASSEMBLY_RIGHT_COLUMN, dasmView->right_column());
}
- (void)restoreConfigurationFromNode:(util::xml::data_node const *)node {
[super restoreConfigurationFromNode:node];
debug_view_disasm *const dasmView = downcast<debug_view_disasm *>(view);
- dasmView->set_right_column((disasm_right_column)node->get_attribute_int("rightbar", dasmView->right_column()));
+ dasmView->set_right_column((disasm_right_column)node->get_attribute_int(osd::debugger::ATTR_WINDOW_DISASSEMBLY_RIGHT_COLUMN, dasmView->right_column()));
}
@end
diff --git a/src/osd/modules/debugger/osx/disassemblyviewer.mm b/src/osd/modules/debugger/osx/disassemblyviewer.mm
index 1f286a6bfc4..20ec457f628 100644
--- a/src/osd/modules/debugger/osx/disassemblyviewer.mm
+++ b/src/osd/modules/debugger/osx/disassemblyviewer.mm
@@ -49,7 +49,7 @@
expressionFrame.size.width,
0)];
[subviewButton setAutoresizingMask:(NSViewWidthSizable | NSViewMinXMargin | NSViewMinYMargin)];
- [subviewButton setBezelStyle:NSShadowlessSquareBezelStyle];
+ [subviewButton setBezelStyle:NSBezelStyleShadowlessSquare];
[subviewButton setFocusRingType:NSFocusRingTypeNone];
[subviewButton setFont:defaultFont];
[subviewButton setTarget:self];
@@ -120,9 +120,11 @@
// calculate the optimal size for everything
NSSize const desired = [NSScrollView frameSizeForContentSize:[dasmView maximumFrameSize]
- hasHorizontalScroller:YES
- hasVerticalScroller:YES
- borderType:[dasmScroll borderType]];
+ horizontalScrollerClass:[NSScroller class]
+ verticalScrollerClass:[NSScroller class]
+ borderType:[dasmScroll borderType]
+ controlSize:NSControlSizeRegular
+ scrollerStyle:NSScrollerStyleOverlay];
[self cascadeWindowWithDesiredSize:desired forView:dasmScroll];
// don't forget the result
@@ -182,7 +184,7 @@
// if it doesn't exist, add a new one
if (bp == nullptr)
{
- uint32_t const bpnum = device.debug()->breakpoint_set(address, nullptr, nullptr);
+ uint32_t const bpnum = device.debug()->breakpoint_set(address);
machine->debugger().console().printf("Breakpoint %X set\n", bpnum);
}
else
@@ -232,15 +234,15 @@
- (void)saveConfigurationToNode:(util::xml::data_node *)node {
[super saveConfigurationToNode:node];
- node->set_attribute_int("type", MAME_DEBUGGER_WINDOW_TYPE_DISASSEMBLY_VIEWER);
- node->set_attribute_int("cpu", [dasmView selectedSubviewIndex]);
+ node->set_attribute_int(osd::debugger::ATTR_WINDOW_TYPE, osd::debugger::WINDOW_TYPE_DISASSEMBLY_VIEWER);
+ node->set_attribute_int(osd::debugger::ATTR_WINDOW_DISASSEMBLY_CPU, [dasmView selectedSubviewIndex]);
[dasmView saveConfigurationToNode:node];
}
- (void)restoreConfigurationFromNode:(util::xml::data_node const *)node {
[super restoreConfigurationFromNode:node];
- int const region = node->get_attribute_int("cpu", [dasmView selectedSubviewIndex]);
+ int const region = node->get_attribute_int(osd::debugger::ATTR_WINDOW_DISASSEMBLY_CPU, [dasmView selectedSubviewIndex]);
[dasmView selectSubviewAtIndex:region];
[window setTitle:[NSString stringWithFormat:@"Disassembly: %@", [dasmView selectedSubviewName]]];
[subviewButton selectItemAtIndex:[subviewButton indexOfItemWithTag:[dasmView selectedSubviewIndex]]];
diff --git a/src/osd/modules/debugger/osx/errorlogviewer.mm b/src/osd/modules/debugger/osx/errorlogviewer.mm
index 1fd12c9c9c1..68d6f312b7c 100644
--- a/src/osd/modules/debugger/osx/errorlogviewer.mm
+++ b/src/osd/modules/debugger/osx/errorlogviewer.mm
@@ -43,11 +43,13 @@
// calculate the optimal size for everything
{
NSSize desired = [NSScrollView frameSizeForContentSize:[logView maximumFrameSize]
- hasHorizontalScroller:YES
- hasVerticalScroller:YES
- borderType:[logScroll borderType]];
+ horizontalScrollerClass:[NSScroller class]
+ verticalScrollerClass:[NSScroller class]
+ borderType:[logScroll borderType]
+ controlSize:NSControlSizeRegular
+ scrollerStyle:NSScrollerStyleOverlay];
- // this thing starts with no content, so its prefered height may be very small
+ // this thing starts with no content, so its preferred height may be very small
desired.height = std::max(desired.height, CGFloat(240));
[self cascadeWindowWithDesiredSize:desired forView:logScroll];
}
@@ -64,7 +66,7 @@
- (void)saveConfigurationToNode:(util::xml::data_node *)node {
[super saveConfigurationToNode:node];
- node->set_attribute_int("type", MAME_DEBUGGER_WINDOW_TYPE_ERROR_LOG_VIEWER);
+ node->set_attribute_int(osd::debugger::ATTR_WINDOW_TYPE, osd::debugger::WINDOW_TYPE_ERROR_LOG_VIEWER);
}
@end
diff --git a/src/osd/modules/debugger/osx/memoryview.mm b/src/osd/modules/debugger/osx/memoryview.mm
index 03055bd7daf..24521e81ba4 100644
--- a/src/osd/modules/debugger/osx/memoryview.mm
+++ b/src/osd/modules/debugger/osx/memoryview.mm
@@ -212,20 +212,22 @@
- (void)saveConfigurationToNode:(util::xml::data_node *)node {
[super saveConfigurationToNode:node];
debug_view_memory *const memView = downcast<debug_view_memory *>(view);
- node->set_attribute_int("reverse", memView->reverse() ? 1 : 0);
- node->set_attribute_int("addressmode", memView->physical() ? 1 : 0);
- node->set_attribute_int("dataformat", int(memView->get_data_format()));
- node->set_attribute_int("rowchunks", memView->chunks_per_row());
+ node->set_attribute_int(osd::debugger::ATTR_WINDOW_MEMORY_REVERSE_COLUMNS, memView->reverse() ? 1 : 0);
+ node->set_attribute_int(osd::debugger::ATTR_WINDOW_MEMORY_ADDRESS_MODE, memView->physical() ? 1 : 0);
+ node->get_attribute_int(osd::debugger::ATTR_WINDOW_MEMORY_ADDRESS_RADIX, memView->address_radix());
+ node->set_attribute_int(osd::debugger::ATTR_WINDOW_MEMORY_DATA_FORMAT, int(memView->get_data_format()));
+ node->set_attribute_int(osd::debugger::ATTR_WINDOW_MEMORY_ROW_CHUNKS, memView->chunks_per_row());
}
- (void)restoreConfigurationFromNode:(util::xml::data_node const *)node {
[super restoreConfigurationFromNode:node];
debug_view_memory *const memView = downcast<debug_view_memory *>(view);
- memView->set_reverse(0 != node->get_attribute_int("reverse", memView->reverse() ? 1 : 0));
- memView->set_physical(0 != node->get_attribute_int("addressmode", memView->physical() ? 1 : 0));
- memView->set_data_format(debug_view_memory::data_format(node->get_attribute_int("dataformat", int(memView->get_data_format()))));
- memView->set_chunks_per_row(node->get_attribute_int("rowchunks", memView->chunks_per_row()));
+ memView->set_reverse(0 != node->get_attribute_int(osd::debugger::ATTR_WINDOW_MEMORY_REVERSE_COLUMNS, memView->reverse() ? 1 : 0));
+ memView->set_physical(0 != node->get_attribute_int(osd::debugger::ATTR_WINDOW_MEMORY_ADDRESS_MODE, memView->physical() ? 1 : 0));
+ memView->set_address_radix(node->get_attribute_int(osd::debugger::ATTR_WINDOW_MEMORY_ADDRESS_RADIX, memView->address_radix()));
+ memView->set_data_format(debug_view_memory::data_format(node->get_attribute_int(osd::debugger::ATTR_WINDOW_MEMORY_DATA_FORMAT, int(memView->get_data_format()))));
+ memView->set_chunks_per_row(node->get_attribute_int(osd::debugger::ATTR_WINDOW_MEMORY_ROW_CHUNKS, memView->chunks_per_row()));
}
diff --git a/src/osd/modules/debugger/osx/memoryviewer.mm b/src/osd/modules/debugger/osx/memoryviewer.mm
index b1064aee69f..1d45650dcbb 100644
--- a/src/osd/modules/debugger/osx/memoryviewer.mm
+++ b/src/osd/modules/debugger/osx/memoryviewer.mm
@@ -46,7 +46,7 @@
// create the subview popup
subviewButton = [[NSPopUpButton alloc] initWithFrame:NSMakeRect(0, 0, 100, 19)];
[subviewButton setAutoresizingMask:(NSViewWidthSizable | NSViewMinXMargin | NSViewMinYMargin)];
- [subviewButton setBezelStyle:NSShadowlessSquareBezelStyle];
+ [subviewButton setBezelStyle:NSBezelStyleShadowlessSquare];
[subviewButton setFocusRingType:NSFocusRingTypeNone];
[subviewButton setFont:defaultFont];
[subviewButton setTarget:self];
@@ -118,9 +118,11 @@
// calculate the optimal size for everything
NSSize const desired = [NSScrollView frameSizeForContentSize:[memoryView maximumFrameSize]
- hasHorizontalScroller:YES
- hasVerticalScroller:YES
- borderType:[memoryScroll borderType]];
+ horizontalScrollerClass:[NSScroller class]
+ verticalScrollerClass:[NSScroller class]
+ borderType:[memoryScroll borderType]
+ controlSize:NSControlSizeRegular
+ scrollerStyle:NSScrollerStyleOverlay];
[self cascadeWindowWithDesiredSize:desired forView:memoryScroll];
// don't forget the result
@@ -178,15 +180,15 @@
- (void)saveConfigurationToNode:(util::xml::data_node *)node {
[super saveConfigurationToNode:node];
- node->set_attribute_int("type", MAME_DEBUGGER_WINDOW_TYPE_MEMORY_VIEWER);
- node->set_attribute_int("memoryregion", [memoryView selectedSubviewIndex]);
+ node->set_attribute_int(osd::debugger::ATTR_WINDOW_TYPE, osd::debugger::WINDOW_TYPE_MEMORY_VIEWER);
+ node->set_attribute_int(osd::debugger::ATTR_WINDOW_MEMORY_REGION, [memoryView selectedSubviewIndex]);
[memoryView saveConfigurationToNode:node];
}
- (void)restoreConfigurationFromNode:(util::xml::data_node const *)node {
[super restoreConfigurationFromNode:node];
- int const region = node->get_attribute_int("memoryregion", [memoryView selectedSubviewIndex]);
+ int const region = node->get_attribute_int(osd::debugger::ATTR_WINDOW_MEMORY_REGION, [memoryView selectedSubviewIndex]);
[memoryView selectSubviewAtIndex:region];
[window setTitle:[NSString stringWithFormat:@"Memory: %@", [memoryView selectedSubviewName]]];
[subviewButton selectItemAtIndex:[subviewButton indexOfItemWithTag:[memoryView selectedSubviewIndex]]];
diff --git a/src/osd/modules/debugger/osx/pointsviewer.mm b/src/osd/modules/debugger/osx/pointsviewer.mm
index 0399fb10d1b..8b2f69c50b5 100644
--- a/src/osd/modules/debugger/osx/pointsviewer.mm
+++ b/src/osd/modules/debugger/osx/pointsviewer.mm
@@ -33,7 +33,7 @@
// create the subview popup
subviewButton = [[NSPopUpButton alloc] initWithFrame:NSMakeRect(0, 0, 100, 19)];
[subviewButton setAutoresizingMask:(NSViewWidthSizable | NSViewMinYMargin)];
- [subviewButton setBezelStyle:NSShadowlessSquareBezelStyle];
+ [subviewButton setBezelStyle:NSBezelStyleShadowlessSquare];
[subviewButton setFocusRingType:NSFocusRingTypeNone];
[subviewButton setFont:defaultFont];
[subviewButton setTarget:self];
@@ -139,17 +139,23 @@
// calculate the optimal size for everything
NSSize const breakDesired = [NSScrollView frameSizeForContentSize:[breakView maximumFrameSize]
- hasHorizontalScroller:YES
- hasVerticalScroller:YES
- borderType:[breakScroll borderType]];
+ horizontalScrollerClass:[NSScroller class]
+ verticalScrollerClass:[NSScroller class]
+ borderType:[breakScroll borderType]
+ controlSize:NSControlSizeRegular
+ scrollerStyle:NSScrollerStyleOverlay];
NSSize const watchDesired = [NSScrollView frameSizeForContentSize:[watchView maximumFrameSize]
- hasHorizontalScroller:YES
- hasVerticalScroller:YES
- borderType:[watchScroll borderType]];
+ horizontalScrollerClass:[NSScroller class]
+ verticalScrollerClass:[NSScroller class]
+ borderType:[watchScroll borderType]
+ controlSize:NSControlSizeRegular
+ scrollerStyle:NSScrollerStyleOverlay];
NSSize const registerDesired = [NSScrollView frameSizeForContentSize:[registerView maximumFrameSize]
- hasHorizontalScroller:YES
- hasVerticalScroller:YES
- borderType:[registerScroll borderType]];
+ horizontalScrollerClass:[NSScroller class]
+ verticalScrollerClass:[NSScroller class]
+ borderType:[registerScroll borderType]
+ controlSize:NSControlSizeRegular
+ scrollerStyle:NSScrollerStyleOverlay];
NSSize const desired = NSMakeSize(std::max({ breakDesired.width, watchDesired.width, registerDesired.width }),
std::max({ breakDesired.height, watchDesired.height, registerDesired.height }));
[self cascadeWindowWithDesiredSize:desired forView:tabs];
@@ -172,14 +178,14 @@
- (void)saveConfigurationToNode:(util::xml::data_node *)node {
[super saveConfigurationToNode:node];
- node->set_attribute_int("type", MAME_DEBUGGER_WINDOW_TYPE_POINTS_VIEWER);
- node->set_attribute_int("bwtype", [tabs indexOfTabViewItem:[tabs selectedTabViewItem]]);
+ node->set_attribute_int(osd::debugger::ATTR_WINDOW_TYPE, osd::debugger::WINDOW_TYPE_POINTS_VIEWER);
+ node->set_attribute_int(osd::debugger::ATTR_WINDOW_POINTS_TYPE, [tabs indexOfTabViewItem:[tabs selectedTabViewItem]]);
}
- (void)restoreConfigurationFromNode:(util::xml::data_node const *)node {
[super restoreConfigurationFromNode:node];
- int const tab = node->get_attribute_int("bwtype", [tabs indexOfTabViewItem:[tabs selectedTabViewItem]]);
+ int const tab = node->get_attribute_int(osd::debugger::ATTR_WINDOW_POINTS_TYPE, [tabs indexOfTabViewItem:[tabs selectedTabViewItem]]);
if ((0 <= tab) && ([tabs numberOfTabViewItems] > tab))
{
[subviewButton selectItemAtIndex:tab];
diff --git a/src/osd/modules/debugger/qt/breakpointswindow.cpp b/src/osd/modules/debugger/qt/breakpointswindow.cpp
index 6af8fe7ba36..16c8af6bdb3 100644
--- a/src/osd/modules/debugger/qt/breakpointswindow.cpp
+++ b/src/osd/modules/debugger/qt/breakpointswindow.cpp
@@ -6,15 +6,23 @@
#include "debug/debugcon.h"
#include "debug/debugcpu.h"
+#include "util/xmlfile.h"
+
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+#include <QtGui/QActionGroup>
+#else
#include <QtWidgets/QActionGroup>
+#endif
#include <QtWidgets/QHBoxLayout>
#include <QtWidgets/QMenu>
#include <QtWidgets/QMenuBar>
#include <QtWidgets/QVBoxLayout>
-BreakpointsWindow::BreakpointsWindow(running_machine &machine, QWidget *parent) :
- WindowQt(machine, nullptr)
+namespace osd::debugger::qt {
+
+BreakpointsWindow::BreakpointsWindow(DebuggerQt &debugger, QWidget *parent) :
+ WindowQt(debugger, nullptr)
{
setWindowTitle("Debug: All Breakpoints");
@@ -79,6 +87,47 @@ BreakpointsWindow::~BreakpointsWindow()
}
+void BreakpointsWindow::restoreConfiguration(util::xml::data_node const &node)
+{
+ WindowQt::restoreConfiguration(node);
+
+ auto const type = node.get_attribute_int(ATTR_WINDOW_POINTS_TYPE, -1);
+ QActionGroup *typeGroup = findChild<QActionGroup *>("typegroup");
+ if ((0 <= type) && (typeGroup->actions().size() > type))
+ typeGroup->actions()[type]->trigger();
+
+ m_breakpointsView->restoreConfigurationFromNode(node);
+
+}
+
+
+void BreakpointsWindow::saveConfigurationToNode(util::xml::data_node &node)
+{
+ WindowQt::saveConfigurationToNode(node);
+
+ node.set_attribute_int(ATTR_WINDOW_TYPE, WINDOW_TYPE_POINTS_VIEWER);
+ if (m_breakpointsView)
+ {
+ switch (m_breakpointsView->view()->type())
+ {
+ case DVT_BREAK_POINTS:
+ node.set_attribute_int(ATTR_WINDOW_POINTS_TYPE, 0);
+ break;
+ case DVT_WATCH_POINTS:
+ node.set_attribute_int(ATTR_WINDOW_POINTS_TYPE, 1);
+ break;
+ case DVT_REGISTER_POINTS:
+ node.set_attribute_int(ATTR_WINDOW_POINTS_TYPE, 2);
+ break;
+ default:
+ break;
+ }
+ }
+
+ m_breakpointsView->saveConfigurationToNode(node);
+}
+
+
void BreakpointsWindow::typeChanged(QAction* changedTo)
{
// Clean
@@ -107,45 +156,4 @@ void BreakpointsWindow::typeChanged(QAction* changedTo)
layout->addWidget(m_breakpointsView);
}
-
-
-//=========================================================================
-// BreakpointsWindowQtConfig
-//=========================================================================
-void BreakpointsWindowQtConfig::buildFromQWidget(QWidget *widget)
-{
- WindowQtConfig::buildFromQWidget(widget);
- BreakpointsWindow *window = dynamic_cast<BreakpointsWindow *>(widget);
-
- QActionGroup* typeGroup = window->findChild<QActionGroup*>("typegroup");
- if (typeGroup->checkedAction()->text() == "Breakpoints")
- m_bwType = 0;
- else if (typeGroup->checkedAction()->text() == "Watchpoints")
- m_bwType = 1;
- else if (typeGroup->checkedAction()->text() == "Registerpoints")
- m_bwType = 2;
-}
-
-
-void BreakpointsWindowQtConfig::applyToQWidget(QWidget* widget)
-{
- WindowQtConfig::applyToQWidget(widget);
- BreakpointsWindow *window = dynamic_cast<BreakpointsWindow *>(widget);
-
- QActionGroup *typeGroup = window->findChild<QActionGroup *>("typegroup");
- typeGroup->actions()[m_bwType]->trigger();
-}
-
-
-void BreakpointsWindowQtConfig::addToXmlDataNode(util::xml::data_node &node) const
-{
- WindowQtConfig::addToXmlDataNode(node);
- node.set_attribute_int("bwtype", m_bwType);
-}
-
-
-void BreakpointsWindowQtConfig::recoverFromXmlNode(util::xml::data_node const &node)
-{
- WindowQtConfig::recoverFromXmlNode(node);
- m_bwType = node.get_attribute_int("bwtype", m_bwType);
-}
+} // namespace osd::debugger::qt
diff --git a/src/osd/modules/debugger/qt/breakpointswindow.h b/src/osd/modules/debugger/qt/breakpointswindow.h
index fab5ea149e9..0a07b4facfb 100644
--- a/src/osd/modules/debugger/qt/breakpointswindow.h
+++ b/src/osd/modules/debugger/qt/breakpointswindow.h
@@ -7,6 +7,8 @@
#include "windowqt.h"
+namespace osd::debugger::qt {
+
//============================================================
// The Breakpoints Window.
//============================================================
@@ -15,9 +17,14 @@ class BreakpointsWindow : public WindowQt
Q_OBJECT
public:
- BreakpointsWindow(running_machine &machine, QWidget *parent = nullptr);
+ BreakpointsWindow(DebuggerQt &debugger, QWidget *parent = nullptr);
virtual ~BreakpointsWindow();
+ virtual void restoreConfiguration(util::xml::data_node const &node) override;
+
+protected:
+ virtual void saveConfigurationToNode(util::xml::data_node &node) override;
+
private slots:
void typeChanged(QAction *changedTo);
@@ -26,28 +33,6 @@ private:
DebuggerView *m_breakpointsView;
};
-
-//=========================================================================
-// A way to store the configuration of a window long enough to read/write.
-//=========================================================================
-class BreakpointsWindowQtConfig : public WindowQtConfig
-{
-public:
- BreakpointsWindowQtConfig() :
- WindowQtConfig(WIN_TYPE_BREAK_POINTS),
- m_bwType(0)
- {
- }
-
- ~BreakpointsWindowQtConfig() {}
-
- // Settings
- int m_bwType;
-
- void buildFromQWidget(QWidget *widget);
- void applyToQWidget(QWidget *widget);
- void addToXmlDataNode(util::xml::data_node &node) const;
- void recoverFromXmlNode(util::xml::data_node const &node);
-};
+} // namespace osd::debugger::qt
#endif // MAME_DEBUGGER_QT_BREAKPOINTSWINDOW_H
diff --git a/src/osd/modules/debugger/qt/dasmwindow.cpp b/src/osd/modules/debugger/qt/dasmwindow.cpp
index 44ce8bac988..144e2f32f5d 100644
--- a/src/osd/modules/debugger/qt/dasmwindow.cpp
+++ b/src/osd/modules/debugger/qt/dasmwindow.cpp
@@ -8,15 +8,26 @@
#include "debug/dvdisasm.h"
#include "debug/points.h"
+#include "util/xmlfile.h"
+
+#include <QtGui/QKeyEvent>
#include <QtWidgets/QHBoxLayout>
#include <QtWidgets/QVBoxLayout>
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+#include <QtGui/QAction>
+#include <QtGui/QActionGroup>
+#else
#include <QtWidgets/QAction>
+#endif
#include <QtWidgets/QMenu>
#include <QtWidgets/QMenuBar>
-DasmWindow::DasmWindow(running_machine &machine, QWidget *parent) :
- WindowQt(machine, nullptr)
+namespace osd::debugger::qt {
+
+DasmWindow::DasmWindow(DebuggerQt &debugger, QWidget *parent) :
+ WindowQt(debugger, nullptr),
+ m_inputHistory()
{
setWindowTitle("Debug: Disassembly View");
@@ -37,6 +48,8 @@ DasmWindow::DasmWindow(running_machine &machine, QWidget *parent) :
// The input edit
m_inputEdit = new QLineEdit(topSubFrame);
connect(m_inputEdit, &QLineEdit::returnPressed, this, &DasmWindow::expressionSubmitted);
+ connect(m_inputEdit, &QLineEdit::textEdited, this, &DasmWindow::expressionEdited);
+ m_inputEdit->installEventFilter(this);
// The cpu combo box
m_cpuComboBox = new QComboBox(topSubFrame);
@@ -49,7 +62,7 @@ DasmWindow::DasmWindow(running_machine &machine, QWidget *parent) :
connect(m_dasmView, &DebuggerView::updated, this, &DasmWindow::dasmViewUpdated);
// Force a recompute of the disassembly region
- downcast<debug_view_disasm *>(m_dasmView->view())->set_expression("curpc");
+ m_dasmView->view<debug_view_disasm>()->set_expression("curpc");
// Populate the combo box & set the proper CPU
populateComboBox();
@@ -78,7 +91,7 @@ DasmWindow::DasmWindow(running_machine &machine, QWidget *parent) :
m_breakpointEnableAct = new QAction("Disable Breakpoint at Cursor", this);
m_runToCursorAct = new QAction("Run to Cursor", this);
m_breakpointToggleAct->setShortcut(Qt::Key_F9);
- m_breakpointEnableAct->setShortcut(Qt::SHIFT + Qt::Key_F9);
+ m_breakpointEnableAct->setShortcut(Qt::SHIFT | Qt::Key_F9);
m_runToCursorAct->setShortcut(Qt::Key_F4);
connect(m_breakpointToggleAct, &QAction::triggered, this, &DasmWindow::toggleBreakpointAtCursor);
connect(m_breakpointEnableAct, &QAction::triggered, this, &DasmWindow::enableBreakpointAtCursor);
@@ -90,6 +103,9 @@ DasmWindow::DasmWindow(running_machine &machine, QWidget *parent) :
QAction *rightActRaw = new QAction("Raw Opcodes", this);
QAction *rightActEncrypted = new QAction("Encrypted Opcodes", this);
QAction *rightActComments = new QAction("Comments", this);
+ rightActRaw->setData(int(DASM_RIGHTCOL_RAW));
+ rightActEncrypted->setData(int(DASM_RIGHTCOL_ENCRYPTED));
+ rightActComments->setData(int(DASM_RIGHTCOL_COMMENTS));
rightActRaw->setCheckable(true);
rightActEncrypted->setCheckable(true);
rightActComments->setCheckable(true);
@@ -117,6 +133,99 @@ DasmWindow::~DasmWindow()
}
+void DasmWindow::restoreConfiguration(util::xml::data_node const &node)
+{
+ WindowQt::restoreConfiguration(node);
+
+ debug_view_disasm &dasmview = *m_dasmView->view<debug_view_disasm>();
+
+ auto const cpu = node.get_attribute_int(ATTR_WINDOW_DISASSEMBLY_CPU, m_dasmView->sourceIndex());
+ if ((0 <= cpu) && (m_cpuComboBox->count() > cpu))
+ m_cpuComboBox->setCurrentIndex(cpu);
+
+ auto const rightbar = node.get_attribute_int(ATTR_WINDOW_DISASSEMBLY_RIGHT_COLUMN, dasmview.right_column());
+ QActionGroup *const rightBarGroup = findChild<QActionGroup *>("rightbargroup");
+ for (QAction *action : rightBarGroup->actions())
+ {
+ if (action->data().toInt() == rightbar)
+ {
+ action->trigger();
+ break;
+ }
+ }
+
+ util::xml::data_node const *const expression = node.get_child(NODE_WINDOW_EXPRESSION);
+ if (expression && expression->get_value())
+ {
+ m_inputEdit->setText(QString::fromUtf8(expression->get_value()));
+ expressionSubmitted();
+ }
+
+ m_dasmView->restoreConfigurationFromNode(node);
+ m_inputHistory.restoreConfigurationFromNode(node);
+}
+
+
+void DasmWindow::saveConfigurationToNode(util::xml::data_node &node)
+{
+ WindowQt::saveConfigurationToNode(node);
+
+ node.set_attribute_int(ATTR_WINDOW_TYPE, WINDOW_TYPE_DISASSEMBLY_VIEWER);
+
+ debug_view_disasm &dasmview = *m_dasmView->view<debug_view_disasm>();
+ node.set_attribute_int(ATTR_WINDOW_DISASSEMBLY_CPU, m_dasmView->sourceIndex());
+ node.set_attribute_int(ATTR_WINDOW_DISASSEMBLY_RIGHT_COLUMN, dasmview.right_column());
+ node.add_child(NODE_WINDOW_EXPRESSION, dasmview.expression());
+
+ m_dasmView->saveConfigurationToNode(node);
+ m_inputHistory.saveConfigurationToNode(node);
+}
+
+
+// Used to intercept the user hitting the up arrow in the input widget
+bool DasmWindow::eventFilter(QObject *obj, QEvent *event)
+{
+ // Only filter keypresses
+ if (event->type() != QEvent::KeyPress)
+ return QObject::eventFilter(obj, event);
+
+ QKeyEvent const &keyEvent = *static_cast<QKeyEvent *>(event);
+
+ // Catch up & down keys
+ if (keyEvent.key() == Qt::Key_Escape)
+ {
+ m_inputEdit->setText(QString::fromUtf8(m_dasmView->view<debug_view_disasm>()->expression()));
+ m_inputEdit->selectAll();
+ m_inputHistory.reset();
+ return true;
+ }
+ else if (keyEvent.key() == Qt::Key_Up)
+ {
+ QString const *const hist = m_inputHistory.previous(m_inputEdit->text());
+ if (hist)
+ {
+ m_inputEdit->setText(*hist);
+ m_inputEdit->setSelection(hist->size(), 0);
+ }
+ return true;
+ }
+ else if (keyEvent.key() == Qt::Key_Down)
+ {
+ QString const *const hist = m_inputHistory.next(m_inputEdit->text());
+ if (hist)
+ {
+ m_inputEdit->setText(*hist);
+ m_inputEdit->setSelection(hist->size(), 0);
+ }
+ return true;
+ }
+ else
+ {
+ return QObject::eventFilter(obj, event);
+ }
+}
+
+
void DasmWindow::cpuChanged(int index)
{
if (index < m_dasmView->view()->source_count())
@@ -130,8 +239,18 @@ void DasmWindow::cpuChanged(int index)
void DasmWindow::expressionSubmitted()
{
const QString expression = m_inputEdit->text();
- downcast<debug_view_disasm *>(m_dasmView->view())->set_expression(expression.toLocal8Bit().data());
- m_dasmView->viewport()->update();
+ m_dasmView->view<debug_view_disasm>()->set_expression(expression.toUtf8().data());
+ m_inputEdit->selectAll();
+
+ // Add history
+ if (!expression.isEmpty())
+ m_inputHistory.add(expression);
+}
+
+
+void DasmWindow::expressionEdited(QString const &text)
+{
+ m_inputHistory.edit();
}
@@ -139,7 +258,7 @@ void DasmWindow::toggleBreakpointAtCursor(bool changedTo)
{
if (m_dasmView->view()->cursor_visible())
{
- offs_t const address = downcast<debug_view_disasm *>(m_dasmView->view())->selected_address();
+ offs_t const address = m_dasmView->view<debug_view_disasm>()->selected_address();
device_t *const device = m_dasmView->view()->source()->device();
device_debug *const cpuinfo = device->debug();
@@ -149,7 +268,7 @@ void DasmWindow::toggleBreakpointAtCursor(bool changedTo)
// If none exists, add a new one
if (!bp)
{
- int32_t bpindex = cpuinfo->breakpoint_set(address, nullptr, nullptr);
+ int32_t bpindex = cpuinfo->breakpoint_set(address);
m_machine.debugger().console().printf("Breakpoint %X set\n", bpindex);
}
else
@@ -161,8 +280,6 @@ void DasmWindow::toggleBreakpointAtCursor(bool changedTo)
m_machine.debug_view().update_all();
m_machine.debugger().refresh_display();
}
-
- refreshAll();
}
@@ -170,7 +287,7 @@ void DasmWindow::enableBreakpointAtCursor(bool changedTo)
{
if (m_dasmView->view()->cursor_visible())
{
- offs_t const address = downcast<debug_view_disasm *>(m_dasmView->view())->selected_address();
+ offs_t const address = m_dasmView->view<debug_view_disasm>()->selected_address();
device_t *const device = m_dasmView->view()->source()->device();
device_debug *const cpuinfo = device->debug();
@@ -185,8 +302,6 @@ void DasmWindow::enableBreakpointAtCursor(bool changedTo)
m_machine.debugger().refresh_display();
}
}
-
- refreshAll();
}
@@ -194,7 +309,7 @@ void DasmWindow::runToCursor(bool changedTo)
{
if (m_dasmView->view()->cursor_visible())
{
- offs_t const address = downcast<debug_view_disasm *>(m_dasmView->view())->selected_address();
+ offs_t const address = m_dasmView->view<debug_view_disasm>()->selected_address();
m_dasmView->view()->source()->device()->debug()->go(address);
}
}
@@ -202,19 +317,8 @@ void DasmWindow::runToCursor(bool changedTo)
void DasmWindow::rightBarChanged(QAction* changedTo)
{
- debug_view_disasm* dasmView = downcast<debug_view_disasm*>(m_dasmView->view());
- if (changedTo->text() == "Raw Opcodes")
- {
- dasmView->set_right_column(DASM_RIGHTCOL_RAW);
- }
- else if (changedTo->text() == "Encrypted Opcodes")
- {
- dasmView->set_right_column(DASM_RIGHTCOL_ENCRYPTED);
- }
- else if (changedTo->text() == "Comments")
- {
- dasmView->set_right_column(DASM_RIGHTCOL_COMMENTS);
- }
+ debug_view_disasm *const dasmView = m_dasmView->view<debug_view_disasm>();
+ dasmView->set_right_column(disasm_right_column(changedTo->data().toInt()));
m_dasmView->viewport()->update();
}
@@ -226,7 +330,7 @@ void DasmWindow::dasmViewUpdated()
bool breakpointEnabled = false;
if (haveCursor)
{
- offs_t const address = downcast<debug_view_disasm *>(m_dasmView->view())->selected_address();
+ offs_t const address = m_dasmView->view<debug_view_disasm>()->selected_address();
device_t *const device = m_dasmView->view()->source()->device();
device_debug *const cpuinfo = device->debug();
@@ -275,47 +379,4 @@ void DasmWindow::setToCurrentCpu()
}
}
-
-//=========================================================================
-// DasmWindowQtConfig
-//=========================================================================
-void DasmWindowQtConfig::buildFromQWidget(QWidget *widget)
-{
- WindowQtConfig::buildFromQWidget(widget);
- DasmWindow *window = dynamic_cast<DasmWindow *>(widget);
- QComboBox *cpu = window->findChild<QComboBox *>("cpu");
- m_cpu = cpu->currentIndex();
-
- QActionGroup *rightBarGroup = window->findChild<QActionGroup *>("rightbargroup");
- if (rightBarGroup->checkedAction()->text() == "Raw Opcodes")
- m_rightBar = 0;
- else if (rightBarGroup->checkedAction()->text() == "Encrypted Opcodes")
- m_rightBar = 1;
- else if (rightBarGroup->checkedAction()->text() == "Comments")
- m_rightBar = 2;
-}
-
-void DasmWindowQtConfig::applyToQWidget(QWidget *widget)
-{
- WindowQtConfig::applyToQWidget(widget);
- DasmWindow *window = dynamic_cast<DasmWindow *>(widget);
- QComboBox *cpu = window->findChild<QComboBox *>("cpu");
- cpu->setCurrentIndex(m_cpu);
-
- QActionGroup *rightBarGroup = window->findChild<QActionGroup *>("rightbargroup");
- rightBarGroup->actions()[m_rightBar]->trigger();
-}
-
-void DasmWindowQtConfig::addToXmlDataNode(util::xml::data_node &node) const
-{
- WindowQtConfig::addToXmlDataNode(node);
- node.set_attribute_int("cpu", m_cpu);
- node.set_attribute_int("rightbar", m_rightBar);
-}
-
-void DasmWindowQtConfig::recoverFromXmlNode(util::xml::data_node const &node)
-{
- WindowQtConfig::recoverFromXmlNode(node);
- m_cpu = node.get_attribute_int("cpu", m_cpu);
- m_rightBar = node.get_attribute_int("rightbar", m_rightBar);
-}
+} // namespace osd::debugger::qt
diff --git a/src/osd/modules/debugger/qt/dasmwindow.h b/src/osd/modules/debugger/qt/dasmwindow.h
index fc4ce11d731..df3fc0699a8 100644
--- a/src/osd/modules/debugger/qt/dasmwindow.h
+++ b/src/osd/modules/debugger/qt/dasmwindow.h
@@ -3,6 +3,8 @@
#ifndef MAME_DEBUGGER_QT_DASMWINDOW_H
#define MAME_DEBUGGER_QT_DASMWINDOW_H
+#pragma once
+
#include "debuggerview.h"
#include "windowqt.h"
@@ -10,6 +12,8 @@
#include <QtWidgets/QLineEdit>
+namespace osd::debugger::qt {
+
//============================================================
// The Disassembly Window.
//============================================================
@@ -18,12 +22,21 @@ class DasmWindow : public WindowQt
Q_OBJECT
public:
- DasmWindow(running_machine &machine, QWidget *parent = nullptr);
+ DasmWindow(DebuggerQt &debugger, QWidget *parent = nullptr);
virtual ~DasmWindow();
+ virtual void restoreConfiguration(util::xml::data_node const &node) override;
+
+protected:
+ virtual void saveConfigurationToNode(util::xml::data_node &node) override;
+
+ // Used to intercept the user hitting the up arrow in the input widget
+ virtual bool eventFilter(QObject *obj, QEvent *event) override;
+
private slots:
void cpuChanged(int index);
void expressionSubmitted();
+ void expressionEdited(QString const &text);
void toggleBreakpointAtCursor(bool changedTo);
void enableBreakpointAtCursor(bool changedTo);
@@ -45,33 +58,11 @@ private:
QAction *m_breakpointToggleAct;
QAction *m_breakpointEnableAct;
QAction *m_runToCursorAct;
-};
-
-//=========================================================================
-// A way to store the configuration of a window long enough to read/write.
-//=========================================================================
-class DasmWindowQtConfig : public WindowQtConfig
-{
-public:
- DasmWindowQtConfig() :
- WindowQtConfig(WIN_TYPE_DASM),
- m_cpu(0),
- m_rightBar(0)
- {
- }
-
- ~DasmWindowQtConfig() {}
-
- // Settings
- int m_cpu;
- int m_rightBar;
-
- void buildFromQWidget(QWidget *widget);
- void applyToQWidget(QWidget *widget);
- void addToXmlDataNode(util::xml::data_node &node) const;
- void recoverFromXmlNode(util::xml::data_node const &node);
+ // Expression history
+ CommandHistory m_inputHistory;
};
+} // namespace osd::debugger::qt
#endif // MAME_DEBUGGER_QT_DASMWINDOW_H
diff --git a/src/osd/modules/debugger/qt/debuggerview.cpp b/src/osd/modules/debugger/qt/debuggerview.cpp
index a1c8bcf2aec..84035c07ed4 100644
--- a/src/osd/modules/debugger/qt/debuggerview.cpp
+++ b/src/osd/modules/debugger/qt/debuggerview.cpp
@@ -3,8 +3,12 @@
#include "emu.h"
#include "debuggerview.h"
+#include "../xmlconfig.h"
+
#include "modules/lib/osdobj_common.h"
+#include "xmlfile.h"
+
#include <QtCore/QMimeData>
#include <QtGui/QClipboard>
#include <QtGui/QKeyEvent>
@@ -12,9 +16,8 @@
#include <QtWidgets/QApplication>
#include <QtWidgets/QScrollBar>
-#if QT_VERSION < QT_VERSION_CHECK(5, 11, 0)
-#define horizontalAdvance width
-#endif
+
+namespace osd::debugger::qt {
DebuggerView::DebuggerView(
debug_view_type type,
@@ -51,6 +54,19 @@ DebuggerView::~DebuggerView()
m_machine.debug_view().free_view(*m_view);
}
+
+int DebuggerView::sourceIndex() const
+{
+ if (m_view)
+ {
+ debug_view_source const *const source = m_view->source();
+ if (source)
+ return m_view->source_index(*source);
+ }
+ return -1;
+}
+
+
void DebuggerView::paintEvent(QPaintEvent *event)
{
// Tell the MAME debug view how much real estate is available
@@ -174,9 +190,43 @@ void DebuggerView::paintEvent(QPaintEvent *event)
}
}
+
+void DebuggerView::restoreConfigurationFromNode(util::xml::data_node const &node)
+{
+ if (m_view->cursor_supported())
+ {
+ util::xml::data_node const *const selection = node.get_child(NODE_WINDOW_SELECTION);
+ if (selection)
+ {
+ debug_view_xy pos = m_view->cursor_position();
+ m_view->set_cursor_visible(0 != selection->get_attribute_int(ATTR_SELECTION_CURSOR_VISIBLE, m_view->cursor_visible() ? 1 : 0));
+ selection->get_attribute_int(ATTR_SELECTION_CURSOR_X, pos.x);
+ selection->get_attribute_int(ATTR_SELECTION_CURSOR_Y, pos.y);
+ m_view->set_cursor_position(pos);
+ }
+ }
+}
+
+
+void DebuggerView::saveConfigurationToNode(util::xml::data_node &node)
+{
+ if (m_view->cursor_supported())
+ {
+ util::xml::data_node *const selection = node.add_child(NODE_WINDOW_SELECTION, nullptr);
+ if (selection)
+ {
+ debug_view_xy const pos = m_view->cursor_position();
+ selection->set_attribute_int(ATTR_SELECTION_CURSOR_VISIBLE, m_view->cursor_visible() ? 1 : 0);
+ selection->set_attribute_int(ATTR_SELECTION_CURSOR_X, pos.x);
+ selection->set_attribute_int(ATTR_SELECTION_CURSOR_Y, pos.y);
+ }
+ }
+}
+
+
void DebuggerView::keyPressEvent(QKeyEvent* event)
{
- if (m_view == nullptr)
+ if (!m_view)
return QWidget::keyPressEvent(event);
Qt::KeyboardModifiers keyMods = QApplication::keyboardModifiers();
@@ -361,3 +411,5 @@ void DebuggerView::debuggerViewUpdate(debug_view &debugView, void *osdPrivate)
dView->update();
emit dView->updated();
}
+
+} // namespace osd::debugger::qt
diff --git a/src/osd/modules/debugger/qt/debuggerview.h b/src/osd/modules/debugger/qt/debuggerview.h
index a38b3b11152..cc68dd69d30 100644
--- a/src/osd/modules/debugger/qt/debuggerview.h
+++ b/src/osd/modules/debugger/qt/debuggerview.h
@@ -3,12 +3,16 @@
#ifndef MAME_DEBUGGER_QT_DEBUGGERVIEW_H
#define MAME_DEBUGGER_QT_DEBUGGERVIEW_H
+#pragma once
+
#include "debug/debugvw.h"
#include <QtWidgets/QAbstractScrollArea>
#include <QtWidgets/QMenu>
+namespace osd::debugger::qt {
+
class DebuggerView : public QAbstractScrollArea
{
Q_OBJECT
@@ -17,19 +21,24 @@ public:
DebuggerView(debug_view_type type, running_machine &machine, QWidget *parent = nullptr);
virtual ~DebuggerView();
- void paintEvent(QPaintEvent *event);
+ virtual void paintEvent(QPaintEvent *event) override;
// Setters and accessors
void setPreferBottom(bool pb) { m_preferBottom = pb; }
debug_view *view() { return m_view; }
+ template <typename T> T *view() { return downcast<T *>(m_view); }
+ int sourceIndex() const;
+
+ virtual void restoreConfigurationFromNode(util::xml::data_node const &node);
+ virtual void saveConfigurationToNode(util::xml::data_node &node);
signals:
void updated();
protected:
- void keyPressEvent(QKeyEvent *event) override;
- void mousePressEvent(QMouseEvent *event) override;
- void contextMenuEvent(QContextMenuEvent *event) override;
+ virtual void keyPressEvent(QKeyEvent *event) override;
+ virtual void mousePressEvent(QMouseEvent *event) override;
+ virtual void contextMenuEvent(QContextMenuEvent *event) override;
virtual void addItemsToContextMenu(QMenu *menu);
@@ -49,4 +58,6 @@ private:
bool m_preferBottom;
};
+} // namespace osd::debugger::qt
+
#endif // MAME_DEBUGGER_QT_DEBUGGERVIEW_H
diff --git a/src/osd/modules/debugger/qt/deviceinformationwindow.cpp b/src/osd/modules/debugger/qt/deviceinformationwindow.cpp
index 431a0df492a..2e06d8fb1ed 100644
--- a/src/osd/modules/debugger/qt/deviceinformationwindow.cpp
+++ b/src/osd/modules/debugger/qt/deviceinformationwindow.cpp
@@ -1,15 +1,19 @@
// license:BSD-3-Clause
// copyright-holders:Andrew Gardner
#include "emu.h"
+#include "deviceinformationwindow.h"
+
+#include "util/xmlfile.h"
+
#include <QtWidgets/QFrame>
#include <QtWidgets/QLabel>
#include <QtWidgets/QVBoxLayout>
-#include "deviceinformationwindow.h"
+namespace osd::debugger::qt {
-DeviceInformationWindow::DeviceInformationWindow(running_machine &machine, device_t *device, QWidget *parent) :
- WindowQt(machine, nullptr),
+DeviceInformationWindow::DeviceInformationWindow(DebuggerQt &debugger, device_t *device, QWidget *parent) :
+ WindowQt(debugger, nullptr),
m_device(device)
{
if (parent)
@@ -27,6 +31,26 @@ DeviceInformationWindow::~DeviceInformationWindow()
{
}
+
+void DeviceInformationWindow::restoreConfiguration(util::xml::data_node const &node)
+{
+ WindowQt::restoreConfiguration(node);
+
+ auto const tag = node.get_attribute_string(ATTR_WINDOW_DEVICE_TAG, ":");
+ set_device(tag);
+}
+
+
+void DeviceInformationWindow::saveConfigurationToNode(util::xml::data_node &node)
+{
+ WindowQt::saveConfigurationToNode(node);
+
+ node.set_attribute_int(ATTR_WINDOW_TYPE, WINDOW_TYPE_DEVICE_INFO_VIEWER);
+
+ node.set_attribute(ATTR_WINDOW_DEVICE_TAG, m_device->tag());
+}
+
+
void DeviceInformationWindow::fill_device_information()
{
setWindowTitle(util::string_format("Debug: Device %s", m_device->tag()).c_str());
@@ -99,40 +123,4 @@ void DeviceInformationWindow::set_device(const char *tag)
fill_device_information();
}
-const char *DeviceInformationWindow::device_tag() const
-{
- return m_device->tag();
-}
-
-
-//=========================================================================
-// DeviceInformationWindowQtConfig
-//=========================================================================
-void DeviceInformationWindowQtConfig::buildFromQWidget(QWidget *widget)
-{
- WindowQtConfig::buildFromQWidget(widget);
- DeviceInformationWindow *window = dynamic_cast<DeviceInformationWindow *>(widget);
- m_device_tag = window->device_tag();
-}
-
-
-void DeviceInformationWindowQtConfig::applyToQWidget(QWidget *widget)
-{
- WindowQtConfig::applyToQWidget(widget);
- DeviceInformationWindow *window = dynamic_cast<DeviceInformationWindow *>(widget);
- window->set_device(m_device_tag.c_str());
-}
-
-
-void DeviceInformationWindowQtConfig::addToXmlDataNode(util::xml::data_node &node) const
-{
- WindowQtConfig::addToXmlDataNode(node);
- node.set_attribute("device-tag", m_device_tag.c_str());
-}
-
-
-void DeviceInformationWindowQtConfig::recoverFromXmlNode(util::xml::data_node const &node)
-{
- WindowQtConfig::recoverFromXmlNode(node);
- m_device_tag = node.get_attribute_string("device-tag", ":");
-}
+} // namespace osd::debugger::qt
diff --git a/src/osd/modules/debugger/qt/deviceinformationwindow.h b/src/osd/modules/debugger/qt/deviceinformationwindow.h
index c7bfa68527d..e036a76e782 100644
--- a/src/osd/modules/debugger/qt/deviceinformationwindow.h
+++ b/src/osd/modules/debugger/qt/deviceinformationwindow.h
@@ -3,8 +3,13 @@
#ifndef MAME_DEBUGGER_QT_DEVICEINFORMATIONWINDOW_H
#define MAME_DEBUGGER_QT_DEVICEINFORMATIONWINDOW_H
+#pragma once
+
#include "windowqt.h"
+
+namespace osd::debugger::qt {
+
//============================================================
// The Device Information Window.
//============================================================
@@ -13,11 +18,15 @@ class DeviceInformationWindow : public WindowQt
Q_OBJECT
public:
- DeviceInformationWindow(running_machine &machine, device_t *device = nullptr, QWidget* parent=nullptr);
+ DeviceInformationWindow(DebuggerQt &debugger, device_t *device = nullptr, QWidget* parent=nullptr);
virtual ~DeviceInformationWindow();
void set_device(const char *tag);
- const char *device_tag() const;
+
+ virtual void restoreConfiguration(util::xml::data_node const &node) override;
+
+protected:
+ virtual void saveConfigurationToNode(util::xml::data_node &node) override;
private:
device_t *m_device;
@@ -25,29 +34,6 @@ private:
void fill_device_information();
};
-
-
-
-//=========================================================================
-// A way to store the configuration of a window long enough to read/write.
-//=========================================================================
-class DeviceInformationWindowQtConfig : public WindowQtConfig
-{
-public:
- std::string m_device_tag;
-
- DeviceInformationWindowQtConfig() :
- WindowQtConfig(WIN_TYPE_DEVICE_INFORMATION)
- {
- }
-
- ~DeviceInformationWindowQtConfig() {}
-
- void buildFromQWidget(QWidget *widget);
- void applyToQWidget(QWidget *widget);
- void addToXmlDataNode(util::xml::data_node &node) const;
- void recoverFromXmlNode(util::xml::data_node const &node);
-};
-
+} // namespace osd::debugger::qt
#endif // MAME_DEBUGGER_QT_DEVICEINFORMATIONWINDOW_H
diff --git a/src/osd/modules/debugger/qt/deviceswindow.cpp b/src/osd/modules/debugger/qt/deviceswindow.cpp
index 0e7a94ceb97..2c39c8cb0e8 100644
--- a/src/osd/modules/debugger/qt/deviceswindow.cpp
+++ b/src/osd/modules/debugger/qt/deviceswindow.cpp
@@ -2,8 +2,14 @@
// copyright-holders:Andrew Gardner
#include "emu.h"
#include "deviceswindow.h"
+
#include "deviceinformationwindow.h"
+#include "util/xmlfile.h"
+
+
+namespace osd::debugger::qt {
+
DevicesWindowModel::DevicesWindowModel(running_machine &machine, QObject *parent) :
m_machine(machine)
{
@@ -107,9 +113,9 @@ int DevicesWindowModel::columnCount(const QModelIndex &parent) const
-DevicesWindow::DevicesWindow(running_machine &machine, QWidget *parent) :
- WindowQt(machine, nullptr),
- m_devices_model(machine)
+DevicesWindow::DevicesWindow(DebuggerQt &debugger, QWidget *parent) :
+ WindowQt(debugger, nullptr),
+ m_devices_model(debugger.machine())
{
m_selected_device = nullptr;
@@ -148,35 +154,15 @@ void DevicesWindow::currentRowChanged(const QModelIndex &current, const QModelIn
void DevicesWindow::activated(const QModelIndex &index)
{
device_t *dev = static_cast<device_t *>(index.internalPointer());
- (new DeviceInformationWindow(m_machine, dev, this))->show();
+ (new DeviceInformationWindow(m_debugger, dev, this))->show();
}
-
-//=========================================================================
-// DevicesWindowQtConfig
-//=========================================================================
-void DevicesWindowQtConfig::buildFromQWidget(QWidget *widget)
+void DevicesWindow::saveConfigurationToNode(util::xml::data_node &node)
{
- WindowQtConfig::buildFromQWidget(widget);
- // DevicesWindow *window = dynamic_cast<DevicesWindow *>(widget);
-}
+ WindowQt::saveConfigurationToNode(node);
-
-void DevicesWindowQtConfig::applyToQWidget(QWidget *widget)
-{
- WindowQtConfig::applyToQWidget(widget);
- // DevicesWindow *window = dynamic_cast<DevicesWindow *>(widget);
+ node.set_attribute_int(ATTR_WINDOW_TYPE, WINDOW_TYPE_DEVICES_VIEWER);
}
-
-void DevicesWindowQtConfig::addToXmlDataNode(util::xml::data_node &node) const
-{
- WindowQtConfig::addToXmlDataNode(node);
-}
-
-
-void DevicesWindowQtConfig::recoverFromXmlNode(util::xml::data_node const &node)
-{
- WindowQtConfig::recoverFromXmlNode(node);
-}
+} // namespace osd::debugger::qt
diff --git a/src/osd/modules/debugger/qt/deviceswindow.h b/src/osd/modules/debugger/qt/deviceswindow.h
index 884ad87d421..d337817fac0 100644
--- a/src/osd/modules/debugger/qt/deviceswindow.h
+++ b/src/osd/modules/debugger/qt/deviceswindow.h
@@ -3,11 +3,15 @@
#ifndef MAME_DEBUGGER_QT_DEVICESWINDOW_H
#define MAME_DEBUGGER_QT_DEVICESWINDOW_H
+#pragma once
+
#include "windowqt.h"
#include <QtWidgets/QTreeView>
+namespace osd::debugger::qt {
+
//============================================================
// The model for the treeview
//============================================================
@@ -40,40 +44,22 @@ class DevicesWindow : public WindowQt
Q_OBJECT
public:
- DevicesWindow(running_machine &machine, QWidget *parent = nullptr);
+ DevicesWindow(DebuggerQt &debugger, QWidget *parent = nullptr);
virtual ~DevicesWindow();
public slots:
void currentRowChanged(const QModelIndex &current, const QModelIndex &previous);
void activated(const QModelIndex &index);
+protected:
+ virtual void saveConfigurationToNode(util::xml::data_node &node) override;
+
private:
QTreeView *m_devices_view;
DevicesWindowModel m_devices_model;
device_t *m_selected_device;
};
-
-
-
-//=========================================================================
-// A way to store the configuration of a window long enough to read/write.
-//=========================================================================
-class DevicesWindowQtConfig : public WindowQtConfig
-{
-public:
- DevicesWindowQtConfig() :
- WindowQtConfig(WIN_TYPE_DEVICES)
- {
- }
-
- ~DevicesWindowQtConfig() {}
-
- void buildFromQWidget(QWidget *widget);
- void applyToQWidget(QWidget *widget);
- void addToXmlDataNode(util::xml::data_node &node) const;
- void recoverFromXmlNode(util::xml::data_node const &node);
-};
-
+} // namespace osd::debugger::qt
#endif // MAME_DEBUGGER_QT_DEVICESWINDOW_H
diff --git a/src/osd/modules/debugger/qt/logwindow.cpp b/src/osd/modules/debugger/qt/logwindow.cpp
index 9649014fc6f..dfbe947caca 100644
--- a/src/osd/modules/debugger/qt/logwindow.cpp
+++ b/src/osd/modules/debugger/qt/logwindow.cpp
@@ -1,17 +1,21 @@
// license:BSD-3-Clause
// copyright-holders:Andrew Gardner
#include "emu.h"
-#include <QtWidgets/QVBoxLayout>
-
#include "logwindow.h"
#include "debug/debugcon.h"
#include "debug/debugcpu.h"
#include "debug/dvdisasm.h"
+#include "util/xmlfile.h"
+
+#include <QtWidgets/QVBoxLayout>
+
+
+namespace osd::debugger::qt {
-LogWindow::LogWindow(running_machine &machine, QWidget *parent) :
- WindowQt(machine, nullptr)
+LogWindow::LogWindow(DebuggerQt &debugger, QWidget *parent) :
+ WindowQt(debugger, nullptr)
{
setWindowTitle("Debug: Machine Log");
@@ -44,28 +48,21 @@ LogWindow::~LogWindow()
}
-//=========================================================================
-// LogWindowQtConfig
-//=========================================================================
-void LogWindowQtConfig::buildFromQWidget(QWidget *widget)
+void LogWindow::restoreConfiguration(util::xml::data_node const &node)
{
- WindowQtConfig::buildFromQWidget(widget);
-}
-
+ WindowQt::restoreConfiguration(node);
-void LogWindowQtConfig::applyToQWidget(QWidget *widget)
-{
- WindowQtConfig::applyToQWidget(widget);
+ m_logView->restoreConfigurationFromNode(node);
}
-void LogWindowQtConfig::addToXmlDataNode(util::xml::data_node &node) const
+void LogWindow::saveConfigurationToNode(util::xml::data_node &node)
{
- WindowQtConfig::addToXmlDataNode(node);
-}
+ WindowQt::saveConfigurationToNode(node);
+ node.set_attribute_int(ATTR_WINDOW_TYPE, WINDOW_TYPE_ERROR_LOG_VIEWER);
-void LogWindowQtConfig::recoverFromXmlNode(util::xml::data_node const &node)
-{
- WindowQtConfig::recoverFromXmlNode(node);
+ m_logView->saveConfigurationToNode(node);
}
+
+} // namespace osd::debugger::qt
diff --git a/src/osd/modules/debugger/qt/logwindow.h b/src/osd/modules/debugger/qt/logwindow.h
index 05d4d15514f..f85d490ea75 100644
--- a/src/osd/modules/debugger/qt/logwindow.h
+++ b/src/osd/modules/debugger/qt/logwindow.h
@@ -3,10 +3,14 @@
#ifndef MAME_DEBUGGER_QT_LOGWINDOW_H
#define MAME_DEBUGGER_QT_LOGWINDOW_H
+#pragma once
+
#include "debuggerview.h"
#include "windowqt.h"
+namespace osd::debugger::qt {
+
//============================================================
// The Log Window.
//============================================================
@@ -15,33 +19,19 @@ class LogWindow : public WindowQt
Q_OBJECT
public:
- LogWindow(running_machine &machine, QWidget *parent = nullptr);
+ LogWindow(DebuggerQt &debugger, QWidget *parent = nullptr);
virtual ~LogWindow();
+ virtual void restoreConfiguration(util::xml::data_node const &node) override;
+
+protected:
+ virtual void saveConfigurationToNode(util::xml::data_node &node) override;
+
private:
// Widgets
DebuggerView *m_logView;
};
-
-//=========================================================================
-// A way to store the configuration of a window long enough to read/write.
-//=========================================================================
-class LogWindowQtConfig : public WindowQtConfig
-{
-public:
- LogWindowQtConfig() :
- WindowQtConfig(WIN_TYPE_LOG)
- {
- }
-
- ~LogWindowQtConfig() {}
-
- void buildFromQWidget(QWidget *widget);
- void applyToQWidget(QWidget *widget);
- void addToXmlDataNode(util::xml::data_node &node) const;
- void recoverFromXmlNode(util::xml::data_node const &node);
-};
-
+} // namespace osd::debugger::qt
#endif // MAME_DEBUGGER_QT_LOGWINDOW_H
diff --git a/src/osd/modules/debugger/qt/mainwindow.cpp b/src/osd/modules/debugger/qt/mainwindow.cpp
index afea2e07919..dba5d18b9ac 100644
--- a/src/osd/modules/debugger/qt/mainwindow.cpp
+++ b/src/osd/modules/debugger/qt/mainwindow.cpp
@@ -8,8 +8,15 @@
#include "debug/dvdisasm.h"
#include "debug/points.h"
+#include "util/xmlfile.h"
+
#include <QtGui/QCloseEvent>
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+#include <QtGui/QAction>
+#include <QtGui/QActionGroup>
+#else
#include <QtWidgets/QAction>
+#endif
#include <QtWidgets/QDockWidget>
#include <QtWidgets/QFileDialog>
#include <QtWidgets/QMenu>
@@ -17,10 +24,12 @@
#include <QtWidgets/QScrollBar>
-MainWindow::MainWindow(running_machine &machine, QWidget *parent) :
- WindowQt(machine, nullptr),
- m_historyIndex(0),
- m_inputHistory()
+namespace osd::debugger::qt {
+
+MainWindow::MainWindow(DebuggerQt &debugger, QWidget *parent) :
+ WindowQt(debugger, nullptr),
+ m_inputHistory(),
+ m_exiting(false)
{
setGeometry(300, 300, 1000, 600);
@@ -32,6 +41,7 @@ MainWindow::MainWindow(running_machine &machine, QWidget *parent) :
// The input line
m_inputEdit = new QLineEdit(mainWindowFrame);
connect(m_inputEdit, &QLineEdit::returnPressed, this, &MainWindow::executeCommandSlot);
+ connect(m_inputEdit, &QLineEdit::textEdited, this, &MainWindow::commandEditedSlot);
m_inputEdit->installEventFilter(this);
@@ -56,7 +66,7 @@ MainWindow::MainWindow(running_machine &machine, QWidget *parent) :
m_breakpointEnableAct = new QAction("Disable Breakpoint at Cursor", this);
m_runToCursorAct = new QAction("Run to Cursor", this);
m_breakpointToggleAct->setShortcut(Qt::Key_F9);
- m_breakpointEnableAct->setShortcut(Qt::SHIFT + Qt::Key_F9);
+ m_breakpointEnableAct->setShortcut(Qt::SHIFT | Qt::Key_F9);
m_runToCursorAct->setShortcut(Qt::Key_F4);
connect(m_breakpointToggleAct, &QAction::triggered, this, &MainWindow::toggleBreakpointAtCursor);
connect(m_breakpointEnableAct, &QAction::triggered, this, &MainWindow::enableBreakpointAtCursor);
@@ -68,6 +78,9 @@ MainWindow::MainWindow(running_machine &machine, QWidget *parent) :
QAction *rightActRaw = new QAction("Raw Opcodes", this);
QAction *rightActEncrypted = new QAction("Encrypted Opcodes", this);
QAction *rightActComments = new QAction("Comments", this);
+ rightActRaw->setData(int(DASM_RIGHTCOL_RAW));
+ rightActEncrypted->setData(int(DASM_RIGHTCOL_ENCRYPTED));
+ rightActComments->setData(int(DASM_RIGHTCOL_COMMENTS));
rightActRaw->setCheckable(true);
rightActEncrypted->setCheckable(true);
rightActComments->setCheckable(true);
@@ -146,13 +159,54 @@ void MainWindow::setProcessor(device_t *processor)
}
+void MainWindow::restoreConfiguration(util::xml::data_node const &node)
+{
+ WindowQt::restoreConfiguration(node);
+
+ debug_view_disasm &dasmview = *m_dasmFrame->view()->view<debug_view_disasm>();
+
+ restoreState(QByteArray::fromPercentEncoding(node.get_attribute_string("qtwindowstate", "")));
+
+ auto const rightbar = node.get_attribute_int(ATTR_WINDOW_DISASSEMBLY_RIGHT_COLUMN, dasmview.right_column());
+ QActionGroup *const rightBarGroup = findChild<QActionGroup *>("rightbargroup");
+ for (QAction *action : rightBarGroup->actions())
+ {
+ if (action->data().toInt() == rightbar)
+ {
+ action->trigger();
+ break;
+ }
+ }
+
+ m_dasmFrame->view()->restoreConfigurationFromNode(node);
+ m_inputHistory.restoreConfigurationFromNode(node);
+}
+
+
+void MainWindow::saveConfigurationToNode(util::xml::data_node &node)
+{
+ WindowQt::saveConfigurationToNode(node);
+
+ node.set_attribute_int(ATTR_WINDOW_TYPE, WINDOW_TYPE_CONSOLE);
+
+ debug_view_disasm &dasmview = *m_dasmFrame->view()->view<debug_view_disasm>();
+ node.set_attribute_int(ATTR_WINDOW_DISASSEMBLY_RIGHT_COLUMN, dasmview.right_column());
+ node.set_attribute("qtwindowstate", saveState().toPercentEncoding().data());
+
+ m_dasmFrame->view()->saveConfigurationToNode(node);
+ m_inputHistory.saveConfigurationToNode(node);
+}
+
+
// Used to intercept the user clicking 'X' in the upper corner
void MainWindow::closeEvent(QCloseEvent *event)
{
- debugActQuit();
-
- // Insure the window doesn't disappear before we get a chance to save its parameters
- event->ignore();
+ if (!m_exiting)
+ {
+ // Don't actually close the window - it will be brought back on user break
+ debugActRunAndHide();
+ event->ignore();
+ }
}
@@ -160,55 +214,56 @@ void MainWindow::closeEvent(QCloseEvent *event)
bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
// Only filter keypresses
- QKeyEvent *keyEvent = nullptr;
- if (event->type() == QEvent::KeyPress)
- keyEvent = static_cast<QKeyEvent*>(event);
- else
+ if (event->type() != QEvent::KeyPress)
return QObject::eventFilter(obj, event);
+ QKeyEvent const &keyEvent = *static_cast<QKeyEvent *>(event);
+
// Catch up & down keys
- if (keyEvent->key() == Qt::Key_Up || keyEvent->key() == Qt::Key_Down)
+ if (keyEvent.key() == Qt::Key_Escape)
{
- if (keyEvent->key() == Qt::Key_Up)
- {
- if (m_historyIndex > 0)
- m_historyIndex--;
- }
- else if (keyEvent->key() == Qt::Key_Down)
- {
- if (m_historyIndex < m_inputHistory.size())
- m_historyIndex++;
- }
-
- // Populate the input edit or clear it if you're at the end
- if (m_historyIndex == m_inputHistory.size())
+ m_inputEdit->clear();
+ m_inputHistory.reset();
+ return true;
+ }
+ else if (keyEvent.key() == Qt::Key_Up)
+ {
+ QString const *const hist = m_inputHistory.previous(m_inputEdit->text());
+ if (hist)
{
- m_inputEdit->setText("");
+ m_inputEdit->setText(*hist);
+ m_inputEdit->setSelection(hist->size(), 0);
}
- else
+ return true;
+ }
+ else if (keyEvent.key() == Qt::Key_Down)
+ {
+ QString const *const hist = m_inputHistory.next(m_inputEdit->text());
+ if (hist)
{
- m_inputEdit->setText(m_inputHistory[m_historyIndex]);
+ m_inputEdit->setText(*hist);
+ m_inputEdit->setSelection(hist->size(), 0);
}
+ return true;
}
- else if (keyEvent->key() == Qt::Key_Enter)
+ else if (keyEvent.key() == Qt::Key_Enter)
{
executeCommand(false);
+ return true;
}
else
{
return QObject::eventFilter(obj, event);
}
-
- return true;
}
void MainWindow::toggleBreakpointAtCursor(bool changedTo)
{
- debug_view_disasm *const dasmView = downcast<debug_view_disasm*>(m_dasmFrame->view()->view());
+ debug_view_disasm *const dasmView = m_dasmFrame->view()->view<debug_view_disasm>();
if (dasmView->cursor_visible() && (m_machine.debugger().console().get_visible_cpu() == dasmView->source()->device()))
{
- offs_t const address = downcast<debug_view_disasm *>(dasmView)->selected_address();
+ offs_t const address = dasmView->selected_address();
device_debug *const cpuinfo = dasmView->source()->device()->debug();
// Find an existing breakpoint at this address
@@ -221,15 +276,15 @@ void MainWindow::toggleBreakpointAtCursor(bool changedTo)
else
command = string_format("bpclear 0x%X", bp->index());
m_machine.debugger().console().execute_command(command, true);
+ m_machine.debug_view().update_all();
+ m_machine.debugger().refresh_display();
}
-
- refreshAll();
}
void MainWindow::enableBreakpointAtCursor(bool changedTo)
{
- debug_view_disasm *const dasmView = downcast<debug_view_disasm*>(m_dasmFrame->view()->view());
+ debug_view_disasm *const dasmView = m_dasmFrame->view()->view<debug_view_disasm>();
if (dasmView->cursor_visible() && (m_machine.debugger().console().get_visible_cpu() == dasmView->source()->device()))
{
offs_t const address = dasmView->selected_address();
@@ -243,19 +298,19 @@ void MainWindow::enableBreakpointAtCursor(bool changedTo)
int32_t const bpindex = bp->index();
std::string command = string_format(bp->enabled() ? "bpdisable 0x%X" : "bpenable 0x%X", bpindex);
m_machine.debugger().console().execute_command(command, true);
+ m_machine.debug_view().update_all();
+ m_machine.debugger().refresh_display();
}
}
-
- refreshAll();
}
void MainWindow::runToCursor(bool changedTo)
{
- debug_view_disasm *dasmView = downcast<debug_view_disasm*>(m_dasmFrame->view()->view());
+ debug_view_disasm *const dasmView = m_dasmFrame->view()->view<debug_view_disasm>();
if (dasmView->cursor_visible() && (m_machine.debugger().console().get_visible_cpu() == dasmView->source()->device()))
{
- offs_t address = downcast<debug_view_disasm*>(dasmView)->selected_address();
+ offs_t address = dasmView->selected_address();
std::string command = string_format("go 0x%X", address);
m_machine.debugger().console().execute_command(command, true);
}
@@ -264,15 +319,8 @@ void MainWindow::runToCursor(bool changedTo)
void MainWindow::rightBarChanged(QAction *changedTo)
{
- debug_view_disasm *dasmView = downcast<debug_view_disasm*>(m_dasmFrame->view()->view());
-
- if (changedTo->text() == "Raw Opcodes")
- dasmView->set_right_column(DASM_RIGHTCOL_RAW);
- else if (changedTo->text() == "Encrypted Opcodes")
- dasmView->set_right_column(DASM_RIGHTCOL_ENCRYPTED);
- else if (changedTo->text() == "Comments")
- dasmView->set_right_column(DASM_RIGHTCOL_COMMENTS);
-
+ debug_view_disasm *const dasmView = m_dasmFrame->view()->view<debug_view_disasm>();
+ dasmView->set_right_column(disasm_right_column(changedTo->data().toInt()));
m_dasmFrame->view()->viewport()->update();
}
@@ -281,33 +329,35 @@ void MainWindow::executeCommandSlot()
executeCommand(true);
}
-void MainWindow::executeCommand(bool withClear)
+void MainWindow::commandEditedSlot(QString const &text)
{
- QString command = m_inputEdit->text();
+ m_inputHistory.edit();
+}
- // A blank command is a "silent step"
+void MainWindow::executeCommand(bool withClear)
+{
+ QString const command = m_inputEdit->text();
if (command == "")
{
+ // A blank command is a "silent step"
m_machine.debugger().console().get_visible_cpu()->debug()->single_step();
- return;
+ m_inputHistory.reset();
}
+ else
+ {
+ // Send along the command
+ m_machine.debugger().console().execute_command(command.toUtf8().data(), true);
- // Send along the command
- m_machine.debugger().console().execute_command(command.toLocal8Bit().data(), true);
-
- // Add history & set the index to be the top of the stack
- addToHistory(command);
+ // Add history
+ m_inputHistory.add(command);
- // Clear out the text and reset the history pointer only if asked
- if (withClear)
- {
- m_inputEdit->clear();
- m_historyIndex = m_inputHistory.size();
+ // Clear out the text and reset the history pointer only if asked
+ if (withClear)
+ {
+ m_inputEdit->clear();
+ m_inputHistory.edit();
+ }
}
-
- // Refresh
- m_consoleView->viewport()->update();
- refreshAll();
}
@@ -320,7 +370,6 @@ void MainWindow::mountImage(bool changedTo)
if (!img)
{
m_machine.debugger().console().printf("Something is wrong with the mount menu.\n");
- refreshAll();
return;
}
@@ -331,10 +380,10 @@ void MainWindow::mountImage(bool changedTo)
QDir::currentPath(),
tr("All files (*.*)"));
- if (img->load(filename.toUtf8().data()) != image_init_result::PASS)
+ auto [err, message] = img->load(filename.toUtf8().data());
+ if (err)
{
- m_machine.debugger().console().printf("Image could not be mounted.\n");
- refreshAll();
+ m_machine.debugger().console().printf("Image could not be mounted: %s\n", !message.empty() ? message : err.message());
return;
}
@@ -350,7 +399,6 @@ void MainWindow::mountImage(bool changedTo)
parentMenuItem->setTitle(newTitle);
m_machine.debugger().console().printf("Image %s mounted successfully.\n", filename.toUtf8().data());
- refreshAll();
}
@@ -374,13 +422,12 @@ void MainWindow::unmountImage(bool changedTo)
parentMenuItem->setTitle(newTitle);
m_machine.debugger().console().printf("Image successfully unmounted.\n");
- refreshAll();
}
void MainWindow::dasmViewUpdated()
{
- debug_view_disasm *const dasmView = downcast<debug_view_disasm *>(m_dasmFrame->view()->view());
+ debug_view_disasm *const dasmView = m_dasmFrame->view()->view<debug_view_disasm>();
bool const haveCursor = dasmView->cursor_visible() && (m_machine.debugger().console().get_visible_cpu() == dasmView->source()->device());
bool haveBreakpoint = false;
bool breakpointEnabled = false;
@@ -414,21 +461,10 @@ void MainWindow::debugActClose()
}
-void MainWindow::addToHistory(const QString& command)
+void MainWindow::debuggerExit()
{
- if (command == "")
- return;
-
- // Always push back when there is no previous history
- if (m_inputHistory.empty())
- {
- m_inputHistory.push_back(m_inputEdit->text());
- return;
- }
-
- // If there is previous history, make sure it's not what you just executed
- if (m_inputHistory.back() != m_inputEdit->text())
- m_inputHistory.push_back(m_inputEdit->text());
+ m_exiting = true;
+ close();
}
@@ -466,52 +502,6 @@ void MainWindow::createImagesMenu()
}
-//=========================================================================
-// MainWindowQtConfig
-//=========================================================================
-void MainWindowQtConfig::buildFromQWidget(QWidget* widget)
-{
- WindowQtConfig::buildFromQWidget(widget);
- MainWindow *window = dynamic_cast<MainWindow *>(widget);
- m_windowState = window->saveState();
-
- QActionGroup *rightBarGroup = window->findChild<QActionGroup*>("rightbargroup");
- if (rightBarGroup->checkedAction()->text() == "Raw Opcodes")
- m_rightBar = 0;
- else if (rightBarGroup->checkedAction()->text() == "Encrypted Opcodes")
- m_rightBar = 1;
- else if (rightBarGroup->checkedAction()->text() == "Comments")
- m_rightBar = 2;
-}
-
-
-void MainWindowQtConfig::applyToQWidget(QWidget *widget)
-{
- WindowQtConfig::applyToQWidget(widget);
- MainWindow *window = dynamic_cast<MainWindow *>(widget);
- window->restoreState(m_windowState);
-
- QActionGroup* rightBarGroup = window->findChild<QActionGroup*>("rightbargroup");
- rightBarGroup->actions()[m_rightBar]->trigger();
-}
-
-
-void MainWindowQtConfig::addToXmlDataNode(util::xml::data_node &node) const
-{
- WindowQtConfig::addToXmlDataNode(node);
- node.set_attribute_int("rightbar", m_rightBar);
- node.set_attribute("qtwindowstate", m_windowState.toPercentEncoding().data());
-}
-
-
-void MainWindowQtConfig::recoverFromXmlNode(util::xml::data_node const &node)
-{
- WindowQtConfig::recoverFromXmlNode(node);
- const char* state = node.get_attribute_string("qtwindowstate", "");
- m_windowState = QByteArray::fromPercentEncoding(state);
- m_rightBar = node.get_attribute_int("rightbar", m_rightBar);
-}
-
DasmDockWidget::~DasmDockWidget()
{
}
@@ -519,3 +509,5 @@ DasmDockWidget::~DasmDockWidget()
ProcessorDockWidget::~ProcessorDockWidget()
{
}
+
+} // namespace osd::debugger::qt
diff --git a/src/osd/modules/debugger/qt/mainwindow.h b/src/osd/modules/debugger/qt/mainwindow.h
index 6c1e9baefcb..762874b6aee 100644
--- a/src/osd/modules/debugger/qt/mainwindow.h
+++ b/src/osd/modules/debugger/qt/mainwindow.h
@@ -3,6 +3,8 @@
#ifndef MAME_DEBUGGER_QT_MAINWINDOW_H
#define MAME_DEBUGGER_QT_MAINWINDOW_H
+#pragma once
+
#include "debuggerview.h"
#include "windowqt.h"
@@ -12,8 +14,10 @@
#include <QtWidgets/QVBoxLayout>
#include <QtWidgets/QComboBox>
-#include <vector>
+#include <deque>
+
+namespace osd::debugger::qt {
class DasmDockWidget;
class ProcessorDockWidget;
@@ -27,18 +31,21 @@ class MainWindow : public WindowQt
Q_OBJECT
public:
- MainWindow(running_machine &machine, QWidget *parent = nullptr);
+ MainWindow(DebuggerQt &debugger, QWidget *parent = nullptr);
virtual ~MainWindow();
void setProcessor(device_t *processor);
+ virtual void restoreConfiguration(util::xml::data_node const &node) override;
protected:
+ virtual void saveConfigurationToNode(util::xml::data_node &node) override;
+
// Used to intercept the user clicking 'X' in the upper corner
- void closeEvent(QCloseEvent *event);
+ virtual void closeEvent(QCloseEvent *event) override;
// Used to intercept the user hitting the up arrow in the input widget
- bool eventFilter(QObject *obj, QEvent *event);
+ virtual bool eventFilter(QObject *obj, QEvent *event) override;
private slots:
void toggleBreakpointAtCursor(bool changedTo);
@@ -47,19 +54,22 @@ private slots:
void rightBarChanged(QAction *changedTo);
void executeCommandSlot();
+ void commandEditedSlot(QString const &text);
void mountImage(bool changedTo);
void unmountImage(bool changedTo);
void dasmViewUpdated();
- // Closing the main window actually exits the program
- void debugActClose();
-
+ // Closing the main window hides the debugger and runs the emulated system
+ virtual void debugActClose() override;
+ virtual void debuggerExit() override;
private:
void createImagesMenu();
+ void executeCommand(bool withClear);
+
// Widgets and docks
QLineEdit *m_inputEdit;
DebuggerView *m_consoleView;
@@ -72,10 +82,9 @@ private:
QAction *m_runToCursorAct;
// Terminal history
- int m_historyIndex;
- std::vector<QString> m_inputHistory;
- void addToHistory(const QString& command);
- void executeCommand(bool withClear);
+ CommandHistory m_inputHistory;
+
+ bool m_exiting;
};
@@ -149,30 +158,6 @@ private:
DebuggerView *m_processorView;
};
-
-//=========================================================================
-// A way to store the configuration of a window long enough to read/write.
-//=========================================================================
-class MainWindowQtConfig : public WindowQtConfig
-{
-public:
- MainWindowQtConfig() :
- WindowQtConfig(WIN_TYPE_MAIN),
- m_rightBar(0),
- m_windowState()
- {}
-
- ~MainWindowQtConfig() {}
-
- // Settings
- int m_rightBar;
- QByteArray m_windowState;
-
- void buildFromQWidget(QWidget *widget);
- void applyToQWidget(QWidget *widget);
- void addToXmlDataNode(util::xml::data_node &node) const;
- void recoverFromXmlNode(util::xml::data_node const &node);
-};
-
+} // namespace osd::debugger::qt
#endif // MAME_DEBUGGER_QT_MAINWINDOW_H
diff --git a/src/osd/modules/debugger/qt/memorywindow.cpp b/src/osd/modules/debugger/qt/memorywindow.cpp
index 09d13c5d6d4..f5e7502f4d4 100644
--- a/src/osd/modules/debugger/qt/memorywindow.cpp
+++ b/src/osd/modules/debugger/qt/memorywindow.cpp
@@ -7,9 +7,16 @@
#include "debug/debugcon.h"
#include "debug/debugcpu.h"
+#include "util/xmlfile.h"
+
#include <QtGui/QClipboard>
+#include <QtGui/QKeyEvent>
#include <QtGui/QMouseEvent>
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+#include <QtGui/QActionGroup>
+#else
#include <QtWidgets/QActionGroup>
+#endif
#include <QtWidgets/QApplication>
#include <QtWidgets/QHBoxLayout>
#include <QtWidgets/QMenu>
@@ -18,12 +25,12 @@
#include <QtWidgets/QToolTip>
#include <QtWidgets/QVBoxLayout>
-#if QT_VERSION < QT_VERSION_CHECK(5, 11, 0)
-#define horizontalAdvance width
-#endif
-MemoryWindow::MemoryWindow(running_machine &machine, QWidget *parent) :
- WindowQt(machine, nullptr)
+namespace osd::debugger::qt {
+
+MemoryWindow::MemoryWindow(DebuggerQt &debugger, QWidget *parent) :
+ WindowQt(debugger, nullptr),
+ m_inputHistory()
{
setWindowTitle("Debug: Memory View");
@@ -44,6 +51,8 @@ MemoryWindow::MemoryWindow(running_machine &machine, QWidget *parent) :
// The input edit
m_inputEdit = new QLineEdit(topSubFrame);
connect(m_inputEdit, &QLineEdit::returnPressed, this, &MemoryWindow::expressionSubmitted);
+ connect(m_inputEdit, &QLineEdit::textEdited, this, &MemoryWindow::expressionEdited);
+ m_inputEdit->installEventFilter(this);
// The memory space combo box
m_memoryComboBox = new QComboBox(topSubFrame);
@@ -76,28 +85,28 @@ MemoryWindow::MemoryWindow(running_machine &machine, QWidget *parent) :
// Create a data format group
QActionGroup *dataFormat = new QActionGroup(this);
dataFormat->setObjectName("dataformat");
- QAction *formatActOne = new QAction("1-byte hexadecimal", this);
- QAction *formatActTwo = new QAction("2-byte hexadecimal", this);
- QAction *formatActFour = new QAction("4-byte hexadecimal", this);
- QAction *formatActEight = new QAction("8-byte hexadecimal", this);
- QAction *formatActOneOctal = new QAction("1-byte octal", this);
- QAction *formatActTwoOctal = new QAction("2-byte octal", this);
- QAction *formatActFourOctal = new QAction("4-byte octal", this);
- QAction *formatActEightOctal = new QAction("8-byte octal", this);
- QAction *formatAct32bitFloat = new QAction("32 bit floating point", this);
- QAction *formatAct64bitFloat = new QAction("64 bit floating point", this);
- QAction *formatAct80bitFloat = new QAction("80 bit floating point", this);
- formatActOne->setObjectName("formatActOne");
- formatActTwo->setObjectName("formatActTwo");
- formatActFour->setObjectName("formatActFour");
- formatActEight->setObjectName("formatActEight");
- formatActOneOctal->setObjectName("formatActOneOctal");
- formatActTwoOctal->setObjectName("formatActTwoOctal");
- formatActFourOctal->setObjectName("formatActFourOctal");
- formatActEightOctal->setObjectName("formatActEightOctal");
- formatAct32bitFloat->setObjectName("formatAct32bitFloat");
- formatAct64bitFloat->setObjectName("formatAct64bitFloat");
- formatAct80bitFloat->setObjectName("formatAct80bitFloat");
+ QAction *formatActOne = new QAction("1-byte Chunks (Hex)", this);
+ QAction *formatActTwo = new QAction("2-byte Chunks (Hex)", this);
+ QAction *formatActFour = new QAction("4-byte Chunks (Hex)", this);
+ QAction *formatActEight = new QAction("8-byte Chunks (Hex)", this);
+ QAction *formatActOneOctal = new QAction("1-byte Chunks (Octal)", this);
+ QAction *formatActTwoOctal = new QAction("2-byte Chunks (Octal)", this);
+ QAction *formatActFourOctal = new QAction("4-byte Chunks (Octal)", this);
+ QAction *formatActEightOctal = new QAction("8-byte Chunks (Octal)", this);
+ QAction *formatAct32bitFloat = new QAction("32-bit Floating Point", this);
+ QAction *formatAct64bitFloat = new QAction("64-bit Floating Point", this);
+ QAction *formatAct80bitFloat = new QAction("80-bit Floating Point", this);
+ formatActOne->setData(int(debug_view_memory::data_format::HEX_8BIT));
+ formatActTwo->setData(int(debug_view_memory::data_format::HEX_16BIT));
+ formatActFour->setData(int(debug_view_memory::data_format::HEX_32BIT));
+ formatActEight->setData(int(debug_view_memory::data_format::HEX_64BIT));
+ formatActOneOctal->setData(int(debug_view_memory::data_format::OCTAL_8BIT));
+ formatActTwoOctal->setData(int(debug_view_memory::data_format::OCTAL_16BIT));
+ formatActFourOctal->setData(int(debug_view_memory::data_format::OCTAL_32BIT));
+ formatActEightOctal->setData(int(debug_view_memory::data_format::OCTAL_64BIT));
+ formatAct32bitFloat->setData(int(debug_view_memory::data_format::FLOAT_32BIT));
+ formatAct64bitFloat->setData(int(debug_view_memory::data_format::FLOAT_64BIT));
+ formatAct80bitFloat->setData(int(debug_view_memory::data_format::FLOAT_80BIT));
formatActOne->setCheckable(true);
formatActTwo->setCheckable(true);
formatActFour->setCheckable(true);
@@ -139,6 +148,8 @@ MemoryWindow::MemoryWindow(running_machine &machine, QWidget *parent) :
addressGroup->setObjectName("addressgroup");
QAction *addressActLogical = new QAction("Logical Addresses", this);
QAction *addressActPhysical = new QAction("Physical Addresses", this);
+ addressActLogical->setData(false);
+ addressActPhysical->setData(true);
addressActLogical->setCheckable(true);
addressActPhysical->setCheckable(true);
addressActLogical->setActionGroup(addressGroup);
@@ -154,9 +165,9 @@ MemoryWindow::MemoryWindow(running_machine &machine, QWidget *parent) :
QAction *radixActHexadecimal = new QAction("Hexadecimal Addresses", this);
QAction *radixActDecimal = new QAction("Decimal Addresses", this);
QAction *radixActOctal = new QAction("Octal Addresses", this);
- radixActHexadecimal->setObjectName("radixHexadecimal");
- radixActDecimal->setObjectName("radixDecimal");
- radixActOctal->setObjectName("radixOctal");
+ radixActHexadecimal->setData(16);
+ radixActDecimal->setData(10);
+ radixActOctal->setData(8);
radixActHexadecimal->setCheckable(true);
radixActDecimal->setCheckable(true);
radixActOctal->setCheckable(true);
@@ -212,6 +223,91 @@ MemoryWindow::~MemoryWindow()
}
+void MemoryWindow::restoreConfiguration(util::xml::data_node const &node)
+{
+ WindowQt::restoreConfiguration(node);
+
+ debug_view_memory &memView = *m_memTable->view<debug_view_memory>();
+
+ auto const region = node.get_attribute_int(ATTR_WINDOW_MEMORY_REGION, m_memTable->sourceIndex());
+ if ((0 <= region) && (m_memoryComboBox->count() > region))
+ m_memoryComboBox->setCurrentIndex(region);
+
+ auto const reverse = node.get_attribute_int(ATTR_WINDOW_MEMORY_REVERSE_COLUMNS, memView.reverse() ? 1 : 0);
+ if (memView.reverse() != bool(reverse))
+ {
+ memView.set_reverse(bool(reverse));
+ findChild<QAction *>("reverse")->setChecked(bool(reverse));
+ }
+
+ auto const mode = node.get_attribute_int(ATTR_WINDOW_MEMORY_ADDRESS_MODE, memView.physical() ? 1 : 0);
+ QActionGroup *const addressGroup = findChild<QActionGroup *>("addressgroup");
+ for (QAction *action : addressGroup->actions())
+ {
+ if (action->data().toBool() == mode)
+ {
+ action->trigger();
+ break;
+ }
+ }
+
+ auto const radix = node.get_attribute_int(ATTR_WINDOW_MEMORY_ADDRESS_RADIX, memView.address_radix());
+ QActionGroup *const radixGroup = findChild<QActionGroup *>("radixgroup");
+ for (QAction *action : radixGroup->actions())
+ {
+ if (action->data().toInt() == radix)
+ {
+ action->trigger();
+ break;
+ }
+ }
+
+ auto const format = node.get_attribute_int(ATTR_WINDOW_MEMORY_DATA_FORMAT, int(memView.get_data_format()));
+ QActionGroup *const dataFormat = findChild<QActionGroup *>("dataformat");
+ for (QAction *action : dataFormat->actions())
+ {
+ if (action->data().toInt() == format)
+ {
+ action->trigger();
+ break;
+ }
+ }
+
+ auto const chunks = node.get_attribute_int(ATTR_WINDOW_MEMORY_ROW_CHUNKS, memView.chunks_per_row());
+ memView.set_chunks_per_row(chunks);
+
+ util::xml::data_node const *const expression = node.get_child(NODE_WINDOW_EXPRESSION);
+ if (expression && expression->get_value())
+ {
+ m_inputEdit->setText(QString::fromUtf8(expression->get_value()));
+ expressionSubmitted();
+ }
+
+ m_memTable->restoreConfigurationFromNode(node);
+ m_inputHistory.restoreConfigurationFromNode(node);
+}
+
+
+void MemoryWindow::saveConfigurationToNode(util::xml::data_node &node)
+{
+ WindowQt::saveConfigurationToNode(node);
+
+ node.set_attribute_int(ATTR_WINDOW_TYPE, WINDOW_TYPE_MEMORY_VIEWER);
+
+ debug_view_memory &memView = *m_memTable->view<debug_view_memory>();
+ node.set_attribute_int(ATTR_WINDOW_MEMORY_REGION, m_memTable->sourceIndex());
+ node.set_attribute_int(ATTR_WINDOW_MEMORY_REVERSE_COLUMNS, memView.reverse() ? 1 : 0);
+ node.set_attribute_int(ATTR_WINDOW_MEMORY_ADDRESS_MODE, memView.physical() ? 1 : 0);
+ node.set_attribute_int(ATTR_WINDOW_MEMORY_ADDRESS_RADIX, memView.address_radix());
+ node.set_attribute_int(ATTR_WINDOW_MEMORY_DATA_FORMAT, int(memView.get_data_format()));
+ node.set_attribute_int(ATTR_WINDOW_MEMORY_ROW_CHUNKS, memView.chunks_per_row());
+ node.add_child(NODE_WINDOW_EXPRESSION, memView.expression());
+
+ m_memTable->saveConfigurationToNode(node);
+ m_inputHistory.saveConfigurationToNode(node);
+}
+
+
void MemoryWindow::memoryRegionChanged(int index)
{
if (index < m_memTable->view()->source_count())
@@ -220,113 +316,120 @@ void MemoryWindow::memoryRegionChanged(int index)
m_memTable->viewport()->update();
// Update the data format radio buttons to the memory region's default
- debug_view_memory *memView = downcast<debug_view_memory*>(m_memTable->view());
- switch (memView->get_data_format())
+ debug_view_memory *const memView = m_memTable->view<debug_view_memory>();
+
+ QActionGroup *const dataFormat = findChild<QActionGroup *>("dataformat");
+ for (QAction *action : dataFormat->actions())
{
- case debug_view_memory::data_format::HEX_8BIT: dataFormatMenuItem("formatActOne")->setChecked(true); break;
- case debug_view_memory::data_format::HEX_16BIT: dataFormatMenuItem("formatActTwo")->setChecked(true); break;
- case debug_view_memory::data_format::HEX_32BIT: dataFormatMenuItem("formatActFour")->setChecked(true); break;
- case debug_view_memory::data_format::HEX_64BIT: dataFormatMenuItem("formatActEight")->setChecked(true); break;
- case debug_view_memory::data_format::OCTAL_8BIT: dataFormatMenuItem("formatActOneOctal")->setChecked(true); break;
- case debug_view_memory::data_format::OCTAL_16BIT: dataFormatMenuItem("formatActTwoOctal")->setChecked(true); break;
- case debug_view_memory::data_format::OCTAL_32BIT: dataFormatMenuItem("formatActFourOctal")->setChecked(true); break;
- case debug_view_memory::data_format::OCTAL_64BIT: dataFormatMenuItem("formatActEightOctal")->setChecked(true); break;
- case debug_view_memory::data_format::FLOAT_32BIT: dataFormatMenuItem("formatAct32bitFloat")->setChecked(true); break;
- case debug_view_memory::data_format::FLOAT_64BIT: dataFormatMenuItem("formatAct64bitFloat")->setChecked(true); break;
- case debug_view_memory::data_format::FLOAT_80BIT: dataFormatMenuItem("formatAct80bitFloat")->setChecked(true); break;
- default: break;
+ if (debug_view_memory::data_format(action->data().toInt()) == memView->get_data_format())
+ {
+ action->setChecked(true);
+ break;
+ }
}
- switch (memView->address_radix())
+
+ QActionGroup *radixGroup = findChild<QActionGroup *>("radixgroup");
+ for (QAction *action : radixGroup->actions())
{
- case 8: dataFormatMenuItem("radixOctal")->setChecked(true); break;
- case 10: dataFormatMenuItem("radixDecimal")->setChecked(true); break;
- case 16: dataFormatMenuItem("radixHexadecimal")->setChecked(true); break;
- default: break;
+ if (action->data().toInt() == memView->address_radix())
+ {
+ action->setChecked(true);
+ break;
+ }
}
}
}
+// Used to intercept the user hitting the up arrow in the input widget
+bool MemoryWindow::eventFilter(QObject *obj, QEvent *event)
+{
+ // Only filter keypresses
+ if (event->type() != QEvent::KeyPress)
+ return QObject::eventFilter(obj, event);
+
+ QKeyEvent const &keyEvent = *static_cast<QKeyEvent *>(event);
+
+ // Catch up & down keys
+ if (keyEvent.key() == Qt::Key_Escape)
+ {
+ m_inputEdit->setText(QString::fromUtf8(m_memTable->view<debug_view_memory>()->expression()));
+ m_inputEdit->selectAll();
+ m_inputHistory.reset();
+ return true;
+ }
+ else if (keyEvent.key() == Qt::Key_Up)
+ {
+ QString const *const hist = m_inputHistory.previous(m_inputEdit->text());
+ if (hist)
+ {
+ m_inputEdit->setText(*hist);
+ m_inputEdit->setSelection(hist->size(), 0);
+ }
+ return true;
+ }
+ else if (keyEvent.key() == Qt::Key_Down)
+ {
+ QString const *const hist = m_inputHistory.next(m_inputEdit->text());
+ if (hist)
+ {
+ m_inputEdit->setText(*hist);
+ m_inputEdit->setSelection(hist->size(), 0);
+ }
+ return true;
+ }
+ else
+ {
+ return QObject::eventFilter(obj, event);
+ }
+}
+
+
void MemoryWindow::expressionSubmitted()
{
const QString expression = m_inputEdit->text();
- downcast<debug_view_memory *>(m_memTable->view())->set_expression(expression.toLocal8Bit().data());
+ m_memTable->view<debug_view_memory>()->set_expression(expression.toUtf8().data());
+ m_inputEdit->selectAll();
- // Make the cursor pop
- m_memTable->view()->set_cursor_visible(true);
+ // Add history
+ if (!expression.isEmpty())
+ m_inputHistory.add(expression);
+}
- // Check where the cursor is and adjust the scroll accordingly
- debug_view_xy cursorPosition = m_memTable->view()->cursor_position();
- // TODO: check if the region is already visible?
- m_memTable->verticalScrollBar()->setValue(cursorPosition.y);
- m_memTable->update();
- m_memTable->viewport()->update();
+void MemoryWindow::expressionEdited(QString const &text)
+{
+ m_inputHistory.edit();
}
void MemoryWindow::formatChanged(QAction* changedTo)
{
- debug_view_memory *memView = downcast<debug_view_memory*>(m_memTable->view());
-
- if (changedTo->text() == "1-byte hexadecimal")
- memView->set_data_format(debug_view_memory::data_format::HEX_8BIT);
- else if (changedTo->text() == "2-byte hexadecimal")
- memView->set_data_format(debug_view_memory::data_format::HEX_16BIT);
- else if (changedTo->text() == "4-byte hexadecimal")
- memView->set_data_format(debug_view_memory::data_format::HEX_32BIT);
- else if (changedTo->text() == "8-byte hexadecimal")
- memView->set_data_format(debug_view_memory::data_format::HEX_64BIT);
- else if (changedTo->text() == "1-byte octal")
- memView->set_data_format(debug_view_memory::data_format::OCTAL_8BIT);
- else if (changedTo->text() == "2-byte octal")
- memView->set_data_format(debug_view_memory::data_format::OCTAL_16BIT);
- else if (changedTo->text() == "4-byte octal")
- memView->set_data_format(debug_view_memory::data_format::OCTAL_32BIT);
- else if (changedTo->text() == "8-byte octal")
- memView->set_data_format(debug_view_memory::data_format::OCTAL_64BIT);
- else if (changedTo->text() == "32 bit floating point")
- memView->set_data_format(debug_view_memory::data_format::FLOAT_32BIT);
- else if (changedTo->text() == "64 bit floating point")
- memView->set_data_format(debug_view_memory::data_format::FLOAT_64BIT);
- else if (changedTo->text() == "80 bit floating point")
- memView->set_data_format(debug_view_memory::data_format::FLOAT_80BIT);
-
+ debug_view_memory *const memView = m_memTable->view<debug_view_memory>();
+ memView->set_data_format(debug_view_memory::data_format(changedTo->data().toInt()));
m_memTable->viewport()->update();
}
void MemoryWindow::addressChanged(QAction* changedTo)
{
- debug_view_memory *memView = downcast<debug_view_memory *>(m_memTable->view());
-
- if (changedTo->text() == "Logical Addresses")
- memView->set_physical(false);
- else if (changedTo->text() == "Physical Addresses")
- memView->set_physical(true);
-
+ debug_view_memory *const memView = m_memTable->view<debug_view_memory>();
+ memView->set_physical(changedTo->data().toBool());
m_memTable->viewport()->update();
}
void MemoryWindow::radixChanged(QAction* changedTo)
{
- debug_view_memory *memView = downcast<debug_view_memory *>(m_memTable->view());
-
- if (changedTo->text() == "Hexadecimal Addresses")
- memView->set_address_radix(16);
- else if (changedTo->text() == "Decimal Addresses")
- memView->set_address_radix(10);
- else if (changedTo->text() == "Octal Addresses")
- memView->set_address_radix(8);
-
+ debug_view_memory *const memView = m_memTable->view<debug_view_memory>();
+ memView->set_address_radix(changedTo->data().toInt());
m_memTable->viewport()->update();
}
void MemoryWindow::reverseChanged(bool changedTo)
{
- debug_view_memory *memView = downcast<debug_view_memory*>(m_memTable->view());
+ debug_view_memory *const memView = m_memTable->view<debug_view_memory>();
memView->set_reverse(changedTo);
m_memTable->viewport()->update();
}
@@ -334,7 +437,7 @@ void MemoryWindow::reverseChanged(bool changedTo)
void MemoryWindow::increaseBytesPerLine(bool changedTo)
{
- debug_view_memory *memView = downcast<debug_view_memory*>(m_memTable->view());
+ debug_view_memory *const memView = m_memTable->view<debug_view_memory>();
memView->set_chunks_per_row(memView->chunks_per_row() + 1);
m_memTable->viewport()->update();
}
@@ -342,7 +445,7 @@ void MemoryWindow::increaseBytesPerLine(bool changedTo)
void MemoryWindow::decreaseBytesPerLine(bool checked)
{
- debug_view_memory *memView = downcast<debug_view_memory *>(m_memTable->view());
+ debug_view_memory *const memView = m_memTable->view<debug_view_memory>();
memView->set_chunks_per_row(memView->chunks_per_row() - 1);
m_memTable->viewport()->update();
}
@@ -374,25 +477,6 @@ void MemoryWindow::setToCurrentCpu()
}
-// I have a hard time storing QActions as class members. This is a substitute.
-QAction *MemoryWindow::dataFormatMenuItem(const QString& itemName)
-{
- QList<QMenu *> menus = menuBar()->findChildren<QMenu *>();
- for (int i = 0; i < menus.length(); i++)
- {
- if (menus[i]->title() != "&Options")
- continue;
- QList<QAction *> actions = menus[i]->actions();
- for (int j = 0; j < actions.length(); j++)
- {
- if (actions[j]->objectName() == itemName)
- return actions[j];
- }
- }
- return nullptr;
-}
-
-
//=========================================================================
// DebuggerMemView
//=========================================================================
@@ -402,7 +486,7 @@ void DebuggerMemView::addItemsToContextMenu(QMenu *menu)
if (view()->cursor_visible())
{
- debug_view_memory &memView = downcast<debug_view_memory &>(*view());
+ debug_view_memory &memView = *view<debug_view_memory>();
debug_view_memory_source const &source = downcast<debug_view_memory_source const &>(*memView.source());
address_space *const addressSpace = source.space();
if (addressSpace)
@@ -412,29 +496,30 @@ void DebuggerMemView::addItemsToContextMenu(QMenu *menu)
offs_t const address = addressSpace->byte_to_address(memView.addressAtCursorPosition(pos));
offs_t a = address & addressSpace->logaddrmask();
bool good = false;
- if (!addressSpace->device().memory().translate(addressSpace->spacenum(), TRANSLATE_READ_DEBUG, a))
+ address_space *tspace;
+ if (!addressSpace->device().memory().translate(addressSpace->spacenum(), device_memory_interface::TR_READ, a, tspace))
{
m_lastPc = "Bad address";
}
else
{
- uint64_t memValue = addressSpace->unmap();
- auto dis = addressSpace->device().machine().disable_side_effects();
- switch (addressSpace->data_width())
+ uint64_t memValue = tspace->unmap();
+ auto dis = tspace->device().machine().disable_side_effects();
+ switch (tspace->data_width())
{
- case 8: memValue = addressSpace->read_byte(a); break;
- case 16: memValue = addressSpace->read_word_unaligned(a); break;
- case 32: memValue = addressSpace->read_dword_unaligned(a); break;
- case 64: memValue = addressSpace->read_qword_unaligned(a); break;
+ case 8: memValue = tspace->read_byte(a); break;
+ case 16: memValue = tspace->read_word_unaligned(a); break;
+ case 32: memValue = tspace->read_dword_unaligned(a); break;
+ case 64: memValue = tspace->read_qword_unaligned(a); break;
}
offs_t const pc = source.device()->debug()->track_mem_pc_from_space_address_data(
- addressSpace->spacenum(),
+ tspace->spacenum(),
address,
memValue);
if (pc != offs_t(-1))
{
- if (addressSpace->is_octal())
+ if (tspace->is_octal())
m_lastPc = QString("Address %1 written at PC=%2").arg(address, 2, 8).arg(pc, 2, 8);
else
m_lastPc = QString("Address %1 written at PC=%2").arg(address, 2, 16).arg(pc, 2, 16);
@@ -462,99 +547,4 @@ void DebuggerMemView::copyLastPc()
QApplication::clipboard()->setText(m_lastPc);
}
-
-//=========================================================================
-// MemoryWindowQtConfig
-//=========================================================================
-void MemoryWindowQtConfig::buildFromQWidget(QWidget *widget)
-{
- WindowQtConfig::buildFromQWidget(widget);
- MemoryWindow *window = dynamic_cast<MemoryWindow *>(widget);
- QComboBox *memoryRegion = window->findChild<QComboBox*>("memoryregion");
- m_memoryRegion = memoryRegion->currentIndex();
-
- QAction *reverse = window->findChild<QAction *>("reverse");
- m_reverse = reverse->isChecked();
-
- QActionGroup *addressGroup = window->findChild<QActionGroup*>("addressgroup");
- if (addressGroup->checkedAction()->text() == "Logical Addresses")
- m_addressMode = 0;
- else if (addressGroup->checkedAction()->text() == "Physical Addresses")
- m_addressMode = 1;
-
- QActionGroup *radixGroup = window->findChild<QActionGroup*>("radixgroup");
- if (radixGroup->checkedAction()->text() == "Hexadecimal Addresses")
- m_addressRadix = 0;
- else if (radixGroup->checkedAction()->text() == "Decimal Addresses")
- m_addressRadix = 1;
- else if (radixGroup->checkedAction()->text() == "Octal Addresses")
- m_addressRadix = 2;
-
- QActionGroup *dataFormat = window->findChild<QActionGroup*>("dataformat");
- if (dataFormat->checkedAction()->text() == "1-byte hexadecimal")
- m_dataFormat = 0;
- else if (dataFormat->checkedAction()->text() == "2-byte hexadecimal")
- m_dataFormat = 1;
- else if (dataFormat->checkedAction()->text() == "4-byte hexadecimal")
- m_dataFormat = 2;
- else if (dataFormat->checkedAction()->text() == "8-byte hexadecimal")
- m_dataFormat = 3;
- else if (dataFormat->checkedAction()->text() == "1-byte octal")
- m_dataFormat = 4;
- else if (dataFormat->checkedAction()->text() == "2-byte octal")
- m_dataFormat = 5;
- else if (dataFormat->checkedAction()->text() == "4-byte octal")
- m_dataFormat = 6;
- else if (dataFormat->checkedAction()->text() == "8-byte octal")
- m_dataFormat = 7;
- else if (dataFormat->checkedAction()->text() == "32 bit floating point")
- m_dataFormat = 8;
- else if (dataFormat->checkedAction()->text() == "64 bit floating point")
- m_dataFormat = 9;
- else if (dataFormat->checkedAction()->text() == "80 bit floating point")
- m_dataFormat = 10;
-}
-
-
-void MemoryWindowQtConfig::applyToQWidget(QWidget *widget)
-{
- WindowQtConfig::applyToQWidget(widget);
- MemoryWindow *window = dynamic_cast<MemoryWindow *>(widget);
- QComboBox *memoryRegion = window->findChild<QComboBox *>("memoryregion");
- memoryRegion->setCurrentIndex(m_memoryRegion);
-
- QAction *reverse = window->findChild<QAction *>("reverse");
- if (m_reverse)
- reverse->trigger();
-
- QActionGroup *addressGroup = window->findChild<QActionGroup*>("addressgroup");
- addressGroup->actions()[m_addressMode]->trigger();
-
- QActionGroup *radixGroup = window->findChild<QActionGroup*>("radixgroup");
- radixGroup->actions()[m_addressRadix]->trigger();
-
- QActionGroup *dataFormat = window->findChild<QActionGroup*>("dataformat");
- dataFormat->actions()[m_dataFormat]->trigger();
-}
-
-
-void MemoryWindowQtConfig::addToXmlDataNode(util::xml::data_node &node) const
-{
- WindowQtConfig::addToXmlDataNode(node);
- node.set_attribute_int("memoryregion", m_memoryRegion);
- node.set_attribute_int("reverse", m_reverse);
- node.set_attribute_int("addressmode", m_addressMode);
- node.set_attribute_int("addressradix", m_addressRadix);
- node.set_attribute_int("dataformat", m_dataFormat);
-}
-
-
-void MemoryWindowQtConfig::recoverFromXmlNode(util::xml::data_node const &node)
-{
- WindowQtConfig::recoverFromXmlNode(node);
- m_memoryRegion = node.get_attribute_int("memoryregion", m_memoryRegion);
- m_reverse = node.get_attribute_int("reverse", m_reverse);
- m_addressMode = node.get_attribute_int("addressmode", m_addressMode);
- m_addressRadix = node.get_attribute_int("addressradix", m_addressRadix);
- m_dataFormat = node.get_attribute_int("dataformat", m_dataFormat);
-}
+} // namespace osd::debugger::qt
diff --git a/src/osd/modules/debugger/qt/memorywindow.h b/src/osd/modules/debugger/qt/memorywindow.h
index 86193cc3edc..ed5c5b30cb0 100644
--- a/src/osd/modules/debugger/qt/memorywindow.h
+++ b/src/osd/modules/debugger/qt/memorywindow.h
@@ -3,12 +3,17 @@
#ifndef MAME_DEBUGGER_QT_MEMORYWINDOW_H
#define MAME_DEBUGGER_QT_MEMORYWINDOW_H
+#pragma once
+
#include "debuggerview.h"
#include "windowqt.h"
#include <QtWidgets/QComboBox>
#include <QtWidgets/QLineEdit>
+
+namespace osd::debugger::qt {
+
class DebuggerMemView;
@@ -20,12 +25,22 @@ class MemoryWindow : public WindowQt
Q_OBJECT
public:
- MemoryWindow(running_machine &machine, QWidget *parent = nullptr);
+ MemoryWindow(DebuggerQt &debugger, QWidget *parent = nullptr);
virtual ~MemoryWindow();
+ virtual void restoreConfiguration(util::xml::data_node const &node) override;
+
+protected:
+ virtual void saveConfigurationToNode(util::xml::data_node &node) override;
+
+ // Used to intercept the user hitting the up arrow in the input widget
+ virtual bool eventFilter(QObject *obj, QEvent *event) override;
+
private slots:
void memoryRegionChanged(int index);
void expressionSubmitted();
+ void expressionEdited(QString const &text);
+
void formatChanged(QAction *changedTo);
void addressChanged(QAction *changedTo);
void radixChanged(QAction *changedTo);
@@ -36,12 +51,14 @@ private slots:
private:
void populateComboBox();
void setToCurrentCpu();
- QAction *dataFormatMenuItem(const QString &itemName);
// Widgets
QLineEdit *m_inputEdit;
QComboBox *m_memoryComboBox;
DebuggerMemView *m_memTable;
+
+ // Expression history
+ CommandHistory m_inputHistory;
};
@@ -69,37 +86,6 @@ private:
QString m_lastPc;
};
-
-//=========================================================================
-// A way to store the configuration of a window long enough to read/write.
-//=========================================================================
-class MemoryWindowQtConfig : public WindowQtConfig
-{
-public:
- MemoryWindowQtConfig() :
- WindowQtConfig(WIN_TYPE_MEMORY),
- m_reverse(0),
- m_addressMode(0),
- m_addressRadix(0),
- m_dataFormat(0),
- m_memoryRegion(0)
- {
- }
-
- ~MemoryWindowQtConfig() {}
-
- // Settings
- int m_reverse;
- int m_addressMode;
- int m_addressRadix;
- int m_dataFormat;
- int m_memoryRegion;
-
- void buildFromQWidget(QWidget *widget);
- void applyToQWidget(QWidget *widget);
- void addToXmlDataNode(util::xml::data_node &node) const;
- void recoverFromXmlNode(util::xml::data_node const &node);
-};
-
+} // namespace osd::debugger::qt
#endif // MAME_DEBUGGER_QT_MEMORYWINDOW_H
diff --git a/src/osd/modules/debugger/qt/windowqt.cpp b/src/osd/modules/debugger/qt/windowqt.cpp
index 852d1f5449c..783c5a24393 100644
--- a/src/osd/modules/debugger/qt/windowqt.cpp
+++ b/src/osd/modules/debugger/qt/windowqt.cpp
@@ -12,38 +12,46 @@
#include "debug/debugcon.h"
#include "debug/debugcpu.h"
+#include "util/xmlfile.h"
+
#include <QtWidgets/QMenu>
#include <QtWidgets/QMenuBar>
-bool WindowQt::s_refreshAll = false;
-bool WindowQt::s_hideAll = false;
+namespace osd::debugger::qt {
// Since all debug windows are intended to be top-level, this inherited
// constructor is always called with a nullptr parent. The passed-in parent widget,
// however, is often used to place each child window & the code to do this can
// be found in most of the inherited classes.
-WindowQt::WindowQt(running_machine &machine, QWidget *parent) :
+WindowQt::WindowQt(DebuggerQt &debugger, QWidget *parent) :
QMainWindow(parent),
- m_machine(machine)
+ m_debugger(debugger),
+ m_machine(debugger.machine())
{
setAttribute(Qt::WA_DeleteOnClose, true);
+ // Subscribe to signals
+ connect(&debugger, &DebuggerQt::exitDebugger, this, &WindowQt::debuggerExit);
+ connect(&debugger, &DebuggerQt::hideAllWindows, this, &WindowQt::hide);
+ connect(&debugger, &DebuggerQt::showAllWindows, this, &WindowQt::show);
+ connect(&debugger, &DebuggerQt::saveConfiguration, this, &WindowQt::saveConfiguration);
+
// The Debug menu bar
QAction *debugActOpenMemory = new QAction("New &Memory Window", this);
debugActOpenMemory->setShortcut(QKeySequence("Ctrl+M"));
connect(debugActOpenMemory, &QAction::triggered, this, &WindowQt::debugActOpenMemory);
- QAction *debugActOpenDasm = new QAction("New &Dasm Window", this);
+ QAction *debugActOpenDasm = new QAction("New &Disassembly Window", this);
debugActOpenDasm->setShortcut(QKeySequence("Ctrl+D"));
connect(debugActOpenDasm, &QAction::triggered, this, &WindowQt::debugActOpenDasm);
- QAction *debugActOpenLog = new QAction("New &Log Window", this);
+ QAction *debugActOpenLog = new QAction("New Error &Log Window", this);
debugActOpenLog->setShortcut(QKeySequence("Ctrl+L"));
connect(debugActOpenLog, &QAction::triggered, this, &WindowQt::debugActOpenLog);
- QAction *debugActOpenPoints = new QAction("New &Break|Watchpoints Window", this);
+ QAction *debugActOpenPoints = new QAction("New (&Break|Watch)points Window", this);
debugActOpenPoints->setShortcut(QKeySequence("Ctrl+B"));
connect(debugActOpenPoints, &QAction::triggered, this, &WindowQt::debugActOpenPoints);
@@ -128,9 +136,10 @@ WindowQt::~WindowQt()
{
}
+
void WindowQt::debugActOpenMemory()
{
- MemoryWindow *foo = new MemoryWindow(m_machine, this);
+ MemoryWindow *foo = new MemoryWindow(m_debugger, this);
// A valiant effort, but it just doesn't wanna' hide behind the main window & not make a new toolbar icon
// foo->setWindowFlags(Qt::Dialog);
// foo->setWindowFlags(foo->windowFlags() & ~Qt::WindowStaysOnTopHint);
@@ -140,7 +149,7 @@ void WindowQt::debugActOpenMemory()
void WindowQt::debugActOpenDasm()
{
- DasmWindow *foo = new DasmWindow(m_machine, this);
+ DasmWindow *foo = new DasmWindow(m_debugger, this);
// A valiant effort, but it just doesn't wanna' hide behind the main window & not make a new toolbar icon
// foo->setWindowFlags(Qt::Dialog);
// foo->setWindowFlags(foo->windowFlags() & ~Qt::WindowStaysOnTopHint);
@@ -150,7 +159,7 @@ void WindowQt::debugActOpenDasm()
void WindowQt::debugActOpenLog()
{
- LogWindow *foo = new LogWindow(m_machine, this);
+ LogWindow *foo = new LogWindow(m_debugger, this);
// A valiant effort, but it just doesn't wanna' hide behind the main window & not make a new toolbar icon
// foo->setWindowFlags(Qt::Dialog);
// foo->setWindowFlags(foo->windowFlags() & ~Qt::WindowStaysOnTopHint);
@@ -160,7 +169,7 @@ void WindowQt::debugActOpenLog()
void WindowQt::debugActOpenPoints()
{
- BreakpointsWindow *foo = new BreakpointsWindow(m_machine, this);
+ BreakpointsWindow *foo = new BreakpointsWindow(m_debugger, this);
// A valiant effort, but it just doesn't wanna' hide behind the main window & not make a new toolbar icon
// foo->setWindowFlags(Qt::Dialog);
// foo->setWindowFlags(foo->windowFlags() & ~Qt::WindowStaysOnTopHint);
@@ -170,7 +179,7 @@ void WindowQt::debugActOpenPoints()
void WindowQt::debugActOpenDevices()
{
- DevicesWindow *foo = new DevicesWindow(m_machine, this);
+ DevicesWindow *foo = new DevicesWindow(m_debugger, this);
// A valiant effort, but it just doesn't wanna' hide behind the main window & not make a new toolbar icon
// foo->setWindowFlags(Qt::Dialog);
// foo->setWindowFlags(foo->windowFlags() & ~Qt::WindowStaysOnTopHint);
@@ -186,7 +195,7 @@ void WindowQt::debugActRun()
void WindowQt::debugActRunAndHide()
{
m_machine.debugger().console().get_visible_cpu()->debug()->go();
- hideAll();
+ m_debugger.hideAll();
}
void WindowQt::debugActRunToNextCpu()
@@ -240,40 +249,154 @@ void WindowQt::debugActQuit()
m_machine.schedule_exit();
}
+void WindowQt::debuggerExit()
+{
+ close();
+}
+
+
+void WindowQt::restoreConfiguration(util::xml::data_node const &node)
+{
+ QPoint p(geometry().topLeft());
+ p.setX(node.get_attribute_int(ATTR_WINDOW_POSITION_X, p.x()));
+ p.setY(node.get_attribute_int(ATTR_WINDOW_POSITION_Y, p.y()));
+
+ QSize s(size());
+ s.setWidth(node.get_attribute_int(ATTR_WINDOW_WIDTH, s.width()));
+ s.setHeight(node.get_attribute_int(ATTR_WINDOW_HEIGHT, s.height()));
+
+ // TODO: sanity checks, restrict to screen area
+
+ setGeometry(p.x(), p.y(), s.width(), s.height());
+}
+
+
+void WindowQt::saveConfiguration(util::xml::data_node &parentnode)
+{
+ util::xml::data_node *const node = parentnode.add_child(NODE_WINDOW, nullptr);
+ if (node)
+ saveConfigurationToNode(*node);
+}
+
-//=========================================================================
-// WindowQtConfig
-//=========================================================================
-void WindowQtConfig::buildFromQWidget(QWidget *widget)
+void WindowQt::saveConfigurationToNode(util::xml::data_node &node)
{
- m_position.setX(widget->geometry().topLeft().x());
- m_position.setY(widget->geometry().topLeft().y());
- m_size.setX(widget->size().width());
- m_size.setY(widget->size().height());
+ node.set_attribute_int(ATTR_WINDOW_POSITION_X, geometry().topLeft().x());
+ node.set_attribute_int(ATTR_WINDOW_POSITION_Y, geometry().topLeft().y());
+ node.set_attribute_int(ATTR_WINDOW_WIDTH, size().width());
+ node.set_attribute_int(ATTR_WINDOW_HEIGHT, size().height());
}
-void WindowQtConfig::applyToQWidget(QWidget *widget)
+CommandHistory::CommandHistory() :
+ m_history(),
+ m_current(),
+ m_position(-1)
{
- widget->setGeometry(m_position.x(), m_position.y(), m_size.x(), m_size.y());
}
-void WindowQtConfig::addToXmlDataNode(util::xml::data_node &node) const
+CommandHistory::~CommandHistory()
{
- node.set_attribute_int("type", m_type);
- node.set_attribute_int("position_x", m_position.x());
- node.set_attribute_int("position_y", m_position.y());
- node.set_attribute_int("size_x", m_size.x());
- node.set_attribute_int("size_y", m_size.y());
}
-void WindowQtConfig::recoverFromXmlNode(util::xml::data_node const &node)
+void CommandHistory::add(QString const &entry)
{
- m_size.setX(node.get_attribute_int("size_x", m_size.x()));
- m_size.setY(node.get_attribute_int("size_y", m_size.y()));
- m_position.setX(node.get_attribute_int("position_x", m_position.x()));
- m_position.setY(node.get_attribute_int("position_y", m_position.y()));
- m_type = (WindowQtConfig::WindowType)node.get_attribute_int("type", m_type);
+ if (m_history.empty() || (m_history.front() != entry))
+ {
+ while (m_history.size() >= CAPACITY)
+ m_history.pop_back();
+ m_history.push_front(entry);
+ }
+ m_position = 0;
}
+
+
+QString const *CommandHistory::previous(QString const &current)
+{
+ if ((m_position + 1) < m_history.size())
+ {
+ if (0 > m_position)
+ m_current = std::make_unique<QString>(current);
+ return &m_history[++m_position];
+ }
+ else
+ {
+ return nullptr;
+ }
+}
+
+
+QString const *CommandHistory::next(QString const &current)
+{
+ if (0 < m_position)
+ {
+ return &m_history[--m_position];
+ }
+ else if (!m_position && m_current && (m_history.front() != *m_current))
+ {
+ --m_position;
+ return m_current.get();
+ }
+ else
+ {
+ return nullptr;
+ }
+}
+
+
+void CommandHistory::edit()
+{
+ if (!m_position)
+ --m_position;
+}
+
+
+void CommandHistory::reset()
+{
+ m_position = -1;
+ m_current.reset();
+}
+
+
+void CommandHistory::clear()
+{
+ m_position = -1;
+ m_current.reset();
+ m_history.clear();
+}
+
+
+void CommandHistory::restoreConfigurationFromNode(util::xml::data_node const &node)
+{
+ clear();
+ util::xml::data_node const *const historynode = node.get_child(NODE_WINDOW_HISTORY);
+ if (historynode)
+ {
+ util::xml::data_node const *itemnode = historynode->get_child(NODE_HISTORY_ITEM);
+ while (itemnode)
+ {
+ if (itemnode->get_value() && *itemnode->get_value())
+ {
+ while (m_history.size() >= CAPACITY)
+ m_history.pop_back();
+ m_history.push_front(QString::fromUtf8(itemnode->get_value()));
+ }
+ itemnode = itemnode->get_next_sibling(NODE_HISTORY_ITEM);
+ }
+ }
+}
+
+
+void CommandHistory::saveConfigurationToNode(util::xml::data_node &node)
+{
+ util::xml::data_node *const historynode = node.add_child(NODE_WINDOW_HISTORY, nullptr);
+ if (historynode)
+ {
+ for (auto it = m_history.crbegin(); m_history.crend() != it; ++it)
+ historynode->add_child(NODE_HISTORY_ITEM, it->toUtf8().data());
+ }
+}
+
+} // namespace osd::debugger::qt
diff --git a/src/osd/modules/debugger/qt/windowqt.h b/src/osd/modules/debugger/qt/windowqt.h
index 15cbe470f2f..8085f9a63bf 100644
--- a/src/osd/modules/debugger/qt/windowqt.h
+++ b/src/osd/modules/debugger/qt/windowqt.h
@@ -3,11 +3,39 @@
#ifndef MAME_DEBUGGER_QT_WINDOWQT_H
#define MAME_DEBUGGER_QT_WINDOWQT_H
-#include "config.h"
+#include "../xmlconfig.h"
+
#include "debugger.h"
#include <QtWidgets/QMainWindow>
+#include <deque>
+#include <memory>
+
+
+namespace osd::debugger::qt {
+
+//============================================================
+// The Qt debugger module interface
+//============================================================
+class DebuggerQt : public QObject
+{
+ Q_OBJECT
+
+public:
+ virtual ~DebuggerQt() { }
+
+ virtual running_machine &machine() const = 0;
+
+ void hideAll() { emit hideAllWindows(); }
+
+signals:
+ void exitDebugger();
+ void hideAllWindows();
+ void showAllWindows();
+ void saveConfiguration(util::xml::data_node &parentnode);
+};
+
//============================================================
// The Qt window that everyone derives from.
@@ -17,18 +45,9 @@ class WindowQt : public QMainWindow
Q_OBJECT
public:
- WindowQt(running_machine &machine, QWidget *parent = nullptr);
virtual ~WindowQt();
- // The interface to an all-window refresh
- void refreshAll() { s_refreshAll = true; }
- bool wantsRefresh() { return s_refreshAll; }
- void clearRefreshFlag() { s_refreshAll = false; }
-
- void hideAll() { s_hideAll = true; }
- bool wantsHide() { return s_hideAll; }
- void clearHideFlag() { s_hideAll = false; }
-
+ virtual void restoreConfiguration(util::xml::data_node const &node);
protected slots:
void debugActOpenMemory();
@@ -48,52 +67,48 @@ protected slots:
void debugActHardReset();
virtual void debugActClose();
void debugActQuit();
+ virtual void debuggerExit();
+private slots:
+ void saveConfiguration(util::xml::data_node &parentnode);
protected:
- running_machine &m_machine;
+ WindowQt(DebuggerQt &debugger, QWidget *parent = nullptr);
+
+ virtual void saveConfigurationToNode(util::xml::data_node &node);
- static bool s_refreshAll;
- static bool s_hideAll;
+ DebuggerQt &m_debugger;
+ running_machine &m_machine;
};
-//=========================================================================
-// A way to store the configuration of a window long enough to read/write.
-//=========================================================================
-class WindowQtConfig
+//============================================================
+// Command history helper
+//============================================================
+class CommandHistory
{
public:
- enum WindowType
- {
- WIN_TYPE_UNKNOWN,
- WIN_TYPE_MAIN,
- WIN_TYPE_MEMORY,
- WIN_TYPE_DASM,
- WIN_TYPE_LOG,
- WIN_TYPE_BREAK_POINTS,
- WIN_TYPE_DEVICES,
- WIN_TYPE_DEVICE_INFORMATION
- };
+ CommandHistory();
+ ~CommandHistory();
-public:
- WindowQtConfig(const WindowType& type=WIN_TYPE_UNKNOWN) :
- m_type(type),
- m_size(800, 600),
- m_position(120, 120)
- {}
- virtual ~WindowQtConfig() {}
-
- // Settings
- WindowType m_type;
- QPoint m_size;
- QPoint m_position;
-
- virtual void buildFromQWidget(QWidget *widget);
- virtual void applyToQWidget(QWidget *widget);
- virtual void addToXmlDataNode(util::xml::data_node &node) const;
- virtual void recoverFromXmlNode(util::xml::data_node const &node);
+ void add(QString const &entry);
+ QString const *previous(QString const &current);
+ QString const *next(QString const &current);
+ void edit();
+ void reset();
+ void clear();
+
+ void restoreConfigurationFromNode(util::xml::data_node const &node);
+ void saveConfigurationToNode(util::xml::data_node &node);
+
+private:
+ static inline constexpr unsigned CAPACITY = 100U;
+
+ std::deque<QString> m_history;
+ std::unique_ptr<QString> m_current;
+ int m_position;
};
+} // namespace osd::debugger::qt
#endif // MAME_DEBUGGER_QT_WINDOWQT_H
diff --git a/src/osd/modules/debugger/win/consolewininfo.cpp b/src/osd/modules/debugger/win/consolewininfo.cpp
index b2f12b69331..3a4a52be2e2 100644
--- a/src/osd/modules/debugger/win/consolewininfo.cpp
+++ b/src/osd/modules/debugger/win/consolewininfo.cpp
@@ -12,6 +12,9 @@
#include "debugviewinfo.h"
#include "uimetrics.h"
+// devices
+#include "imagedev/cassette.h"
+
// emu
#include "debug/debugcon.h"
#include "debugger.h"
@@ -19,8 +22,8 @@
#include "softlist_dev.h"
#include "debug/debugcpu.h"
-// devices
-#include "imagedev/cassette.h"
+// util
+#include "util/xmlfile.h"
// osd/windows
#include "winutf8.h"
@@ -39,6 +42,8 @@
#include <wrl/client.h>
+namespace osd::debugger::win {
+
namespace {
class comdlg_filter_helper
@@ -121,7 +126,7 @@ void choose_image(device_image_interface &device, HWND owner, REFCLSID class_id,
// create file dialog
Microsoft::WRL::ComPtr<IFileDialog> dialog;
- hr = CoCreateInstance(class_id, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(dialog.GetAddressOf()));
+ hr = CoCreateInstance(class_id, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&dialog));
// set file types
if (SUCCEEDED(hr))
@@ -154,7 +159,7 @@ void choose_image(device_image_interface &device, HWND owner, REFCLSID class_id,
// FIXME: strip off archive names - opening a file inside an archive decompresses it to a temporary location
std::wstring wfull = osd::text::to_wstring(full);
Microsoft::WRL::ComPtr<IShellItem> item;
- if (SUCCEEDED(SHCreateItemFromParsingName(wfull.c_str(), nullptr, IID_PPV_ARGS(item.GetAddressOf()))))
+ if (SUCCEEDED(SHCreateItemFromParsingName(wfull.c_str(), nullptr, IID_PPV_ARGS(&item))))
{
//dialog->SetFolder(item); disabled until
}
@@ -171,7 +176,7 @@ void choose_image(device_image_interface &device, HWND owner, REFCLSID class_id,
if (SUCCEEDED(hr))
{
Microsoft::WRL::ComPtr<IShellItem> result;
- hr = dialog->GetResult(result.GetAddressOf());
+ hr = dialog->GetResult(&result);
if (SUCCEEDED(hr))
{
PWSTR selection = nullptr;
@@ -209,7 +214,7 @@ consolewin_info::consolewin_info(debugger_windows_interface &debugger) :
m_current_cpu(nullptr),
m_devices_menu(nullptr)
{
- if ((window() == nullptr) || (m_views[0] == nullptr))
+ if (!window() || !m_views[0])
goto cleanup;
// create the views
@@ -221,21 +226,30 @@ consolewin_info::consolewin_info(debugger_windows_interface &debugger) :
goto cleanup;
{
- // Add image menu only if image devices exist
+ // add image menu only if image devices exist
image_interface_enumerator iter(machine().root_device());
if (iter.first() != nullptr)
{
m_devices_menu = CreatePopupMenu();
for (device_image_interface &img : iter)
{
- if (!img.user_loadable())
- continue;
- osd::text::tstring tc_buf = osd::text::to_tstring(string_format("%s : %s", img.device().name(), img.exists() ? img.filename() : "[no image]"));
- AppendMenu(m_devices_menu, MF_ENABLED, 0, tc_buf.c_str());
+ if (img.user_loadable())
+ {
+ osd::text::tstring tc_buf = osd::text::to_tstring(string_format("%s : %s", img.device().name(), img.exists() ? img.filename() : "[no image]"));
+ AppendMenu(m_devices_menu, MF_ENABLED, 0, tc_buf.c_str());
+ }
}
AppendMenu(GetMenu(window()), MF_ENABLED | MF_POPUP, (UINT_PTR)m_devices_menu, TEXT("Media"));
}
+ // add the settings menu
+ HMENU const settingsmenu = CreatePopupMenu();
+ AppendMenu(settingsmenu, MF_ENABLED, ID_SAVE_WINDOWS, TEXT("Save Window Arrangement"));
+ AppendMenu(settingsmenu, MF_DISABLED | MF_SEPARATOR, 0, TEXT(""));
+ AppendMenu(settingsmenu, MF_ENABLED, ID_LIGHT_BACKGROUND, TEXT("Light Background"));
+ AppendMenu(settingsmenu, MF_ENABLED, ID_DARK_BACKGROUND, TEXT("Dark Background"));
+ AppendMenu(GetMenu(window()), MF_ENABLED | MF_POPUP, (UINT_PTR)settingsmenu, TEXT("Settings"));
+
// get the work bounds
RECT work_bounds, bounds;
SystemParametersInfo(SPI_GETWORKAREA, 0, &work_bounds, 0);
@@ -346,7 +360,7 @@ void consolewin_info::update_menu()
{
disasmbasewin_info::update_menu();
- if (m_devices_menu != nullptr)
+ if (m_devices_menu)
{
// create the image menu
uint32_t cnt = 0;
@@ -432,70 +446,97 @@ void consolewin_info::update_menu()
cnt++;
}
}
+
+ HMENU const menu = GetMenu(window());
+ CheckMenuItem(menu, ID_SAVE_WINDOWS, MF_BYCOMMAND | (debugger().get_save_window_arrangement() ? MF_CHECKED : MF_UNCHECKED));
+ CheckMenuItem(menu, ID_LIGHT_BACKGROUND, MF_BYCOMMAND | ((ui_metrics::THEME_LIGHT_BACKGROUND == metrics().get_color_theme()) ? MF_CHECKED : MF_UNCHECKED));
+ CheckMenuItem(menu, ID_DARK_BACKGROUND, MF_BYCOMMAND | ((ui_metrics::THEME_DARK_BACKGROUND == metrics().get_color_theme()) ? MF_CHECKED : MF_UNCHECKED));
}
bool consolewin_info::handle_command(WPARAM wparam, LPARAM lparam)
{
- if ((HIWORD(wparam) == 0) && (LOWORD(wparam) >= ID_DEVICE_OPTIONS))
+ if (HIWORD(wparam) == 0)
{
- uint32_t const devid = (LOWORD(wparam) - ID_DEVICE_OPTIONS) / DEVOPTION_MAX;
- image_interface_enumerator iter(machine().root_device());
- device_image_interface *const img = iter.byindex(devid);
- if (img != nullptr)
+ if (LOWORD(wparam) >= ID_DEVICE_OPTIONS)
{
- switch ((LOWORD(wparam) - ID_DEVICE_OPTIONS) % DEVOPTION_MAX)
- {
- case DEVOPTION_ITEM:
- // TODO: this is supposed to show a software list item picker - it never worked properly
- return true;
- case DEVOPTION_OPEN :
- open_image_file(*img);
- return true;
- case DEVOPTION_CREATE:
- create_image_file(*img);
- return true;
- case DEVOPTION_CLOSE:
- img->unload();
- return true;
- }
- if (img->device().type() == CASSETTE)
+ uint32_t const devid = (LOWORD(wparam) - ID_DEVICE_OPTIONS) / DEVOPTION_MAX;
+ image_interface_enumerator iter(machine().root_device());
+ device_image_interface *const img = iter.byindex(devid);
+ if (img != nullptr)
{
- auto *const cassette = downcast<cassette_image_device *>(&img->device());
- bool s;
switch ((LOWORD(wparam) - ID_DEVICE_OPTIONS) % DEVOPTION_MAX)
{
- case DEVOPTION_CASSETTE_STOPPAUSE:
- cassette->change_state(CASSETTE_STOPPED, CASSETTE_MASK_UISTATE);
+ case DEVOPTION_ITEM:
+ // TODO: this is supposed to show a software list item picker - it never worked properly
return true;
- case DEVOPTION_CASSETTE_PLAY:
- cassette->change_state(CASSETTE_PLAY, CASSETTE_MASK_UISTATE);
+ case DEVOPTION_OPEN :
+ open_image_file(*img);
return true;
- case DEVOPTION_CASSETTE_RECORD:
- cassette->change_state(CASSETTE_RECORD, CASSETTE_MASK_UISTATE);
+ case DEVOPTION_CREATE:
+ create_image_file(*img);
return true;
- case DEVOPTION_CASSETTE_REWIND:
- cassette->seek(0.0, SEEK_SET); // to start
+ case DEVOPTION_CLOSE:
+ img->unload();
return true;
- case DEVOPTION_CASSETTE_FASTFORWARD:
- cassette->seek(+300.0, SEEK_CUR); // 5 minutes forward or end, whichever comes first
- break;
- case DEVOPTION_CASSETTE_MOTOR:
- s =((cassette->get_state() & CASSETTE_MASK_MOTOR) == CASSETTE_MOTOR_DISABLED);
- cassette->change_state(s ? CASSETTE_MOTOR_ENABLED : CASSETTE_MOTOR_DISABLED, CASSETTE_MASK_MOTOR);
- break;
- case DEVOPTION_CASSETTE_SOUND:
- s =((cassette->get_state() & CASSETTE_MASK_SPEAKER) == CASSETTE_SPEAKER_MUTED);
- cassette->change_state(s ? CASSETTE_SPEAKER_ENABLED : CASSETTE_SPEAKER_MUTED, CASSETTE_MASK_SPEAKER);
- break;
+ }
+ if (img->device().type() == CASSETTE)
+ {
+ auto *const cassette = downcast<cassette_image_device *>(&img->device());
+ bool s;
+ switch ((LOWORD(wparam) - ID_DEVICE_OPTIONS) % DEVOPTION_MAX)
+ {
+ case DEVOPTION_CASSETTE_STOPPAUSE:
+ cassette->change_state(CASSETTE_STOPPED, CASSETTE_MASK_UISTATE);
+ return true;
+ case DEVOPTION_CASSETTE_PLAY:
+ cassette->change_state(CASSETTE_PLAY, CASSETTE_MASK_UISTATE);
+ return true;
+ case DEVOPTION_CASSETTE_RECORD:
+ cassette->change_state(CASSETTE_RECORD, CASSETTE_MASK_UISTATE);
+ return true;
+ case DEVOPTION_CASSETTE_REWIND:
+ cassette->seek(0.0, SEEK_SET); // to start
+ return true;
+ case DEVOPTION_CASSETTE_FASTFORWARD:
+ cassette->seek(+300.0, SEEK_CUR); // 5 minutes forward or end, whichever comes first
+ return true;
+ case DEVOPTION_CASSETTE_MOTOR:
+ s = ((cassette->get_state() & CASSETTE_MASK_MOTOR) == CASSETTE_MOTOR_DISABLED);
+ cassette->change_state(s ? CASSETTE_MOTOR_ENABLED : CASSETTE_MOTOR_DISABLED, CASSETTE_MASK_MOTOR);
+ return true;
+ case DEVOPTION_CASSETTE_SOUND:
+ s = ((cassette->get_state() & CASSETTE_MASK_SPEAKER) == CASSETTE_SPEAKER_MUTED);
+ cassette->change_state(s ? CASSETTE_SPEAKER_ENABLED : CASSETTE_SPEAKER_MUTED, CASSETTE_MASK_SPEAKER);
+ return true;
+ }
}
}
}
+ else switch (LOWORD(wparam))
+ {
+ case ID_SAVE_WINDOWS:
+ debugger().set_save_window_arrangement(!debugger().get_save_window_arrangement());
+ return true;
+ case ID_LIGHT_BACKGROUND:
+ debugger().set_color_theme(ui_metrics::THEME_LIGHT_BACKGROUND);
+ return true;
+ case ID_DARK_BACKGROUND:
+ debugger().set_color_theme(ui_metrics::THEME_DARK_BACKGROUND);
+ return true;
+ }
}
return disasmbasewin_info::handle_command(wparam, lparam);
}
+void consolewin_info::save_configuration_to_node(util::xml::data_node &node)
+{
+ disasmbasewin_info::save_configuration_to_node(node);
+ node.set_attribute_int(ATTR_WINDOW_TYPE, WINDOW_TYPE_CONSOLE);
+}
+
+
void consolewin_info::process_string(std::string const &string)
{
if (string.empty()) // an empty string is a single step
@@ -515,9 +556,11 @@ void consolewin_info::open_image_file(device_image_interface &device)
window(),
CLSID_FileOpenDialog,
true,
- [&device] (std::string_view selection)
+ [this, &device] (std::string_view selection)
{
- device.load(selection);
+ auto [err, message] = device.load(selection);
+ if (err)
+ machine().debugger().console().printf("Error mounting image file: %s\n", !message.empty() ? message : err.message());
});
}
@@ -529,9 +572,11 @@ void consolewin_info::create_image_file(device_image_interface &device)
window(),
CLSID_FileSaveDialog,
false,
- [&device] (std::string_view selection)
+ [this, &device] (std::string_view selection)
{
- device.create(selection, device.device_get_indexed_creatable_format(0), nullptr);
+ auto [err, message] = device.create(selection, device.device_get_indexed_creatable_format(0), nullptr);
+ if (err)
+ machine().debugger().console().printf("Error creating image file: %s\n", !message.empty() ? message : err.message());
});
}
@@ -589,3 +634,5 @@ bool consolewin_info::get_softlist_info(device_image_interface &device)
return passes_tests;
}
+
+} // namespace osd::debugger::win
diff --git a/src/osd/modules/debugger/win/consolewininfo.h b/src/osd/modules/debugger/win/consolewininfo.h
index 2d93895b64d..e79ba667a11 100644
--- a/src/osd/modules/debugger/win/consolewininfo.h
+++ b/src/osd/modules/debugger/win/consolewininfo.h
@@ -15,6 +15,8 @@
#include "disasmbasewininfo.h"
+namespace osd::debugger::win {
+
class consolewin_info : public disasmbasewin_info
{
public:
@@ -27,6 +29,7 @@ protected:
virtual void recompute_children() override;
virtual void update_menu() override;
virtual bool handle_command(WPARAM wparam, LPARAM lparam) override;
+ virtual void save_configuration_to_node(util::xml::data_node &node) override;
private:
enum
@@ -52,8 +55,10 @@ private:
bool get_softlist_info(device_image_interface &img);
device_t *m_current_cpu;
- HMENU m_devices_menu;
+ HMENU m_devices_menu;
std::map<std::string,std::string> slmap;
};
+} // namespace osd::debugger::win
+
#endif // MAME_DEBUGGER_WIN_CONSOLEWININFO_H
diff --git a/src/osd/modules/debugger/win/debugbaseinfo.cpp b/src/osd/modules/debugger/win/debugbaseinfo.cpp
index 1be4f892da7..0de7331cbc8 100644
--- a/src/osd/modules/debugger/win/debugbaseinfo.cpp
+++ b/src/osd/modules/debugger/win/debugbaseinfo.cpp
@@ -10,6 +10,8 @@
#include "debugbaseinfo.h"
+namespace osd::debugger::win {
+
debugbase_info::debugbase_info(debugger_windows_interface &debugger) :
m_debugger(debugger),
m_machine(debugger.machine()),
@@ -60,3 +62,5 @@ void debugbase_info::smart_show_window(HWND wnd, bool show)
if (visible != show)
ShowWindow(wnd, show ? SW_SHOW : SW_HIDE);
}
+
+} // namespace osd::debugger::win
diff --git a/src/osd/modules/debugger/win/debugbaseinfo.h b/src/osd/modules/debugger/win/debugbaseinfo.h
index 15f4b845e7c..da874a6b8fd 100644
--- a/src/osd/modules/debugger/win/debugbaseinfo.h
+++ b/src/osd/modules/debugger/win/debugbaseinfo.h
@@ -13,6 +13,8 @@
#include "debugwin.h"
+namespace osd::debugger::win {
+
class debugbase_info
{
protected:
@@ -35,4 +37,6 @@ private:
bool const &m_waiting_for_debugger;
};
-#endif
+} // namespace osd::debugger::win
+
+#endif // MAME_DEBUGGER_WIN_DEBUGBASEINFO_H
diff --git a/src/osd/modules/debugger/win/debugviewinfo.cpp b/src/osd/modules/debugger/win/debugviewinfo.cpp
index 6965d032dfa..8f3f05c16d2 100644
--- a/src/osd/modules/debugger/win/debugviewinfo.cpp
+++ b/src/osd/modules/debugger/win/debugviewinfo.cpp
@@ -2,7 +2,7 @@
// copyright-holders:Aaron Giles, Vas Crabb
//============================================================
//
-// debugview.c - Win32 debug window handling
+// debugviewinfo.cpp - Win32 debug window handling
//
//============================================================
@@ -12,9 +12,12 @@
#include "debugwininfo.h"
#include "uimetrics.h"
#include "debugger.h"
+
#include "debug/debugcon.h"
#include "debug/debugcpu.h"
+#include "util/xmlfile.h"
+
#include "strconv.h"
#include "winutil.h"
@@ -22,6 +25,8 @@
#include <mmsystem.h>
+namespace osd::debugger::win {
+
// debugger view styles
#define DEBUG_VIEW_STYLE WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN
#define DEBUG_VIEW_STYLE_EX 0
@@ -180,6 +185,18 @@ void debugview_info::send_pagedown()
}
+int debugview_info::source_index() const
+{
+ if (m_view)
+ {
+ debug_view_source const *const source = m_view->source();
+ if (source)
+ return m_view->source_index(*source);
+ }
+ return -1;
+}
+
+
char const *debugview_info::source_name() const
{
if (m_view)
@@ -284,6 +301,56 @@ HWND debugview_info::create_source_combobox(HWND parent, LONG_PTR userdata)
}
+void debugview_info::restore_configuration_from_node(util::xml::data_node const &node)
+{
+ if (m_view->cursor_supported())
+ {
+ util::xml::data_node const *const selection = node.get_child(NODE_WINDOW_SELECTION);
+ if (selection)
+ {
+ debug_view_xy pos = m_view->cursor_position();
+ m_view->set_cursor_visible(0 != selection->get_attribute_int(ATTR_SELECTION_CURSOR_VISIBLE, m_view->cursor_visible() ? 1 : 0));
+ selection->get_attribute_int(ATTR_SELECTION_CURSOR_X, pos.x);
+ selection->get_attribute_int(ATTR_SELECTION_CURSOR_Y, pos.y);
+ m_view->set_cursor_position(pos);
+ }
+ }
+
+ util::xml::data_node const *const scroll = node.get_child(NODE_WINDOW_SCROLL);
+ if (scroll)
+ {
+ debug_view_xy origin = m_view->visible_position();
+ origin.x = scroll->get_attribute_int(ATTR_SCROLL_ORIGIN_X, origin.x * metrics().debug_font_width()) / metrics().debug_font_width();
+ origin.y = scroll->get_attribute_int(ATTR_SCROLL_ORIGIN_Y, origin.y * metrics().debug_font_height()) / metrics().debug_font_height();
+ m_view->set_visible_position(origin);
+ }
+}
+
+
+void debugview_info::save_configuration_to_node(util::xml::data_node &node)
+{
+ if (m_view->cursor_supported())
+ {
+ util::xml::data_node *const selection = node.add_child(NODE_WINDOW_SELECTION, nullptr);
+ if (selection)
+ {
+ debug_view_xy const pos = m_view->cursor_position();
+ selection->set_attribute_int(ATTR_SELECTION_CURSOR_VISIBLE, m_view->cursor_visible() ? 1 : 0);
+ selection->set_attribute_int(ATTR_SELECTION_CURSOR_X, pos.x);
+ selection->set_attribute_int(ATTR_SELECTION_CURSOR_Y, pos.y);
+ }
+ }
+
+ util::xml::data_node *const scroll = node.add_child(NODE_WINDOW_SCROLL, nullptr);
+ if (scroll)
+ {
+ debug_view_xy const origin = m_view->visible_position();
+ scroll->set_attribute_int(ATTR_SCROLL_ORIGIN_X, origin.x * metrics().debug_font_width());
+ scroll->set_attribute_int(ATTR_SCROLL_ORIGIN_Y, origin.y * metrics().debug_font_height());
+ }
+}
+
+
void debugview_info::add_items_to_context_menu(HMENU menu)
{
AppendMenu(menu, MF_ENABLED, ID_CONTEXT_COPY_VISIBLE, TEXT("Copy Visible"));
@@ -433,7 +500,7 @@ void debugview_info::draw_contents(HDC windc)
for (int iter = 0; iter < 2; iter++)
{
COLORREF fgcolor;
- COLORREF bgcolor = RGB(0xff,0xff,0xff);
+ COLORREF bgcolor = metrics().view_colors(DCA_NORMAL).second;
HBRUSH bgbrush = nullptr;
int last_attrib = -1;
TCHAR buffer[256];
@@ -457,20 +524,8 @@ void debugview_info::draw_contents(HDC windc)
{
COLORREF oldbg = bgcolor;
- // pick new background color
- bgcolor = RGB(0xff,0xff,0xff);
- if (viewdata[col].attrib & DCA_VISITED) bgcolor = RGB(0xc6, 0xe2, 0xff);
- if (viewdata[col].attrib & DCA_ANCILLARY) bgcolor = RGB(0xe0,0xe0,0xe0);
- if (viewdata[col].attrib & DCA_SELECTED) bgcolor = RGB(0xff,0x80,0x80);
- if (viewdata[col].attrib & DCA_CURRENT) bgcolor = RGB(0xff,0xff,0x00);
- if ((viewdata[col].attrib & DCA_SELECTED) && (viewdata[col].attrib & DCA_CURRENT)) bgcolor = RGB(0xff,0xc0,0x80);
-
- // pick new foreground color
- fgcolor = RGB(0x00,0x00,0x00);
- if (viewdata[col].attrib & DCA_CHANGED) fgcolor = RGB(0xff,0x00,0x00);
- if (viewdata[col].attrib & DCA_INVALID) fgcolor = RGB(0x00,0x00,0xff);
- if (viewdata[col].attrib & DCA_DISABLED) fgcolor = RGB((GetRValue(fgcolor) + GetRValue(bgcolor)) / 2, (GetGValue(fgcolor) + GetGValue(bgcolor)) / 2, (GetBValue(fgcolor) + GetBValue(bgcolor)) / 2);
- if (viewdata[col].attrib & DCA_COMMENT) fgcolor = RGB(0x00,0x80,0x00);
+ // pick new colors
+ std::tie(fgcolor, bgcolor) = metrics().view_colors(viewdata[col].attrib);
// flush any pending drawing
if (count > 0)
@@ -481,7 +536,7 @@ void debugview_info::draw_contents(HDC windc)
FillRect(dc, &bounds, bgbrush);
if (do_filldown)
{
- COLORREF const filldown = (last_attrib & DCA_ANCILLARY) ? RGB(0xe0,0xe0,0xe0) : RGB(0xff,0xff,0xff);
+ COLORREF const filldown = metrics().view_colors(last_attrib & DCA_ANCILLARY).second;
if (oldbg != filldown)
{
DeleteObject(bgbrush);
@@ -528,7 +583,7 @@ void debugview_info::draw_contents(HDC windc)
FillRect(dc, &bounds, bgbrush);
if (do_filldown)
{
- COLORREF const filldown = (last_attrib & DCA_ANCILLARY) ? RGB(0xe0,0xe0,0xe0) : RGB(0xff,0xff,0xff);
+ COLORREF const filldown = metrics().view_colors(last_attrib & DCA_ANCILLARY).second;
if (bgcolor != filldown)
{
DeleteObject(bgbrush);
@@ -1021,3 +1076,5 @@ void debugview_info::register_window_class()
s_window_class_registered = true;
}
}
+
+} // namespace osd::debugger::win
diff --git a/src/osd/modules/debugger/win/debugviewinfo.h b/src/osd/modules/debugger/win/debugviewinfo.h
index beb5ee66ff0..a009c368441 100644
--- a/src/osd/modules/debugger/win/debugviewinfo.h
+++ b/src/osd/modules/debugger/win/debugviewinfo.h
@@ -17,6 +17,8 @@
#include "debug/debugvw.h"
+namespace osd::debugger::win {
+
class debugview_info : protected debugbase_info
{
public:
@@ -42,6 +44,7 @@ public:
bool cursor_supported() const { return m_view->cursor_supported(); }
bool cursor_visible() const { return m_view->cursor_visible(); }
+ int source_index() const;
char const *source_name() const;
device_t *source_device() const;
bool source_is_visible_cpu() const;
@@ -51,6 +54,9 @@ public:
HWND create_source_combobox(HWND parent, LONG_PTR userdata);
+ virtual void restore_configuration_from_node(util::xml::data_node const &node);
+ virtual void save_configuration_to_node(util::xml::data_node &node);
+
protected:
enum
{
@@ -86,4 +92,6 @@ private:
static bool s_window_class_registered;
};
-#endif
+} // namespace osd::debugger::win
+
+#endif // MAME_DEBUGGER_WIN_DEBUGVIEWINFO_H
diff --git a/src/osd/modules/debugger/win/debugwin.h b/src/osd/modules/debugger/win/debugwin.h
index e999b87334f..52303eefc2c 100644
--- a/src/osd/modules/debugger/win/debugwin.h
+++ b/src/osd/modules/debugger/win/debugwin.h
@@ -10,6 +10,8 @@
#pragma once
+#include "../xmlconfig.h"
+
// standard windows headers
#include <windows.h>
#include <windowsx.h>
@@ -20,6 +22,8 @@
#endif
+namespace osd::debugger::win {
+
class debugview_info;
class debugwin_info;
class ui_metrics;
@@ -33,6 +37,9 @@ public:
virtual running_machine &machine() const = 0;
virtual ui_metrics &metrics() const = 0;
+ virtual void set_color_theme(int index) = 0;
+ virtual bool get_save_window_arrangement() const = 0;
+ virtual void set_save_window_arrangement(bool save) = 0;
virtual bool const &waiting_for_debugger() const = 0;
virtual bool seq_pressed() const = 0;
@@ -45,6 +52,10 @@ public:
virtual void show_all() = 0;
virtual void hide_all() = 0;
+
+ virtual void stagger_window(HWND window, int width, int height) = 0;
};
-#endif
+} // namespace osd::debugger::win
+
+#endif // MAME_DEBUGGER_WIN_DEBUGWIN_H
diff --git a/src/osd/modules/debugger/win/debugwininfo.cpp b/src/osd/modules/debugger/win/debugwininfo.cpp
index fdd486f3e80..8c3275a7549 100644
--- a/src/osd/modules/debugger/win/debugwininfo.cpp
+++ b/src/osd/modules/debugger/win/debugwininfo.cpp
@@ -2,7 +2,7 @@
// copyright-holders:Aaron Giles, Vas Crabb
//============================================================
//
-// debugwininfo.c - Win32 debug window handling
+// debugwininfo.cpp - Win32 debug window handling
//
//============================================================
@@ -14,12 +14,19 @@
#include "debugger.h"
#include "debug/debugcon.h"
#include "debug/debugcpu.h"
+
+#include "util/xmlfile.h"
+
#include "window.h"
#include "winutf8.h"
-
#include "winutil.h"
+
#include "modules/lib/osdobj_common.h"
+#include <cstring>
+
+
+namespace osd::debugger::win {
bool debugwin_info::s_window_class_registered = false;
@@ -37,9 +44,14 @@ debugwin_info::debugwin_info(debugger_windows_interface &debugger, bool is_main_
{
register_window_class();
- m_wnd = win_create_window_ex_utf8(DEBUG_WINDOW_STYLE_EX, "MAMEDebugWindow", title, DEBUG_WINDOW_STYLE,
- 0, 0, 100, 100, std::static_pointer_cast<win_window_info>(osd_common_t::s_window_list.front())->platform_window(), create_standard_menubar(), GetModuleHandleUni(), this);
- if (m_wnd == nullptr)
+ m_wnd = win_create_window_ex_utf8(
+ DEBUG_WINDOW_STYLE_EX, "MAMEDebugWindow", title, DEBUG_WINDOW_STYLE,
+ 0, 0, 100, 100,
+ dynamic_cast<win_window_info &>(*osd_common_t::window_list().front()).platform_window(),
+ create_standard_menubar(),
+ GetModuleHandleUni(),
+ this);
+ if (!m_wnd)
return;
RECT work_bounds;
@@ -54,6 +66,12 @@ debugwin_info::~debugwin_info()
}
+void debugwin_info::redraw()
+{
+ RedrawWindow(m_wnd, nullptr, nullptr, RDW_INVALIDATE | RDW_ALLCHILDREN);
+}
+
+
void debugwin_info::destroy()
{
for (int curview = 0; curview < MAX_VIEWS; curview++)
@@ -251,6 +269,89 @@ bool debugwin_info::handle_key(WPARAM wparam, LPARAM lparam)
}
+void debugwin_info::save_configuration(util::xml::data_node &parentnode)
+{
+ util::xml::data_node *const node = parentnode.add_child(NODE_WINDOW, nullptr);
+ if (node)
+ save_configuration_to_node(*node);
+}
+
+
+void debugwin_info::restore_configuration_from_node(util::xml::data_node const &node)
+{
+ // get current size to use for defaults
+ RECT bounds;
+ POINT origin;
+ origin.x = 0;
+ origin.y = 0;
+ if (!GetClientRect(window(), &bounds) && ClientToScreen(window(), &origin))
+ return;
+
+ // get saved size and adjust for window chrome
+ RECT desired;
+ desired.left = node.get_attribute_int(ATTR_WINDOW_POSITION_X, origin.x);
+ desired.top = node.get_attribute_int(ATTR_WINDOW_POSITION_Y, origin.y);
+ desired.right = desired.left + node.get_attribute_int(ATTR_WINDOW_WIDTH, bounds.right);
+ desired.bottom = desired.top + node.get_attribute_int(ATTR_WINDOW_HEIGHT, bounds.bottom);
+ // TODO: sanity checks...
+ if (!AdjustWindowRectEx(&desired, DEBUG_WINDOW_STYLE, GetMenu(window()) ? TRUE : FALSE, DEBUG_WINDOW_STYLE_EX))
+ return;
+
+ // actually move the window
+ MoveWindow(
+ window(),
+ desired.left,
+ desired.top,
+ desired.right - desired.left,
+ desired.bottom - desired.top,
+ TRUE);
+
+ // restrict to one monitor and avoid toolbars
+ HMONITOR const nearest_monitor = MonitorFromWindow(window(), MONITOR_DEFAULTTONEAREST);
+ if (nearest_monitor)
+ {
+ MONITORINFO info;
+ std::memset(&info, 0, sizeof(info));
+ info.cbSize = sizeof(info);
+ if (GetMonitorInfo(nearest_monitor, &info))
+ {
+ if (desired.right > info.rcWork.right)
+ {
+ desired.left -= desired.right - info.rcWork.right;
+ desired.right = info.rcWork.right;
+ }
+ if (desired.bottom > info.rcWork.bottom)
+ {
+ desired.top -= desired.bottom - info.rcWork.bottom;
+ desired.bottom = info.rcWork.bottom;
+ }
+ if (desired.left < info.rcWork.left)
+ {
+ desired.right += info.rcWork.left - desired.left;
+ desired.left = info.rcWork.left;
+ }
+ if (desired.top < info.rcWork.top)
+ {
+ desired.bottom += info.rcWork.top - desired.top;
+ desired.top = info.rcWork.top;
+ }
+ desired.bottom = std::min(info.rcWork.bottom, desired.bottom);
+ desired.right = std::min(info.rcWork.right, desired.right);
+ MoveWindow(
+ window(),
+ desired.left,
+ desired.top,
+ desired.right - desired.left,
+ desired.bottom - desired.top,
+ TRUE);
+ }
+ }
+
+ // sort out contents
+ recompute_children();
+}
+
+
void debugwin_info::recompute_children()
{
if (m_views[0] != nullptr)
@@ -392,6 +493,22 @@ void debugwin_info::draw_border(HDC dc, RECT &bounds)
}
+void debugwin_info::save_configuration_to_node(util::xml::data_node &node)
+{
+ RECT bounds;
+ POINT origin;
+ origin.x = 0;
+ origin.y = 0;
+ if (GetClientRect(window(), &bounds) && ClientToScreen(window(), &origin))
+ {
+ node.set_attribute_int(ATTR_WINDOW_POSITION_X, origin.x);
+ node.set_attribute_int(ATTR_WINDOW_POSITION_Y, origin.y);
+ node.set_attribute_int(ATTR_WINDOW_WIDTH, bounds.right);
+ node.set_attribute_int(ATTR_WINDOW_HEIGHT, bounds.bottom);
+ }
+}
+
+
void debugwin_info::draw_border(HDC dc, HWND child)
{
RECT bounds;
@@ -620,3 +737,5 @@ void debugwin_info::register_window_class()
s_window_class_registered = true;
}
}
+
+} // namespace osd::debugger::win
diff --git a/src/osd/modules/debugger/win/debugwininfo.h b/src/osd/modules/debugger/win/debugwininfo.h
index 20cea0d477d..f6f37c86955 100644
--- a/src/osd/modules/debugger/win/debugwininfo.h
+++ b/src/osd/modules/debugger/win/debugwininfo.h
@@ -15,10 +15,11 @@
#include "debugbaseinfo.h"
+namespace osd::debugger::win {
+
class debugwin_info : protected debugbase_info
{
public:
- debugwin_info(debugger_windows_interface &debugger, bool is_main_console, LPCSTR title, WNDPROC handler);
virtual ~debugwin_info();
bool is_valid() const { return m_wnd != nullptr; }
@@ -40,6 +41,7 @@ public:
void show() const { smart_show_window(m_wnd, true); }
void hide() const { smart_show_window(m_wnd, false); }
void set_foreground() const { SetForegroundWindow(m_wnd); }
+ void redraw();
void destroy();
virtual bool set_default_focus();
@@ -49,6 +51,9 @@ public:
virtual bool handle_key(WPARAM wparam, LPARAM lparam);
+ void save_configuration(util::xml::data_node &parentnode);
+ virtual void restore_configuration_from_node(util::xml::data_node const &node);
+
protected:
static DWORD const DEBUG_WINDOW_STYLE = (WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN) & (~WS_MINIMIZEBOX & ~WS_MAXIMIZEBOX);
static DWORD const DEBUG_WINDOW_STYLE_EX = 0;
@@ -108,9 +113,15 @@ protected:
ID_CLEAR_LOG,
+ ID_SAVE_WINDOWS,
+ ID_LIGHT_BACKGROUND,
+ ID_DARK_BACKGROUND,
+
ID_DEVICE_OPTIONS // always keep this at the end
};
+ debugwin_info(debugger_windows_interface &debugger, bool is_main_console, LPCSTR title, WNDPROC handler);
+
bool is_main_console() const { return m_is_main_console; }
HWND window() const { return m_wnd; }
uint32_t minwidth() const { return m_minwidth; }
@@ -125,6 +136,8 @@ protected:
void draw_border(HDC dc, RECT &bounds);
void draw_border(HDC dc, HWND child);
+ virtual void save_configuration_to_node(util::xml::data_node &node);
+
std::unique_ptr<debugview_info> m_views[MAX_VIEWS];
private:
@@ -141,12 +154,14 @@ private:
HWND m_wnd;
WNDPROC const m_handler;
- uint32_t m_minwidth, m_maxwidth;
- uint32_t m_minheight, m_maxheight;
+ uint32_t m_minwidth, m_maxwidth;
+ uint32_t m_minheight, m_maxheight;
- uint16_t m_ignore_char_lparam;
+ uint16_t m_ignore_char_lparam;
static bool s_window_class_registered;
};
-#endif
+} // namespace osd::debugger::win
+
+#endif // MAME_DEBUGGER_WIN_DEBUGWININFO_H
diff --git a/src/osd/modules/debugger/win/disasmbasewininfo.cpp b/src/osd/modules/debugger/win/disasmbasewininfo.cpp
index f68a7652c77..48771c4f133 100644
--- a/src/osd/modules/debugger/win/disasmbasewininfo.cpp
+++ b/src/osd/modules/debugger/win/disasmbasewininfo.cpp
@@ -2,7 +2,7 @@
// copyright-holders:Aaron Giles, Vas Crabb
//============================================================
//
-// disasmbasewininfo.c - Win32 debug window handling
+// disasmbasewininfo.cpp - Win32 debug window handling
//
//============================================================
@@ -20,6 +20,8 @@
//#include "winutf8.h"
+namespace osd::debugger::win {
+
disasmbasewin_info::disasmbasewin_info(debugger_windows_interface &debugger, bool is_main_console, LPCSTR title, WNDPROC handler) :
editwin_info(debugger, is_main_console, title, handler)
{
@@ -27,7 +29,7 @@ disasmbasewin_info::disasmbasewin_info(debugger_windows_interface &debugger, boo
return;
m_views[0].reset(new disasmview_info(debugger, *this, window()));
- if ((m_views[0] == nullptr) || !m_views[0]->is_valid())
+ if (!m_views[0] || !m_views[0]->is_valid())
{
m_views[0].reset();
return;
@@ -118,7 +120,7 @@ void disasmbasewin_info::update_menu()
// first find an existing breakpoint at this address
const debug_breakpoint *bp = debug->breakpoint_find(address);
- if (bp == nullptr)
+ if (!bp)
{
ModifyMenu(menu, ID_TOGGLE_BREAKPOINT, MF_BYCOMMAND, ID_TOGGLE_BREAKPOINT, TEXT("Set breakpoint at cursor\tF9"));
ModifyMenu(menu, ID_DISABLE_BREAKPOINT, MF_BYCOMMAND, ID_DISABLE_BREAKPOINT, TEXT("Disable breakpoint at cursor\tShift+F9"));
@@ -131,7 +133,7 @@ void disasmbasewin_info::update_menu()
else
ModifyMenu(menu, ID_DISABLE_BREAKPOINT, MF_BYCOMMAND, ID_DISABLE_BREAKPOINT, TEXT("Enable breakpoint at cursor\tShift+F9"));
}
- bool const available = (bp != nullptr) && (!is_main_console() || dasmview->source_is_visible_cpu());
+ bool const available = bp && (!is_main_console() || dasmview->source_is_visible_cpu());
EnableMenuItem(menu, ID_DISABLE_BREAKPOINT, MF_BYCOMMAND | (available ? MF_ENABLED : MF_GRAYED));
}
else
@@ -174,7 +176,7 @@ bool disasmbasewin_info::handle_command(WPARAM wparam, LPARAM lparam)
{
if (bp == nullptr)
{
- int32_t bpindex = debug->breakpoint_set(address, nullptr, nullptr);
+ int32_t bpindex = debug->breakpoint_set(address);
machine().debugger().console().printf("Breakpoint %X set\n", bpindex);
}
else
@@ -263,3 +265,19 @@ bool disasmbasewin_info::handle_command(WPARAM wparam, LPARAM lparam)
}
return editwin_info::handle_command(wparam, lparam);
}
+
+
+void disasmbasewin_info::restore_configuration_from_node(util::xml::data_node const &node)
+{
+ editwin_info::restore_configuration_from_node(node);
+ m_views[0]->restore_configuration_from_node(node);
+}
+
+
+void disasmbasewin_info::save_configuration_to_node(util::xml::data_node &node)
+{
+ editwin_info::save_configuration_to_node(node);
+ m_views[0]->save_configuration_to_node(node);
+}
+
+} // namespace osd::debugger::win
diff --git a/src/osd/modules/debugger/win/disasmbasewininfo.h b/src/osd/modules/debugger/win/disasmbasewininfo.h
index c22f7f08e78..1ef8245b5a0 100644
--- a/src/osd/modules/debugger/win/disasmbasewininfo.h
+++ b/src/osd/modules/debugger/win/disasmbasewininfo.h
@@ -15,6 +15,8 @@
#include "editwininfo.h"
+namespace osd::debugger::win {
+
class disasmbasewin_info : public editwin_info
{
public:
@@ -22,10 +24,14 @@ public:
virtual ~disasmbasewin_info();
virtual bool handle_key(WPARAM wparam, LPARAM lparam) override;
+ virtual void restore_configuration_from_node(util::xml::data_node const &node) override;
protected:
virtual void update_menu() override;
virtual bool handle_command(WPARAM wparam, LPARAM lparam) override;
+ virtual void save_configuration_to_node(util::xml::data_node &node) override;
};
+} // namespace osd::debugger::win
+
#endif // MAME_DEBUGGER_WIN_DISASMBASEWININFO_H
diff --git a/src/osd/modules/debugger/win/disasmviewinfo.cpp b/src/osd/modules/debugger/win/disasmviewinfo.cpp
index 8884bee5195..3cf9dbd70ff 100644
--- a/src/osd/modules/debugger/win/disasmviewinfo.cpp
+++ b/src/osd/modules/debugger/win/disasmviewinfo.cpp
@@ -2,13 +2,17 @@
// copyright-holders:Aaron Giles, Vas Crabb
//============================================================
//
-// disasmviewinfo.c - Win32 debug window handling
+// disasmviewinfo.cpp - Win32 debug window handling
//
//============================================================
#include "emu.h"
#include "disasmviewinfo.h"
+#include "util/xmlfile.h"
+
+
+namespace osd::debugger::win {
disasmview_info::disasmview_info(debugger_windows_interface &debugger, debugwin_info &owner, HWND parent) :
debugview_info(debugger, owner, parent, DVT_DISASSEMBLY)
@@ -21,6 +25,12 @@ disasmview_info::~disasmview_info()
}
+char const *disasmview_info::expression() const
+{
+ return view<debug_view_disasm>()->expression();
+}
+
+
disasm_right_column disasmview_info::right_column() const
{
return view<debug_view_disasm>()->right_column();
@@ -43,3 +53,23 @@ void disasmview_info::set_right_column(disasm_right_column contents)
{
view<debug_view_disasm>()->set_right_column(contents);
}
+
+
+void disasmview_info::restore_configuration_from_node(util::xml::data_node const &node)
+{
+ debug_view_disasm &dasmview(*view<debug_view_disasm>());
+ dasmview.set_right_column(disasm_right_column(node.get_attribute_int(ATTR_WINDOW_DISASSEMBLY_RIGHT_COLUMN, dasmview.right_column())));
+
+ debugview_info::restore_configuration_from_node(node);
+}
+
+
+void disasmview_info::save_configuration_to_node(util::xml::data_node &node)
+{
+ debugview_info::save_configuration_to_node(node);
+
+ debug_view_disasm &dasmview(*view<debug_view_disasm>());
+ node.set_attribute_int(ATTR_WINDOW_DISASSEMBLY_RIGHT_COLUMN, dasmview.right_column());
+}
+
+} // namespace osd::debugger::win
diff --git a/src/osd/modules/debugger/win/disasmviewinfo.h b/src/osd/modules/debugger/win/disasmviewinfo.h
index 0685d762346..809f92b0c14 100644
--- a/src/osd/modules/debugger/win/disasmviewinfo.h
+++ b/src/osd/modules/debugger/win/disasmviewinfo.h
@@ -17,17 +17,25 @@
#include "debug/dvdisasm.h"
+namespace osd::debugger::win {
+
class disasmview_info : public debugview_info
{
public:
disasmview_info(debugger_windows_interface &debugger, debugwin_info &owner, HWND parent);
virtual ~disasmview_info();
+ char const *expression() const;
disasm_right_column right_column() const;
offs_t selected_address() const;
void set_expression(const std::string &expression);
void set_right_column(disasm_right_column contents);
+
+ virtual void restore_configuration_from_node(util::xml::data_node const &node) override;
+ virtual void save_configuration_to_node(util::xml::data_node &node) override;
};
+} // namespace osd::debugger::win
+
#endif // MAME_DEBUGGER_WIN_DISASMVIEWINFO_H
diff --git a/src/osd/modules/debugger/win/disasmwininfo.cpp b/src/osd/modules/debugger/win/disasmwininfo.cpp
index b94eadbba03..6b38609ace8 100644
--- a/src/osd/modules/debugger/win/disasmwininfo.cpp
+++ b/src/osd/modules/debugger/win/disasmwininfo.cpp
@@ -2,7 +2,7 @@
// copyright-holders:Aaron Giles, Vas Crabb
//============================================================
//
-// disasmwininfo.c - Win32 debug window handling
+// disasmwininfo.cpp - Win32 debug window handling
//
//============================================================
@@ -12,9 +12,14 @@
#include "debugviewinfo.h"
#include "disasmviewinfo.h"
#include "uimetrics.h"
+
+#include "util/xmlfile.h"
+
#include "winutf8.h"
+namespace osd::debugger::win {
+
disasmwin_info::disasmwin_info(debugger_windows_interface &debugger) :
disasmbasewin_info(debugger, false, "Disassembly", nullptr),
m_combownd(nullptr)
@@ -34,11 +39,11 @@ disasmwin_info::disasmwin_info(debugger_windows_interface &debugger) :
update_caption();
// recompute the children once to get the maxwidth
- disasmwin_info::recompute_children();
+ recompute_children();
// position the window and recompute children again
- SetWindowPos(window(), HWND_TOP, 100, 100, maxwidth(), 200, SWP_SHOWWINDOW);
- disasmwin_info::recompute_children();
+ debugger.stagger_window(window(), maxwidth(), 200);
+ recompute_children();
// mark the edit box as the default focus and set it
editwin_info::set_default_focus();
@@ -143,3 +148,34 @@ void disasmwin_info::update_caption()
{
win_set_window_text_utf8(window(), std::string("Disassembly: ").append(m_views[0]->source_name()).c_str());
}
+
+
+void disasmwin_info::restore_configuration_from_node(util::xml::data_node const &node)
+{
+ m_views[0]->set_source_index(node.get_attribute_int(ATTR_WINDOW_DISASSEMBLY_CPU, m_views[0]->source_index()));
+ int const cursource = m_views[0]->source_index();
+ if (0 <= cursource)
+ SendMessage(m_combownd, CB_SETCURSEL, cursource, 0);
+ update_caption();
+
+ util::xml::data_node const *const expr = node.get_child(NODE_WINDOW_EXPRESSION);
+ if (expr && expr->get_value())
+ {
+ set_editwnd_text(expr->get_value());
+ process_string(expr->get_value());
+ }
+
+ disasmbasewin_info::restore_configuration_from_node(node);
+}
+
+
+void disasmwin_info::save_configuration_to_node(util::xml::data_node &node)
+{
+ disasmbasewin_info::save_configuration_to_node(node);
+
+ node.set_attribute_int(ATTR_WINDOW_TYPE, WINDOW_TYPE_DISASSEMBLY_VIEWER);
+ node.set_attribute_int(ATTR_WINDOW_DISASSEMBLY_CPU, m_views[0]->source_index());
+ node.add_child(NODE_WINDOW_EXPRESSION, downcast<disasmview_info *>(m_views[0].get())->expression());
+}
+
+} // namespace osd::debugger::win
diff --git a/src/osd/modules/debugger/win/disasmwininfo.h b/src/osd/modules/debugger/win/disasmwininfo.h
index 71764bab0ef..e5a5ceaaa0e 100644
--- a/src/osd/modules/debugger/win/disasmwininfo.h
+++ b/src/osd/modules/debugger/win/disasmwininfo.h
@@ -15,16 +15,21 @@
#include "disasmbasewininfo.h"
+namespace osd::debugger::win {
+
class disasmwin_info : public disasmbasewin_info
{
public:
disasmwin_info(debugger_windows_interface &debugger);
virtual ~disasmwin_info();
+ virtual void restore_configuration_from_node(util::xml::data_node const &node) override;
+
protected:
virtual void recompute_children() override;
virtual bool handle_command(WPARAM wparam, LPARAM lparam) override;
virtual void draw_contents(HDC dc) override;
+ virtual void save_configuration_to_node(util::xml::data_node &node) override;
private:
virtual void process_string(const std::string &string) override;
@@ -34,4 +39,6 @@ private:
HWND m_combownd;
};
-#endif
+} // namespace osd::debugger::win
+
+#endif // MAME_DEBUGGER_WIN_DISASMWININFO_H
diff --git a/src/osd/modules/debugger/win/editwininfo.cpp b/src/osd/modules/debugger/win/editwininfo.cpp
index d7959afd5f1..c62d2b1f4f7 100644
--- a/src/osd/modules/debugger/win/editwininfo.cpp
+++ b/src/osd/modules/debugger/win/editwininfo.cpp
@@ -2,7 +2,7 @@
// copyright-holders:Aaron Giles, Vas Crabb
//============================================================
//
-// editwininfo.c - Win32 debug window handling
+// editwininfo.cpp - Win32 debug window handling
//
//============================================================
@@ -12,18 +12,22 @@
#include "debugviewinfo.h"
#include "uimetrics.h"
+#include "xmlfile.h"
+
#include "strconv.h"
#include "winutil.h"
+namespace osd::debugger::win {
+
namespace {
constexpr DWORD EDIT_BOX_STYLE = WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL;
constexpr DWORD EDIT_BOX_STYLE_EX = 0;
constexpr int MAX_EDIT_STRING = 256;
-constexpr int HISTORY_LENGTH = 20;
+constexpr int HISTORY_LENGTH = 100;
} // anonymous namespace
@@ -34,7 +38,7 @@ editwin_info::editwin_info(debugger_windows_interface &debugger, bool is_main_co
m_edit_defstr(),
m_original_editproc(nullptr),
m_history(),
- m_last_history(0)
+ m_last_history(-1)
{
if (window() == nullptr)
return;
@@ -105,6 +109,43 @@ void editwin_info::draw_contents(HDC dc)
}
+void editwin_info::restore_configuration_from_node(util::xml::data_node const &node)
+{
+ m_history.clear();
+ util::xml::data_node const *const hist = node.get_child(NODE_WINDOW_HISTORY);
+ if (hist)
+ {
+ util::xml::data_node const *item = hist->get_child(NODE_HISTORY_ITEM);
+ while (item)
+ {
+ if (item->get_value() && *item->get_value())
+ {
+ while (m_history.size() >= HISTORY_LENGTH)
+ m_history.pop_back();
+ m_history.emplace_front(osd::text::to_tstring(item->get_value()));
+ }
+ item = item->get_next_sibling(NODE_HISTORY_ITEM);
+ }
+ }
+ m_last_history = -1;
+
+ debugwin_info::restore_configuration_from_node(node);
+}
+
+
+void editwin_info::save_configuration_to_node(util::xml::data_node &node)
+{
+ debugwin_info::save_configuration_to_node(node);
+
+ util::xml::data_node *const hist = node.add_child(NODE_WINDOW_HISTORY, nullptr);
+ if (hist)
+ {
+ for (auto it = m_history.crbegin(); m_history.crend() != it; ++it)
+ hist->add_child(NODE_HISTORY_ITEM, osd::text::from_tstring(*it).c_str());
+ }
+}
+
+
LRESULT editwin_info::edit_proc(UINT message, WPARAM wparam, LPARAM lparam)
{
// handle a few messages
@@ -194,7 +235,7 @@ LRESULT editwin_info::edit_proc(UINT message, WPARAM wparam, LPARAM lparam)
m_history.pop_back();
m_history.emplace_front(buffer);
}
- m_last_history = m_history.size() - 1;
+ m_last_history = -1;
// process
{
@@ -241,3 +282,5 @@ LRESULT CALLBACK editwin_info::static_edit_proc(HWND wnd, UINT message, WPARAM w
assert(info->m_editwnd == wnd);
return info->edit_proc(message, wparam, lparam);
}
+
+} // namespace osd::debugger::win
diff --git a/src/osd/modules/debugger/win/editwininfo.h b/src/osd/modules/debugger/win/editwininfo.h
index 2156d8ba68d..e2c0ce3c4b8 100644
--- a/src/osd/modules/debugger/win/editwininfo.h
+++ b/src/osd/modules/debugger/win/editwininfo.h
@@ -18,6 +18,8 @@
#include <string>
+namespace osd::debugger::win {
+
class editwin_info : public debugwin_info
{
public:
@@ -28,6 +30,8 @@ public:
virtual bool set_default_focus() override;
+ virtual void restore_configuration_from_node(util::xml::data_node const &node) override;
+
protected:
constexpr static DWORD COMBO_BOX_STYLE = WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | WS_VSCROLL;
constexpr static DWORD COMBO_BOX_STYLE_EX = 0;
@@ -39,6 +43,8 @@ protected:
virtual void draw_contents(HDC dc) override;
+ virtual void save_configuration_to_node(util::xml::data_node &node) override;
+
private:
typedef std::deque<std::basic_string<TCHAR> > history_deque;
@@ -55,4 +61,6 @@ private:
int m_last_history;
};
-#endif
+} // namespace osd::debugger::win
+
+#endif // MAME_DEBUGGER_WIN_EDITWININFO_H
diff --git a/src/osd/modules/debugger/win/logviewinfo.cpp b/src/osd/modules/debugger/win/logviewinfo.cpp
index affd4acd17a..c6bbdfacb88 100644
--- a/src/osd/modules/debugger/win/logviewinfo.cpp
+++ b/src/osd/modules/debugger/win/logviewinfo.cpp
@@ -2,7 +2,7 @@
// copyright-holders:Samuele Zannoli
//============================================================
//
-// logviewinfo.c - Win32 debug log window handling
+// logviewinfo.cpp - Win32 debug log window handling
//
//============================================================
@@ -12,6 +12,8 @@
#include "debug/dvtext.h"
+namespace osd::debugger::win {
+
logview_info::logview_info(debugger_windows_interface &debugger, debugwin_info &owner, HWND parent) :
debugview_info(debugger, owner, parent, DVT_LOG)
{
@@ -27,3 +29,5 @@ void logview_info::clear()
{
view<debug_view_log>()->clear();
}
+
+} // namespace osd::debugger::win
diff --git a/src/osd/modules/debugger/win/logviewinfo.h b/src/osd/modules/debugger/win/logviewinfo.h
index d7ca0df8c9e..15de2a3a095 100644
--- a/src/osd/modules/debugger/win/logviewinfo.h
+++ b/src/osd/modules/debugger/win/logviewinfo.h
@@ -15,6 +15,8 @@
#include "debugviewinfo.h"
+namespace osd::debugger::win {
+
class logview_info : public debugview_info
{
public:
@@ -24,4 +26,6 @@ public:
void clear();
};
+} // namespace osd::debugger::win
+
#endif // MAME_DEBUGGER_WIN_LOGVIEWINFO_H
diff --git a/src/osd/modules/debugger/win/logwininfo.cpp b/src/osd/modules/debugger/win/logwininfo.cpp
index 88b6022aa9a..40515906bb1 100644
--- a/src/osd/modules/debugger/win/logwininfo.cpp
+++ b/src/osd/modules/debugger/win/logwininfo.cpp
@@ -2,7 +2,7 @@
// copyright-holders:Aaron Giles, Vas Crabb
//============================================================
//
-// logwininfo.c - Win32 debug window handling
+// logwininfo.cpp - Win32 debug window handling
//
//============================================================
@@ -12,6 +12,10 @@
#include "debugviewinfo.h"
#include "logviewinfo.h"
+#include "util/xmlfile.h"
+
+
+namespace osd::debugger::win {
logwin_info::logwin_info(debugger_windows_interface &debugger) :
debugwin_info(debugger, false, std::string("Errorlog: ").append(debugger.machine().system().type.fullname()).append(" [").append(debugger.machine().system().name).append("]").c_str(), nullptr)
@@ -41,11 +45,9 @@ logwin_info::logwin_info(debugger_windows_interface &debugger) :
// clamp the min/max size
set_maxwidth(bounds.right - bounds.left);
- // position the window at the bottom-right
- SetWindowPos(window(), HWND_TOP, 100, 100, bounds.right - bounds.left, bounds.bottom - bounds.top, SWP_SHOWWINDOW);
-
- // recompute the children
- debugwin_info::recompute_children();
+ // position the window and recompute children
+ debugger.stagger_window(window(), bounds.right - bounds.left, bounds.bottom - bounds.top);
+ recompute_children();
}
@@ -63,3 +65,12 @@ bool logwin_info::handle_command(WPARAM wparam, LPARAM lparam)
}
return debugwin_info::handle_command(wparam, lparam);
}
+
+
+void logwin_info::save_configuration_to_node(util::xml::data_node &node)
+{
+ debugwin_info::save_configuration_to_node(node);
+ node.set_attribute_int(ATTR_WINDOW_TYPE, WINDOW_TYPE_ERROR_LOG_VIEWER);
+}
+
+} // namespace osd::debugger::win
diff --git a/src/osd/modules/debugger/win/logwininfo.h b/src/osd/modules/debugger/win/logwininfo.h
index b40d184485e..4e822f1b534 100644
--- a/src/osd/modules/debugger/win/logwininfo.h
+++ b/src/osd/modules/debugger/win/logwininfo.h
@@ -15,6 +15,8 @@
#include "debugwininfo.h"
+namespace osd::debugger::win {
+
class logwin_info : public debugwin_info
{
public:
@@ -23,6 +25,9 @@ public:
protected:
virtual bool handle_command(WPARAM wparam, LPARAM lparam) override;
+ virtual void save_configuration_to_node(util::xml::data_node &node) override;
};
-#endif
+} // namespace osd::debugger::win
+
+#endif // MAME_DEBUGGER_WIN_LOGWININFO_H
diff --git a/src/osd/modules/debugger/win/memoryviewinfo.cpp b/src/osd/modules/debugger/win/memoryviewinfo.cpp
index a8891553987..90e23a557a9 100644
--- a/src/osd/modules/debugger/win/memoryviewinfo.cpp
+++ b/src/osd/modules/debugger/win/memoryviewinfo.cpp
@@ -2,16 +2,20 @@
// copyright-holders:Aaron Giles, Vas Crabb
//============================================================
//
-// memoryviewinfo.c - Win32 debug window handling
+// memoryviewinfo.cpp - Win32 debug window handling
//
//============================================================
#include "emu.h"
#include "memoryviewinfo.h"
+#include "util/xmlfile.h"
+
#include "strconv.h"
+namespace osd::debugger::win {
+
memoryview_info::memoryview_info(debugger_windows_interface &debugger, debugwin_info &owner, HWND parent) :
debugview_info(debugger, owner, parent, DVT_MEMORY)
{
@@ -23,6 +27,12 @@ memoryview_info::~memoryview_info()
}
+char const *memoryview_info::expression() const
+{
+ return view<debug_view_memory>()->expression();
+}
+
+
debug_view_memory::data_format memoryview_info::data_format() const
{
return view<debug_view_memory>()->get_data_format();
@@ -83,6 +93,32 @@ void memoryview_info::set_address_radix(int radix)
}
+void memoryview_info::restore_configuration_from_node(util::xml::data_node const &node)
+{
+ debug_view_memory &memview(*view<debug_view_memory>());
+ memview.set_reverse(0 != node.get_attribute_int(ATTR_WINDOW_MEMORY_REVERSE_COLUMNS, memview.reverse() ? 1 : 0));
+ memview.set_physical(0 != node.get_attribute_int(ATTR_WINDOW_MEMORY_ADDRESS_MODE, memview.physical() ? 1 : 0));
+ memview.set_address_radix(node.get_attribute_int(ATTR_WINDOW_MEMORY_ADDRESS_RADIX, memview.address_radix()));
+ memview.set_data_format(debug_view_memory::data_format(node.get_attribute_int(ATTR_WINDOW_MEMORY_DATA_FORMAT, int(memview.get_data_format()))));
+ memview.set_chunks_per_row(node.get_attribute_int(ATTR_WINDOW_MEMORY_ROW_CHUNKS, memview.chunks_per_row()));
+
+ debugview_info::restore_configuration_from_node(node);
+}
+
+
+void memoryview_info::save_configuration_to_node(util::xml::data_node &node)
+{
+ debugview_info::save_configuration_to_node(node);
+
+ debug_view_memory &memview(*view<debug_view_memory>());
+ node.set_attribute_int(ATTR_WINDOW_MEMORY_REVERSE_COLUMNS, memview.reverse() ? 1 : 0);
+ node.set_attribute_int(ATTR_WINDOW_MEMORY_ADDRESS_MODE, memview.physical() ? 1 : 0);
+ node.set_attribute_int(ATTR_WINDOW_MEMORY_ADDRESS_RADIX, memview.address_radix());
+ node.set_attribute_int(ATTR_WINDOW_MEMORY_DATA_FORMAT, int(memview.get_data_format()));
+ node.set_attribute_int(ATTR_WINDOW_MEMORY_ROW_CHUNKS, memview.chunks_per_row());
+}
+
+
void memoryview_info::add_items_to_context_menu(HMENU menu)
{
debugview_info::add_items_to_context_menu(menu);
@@ -107,29 +143,30 @@ void memoryview_info::update_context_menu(HMENU menu)
debug_view_xy const pos = memview.cursor_position();
offs_t const address = space->byte_to_address(memview.addressAtCursorPosition(pos));
offs_t a = address & space->logaddrmask();
- if (!space->device().memory().translate(space->spacenum(), TRANSLATE_READ_DEBUG, a))
+ address_space *tspace;
+ if (!space->device().memory().translate(space->spacenum(), device_memory_interface::TR_READ, a, tspace))
{
m_lastpc = "Bad address";
}
else
{
- uint64_t memval = space->unmap();
- auto dis = space->device().machine().disable_side_effects();
- switch (space->data_width())
+ uint64_t memval = tspace->unmap();
+ auto dis = tspace->device().machine().disable_side_effects();
+ switch (tspace->data_width())
{
- case 8: memval = space->read_byte(a); break;
- case 16: memval = space->read_word_unaligned(a); break;
- case 32: memval = space->read_dword_unaligned(a); break;
- case 64: memval = space->read_qword_unaligned(a); break;
+ case 8: memval = tspace->read_byte(a); break;
+ case 16: memval = tspace->read_word_unaligned(a); break;
+ case 32: memval = tspace->read_dword_unaligned(a); break;
+ case 64: memval = tspace->read_qword_unaligned(a); break;
}
offs_t const pc = source.device()->debug()->track_mem_pc_from_space_address_data(
- space->spacenum(),
+ tspace->spacenum(),
address,
memval);
if (pc != offs_t(-1))
{
- if (space->is_octal())
+ if (tspace->is_octal())
m_lastpc = util::string_format("Address %o written at PC=%o", address, pc);
else
m_lastpc = util::string_format("Address %x written at PC=%x", address, pc);
@@ -167,3 +204,5 @@ void memoryview_info::handle_context_menu(unsigned command)
};
}
+
+} // namespace osd::debugger::win
diff --git a/src/osd/modules/debugger/win/memoryviewinfo.h b/src/osd/modules/debugger/win/memoryviewinfo.h
index ccc451acd3e..514c6c13ec6 100644
--- a/src/osd/modules/debugger/win/memoryviewinfo.h
+++ b/src/osd/modules/debugger/win/memoryviewinfo.h
@@ -18,12 +18,15 @@
#include <string>
+namespace osd::debugger::win {
+
class memoryview_info : public debugview_info
{
public:
memoryview_info(debugger_windows_interface &debugger, debugwin_info &owner, HWND parent);
virtual ~memoryview_info();
+ char const *expression() const;
debug_view_memory::data_format data_format() const;
uint32_t chunks_per_row() const;
bool reverse() const;
@@ -37,6 +40,9 @@ public:
void set_physical(bool physical);
void set_address_radix(int radix);
+ virtual void restore_configuration_from_node(util::xml::data_node const &node) override;
+ virtual void save_configuration_to_node(util::xml::data_node &node) override;
+
protected:
enum
{
@@ -51,4 +57,6 @@ private:
std::string m_lastpc;
};
+} // namespace osd::debugger::win
+
#endif // MAME_DEBUGGER_WIN_MEMORYVIEWINFO_H
diff --git a/src/osd/modules/debugger/win/memorywininfo.cpp b/src/osd/modules/debugger/win/memorywininfo.cpp
index 3ed9b6b9482..92078854e2e 100644
--- a/src/osd/modules/debugger/win/memorywininfo.cpp
+++ b/src/osd/modules/debugger/win/memorywininfo.cpp
@@ -2,7 +2,7 @@
// copyright-holders:Aaron Giles, Vas Crabb
//============================================================
//
-// memorywininfo.c - Win32 debug window handling
+// memorywininfo.cpp - Win32 debug window handling
//
//============================================================
@@ -13,9 +13,13 @@
#include "memoryviewinfo.h"
#include "uimetrics.h"
+#include "util/xmlfile.h"
+
#include "winutf8.h"
+namespace osd::debugger::win {
+
memorywin_info::memorywin_info(debugger_windows_interface &debugger) :
editwin_info(debugger, false, "Memory", nullptr),
m_combownd(nullptr)
@@ -71,11 +75,11 @@ memorywin_info::memorywin_info(debugger_windows_interface &debugger) :
update_caption();
// recompute the children once to get the maxwidth
- memorywin_info::recompute_children();
+ recompute_children();
// position the window and recompute children again
- SetWindowPos(window(), HWND_TOP, 100, 100, maxwidth(), 200, SWP_SHOWWINDOW);
- memorywin_info::recompute_children();
+ debugger.stagger_window(window(), maxwidth(), 200);
+ recompute_children();
// mark the edit box as the default focus and set it
editwin_info::set_default_focus();
@@ -388,3 +392,37 @@ void memorywin_info::update_caption()
{
win_set_window_text_utf8(window(), std::string("Memory: ").append(m_views[0]->source_name()).c_str());
}
+
+
+void memorywin_info::restore_configuration_from_node(util::xml::data_node const &node)
+{
+ m_views[0]->set_source_index(node.get_attribute_int(ATTR_WINDOW_MEMORY_REGION, m_views[0]->source_index()));
+ int const cursource = m_views[0]->source_index();
+ if (0 <= cursource)
+ SendMessage(m_combownd, CB_SETCURSEL, cursource, 0);
+ update_caption();
+
+ util::xml::data_node const *const expr = node.get_child(NODE_WINDOW_EXPRESSION);
+ if (expr && expr->get_value())
+ {
+ set_editwnd_text(expr->get_value());
+ process_string(expr->get_value());
+ }
+
+ editwin_info::restore_configuration_from_node(node);
+
+ m_views[0]->restore_configuration_from_node(node);
+}
+
+
+void memorywin_info::save_configuration_to_node(util::xml::data_node &node)
+{
+ editwin_info::save_configuration_to_node(node);
+
+ node.set_attribute_int(ATTR_WINDOW_TYPE, WINDOW_TYPE_MEMORY_VIEWER);
+ node.set_attribute_int(ATTR_WINDOW_MEMORY_REGION, m_views[0]->source_index());
+ node.add_child(NODE_WINDOW_EXPRESSION, downcast<memoryview_info *>(m_views[0].get())->expression());
+ m_views[0]->save_configuration_to_node(node);
+}
+
+} // namespace osd::debugger::win
diff --git a/src/osd/modules/debugger/win/memorywininfo.h b/src/osd/modules/debugger/win/memorywininfo.h
index e0436605707..a0a4072be0f 100644
--- a/src/osd/modules/debugger/win/memorywininfo.h
+++ b/src/osd/modules/debugger/win/memorywininfo.h
@@ -15,6 +15,8 @@
#include "editwininfo.h"
+namespace osd::debugger::win {
+
class memorywin_info : public editwin_info
{
public:
@@ -22,12 +24,14 @@ public:
virtual ~memorywin_info();
virtual bool handle_key(WPARAM wparam, LPARAM lparam) override;
+ virtual void restore_configuration_from_node(util::xml::data_node const &node) override;
protected:
virtual void recompute_children() override;
virtual void update_menu() override;
virtual bool handle_command(WPARAM wparam, LPARAM lparam) override;
virtual void draw_contents(HDC dc) override;
+ virtual void save_configuration_to_node(util::xml::data_node &node) override;
private:
virtual void process_string(const std::string &string) override;
@@ -37,4 +41,6 @@ private:
HWND m_combownd;
};
-#endif
+} // namespace osd::debugger::win
+
+#endif // MAME_DEBUGGER_WIN_MEMORYWININFO_H
diff --git a/src/osd/modules/debugger/win/pointswininfo.cpp b/src/osd/modules/debugger/win/pointswininfo.cpp
index 93926a697ae..f8fb4f6ce8d 100644
--- a/src/osd/modules/debugger/win/pointswininfo.cpp
+++ b/src/osd/modules/debugger/win/pointswininfo.cpp
@@ -2,7 +2,7 @@
// copyright-holders:Aaron Giles, Vas Crabb
//============================================================
//
-// pointswininfo.c - Win32 debug window handling
+// pointswininfo.cpp - Win32 debug window handling
//
//============================================================
@@ -11,9 +11,13 @@
#include "debugviewinfo.h"
+#include "util/xmlfile.h"
+
#include "winutf8.h"
+namespace osd::debugger::win {
+
pointswin_info::pointswin_info(debugger_windows_interface &debugger) :
debugwin_info(debugger, false, std::string("All Breakpoints").c_str(), nullptr)
{
@@ -44,11 +48,9 @@ pointswin_info::pointswin_info(debugger_windows_interface &debugger) :
// clamp the min/max size
set_maxwidth(bounds.right - bounds.left);
- // position the window at the bottom-right
- SetWindowPos(window(), HWND_TOP, 100, 100, bounds.right - bounds.left, bounds.bottom - bounds.top, SWP_SHOWWINDOW);
-
- // recompute the children
- debugwin_info::recompute_children();
+ // position the window and recompute children
+ debugger.stagger_window(window(), bounds.right - bounds.left, bounds.bottom - bounds.top);
+ recompute_children();
}
@@ -131,3 +133,46 @@ bool pointswin_info::handle_command(WPARAM wparam, LPARAM lparam)
}
return debugwin_info::handle_command(wparam, lparam);
}
+
+
+void pointswin_info::restore_configuration_from_node(util::xml::data_node const &node)
+{
+ switch (node.get_attribute_int(ATTR_WINDOW_POINTS_TYPE, -1))
+ {
+ case 0:
+ SendMessage(window(), WM_COMMAND, ID_SHOW_BREAKPOINTS, 0);
+ break;
+ case 1:
+ SendMessage(window(), WM_COMMAND, ID_SHOW_WATCHPOINTS, 0);
+ break;
+ case 2:
+ SendMessage(window(), WM_COMMAND, ID_SHOW_REGISTERPOINTS, 0);
+ break;
+ }
+
+ debugwin_info::restore_configuration_from_node(node);
+}
+
+
+void pointswin_info::save_configuration_to_node(util::xml::data_node &node)
+{
+ debugwin_info::save_configuration_to_node(node);
+
+ node.set_attribute_int(ATTR_WINDOW_TYPE, WINDOW_TYPE_POINTS_VIEWER);
+ switch (m_views[0]->type())
+ {
+ case DVT_BREAK_POINTS:
+ node.set_attribute_int(ATTR_WINDOW_POINTS_TYPE, 0);
+ break;
+ case DVT_WATCH_POINTS:
+ node.set_attribute_int(ATTR_WINDOW_POINTS_TYPE, 1);
+ break;
+ case DVT_REGISTER_POINTS:
+ node.set_attribute_int(ATTR_WINDOW_POINTS_TYPE, 2);
+ break;
+ default:
+ break;
+ }
+}
+
+} // namespace osd::debugger::win
diff --git a/src/osd/modules/debugger/win/pointswininfo.h b/src/osd/modules/debugger/win/pointswininfo.h
index 4e36155105e..506c68519e8 100644
--- a/src/osd/modules/debugger/win/pointswininfo.h
+++ b/src/osd/modules/debugger/win/pointswininfo.h
@@ -15,6 +15,8 @@
#include "debugwininfo.h"
+namespace osd::debugger::win {
+
class pointswin_info : public debugwin_info
{
public:
@@ -22,10 +24,14 @@ public:
virtual ~pointswin_info();
virtual bool handle_key(WPARAM wparam, LPARAM lparam) override;
+ virtual void restore_configuration_from_node(util::xml::data_node const &node) override;
protected:
virtual void update_menu() override;
virtual bool handle_command(WPARAM wparam, LPARAM lparam) override;
+ virtual void save_configuration_to_node(util::xml::data_node &node) override;
};
-#endif
+} // namespace osd::debugger::win
+
+#endif // MAME_DEBUGGER_WIN_POINTSWININFO_H
diff --git a/src/osd/modules/debugger/win/uimetrics.cpp b/src/osd/modules/debugger/win/uimetrics.cpp
index 67eb045c619..e3d21cda06d 100644
--- a/src/osd/modules/debugger/win/uimetrics.cpp
+++ b/src/osd/modules/debugger/win/uimetrics.cpp
@@ -2,15 +2,48 @@
// copyright-holders:Aaron Giles, Vas Crabb
//============================================================
//
-// uimetrics.c - Win32 debug window handling
+// uimetrics.cpp - Win32 debug window handling
//
//============================================================
#include "emu.h"
#include "uimetrics.h"
+#include "debug/debugvw.h"
+
#include "strconv.h"
+#include <algorithm>
+
+
+namespace osd::debugger::win {
+
+COLORREF const ui_metrics::s_themes[][COLOR_COUNT] = {
+ {
+ RGB(0x00, 0x00, 0x00), // foreground normal
+ RGB(0xff, 0x00, 0x00), // foreground changed
+ RGB(0x00, 0x00, 0xff), // foreground invalid
+ RGB(0x00, 0x80, 0x00), // foreground comment
+ RGB(0xff, 0xff, 0xff), // background normal
+ RGB(0xff, 0x80, 0x80), // background selected
+ RGB(0xe0, 0xe0, 0xe0), // background ancillary
+ RGB(0xff, 0xff, 0x00), // background current
+ RGB(0xff, 0xc0, 0x80), // background current selected
+ RGB(0xc0, 0xe0, 0xff) // background visited
+ },
+ {
+ RGB(0xe0, 0xe0, 0xe0), // foreground normal
+ RGB(0xff, 0x60, 0xff), // foreground changed
+ RGB(0x00, 0xc0, 0xe0), // foreground invalid
+ RGB(0x00, 0xe0, 0x00), // foreground comment
+ RGB(0x00, 0x00, 0x00), // background normal
+ RGB(0xe0, 0x00, 0x00), // background selected
+ RGB(0x40, 0x40, 0x40), // background ancillary
+ RGB(0x00, 0x00, 0xc0), // background current
+ RGB(0xb0, 0x60, 0x00), // background current selected
+ RGB(0x00, 0x40, 0x80) // background visited
+ } };
+
ui_metrics::ui_metrics(osd_options const &options) :
m_debug_font(nullptr),
@@ -22,7 +55,7 @@ ui_metrics::ui_metrics(osd_options const &options) :
{
// create a temporary DC
HDC const temp_dc = GetDC(nullptr);
- if (temp_dc != nullptr)
+ if (temp_dc)
{
float const size = options.debugger_font_size();
char const *const face = options.debugger_font();
@@ -47,6 +80,9 @@ ui_metrics::ui_metrics(osd_options const &options) :
SelectObject(temp_dc, old_font);
ReleaseDC(nullptr, temp_dc);
}
+
+ // set default color theme
+ set_color_theme(THEME_LIGHT_BACKGROUND);
}
@@ -69,3 +105,56 @@ ui_metrics::~ui_metrics()
if (m_debug_font)
DeleteObject(m_debug_font);
}
+
+
+std::pair<COLORREF, COLORREF> ui_metrics::view_colors(u8 attrib) const
+{
+ std::pair<COLORREF, COLORREF> result;
+
+ if (attrib & DCA_SELECTED)
+ result.second = (attrib & DCA_CURRENT) ? m_colors[COLOR_BG_CURRENT_SELECTED] : m_colors[COLOR_BG_SELECTED];
+ else if (attrib & DCA_CURRENT)
+ result.second = m_colors[COLOR_BG_CURRENT];
+ else if (attrib & DCA_ANCILLARY)
+ result.second = m_colors[COLOR_BG_ANCILLARY];
+ else if (attrib & DCA_VISITED)
+ result.second = m_colors[COLOR_BG_VISITED];
+ else
+ result.second = m_colors[COLOR_BG_NORMAL];
+
+ if (DCA_COMMENT & attrib)
+ {
+ result.first = m_colors[COLOR_FG_COMMENT];
+ }
+ else
+ {
+ if (attrib & DCA_INVALID)
+ result.first = m_colors[COLOR_FG_INVALID];
+ else if (attrib & DCA_CHANGED)
+ result.first = m_colors[COLOR_FG_CHANGED];
+ else
+ result.first = m_colors[COLOR_FG_NORMAL];
+
+ if (attrib & DCA_DISABLED)
+ {
+ result.first = RGB(
+ (GetRValue(result.first) + GetRValue(result.second) + 1) >> 1,
+ (GetGValue(result.first) + GetGValue(result.second) + 1) >> 1,
+ (GetBValue(result.first) + GetBValue(result.second) + 1) >> 1);
+ }
+ }
+
+ return result;
+}
+
+
+void ui_metrics::set_color_theme(int index)
+{
+ if ((0 <= index) && (std::size(s_themes) > index))
+ {
+ std::copy(std::begin(s_themes[index]), std::end(s_themes[index]), m_colors);
+ m_color_theme = index;
+ }
+}
+
+} // namespace osd::debugger::win
diff --git a/src/osd/modules/debugger/win/uimetrics.h b/src/osd/modules/debugger/win/uimetrics.h
index 2687ada036c..e45ae810fa6 100644
--- a/src/osd/modules/debugger/win/uimetrics.h
+++ b/src/osd/modules/debugger/win/uimetrics.h
@@ -12,13 +12,22 @@
#include "debugwin.h"
-
#include "modules/lib/osdobj_common.h"
+#include <utility>
+
+
+namespace osd::debugger::win {
class ui_metrics
{
public:
+ enum
+ {
+ THEME_LIGHT_BACKGROUND,
+ THEME_DARK_BACKGROUND
+ };
+
ui_metrics(osd_options const &options);
ui_metrics(ui_metrics const &that);
~ui_metrics();
@@ -31,7 +40,28 @@ public:
uint32_t hscroll_height() const { return m_hscroll_height; }
uint32_t vscroll_width() const { return m_vscroll_width; }
+ std::pair<COLORREF, COLORREF> view_colors(u8 attrib) const;
+ int get_color_theme() const { return m_color_theme; }
+ void set_color_theme(int index);
+
private:
+ enum
+ {
+ COLOR_FG_NORMAL,
+ COLOR_FG_CHANGED,
+ COLOR_FG_INVALID,
+ COLOR_FG_COMMENT,
+
+ COLOR_BG_NORMAL,
+ COLOR_BG_SELECTED,
+ COLOR_BG_ANCILLARY,
+ COLOR_BG_CURRENT,
+ COLOR_BG_CURRENT_SELECTED,
+ COLOR_BG_VISITED,
+
+ COLOR_COUNT
+ };
+
HFONT m_debug_font;
uint32_t m_debug_font_height;
uint32_t m_debug_font_width;
@@ -39,6 +69,13 @@ private:
uint32_t const m_hscroll_height;
uint32_t const m_vscroll_width;
+
+ COLORREF m_colors[COLOR_COUNT];
+ int m_color_theme;
+
+ static COLORREF const s_themes[][COLOR_COUNT];
};
-#endif
+} // namespace osd::debugger::win
+
+#endif // MAME_DEBUGGER_WIN_UIMETRICS_H
diff --git a/src/osd/modules/debugger/xmlconfig.cpp b/src/osd/modules/debugger/xmlconfig.cpp
new file mode 100644
index 00000000000..7e702938bf8
--- /dev/null
+++ b/src/osd/modules/debugger/xmlconfig.cpp
@@ -0,0 +1,53 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+
+#include "xmlconfig.h"
+
+namespace osd::debugger {
+
+char const *const NODE_WINDOW = "window";
+char const *const NODE_COLORS = "colors";
+
+char const *const NODE_WINDOW_SPLITS = "splits";
+char const *const NODE_WINDOW_SELECTION = "selection";
+char const *const NODE_WINDOW_SCROLL = "scroll";
+char const *const NODE_WINDOW_EXPRESSION = "expression";
+char const *const NODE_WINDOW_HISTORY = "history";
+
+char const *const NODE_HISTORY_ITEM = "item";
+
+char const *const ATTR_DEBUGGER_SAVE_WINDOWS = "savewindows";
+
+char const *const ATTR_WINDOW_TYPE = "type";
+char const *const ATTR_WINDOW_POSITION_X = "position_x";
+char const *const ATTR_WINDOW_POSITION_Y = "position_y";
+char const *const ATTR_WINDOW_WIDTH = "size_x";
+char const *const ATTR_WINDOW_HEIGHT = "size_y";
+
+char const *const ATTR_WINDOW_MEMORY_REGION = "memoryregion";
+char const *const ATTR_WINDOW_MEMORY_REVERSE_COLUMNS = "reverse";
+char const *const ATTR_WINDOW_MEMORY_ADDRESS_MODE = "addressmode";
+char const *const ATTR_WINDOW_MEMORY_ADDRESS_RADIX = "addressradix";
+char const *const ATTR_WINDOW_MEMORY_DATA_FORMAT = "dataformat";
+char const *const ATTR_WINDOW_MEMORY_ROW_CHUNKS = "rowchunks";
+
+char const *const ATTR_WINDOW_DISASSEMBLY_CPU = "cpu";
+char const *const ATTR_WINDOW_DISASSEMBLY_RIGHT_COLUMN = "rightbar";
+
+char const *const ATTR_WINDOW_POINTS_TYPE = "bwtype";
+
+char const *const ATTR_WINDOW_DEVICE_TAG = "device-tag";
+
+char const *const ATTR_COLORS_THEME = "theme";
+
+char const *const ATTR_SPLITS_CONSOLE_STATE = "state";
+char const *const ATTR_SPLITS_CONSOLE_DISASSEMBLY = "disassembly";
+
+char const *const ATTR_SELECTION_CURSOR_VISIBLE = "visible";
+char const *const ATTR_SELECTION_CURSOR_X = "start_x";
+char const *const ATTR_SELECTION_CURSOR_Y = "start_y";
+
+char const *const ATTR_SCROLL_ORIGIN_X = "position_x";
+char const *const ATTR_SCROLL_ORIGIN_Y = "position_y";
+
+} // namespace osd::debugger
diff --git a/src/osd/modules/debugger/xmlconfig.h b/src/osd/modules/debugger/xmlconfig.h
new file mode 100644
index 00000000000..ae5cdf8393c
--- /dev/null
+++ b/src/osd/modules/debugger/xmlconfig.h
@@ -0,0 +1,71 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+#ifndef MAME_OSD_DEBUGGER_XMLCONFIG_H
+#define MAME_OSD_DEBUGGER_XMLCONFIG_H
+
+#pragma once
+
+namespace osd::debugger {
+
+// Qt debugger started using these numeric types - they should be switched to mnemonics at some point
+enum
+{
+
+WINDOW_TYPE_CONSOLE = 1,
+WINDOW_TYPE_MEMORY_VIEWER,
+WINDOW_TYPE_DISASSEMBLY_VIEWER,
+WINDOW_TYPE_ERROR_LOG_VIEWER,
+WINDOW_TYPE_POINTS_VIEWER,
+WINDOW_TYPE_DEVICES_VIEWER,
+WINDOW_TYPE_DEVICE_INFO_VIEWER
+
+};
+
+extern char const *const NODE_WINDOW;
+extern char const *const NODE_COLORS;
+
+extern char const *const NODE_WINDOW_SPLITS;
+extern char const *const NODE_WINDOW_SELECTION;
+extern char const *const NODE_WINDOW_SCROLL;
+extern char const *const NODE_WINDOW_EXPRESSION;
+extern char const *const NODE_WINDOW_HISTORY;
+
+extern char const *const NODE_HISTORY_ITEM;
+
+extern char const *const ATTR_DEBUGGER_SAVE_WINDOWS;
+
+extern char const *const ATTR_WINDOW_TYPE;
+extern char const *const ATTR_WINDOW_POSITION_X;
+extern char const *const ATTR_WINDOW_POSITION_Y;
+extern char const *const ATTR_WINDOW_WIDTH;
+extern char const *const ATTR_WINDOW_HEIGHT;
+
+extern char const *const ATTR_WINDOW_MEMORY_REGION;
+extern char const *const ATTR_WINDOW_MEMORY_REVERSE_COLUMNS;
+extern char const *const ATTR_WINDOW_MEMORY_ADDRESS_MODE;
+extern char const *const ATTR_WINDOW_MEMORY_ADDRESS_RADIX;
+extern char const *const ATTR_WINDOW_MEMORY_DATA_FORMAT;
+extern char const *const ATTR_WINDOW_MEMORY_ROW_CHUNKS;
+
+extern char const *const ATTR_WINDOW_DISASSEMBLY_CPU;
+extern char const *const ATTR_WINDOW_DISASSEMBLY_RIGHT_COLUMN;
+
+extern char const *const ATTR_WINDOW_POINTS_TYPE;
+
+extern char const *const ATTR_WINDOW_DEVICE_TAG;
+
+extern char const *const ATTR_COLORS_THEME;
+
+extern char const *const ATTR_SPLITS_CONSOLE_STATE;
+extern char const *const ATTR_SPLITS_CONSOLE_DISASSEMBLY;
+
+extern char const *const ATTR_SELECTION_CURSOR_VISIBLE;
+extern char const *const ATTR_SELECTION_CURSOR_X;
+extern char const *const ATTR_SELECTION_CURSOR_Y;
+
+extern char const *const ATTR_SCROLL_ORIGIN_X;
+extern char const *const ATTR_SCROLL_ORIGIN_Y;
+
+} // namespace osd::debugger
+
+#endif // MAME_OSD_DEBUGGER_XMLCONFIG_H
diff --git a/src/osd/modules/diagnostics/diagnostics_win32.cpp b/src/osd/modules/diagnostics/diagnostics_win32.cpp
index b80bbdfcdba..660d4d91682 100644
--- a/src/osd/modules/diagnostics/diagnostics_win32.cpp
+++ b/src/osd/modules/diagnostics/diagnostics_win32.cpp
@@ -169,8 +169,8 @@ bool stack_walker::s_initialized = false;
// stack_walker - constructor
//-------------------------------------------------
-stack_walker::stack_walker()
- : m_process(GetCurrentProcess()),
+stack_walker::stack_walker() :
+ m_process(GetCurrentProcess()),
m_thread(GetCurrentThread()),
m_first(true)
{
@@ -216,14 +216,18 @@ bool stack_walker::reset()
m_stackframe.AddrStack.Mode = AddrModeFlat;
// pull architecture-specific fields from the context
-#ifdef PTR64
+#if defined(__x86_64__) || defined(_M_X64)
m_stackframe.AddrPC.Offset = m_context.Rip;
m_stackframe.AddrFrame.Offset = m_context.Rsp;
m_stackframe.AddrStack.Offset = m_context.Rsp;
-#else
+#elif defined(__i386__) || defined(_M_IX86)
m_stackframe.AddrPC.Offset = m_context.Eip;
m_stackframe.AddrFrame.Offset = m_context.Ebp;
m_stackframe.AddrStack.Offset = m_context.Esp;
+#elif defined(__aarch64__) || defined(_M_ARM64)
+ m_stackframe.AddrPC.Offset = m_context.Pc;
+ m_stackframe.AddrFrame.Offset = m_context.Fp;
+ m_stackframe.AddrStack.Offset = m_context.Sp;
#endif
return true;
}
@@ -242,14 +246,18 @@ void stack_walker::reset(CONTEXT &initial, HANDLE thread)
m_stackframe.AddrStack.Mode = AddrModeFlat;
// pull architecture-specific fields from the context
-#ifdef PTR64
+#if defined(__x86_64__) || defined(_M_X64)
m_stackframe.AddrPC.Offset = m_context.Rip;
m_stackframe.AddrFrame.Offset = m_context.Rsp;
m_stackframe.AddrStack.Offset = m_context.Rsp;
-#else
+#elif defined(__i386__) || defined(_M_IX86)
m_stackframe.AddrPC.Offset = m_context.Eip;
m_stackframe.AddrFrame.Offset = m_context.Ebp;
m_stackframe.AddrStack.Offset = m_context.Esp;
+#elif defined(__aarch64__) || defined(_M_ARM64)
+ m_stackframe.AddrPC.Offset = m_context.Pc;
+ m_stackframe.AddrFrame.Offset = m_context.Fp;
+ m_stackframe.AddrStack.Offset = m_context.Sp;
#endif
}
@@ -263,10 +271,14 @@ bool stack_walker::unwind()
// if we were able to initialize, then we have everything we need
if (s_initialized)
{
-#ifdef PTR64
+#if defined(__x86_64__) || defined(_M_X64)
return (*m_stack_walk_64)(IMAGE_FILE_MACHINE_AMD64, m_process, m_thread, &m_stackframe, &m_context, nullptr, *m_sym_function_table_access_64, *m_sym_get_module_base_64, nullptr);
-#else
+#elif defined(__i386__) || defined(_M_IX86)
return (*m_stack_walk_64)(IMAGE_FILE_MACHINE_I386, m_process, m_thread, &m_stackframe, &m_context, nullptr, *m_sym_function_table_access_64, *m_sym_get_module_base_64, nullptr);
+#elif defined(__aarch64__) || defined(_M_ARM64)
+ return (*m_stack_walk_64)(IMAGE_FILE_MACHINE_ARM64, m_process, m_thread, &m_stackframe, &m_context, nullptr, *m_sym_function_table_access_64, *m_sym_get_module_base_64, nullptr);
+#else
+ return false;
#endif
}
@@ -289,8 +301,8 @@ bool stack_walker::unwind()
// symbol_manager - constructor
//-------------------------------------------------
-symbol_manager::symbol_manager(const char *argv0)
- : m_mapfile(argv0),
+symbol_manager::symbol_manager(const char *argv0) :
+ m_mapfile(argv0),
m_symfile(argv0),
m_process(GetCurrentProcess()),
m_last_base(0),
@@ -300,7 +312,7 @@ symbol_manager::symbol_manager(const char *argv0)
// compute the name of the mapfile
int extoffs = m_mapfile.find_last_of('.');
if (extoffs != -1)
- m_mapfile.substr(0, extoffs);
+ m_mapfile = m_mapfile.substr(0, extoffs);
m_mapfile.append(".map");
// and the name of the symfile
@@ -509,6 +521,9 @@ bool symbol_manager::parse_sym_line(const char *line, uintptr_t &address, std::s
// first look for a (ty) entry
const char *type = strstr(line, "(ty 20)");
if (type == nullptr)
+ type = strstr(line, "(ty 20)");
+
+ if (type == nullptr)
return false;
// scan forward in the line to find the address
@@ -650,8 +665,8 @@ uintptr_t symbol_manager::get_text_section_base(ULONG &size)
// sampling_profiler - constructor
//-------------------------------------------------
-sampling_profiler::sampling_profiler(uint32_t max_seconds, uint8_t stack_depth = 0)
- : m_target_thread(nullptr),
+sampling_profiler::sampling_profiler(uint32_t max_seconds, uint8_t stack_depth = 0) :
+ m_target_thread(nullptr),
m_thread(nullptr),
m_thread_id(0),
m_thread_exit(false),
@@ -994,7 +1009,7 @@ private:
// print the state of the CPU
fprintf(stderr, "-----------------------------------------------------\n");
-#ifdef PTR64
+#if defined(__x86_64__) || defined(_M_X64)
fprintf(stderr, "RAX=%p RBX=%p RCX=%p RDX=%p\n",
(void *)info->ContextRecord->Rax,
(void *)info->ContextRecord->Rbx,
@@ -1015,7 +1030,7 @@ private:
(void *)info->ContextRecord->R13,
(void *)info->ContextRecord->R14,
(void *)info->ContextRecord->R15);
-#else
+#elif defined(__i386__) || defined(_M_IX86)
fprintf(stderr, "EAX=%p EBX=%p ECX=%p EDX=%p\n",
(void *)info->ContextRecord->Eax,
(void *)info->ContextRecord->Ebx,
@@ -1026,6 +1041,47 @@ private:
(void *)info->ContextRecord->Edi,
(void *)info->ContextRecord->Ebp,
(void *)info->ContextRecord->Esp);
+#elif defined(__aarch64__) || defined(_M_ARM64)
+ fprintf(stderr, " X0=%p X1=%p X2=%p X3=%p\n",
+ (void *)info->ContextRecord->X0,
+ (void *)info->ContextRecord->X1,
+ (void *)info->ContextRecord->X2,
+ (void *)info->ContextRecord->X3);
+ fprintf(stderr, " X4=%p X5=%p X6=%p X7=%p\n",
+ (void *)info->ContextRecord->X4,
+ (void *)info->ContextRecord->X5,
+ (void *)info->ContextRecord->X6,
+ (void *)info->ContextRecord->X7);
+ fprintf(stderr, " X8=%p X9=%p X10=%p X11=%p\n",
+ (void *)info->ContextRecord->X8,
+ (void *)info->ContextRecord->X9,
+ (void *)info->ContextRecord->X10,
+ (void *)info->ContextRecord->X11);
+ fprintf(stderr, "X12=%p X13=%p X14=%p X15=%p\n",
+ (void *)info->ContextRecord->X12,
+ (void *)info->ContextRecord->X13,
+ (void *)info->ContextRecord->X14,
+ (void *)info->ContextRecord->X15);
+ fprintf(stderr, "X16=%p X17=%p X18=%p X19=%p\n",
+ (void *)info->ContextRecord->X16,
+ (void *)info->ContextRecord->X17,
+ (void *)info->ContextRecord->X18,
+ (void *)info->ContextRecord->X19);
+ fprintf(stderr, "X20=%p X21=%p X22=%p X23=%p\n",
+ (void *)info->ContextRecord->X20,
+ (void *)info->ContextRecord->X21,
+ (void *)info->ContextRecord->X22,
+ (void *)info->ContextRecord->X23);
+ fprintf(stderr, "X24=%p X25=%p X26=%p X27=%p\n",
+ (void *)info->ContextRecord->X24,
+ (void *)info->ContextRecord->X25,
+ (void *)info->ContextRecord->X26,
+ (void *)info->ContextRecord->X27);
+ fprintf(stderr, "X28=%p FP=%p LR=%p SP=%p\n",
+ (void *)info->ContextRecord->X28,
+ (void *)info->ContextRecord->Fp,
+ (void *)info->ContextRecord->Lr,
+ (void *)info->ContextRecord->Sp);
#endif
// reprint the actual exception address
diff --git a/src/osd/modules/file/posixdir.cpp b/src/osd/modules/file/posixdir.cpp
index efe68c2eda9..282a58acfc9 100644
--- a/src/osd/modules/file/posixdir.cpp
+++ b/src/osd/modules/file/posixdir.cpp
@@ -193,7 +193,7 @@ bool posix_directory::open_impl(std::string const &dirname)
{
assert(!m_fd);
- m_path = osd_subst_env(dirname);
+ m_path = dirname;
m_fd.reset(::opendir(m_path.c_str()));
return bool(m_fd);
}
diff --git a/src/osd/modules/file/posixfile.cpp b/src/osd/modules/file/posixfile.cpp
index 3b0e7b4b537..c5ce8bf7b4e 100644
--- a/src/osd/modules/file/posixfile.cpp
+++ b/src/osd/modules/file/posixfile.cpp
@@ -257,8 +257,6 @@ std::error_condition osd_file::open(std::string const &path, std::uint32_t openf
for (auto it = dst.begin(); it != dst.end(); ++it)
*it = (INVPATHSEPCH == *it) ? PATHSEPCH : *it;
#endif
- try { dst = osd_subst_env(dst); }
- catch (...) { return std::errc::not_enough_memory; }
// attempt to open the file
int fd = -1;
diff --git a/src/osd/modules/file/winfile.cpp b/src/osd/modules/file/winfile.cpp
index 199537bbdee..84c754cdd6f 100644
--- a/src/osd/modules/file/winfile.cpp
+++ b/src/osd/modules/file/winfile.cpp
@@ -62,12 +62,12 @@ public:
LARGE_INTEGER largeOffset;
largeOffset.QuadPart = offset;
if (!SetFilePointerEx(m_handle, largeOffset, nullptr, FILE_BEGIN))
- return win_error_to_file_error(GetLastError());
+ return win_error_to_error_condition(GetLastError());
// then perform the read
DWORD result = 0;
if (!ReadFile(m_handle, buffer, length, &result, nullptr))
- return win_error_to_file_error(GetLastError());
+ return win_error_to_error_condition(GetLastError());
actual = result;
return std::error_condition();
@@ -79,12 +79,12 @@ public:
LARGE_INTEGER largeOffset;
largeOffset.QuadPart = offset;
if (!SetFilePointerEx(m_handle, largeOffset, nullptr, FILE_BEGIN))
- return win_error_to_file_error(GetLastError());
+ return win_error_to_error_condition(GetLastError());
// then perform the write
DWORD result = 0;
if (!WriteFile(m_handle, buffer, length, &result, nullptr))
- return win_error_to_file_error(GetLastError());
+ return win_error_to_error_condition(GetLastError());
actual = result;
return std::error_condition();
@@ -96,11 +96,11 @@ public:
LARGE_INTEGER largeOffset;
largeOffset.QuadPart = offset;
if (!SetFilePointerEx(m_handle, largeOffset, nullptr, FILE_BEGIN))
- return win_error_to_file_error(GetLastError());
+ return win_error_to_error_condition(GetLastError());
// then perform the truncation
if (!SetEndOfFile(m_handle))
- return win_error_to_file_error(GetLastError());
+ return win_error_to_error_condition(GetLastError());
else
return std::error_condition();
}
@@ -161,12 +161,8 @@ DWORD create_path_recursive(TCHAR *path)
// osd_open
//============================================================
-std::error_condition osd_file::open(std::string const &orig_path, uint32_t openflags, ptr &file, std::uint64_t &filesize) noexcept
+std::error_condition osd_file::open(std::string const &path, uint32_t openflags, ptr &file, std::uint64_t &filesize) noexcept
{
- std::string path;
- try { path = osd_subst_env(orig_path); }
- catch (...) { return std::errc::not_enough_memory; }
-
if (win_check_socket_path(path))
return win_open_socket(path, openflags, file, filesize);
else if (win_check_ptty_path(path))
@@ -229,7 +225,7 @@ std::error_condition osd_file::open(std::string const &orig_path, uint32_t openf
// if we still failed, clean up and free
if (INVALID_HANDLE_VALUE == h)
- return win_error_to_file_error(err);
+ return win_error_to_error_condition(err);
}
// get the file size
@@ -259,7 +255,7 @@ std::error_condition osd_file::open(std::string const &orig_path, uint32_t openf
if (NO_ERROR != err)
{
CloseHandle(h);
- return win_error_to_file_error(err);
+ return win_error_to_error_condition(err);
}
}
@@ -299,7 +295,7 @@ std::error_condition osd_file::remove(std::string const &filename) noexcept
std::error_condition filerr;
if (!DeleteFile(tempstr.c_str()))
- filerr = win_error_to_file_error(GetLastError());
+ filerr = win_error_to_error_condition(GetLastError());
return filerr;
}
@@ -415,12 +411,12 @@ std::error_condition osd_get_full_path(std::string &dst, std::string const &path
std::wstring const w_path(osd::text::to_wstring(path));
DWORD const length(GetFullPathNameW(w_path.c_str(), 0, nullptr, nullptr));
if (!length)
- return win_error_to_file_error(GetLastError());
+ return win_error_to_error_condition(GetLastError());
// allocate a buffer and get the canonical path
std::unique_ptr<wchar_t []> buffer(std::make_unique<wchar_t []>(length));
if (!GetFullPathNameW(w_path.c_str(), length, buffer.get(), nullptr))
- return win_error_to_file_error(GetLastError());
+ return win_error_to_error_condition(GetLastError());
// convert the result back to UTF-8
osd::text::from_wstring(dst, buffer.get());
@@ -534,69 +530,3 @@ bool osd_is_valid_filepath_char(char32_t uchar) noexcept
&& !(uchar >= '\x7F' && uchar <= '\x9F')
&& uchar_isvalid(uchar);
}
-
-
-
-//============================================================
-// win_error_to_file_error
-//============================================================
-
-std::error_condition win_error_to_file_error(DWORD error) noexcept
-{
- // TODO: work out if there's a better way to do this
- switch (error)
- {
- case ERROR_SUCCESS:
- return std::error_condition();
-
- case ERROR_INVALID_HANDLE:
- return std::errc::bad_file_descriptor;
-
- case ERROR_OUTOFMEMORY:
- return std::errc::not_enough_memory;
-
- case ERROR_NOT_SUPPORTED:
- return std::errc::not_supported;
-
- case ERROR_FILE_NOT_FOUND:
- case ERROR_PATH_NOT_FOUND:
- case ERROR_INVALID_NAME:
- return std::errc::no_such_file_or_directory;
-
- case ERROR_FILENAME_EXCED_RANGE:
- return std::errc::filename_too_long;
-
- case ERROR_ACCESS_DENIED:
- case ERROR_SHARING_VIOLATION:
- return std::errc::permission_denied;
-
- case ERROR_ALREADY_EXISTS:
- return std::errc::file_exists;
-
- case ERROR_TOO_MANY_OPEN_FILES:
- return std::errc::too_many_files_open;
-
- case ERROR_WRITE_FAULT:
- case ERROR_READ_FAULT:
- return std::errc::io_error;
-
- case ERROR_HANDLE_DISK_FULL:
- case ERROR_DISK_FULL:
- return std::errc::no_space_on_device;
-
- case ERROR_PATH_BUSY:
- case ERROR_BUSY:
- return std::errc::device_or_resource_busy;
-
- case ERROR_FILE_TOO_LARGE:
- return std::errc::file_too_large;
-
- case ERROR_INVALID_ACCESS:
- case ERROR_NEGATIVE_SEEK:
- case ERROR_BAD_ARGUMENTS:
- return std::errc::invalid_argument;
-
- default:
- return std::error_condition(error, std::system_category());
- }
-}
diff --git a/src/osd/modules/file/winfile.h b/src/osd/modules/file/winfile.h
index 83f0814733d..90cf6e69a60 100644
--- a/src/osd/modules/file/winfile.h
+++ b/src/osd/modules/file/winfile.h
@@ -32,6 +32,4 @@ std::error_condition win_open_socket(std::string const &path, std::uint32_t open
bool win_check_ptty_path(std::string const &path) noexcept;
std::error_condition win_open_ptty(std::string const &path, std::uint32_t openflags, osd_file::ptr &file, std::uint64_t &filesize) noexcept;
-std::error_condition win_error_to_file_error(DWORD error) noexcept;
-
#endif // MAME_OSD_MODULES_FILE_WINFILE_H
diff --git a/src/osd/modules/file/winptty.cpp b/src/osd/modules/file/winptty.cpp
index 7feeacce137..9aac0c5a990 100644
--- a/src/osd/modules/file/winptty.cpp
+++ b/src/osd/modules/file/winptty.cpp
@@ -8,11 +8,11 @@
#include "winutil.h"
#include <cassert>
-
-#include <windows.h>
#include <cstdlib>
#include <cstring>
+#include <windows.h>
+
namespace {
@@ -44,7 +44,7 @@ public:
{
DWORD bytes_read;
if (!ReadFile(m_handle, buffer, count, &bytes_read, nullptr))
- return win_error_to_file_error(GetLastError());
+ return win_error_to_error_condition(GetLastError());
actual = bytes_read;
return std::error_condition();
@@ -54,7 +54,7 @@ public:
{
DWORD bytes_written;
if (!WriteFile(m_handle, buffer, count, &bytes_written, nullptr))
- return win_error_to_file_error(GetLastError());
+ return win_error_to_error_condition(GetLastError());
actual = bytes_written;
return std::error_condition();
@@ -99,7 +99,7 @@ std::error_condition win_open_ptty(std::string const &path, std::uint32_t openfl
if (openflags & OPEN_FLAG_CREATE)
pipe = CreateNamedPipe(t_name.c_str(), PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_NOWAIT, 1, 32, 32, 0, nullptr);
if (INVALID_HANDLE_VALUE == pipe)
- return win_error_to_file_error(GetLastError());
+ return win_error_to_error_condition(GetLastError());
}
else
{
diff --git a/src/osd/modules/file/winrtfile.cpp b/src/osd/modules/file/winrtfile.cpp
index 3de1c19605d..5053f6e0199 100644
--- a/src/osd/modules/file/winrtfile.cpp
+++ b/src/osd/modules/file/winrtfile.cpp
@@ -160,12 +160,8 @@ DWORD create_path_recursive(TCHAR *path)
// osd_open
//============================================================
-osd_file::error osd_file::open(std::string const &orig_path, uint32_t openflags, ptr &file, std::uint64_t &filesize)
+osd_file::error osd_file::open(std::string const &path, uint32_t openflags, ptr &file, std::uint64_t &filesize)
{
- std::string path;
- try { path = osd_subst_env(orig_path); }
- catch (...) { return std::errc::not_enough_memory; }
-
if (win_check_socket_path(path))
return win_open_socket(path, openflags, file, filesize);
else if (win_check_ptty_path(path))
diff --git a/src/osd/modules/font/font_dwrite.cpp b/src/osd/modules/font/font_dwrite.cpp
index 70edc24c0f1..ec152fb1b0d 100644
--- a/src/osd/modules/font/font_dwrite.cpp
+++ b/src/osd/modules/font/font_dwrite.cpp
@@ -6,17 +6,24 @@
*/
#include "font_module.h"
-#include "modules/osdmodule.h"
+
#include "modules/lib/osdlib.h"
#if defined(OSD_WINDOWS)
-#include <windows.h>
+#include "corestr.h"
+
+#include "winutil.h"
+
+#include "osdcore.h"
+#include "strconv.h"
#include <cmath>
#include <memory>
#include <stdexcept>
+#include <windows.h>
+
// Windows Imaging Components
#include <wincodec.h>
@@ -34,10 +41,10 @@ DEFINE_GUID(GUID_WICPixelFormat8bppAlpha, 0xe6cd0116, 0xeeba, 0x4161, 0xaa, 0x85
#include <wrl/client.h>
#undef interface
-#include "strconv.h"
-#include "corestr.h"
-#include "winutil.h"
-#include "osdcore.h"
+
+namespace osd {
+
+namespace {
using namespace Microsoft::WRL;
@@ -361,7 +368,7 @@ public:
bool italic = (strreplace(name, "[I]", "") + strreplace(name, "[i]", "") > 0);
// convert the face name
- std::wstring familyName = osd::text::to_wstring(name.c_str());
+ std::wstring familyName = text::to_wstring(name);
// find the font
HR_RET0(find_font(
@@ -623,7 +630,7 @@ private:
HR_RETHR(fonts->FindFamilyName(familyName.c_str(), &family_index, &exists));
if (!exists)
{
- osd_printf_error("Font with family name %s does not exist.\n", osd::text::from_wstring(familyName));
+ osd_printf_error("Font with family name %s does not exist.\n", text::from_wstring(familyName));
return E_FAIL;
}
@@ -674,7 +681,7 @@ public:
return true;
}
- virtual int init(const osd_options &options) override
+ virtual int init(osd_interface &osd, const osd_options &options) override
{
HRESULT result;
@@ -742,7 +749,7 @@ public:
std::unique_ptr<WCHAR[]> name = nullptr;
HR_RET0(get_localized_familyname(names, name));
- std::string utf8_name = osd::text::from_wstring(name.get());
+ std::string utf8_name = text::from_wstring(name.get());
name.reset();
// Review: should the config name, be unlocalized?
@@ -806,8 +813,15 @@ private:
}
};
+} // anonymous namespace
+
+} // namespace osd
+
#else
-MODULE_NOT_SUPPORTED(font_dwrite, OSD_FONT_PROVIDER, "dwrite")
+
+namespace osd { namespace { MODULE_NOT_SUPPORTED(font_dwrite, OSD_FONT_PROVIDER, "dwrite") } }
+
#endif
-MODULE_DEFINITION(FONT_DWRITE, font_dwrite)
+
+MODULE_DEFINITION(FONT_DWRITE, osd::font_dwrite)
diff --git a/src/osd/modules/font/font_module.h b/src/osd/modules/font/font_module.h
index 81ffaca74e5..7fe04e32628 100644
--- a/src/osd/modules/font/font_module.h
+++ b/src/osd/modules/font/font_module.h
@@ -24,7 +24,7 @@
class font_module
{
public:
- virtual ~font_module() { }
+ virtual ~font_module() = default;
/** attempt to allocate a font instance */
virtual osd_font::ptr font_alloc() = 0;
diff --git a/src/osd/modules/font/font_none.cpp b/src/osd/modules/font/font_none.cpp
index dc6116625a8..abf56007b00 100644
--- a/src/osd/modules/font/font_none.cpp
+++ b/src/osd/modules/font/font_none.cpp
@@ -4,9 +4,12 @@
* font_none.c
*
*/
-
#include "font_module.h"
-#include "modules/osdmodule.h"
+
+
+namespace osd {
+
+namespace {
class osd_font_none : public osd_font
{
@@ -23,10 +26,15 @@ class font_none : public osd_module, public font_module
public:
font_none() : osd_module(OSD_FONT_PROVIDER, "none"), font_module() { }
- virtual int init(const osd_options &options) override { return 0; }
+ virtual int init(osd_interface &osd, const osd_options &options) override { return 0; }
virtual osd_font::ptr font_alloc() override { return std::make_unique<osd_font_none>(); }
virtual bool get_font_families(std::string const &font_path, std::vector<std::pair<std::string, std::string> > &result) override { return false; }
};
-MODULE_DEFINITION(FONT_NONE, font_none)
+} // anonymous namespace
+
+} // namespace osd
+
+
+MODULE_DEFINITION(FONT_NONE, osd::font_none)
diff --git a/src/osd/modules/font/font_osx.cpp b/src/osd/modules/font/font_osx.cpp
index cde01f58b69..a020d51ddce 100644
--- a/src/osd/modules/font/font_osx.cpp
+++ b/src/osd/modules/font/font_osx.cpp
@@ -6,7 +6,6 @@
*/
#include "font_module.h"
-#include "modules/osdmodule.h"
#ifdef SDLMAME_MACOSX
@@ -212,7 +211,7 @@ class font_osx : public osd_module, public font_module
public:
font_osx() : osd_module(OSD_FONT_PROVIDER, "osx"), font_module() { }
- virtual int init(const osd_options &options) override { return 0; }
+ virtual int init(osd_interface &osd, const osd_options &options) override { return 0; }
virtual osd_font::ptr font_alloc() override { return std::make_unique<osd_font_osx>(); }
virtual bool get_font_families(std::string const &font_path, std::vector<std::pair<std::string, std::string> > &result) override;
diff --git a/src/osd/modules/font/font_sdl.cpp b/src/osd/modules/font/font_sdl.cpp
index 6c97f0a71f0..1938c97a44d 100644
--- a/src/osd/modules/font/font_sdl.cpp
+++ b/src/osd/modules/font/font_sdl.cpp
@@ -6,7 +6,6 @@
*/
#include "font_module.h"
-#include "modules/osdmodule.h"
#if defined(SDLMAME_UNIX) && !defined(SDLMAME_MACOSX) && !defined(SDLMAME_HAIKU) && !defined(SDLMAME_ANDROID)
@@ -200,9 +199,8 @@ osd_font_sdl::TTF_Font_ptr osd_font_sdl::TTF_OpenFont_Magic(std::string const &n
unsigned char const ttf_magic[] = { 0x00, 0x01, 0x00, 0x00, 0x00 };
unsigned char const ttc1_magic[] = { 0x74, 0x74, 0x63, 0x66, 0x00, 0x01, 0x00, 0x00 };
unsigned char const ttc2_magic[] = { 0x74, 0x74, 0x63, 0x66, 0x00, 0x02, 0x00, 0x00 };
- auto buffer_size = std::max({ sizeof(ttf_magic), sizeof(ttc1_magic), sizeof(ttc2_magic) });
- unsigned char buffer[buffer_size];
- auto const bytes_read = file.read(buffer, buffer_size);
+ unsigned char buffer[std::max({ sizeof(ttf_magic), sizeof(ttc1_magic), sizeof(ttc2_magic) })];
+ auto const bytes_read = file.read(buffer, std::size(buffer));
file.close();
if (((bytes_read >= sizeof(ttf_magic)) && !std::memcmp(buffer, ttf_magic, sizeof(ttf_magic))) ||
@@ -305,7 +303,7 @@ public:
return std::make_unique<osd_font_sdl>();
}
- virtual int init(const osd_options &options) override
+ virtual int init(osd_interface &osd, const osd_options &options) override
{
if (TTF_Init() == -1)
{
@@ -351,10 +349,10 @@ bool font_sdl::get_font_families(std::string const &font_path, std::vector<std::
{
auto const compare_fonts = [](std::pair<std::string, std::string> const &a, std::pair<std::string, std::string> const &b) -> bool
{
- int const second = core_stricmp(a.second.c_str(), b.second.c_str());
+ int const second = core_stricmp(a.second, b.second);
if (second < 0) return true;
else if (second > 0) return false;
- else return core_stricmp(b.first.c_str(), b.first.c_str()) < 0;
+ else return core_stricmp(b.first, b.first) < 0;
};
std::string config((const char *)val.u.s);
std::string display(config);
diff --git a/src/osd/modules/font/font_windows.cpp b/src/osd/modules/font/font_windows.cpp
index 8e0bd568349..0ec65b67aea 100644
--- a/src/osd/modules/font/font_windows.cpp
+++ b/src/osd/modules/font/font_windows.cpp
@@ -7,7 +7,6 @@
#include "font_module.h"
-#include "modules/osdmodule.h"
#if defined(OSD_WINDOWS) || defined(SDLMAME_WIN32)
@@ -25,6 +24,8 @@
#include <io.h>
+namespace osd {
+
namespace {
class osd_font_windows : public osd_font
@@ -83,7 +84,7 @@ bool osd_font_windows::open(std::string const &font_path, std::string const &_na
logfont.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
// copy in the face name
- osd::text::tstring face = osd::text::to_tstring(name);
+ text::tstring face = text::to_tstring(name);
_tcsncpy(logfont.lfFaceName, face.c_str(), std::size(logfont.lfFaceName));
logfont.lfFaceName[sizeof(logfont.lfFaceName) / sizeof(TCHAR)-1] = 0;
@@ -108,8 +109,8 @@ bool osd_font_windows::open(std::string const &font_path, std::string const &_na
}
// if it doesn't match our request, fail
- std::string utf = osd::text::from_tstring(&realname[0]);
- int result = core_stricmp(utf.c_str(), name.c_str());
+ std::string utf = text::from_tstring(&realname[0]);
+ int result = core_stricmp(utf, name);
// if we didn't match, nuke our font and fall back
if (result != 0)
@@ -288,7 +289,7 @@ class font_win : public osd_module, public font_module
public:
font_win() : osd_module(OSD_FONT_PROVIDER, "win"), font_module() { }
- virtual int init(const osd_options &options) override { return 0; }
+ virtual int init(osd_interface &osd, const osd_options &options) override { return 0; }
virtual osd_font::ptr font_alloc() override { return std::make_unique<osd_font_windows>(); }
@@ -298,7 +299,7 @@ private:
static int CALLBACK font_family_callback(LOGFONT const *lpelfe, TEXTMETRIC const *lpntme, DWORD FontType, LPARAM lParam)
{
auto &result = *reinterpret_cast<std::vector<std::pair<std::string, std::string> > *>(lParam);
- std::string face = osd::text::from_tstring(lpelfe->lfFaceName);
+ std::string face = text::from_tstring(lpelfe->lfFaceName);
if ((face[0] != '@') && (result.empty() || (result.back().first != face))) result.emplace_back(face, face);
return TRUE;
}
@@ -326,10 +327,12 @@ bool font_win::get_font_families(std::string const &font_path, std::vector<std::
} // anonymous namespace
+} // namespace osd
+
#else // defined(OSD_WINDOWS) || defined(SDLMAME_WIN32)
-MODULE_NOT_SUPPORTED(font_win, OSD_FONT_PROVIDER, "win")
+namespace osd { namespace { MODULE_NOT_SUPPORTED(font_win, OSD_FONT_PROVIDER, "win") } }
#endif // defined(OSD_WINDOWS) || defined(SDLMAME_WIN32)
-MODULE_DEFINITION(FONT_WINDOWS, font_win)
+MODULE_DEFINITION(FONT_WINDOWS, osd::font_win)
diff --git a/src/osd/modules/input/assignmenthelper.cpp b/src/osd/modules/input/assignmenthelper.cpp
new file mode 100644
index 00000000000..c044d4b7aa7
--- /dev/null
+++ b/src/osd/modules/input/assignmenthelper.cpp
@@ -0,0 +1,592 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+//============================================================
+//
+// assignmenthelper.cpp - input assignment setup helper
+//
+//============================================================
+
+#include "assignmenthelper.h"
+
+#include "interface/inputseq.h"
+
+#include "inpttype.h"
+
+
+namespace osd {
+
+bool joystick_assignment_helper::add_assignment(
+ input_device::assignment_vector &assignments,
+ ioport_type fieldtype,
+ input_seq_type seqtype,
+ input_item_class itemclass,
+ input_item_modifier modifier,
+ std::initializer_list<input_item_id> items)
+{
+ for (input_item_id item : items)
+ {
+ if (ITEM_ID_INVALID != item)
+ {
+ assignments.emplace_back(
+ fieldtype,
+ seqtype,
+ input_seq(input_code(DEVICE_CLASS_JOYSTICK, 0, itemclass, modifier, item)));
+ return true;
+ }
+ }
+ return false;
+}
+
+
+bool joystick_assignment_helper::add_button_assignment(
+ input_device::assignment_vector &assignments,
+ ioport_type field_type,
+ std::initializer_list<input_item_id> items)
+{
+ return add_assignment(
+ assignments,
+ field_type,
+ SEQ_TYPE_STANDARD,
+ ITEM_CLASS_SWITCH,
+ ITEM_MODIFIER_NONE,
+ items);
+}
+
+
+bool joystick_assignment_helper::add_button_pair_assignment(
+ input_device::assignment_vector &assignments,
+ ioport_type field1,
+ ioport_type field2,
+ input_item_id button1,
+ input_item_id button2)
+{
+ if ((ITEM_ID_INVALID == button1) || (ITEM_ID_INVALID == button2))
+ return false;
+
+ assignments.emplace_back(
+ field1,
+ SEQ_TYPE_STANDARD,
+ make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, button1));
+ assignments.emplace_back(
+ field2,
+ SEQ_TYPE_STANDARD,
+ make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, button2));
+ return true;
+}
+
+
+bool joystick_assignment_helper::add_axis_inc_dec_assignment(
+ input_device::assignment_vector &assignments,
+ ioport_type field_type,
+ input_item_id button_dec,
+ input_item_id button_inc)
+{
+ if ((ITEM_ID_INVALID == button_dec) || (ITEM_ID_INVALID == button_inc))
+ return false;
+
+ assignments.emplace_back(
+ field_type,
+ SEQ_TYPE_DECREMENT,
+ make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, button_dec));
+ assignments.emplace_back(
+ field_type,
+ SEQ_TYPE_INCREMENT,
+ make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, button_inc));
+ return true;
+}
+
+
+bool joystick_assignment_helper::add_axis_pair_assignment(
+ input_device::assignment_vector &assignments,
+ ioport_type field1,
+ ioport_type field2,
+ input_item_id axis)
+{
+ if (ITEM_ID_INVALID == axis)
+ return false;
+
+ assignments.emplace_back(
+ field1,
+ SEQ_TYPE_STANDARD,
+ make_code(
+ ITEM_CLASS_SWITCH,
+ (ITEM_ID_XAXIS == axis) ? ITEM_MODIFIER_LEFT : (ITEM_ID_YAXIS == axis) ? ITEM_MODIFIER_UP : ITEM_MODIFIER_NEG,
+ axis));
+ assignments.emplace_back(
+ field2,
+ SEQ_TYPE_STANDARD,
+ make_code(
+ ITEM_CLASS_SWITCH,
+ (ITEM_ID_XAXIS == axis) ? ITEM_MODIFIER_RIGHT : (ITEM_ID_YAXIS == axis) ? ITEM_MODIFIER_DOWN : ITEM_MODIFIER_POS,
+ axis));
+ return true;
+}
+
+
+bool joystick_assignment_helper::consume_button_pair(
+ input_device::assignment_vector &assignments,
+ ioport_type field1,
+ ioport_type field2,
+ input_item_id &button1,
+ input_item_id &button2)
+{
+ if (!add_button_pair_assignment(assignments, field1, field2, button1, button2))
+ return false;
+
+ button1 = ITEM_ID_INVALID;
+ button2 = ITEM_ID_INVALID;
+ return true;
+}
+
+
+bool joystick_assignment_helper::consume_trigger_pair(
+ input_device::assignment_vector &assignments,
+ ioport_type field1,
+ ioport_type field2,
+ input_item_id &axis1,
+ input_item_id &axis2)
+{
+ if ((ITEM_ID_INVALID == axis1) || (ITEM_ID_INVALID == axis2))
+ return false;
+
+ assignments.emplace_back(
+ field1,
+ SEQ_TYPE_STANDARD,
+ make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NEG, axis1));
+ assignments.emplace_back(
+ field2,
+ SEQ_TYPE_STANDARD,
+ make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NEG, axis2));
+ axis1 = ITEM_ID_INVALID;
+ axis2 = ITEM_ID_INVALID;
+ return true;
+}
+
+
+bool joystick_assignment_helper::consume_axis_pair(
+ input_device::assignment_vector &assignments,
+ ioport_type field1,
+ ioport_type field2,
+ input_item_id &axis)
+{
+ if (!add_axis_pair_assignment(assignments, field1, field2, axis))
+ return false;
+
+ axis = ITEM_ID_INVALID;
+ return true;
+}
+
+
+void joystick_assignment_helper::add_directional_assignments(
+ input_device::assignment_vector &assignments,
+ input_item_id xaxis,
+ input_item_id yaxis,
+ input_item_id leftswitch,
+ input_item_id rightswitch,
+ input_item_id upswitch,
+ input_item_id downswitch)
+{
+ // see if we have complementary pairs of directional switches
+ bool const hswitches = (ITEM_ID_INVALID != leftswitch) && (ITEM_ID_INVALID != rightswitch);
+ bool const vswitches = (ITEM_ID_INVALID != upswitch) && (ITEM_ID_INVALID != downswitch);
+
+ // use X axis if present
+ if (ITEM_ID_INVALID != xaxis)
+ {
+ // use this for horizontal axis movement
+ input_seq const xseq(make_code(ITEM_CLASS_ABSOLUTE, ITEM_MODIFIER_NONE, xaxis));
+ assignments.emplace_back(IPT_PADDLE, SEQ_TYPE_STANDARD, xseq);
+ assignments.emplace_back(IPT_POSITIONAL, SEQ_TYPE_STANDARD, xseq);
+ assignments.emplace_back(IPT_DIAL, SEQ_TYPE_STANDARD, xseq);
+ assignments.emplace_back(IPT_TRACKBALL_X, SEQ_TYPE_STANDARD, xseq);
+ assignments.emplace_back(IPT_AD_STICK_X, SEQ_TYPE_STANDARD, xseq);
+ assignments.emplace_back(IPT_LIGHTGUN_X, SEQ_TYPE_STANDARD, xseq);
+
+ // use it for the main left/right control, too
+ input_seq leftseq(make_code(ITEM_CLASS_SWITCH, (ITEM_ID_XAXIS == xaxis) ? ITEM_MODIFIER_LEFT : ITEM_MODIFIER_NEG, xaxis));
+ input_seq rightseq(make_code(ITEM_CLASS_SWITCH, (ITEM_ID_XAXIS == xaxis) ? ITEM_MODIFIER_RIGHT : ITEM_MODIFIER_POS, xaxis));
+ if (ITEM_ID_INVALID != leftswitch)
+ {
+ leftseq += input_seq::or_code;
+ leftseq += make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, leftswitch);
+ }
+ if (ITEM_ID_INVALID != rightswitch)
+ {
+ rightseq += input_seq::or_code;
+ rightseq += make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, rightswitch);
+ }
+ assignments.emplace_back(IPT_JOYSTICK_LEFT, SEQ_TYPE_STANDARD, leftseq);
+ assignments.emplace_back(IPT_JOYSTICK_RIGHT, SEQ_TYPE_STANDARD, rightseq);
+
+ // use for vertical navigation if there's no Y axis, or horizontal otherwise
+ if (ITEM_ID_INVALID != yaxis)
+ {
+ // if left/right are both present but not both up/down, they'll be taken for vertical navigation
+ if (hswitches && !vswitches)
+ {
+ leftseq.backspace();
+ if (ITEM_ID_INVALID != upswitch)
+ leftseq += make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, upswitch);
+ else
+ leftseq.backspace();
+
+ rightseq.backspace();
+ if (ITEM_ID_INVALID != downswitch)
+ rightseq += make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, downswitch);
+ else
+ rightseq.backspace();
+ }
+ assignments.emplace_back(IPT_UI_LEFT, SEQ_TYPE_STANDARD, leftseq);
+ assignments.emplace_back(IPT_UI_RIGHT, SEQ_TYPE_STANDARD, rightseq);
+ }
+ else
+ {
+ // prefer D-pad up/down for vertical navigation if present
+ if (!hswitches || vswitches)
+ {
+ while (leftseq.length() > 1)
+ leftseq.backspace();
+ if (ITEM_ID_INVALID != upswitch)
+ {
+ leftseq += input_seq::or_code;
+ leftseq += make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, upswitch);
+ }
+
+ while (rightseq.length() > 1)
+ rightseq.backspace();
+ if (ITEM_ID_INVALID != downswitch)
+ {
+ rightseq += input_seq::or_code;
+ rightseq += make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, downswitch);
+ }
+ }
+ assignments.emplace_back(IPT_UI_UP, SEQ_TYPE_STANDARD, leftseq);
+ assignments.emplace_back(IPT_UI_DOWN, SEQ_TYPE_STANDARD, rightseq);
+ }
+ }
+ else
+ {
+ // without a primary analog X axis, we still want D-pad left/right controls if possible
+ add_button_assignment(assignments, IPT_JOYSTICK_LEFT, { leftswitch });
+ add_button_assignment(assignments, IPT_JOYSTICK_RIGHT, { rightswitch });
+
+ // vertical navigation gets first pick on directional controls
+ add_button_assignment(assignments, IPT_UI_LEFT, { (hswitches && !vswitches) ? upswitch : leftswitch });
+ add_button_assignment(assignments, IPT_UI_RIGHT, { (hswitches && !vswitches) ? downswitch : rightswitch });
+ }
+
+ // use Y axis if present
+ if (ITEM_ID_INVALID != yaxis)
+ {
+ // use this for vertical axis movement
+ input_seq const yseq(make_code(ITEM_CLASS_ABSOLUTE, ITEM_MODIFIER_NONE, yaxis));
+ assignments.emplace_back(IPT_PADDLE_V, SEQ_TYPE_STANDARD, yseq);
+ assignments.emplace_back(IPT_POSITIONAL_V, SEQ_TYPE_STANDARD, yseq);
+ assignments.emplace_back(IPT_DIAL_V, SEQ_TYPE_STANDARD, yseq);
+ assignments.emplace_back(IPT_TRACKBALL_Y, SEQ_TYPE_STANDARD, yseq);
+ assignments.emplace_back(IPT_AD_STICK_Y, SEQ_TYPE_STANDARD, yseq);
+ assignments.emplace_back(IPT_LIGHTGUN_Y, SEQ_TYPE_STANDARD, yseq);
+
+ // use it for the main up/down control, too
+ input_seq upseq(make_code(ITEM_CLASS_SWITCH, (ITEM_ID_YAXIS == yaxis) ? ITEM_MODIFIER_UP : ITEM_MODIFIER_NEG, yaxis));
+ input_seq downseq(make_code(ITEM_CLASS_SWITCH, (ITEM_ID_YAXIS == yaxis) ? ITEM_MODIFIER_DOWN : ITEM_MODIFIER_POS, yaxis));
+ if (ITEM_ID_INVALID != upswitch)
+ {
+ upseq += input_seq::or_code;
+ upseq += make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, upswitch);
+ }
+ if (ITEM_ID_INVALID != downswitch)
+ {
+ downseq += input_seq::or_code;
+ downseq += make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, downswitch);
+ }
+ assignments.emplace_back(IPT_JOYSTICK_UP, SEQ_TYPE_STANDARD, upseq);
+ assignments.emplace_back(IPT_JOYSTICK_DOWN, SEQ_TYPE_STANDARD, downseq);
+
+ // if available, this is used for vertical navigation
+ if (hswitches && !vswitches)
+ {
+ if (upseq.length() > 1)
+ upseq.backspace();
+ else
+ upseq += input_seq::or_code;
+ upseq += make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, leftswitch);
+
+ if (downseq.length() > 1)
+ downseq.backspace();
+ else
+ downseq += input_seq::or_code;
+ downseq += make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, rightswitch);
+ }
+ assignments.emplace_back(IPT_UI_UP, SEQ_TYPE_STANDARD, upseq);
+ assignments.emplace_back(IPT_UI_DOWN, SEQ_TYPE_STANDARD, downseq);
+ }
+ else
+ {
+ // without a primary analog Y axis, we still want D-pad up/down controls if possible
+ add_button_assignment(assignments, IPT_JOYSTICK_UP, { upswitch });
+ add_button_assignment(assignments, IPT_JOYSTICK_DOWN, { downswitch });
+
+ // vertical navigation may be assigned to X axis if Y axis is not present
+ bool const dpadflip = (ITEM_ID_INVALID != xaxis) == (!hswitches || vswitches);
+ add_button_assignment(
+ assignments,
+ (ITEM_ID_INVALID != xaxis) ? IPT_UI_LEFT : IPT_UI_UP,
+ { dpadflip ? leftswitch : upswitch });
+ add_button_assignment(
+ assignments,
+ (ITEM_ID_INVALID != xaxis) ? IPT_UI_RIGHT : IPT_UI_DOWN,
+ { dpadflip ? rightswitch : downswitch });
+ }
+
+ // if we're missing either primary axis, fall back to D-pad for analog increment/decrement
+ if ((ITEM_ID_INVALID == xaxis) || (ITEM_ID_INVALID == yaxis))
+ {
+ if (ITEM_ID_INVALID != leftswitch)
+ {
+ input_seq const leftseq(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, leftswitch));
+ assignments.emplace_back(IPT_PADDLE, SEQ_TYPE_DECREMENT, leftseq);
+ assignments.emplace_back(IPT_POSITIONAL, SEQ_TYPE_DECREMENT, leftseq);
+ assignments.emplace_back(IPT_DIAL, SEQ_TYPE_DECREMENT, leftseq);
+ assignments.emplace_back(IPT_TRACKBALL_X, SEQ_TYPE_DECREMENT, leftseq);
+ assignments.emplace_back(IPT_AD_STICK_X, SEQ_TYPE_DECREMENT, leftseq);
+ assignments.emplace_back(IPT_LIGHTGUN_X, SEQ_TYPE_DECREMENT, leftseq);
+ }
+ if (ITEM_ID_INVALID != rightswitch)
+ {
+ input_seq const rightseq(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, rightswitch));
+ assignments.emplace_back(IPT_PADDLE, SEQ_TYPE_INCREMENT, rightseq);
+ assignments.emplace_back(IPT_POSITIONAL, SEQ_TYPE_INCREMENT, rightseq);
+ assignments.emplace_back(IPT_DIAL, SEQ_TYPE_INCREMENT, rightseq);
+ assignments.emplace_back(IPT_TRACKBALL_X, SEQ_TYPE_INCREMENT, rightseq);
+ assignments.emplace_back(IPT_AD_STICK_X, SEQ_TYPE_INCREMENT, rightseq);
+ assignments.emplace_back(IPT_LIGHTGUN_X, SEQ_TYPE_INCREMENT, rightseq);
+ }
+ if (ITEM_ID_INVALID != upswitch)
+ {
+ input_seq const upseq(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, upswitch));
+ assignments.emplace_back(IPT_PADDLE_V, SEQ_TYPE_DECREMENT, upseq);
+ assignments.emplace_back(IPT_POSITIONAL_V, SEQ_TYPE_DECREMENT, upseq);
+ assignments.emplace_back(IPT_DIAL_V, SEQ_TYPE_DECREMENT, upseq);
+ assignments.emplace_back(IPT_TRACKBALL_Y, SEQ_TYPE_DECREMENT, upseq);
+ assignments.emplace_back(IPT_AD_STICK_Y, SEQ_TYPE_DECREMENT, upseq);
+ assignments.emplace_back(IPT_LIGHTGUN_Y, SEQ_TYPE_DECREMENT, upseq);
+ }
+ if (ITEM_ID_INVALID != downswitch)
+ {
+ input_seq const downseq(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, downswitch));
+ assignments.emplace_back(IPT_PADDLE_V, SEQ_TYPE_INCREMENT, downseq);
+ assignments.emplace_back(IPT_POSITIONAL_V, SEQ_TYPE_INCREMENT, downseq);
+ assignments.emplace_back(IPT_DIAL_V, SEQ_TYPE_INCREMENT, downseq);
+ assignments.emplace_back(IPT_TRACKBALL_Y, SEQ_TYPE_INCREMENT, downseq);
+ assignments.emplace_back(IPT_AD_STICK_Y, SEQ_TYPE_INCREMENT, downseq);
+ assignments.emplace_back(IPT_LIGHTGUN_Y, SEQ_TYPE_INCREMENT, downseq);
+ }
+ }
+}
+
+
+void joystick_assignment_helper::add_twin_stick_assignments(
+ input_device::assignment_vector &assignments,
+ input_item_id leftx,
+ input_item_id lefty,
+ input_item_id rightx,
+ input_item_id righty,
+ input_item_id leftleft,
+ input_item_id leftright,
+ input_item_id leftup,
+ input_item_id leftdown,
+ input_item_id rightleft,
+ input_item_id rightright,
+ input_item_id rightup,
+ input_item_id rightdown)
+{
+ // we'll add these at the end if they aren't empty
+ input_seq leftleftseq, leftrightseq, leftupseq, leftdownseq;
+ input_seq rightleftseq, rightrightseq, rightupseq, rightdownseq;
+
+ // only use axes if there are at least two axes in the same orientation
+ bool const useaxes =
+ ((ITEM_ID_INVALID != leftx) && (ITEM_ID_INVALID != rightx)) ||
+ ((ITEM_ID_INVALID != lefty) && (ITEM_ID_INVALID != righty));
+ if (useaxes)
+ {
+ // left stick
+ if (ITEM_ID_INVALID != leftx)
+ {
+ leftleftseq += make_code(
+ ITEM_CLASS_SWITCH,
+ (ITEM_ID_XAXIS == leftx) ? ITEM_MODIFIER_LEFT : ITEM_MODIFIER_NEG,
+ leftx);
+ leftrightseq += make_code(
+ ITEM_CLASS_SWITCH,
+ (ITEM_ID_XAXIS == leftx) ? ITEM_MODIFIER_RIGHT : ITEM_MODIFIER_POS,
+ leftx);
+ }
+ if (ITEM_ID_INVALID != lefty)
+ {
+ leftupseq += make_code(
+ ITEM_CLASS_SWITCH,
+ (ITEM_ID_YAXIS == lefty) ? ITEM_MODIFIER_UP : ITEM_MODIFIER_NEG,
+ lefty);
+ leftdownseq += make_code(
+ ITEM_CLASS_SWITCH,
+ (ITEM_ID_YAXIS == lefty) ? ITEM_MODIFIER_DOWN : ITEM_MODIFIER_POS,
+ lefty);
+ }
+
+ // right stick
+ if (ITEM_ID_INVALID != rightx)
+ {
+ rightleftseq += make_code(
+ ITEM_CLASS_SWITCH,
+ (ITEM_ID_XAXIS == rightx) ? ITEM_MODIFIER_LEFT : ITEM_MODIFIER_NEG,
+ rightx);
+ rightrightseq += make_code(
+ ITEM_CLASS_SWITCH,
+ (ITEM_ID_XAXIS == rightx) ? ITEM_MODIFIER_RIGHT : ITEM_MODIFIER_POS,
+ rightx);
+ }
+ if (ITEM_ID_INVALID != righty)
+ {
+ rightupseq += make_code(
+ ITEM_CLASS_SWITCH,
+ (ITEM_ID_YAXIS == righty) ? ITEM_MODIFIER_UP : ITEM_MODIFIER_NEG,
+ righty);
+ rightdownseq += make_code(
+ ITEM_CLASS_SWITCH,
+ (ITEM_ID_YAXIS == righty) ? ITEM_MODIFIER_DOWN : ITEM_MODIFIER_POS,
+ righty);
+ }
+ }
+
+ // only use switches if we have at least one pair of matching opposing directions
+ bool const lefth = (ITEM_ID_INVALID != leftleft) && (ITEM_ID_INVALID != leftright);
+ bool const leftv = (ITEM_ID_INVALID != leftup) && (ITEM_ID_INVALID != leftdown);
+ bool const righth = (ITEM_ID_INVALID != rightleft) && (ITEM_ID_INVALID != rightright);
+ bool const rightv = (ITEM_ID_INVALID != rightup) && (ITEM_ID_INVALID != rightdown);
+ if ((lefth && righth) || (leftv && rightv))
+ {
+ // left stick
+ if (ITEM_ID_INVALID != leftleft)
+ {
+ if (!leftleftseq.empty())
+ leftleftseq += input_seq::or_code;
+ leftleftseq += make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, leftleft);
+ }
+ if (ITEM_ID_INVALID != leftright)
+ {
+ if (!leftrightseq.empty())
+ leftrightseq += input_seq::or_code;
+ leftrightseq += make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, leftright);
+ }
+ if (ITEM_ID_INVALID != leftup)
+ {
+ if (!leftupseq.empty())
+ leftupseq += input_seq::or_code;
+ leftupseq += make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, leftup);
+ }
+ if (ITEM_ID_INVALID != leftdown)
+ {
+ if (!leftdownseq.empty())
+ leftdownseq += input_seq::or_code;
+ leftdownseq += make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, leftdown);
+ }
+
+ // right stick
+ if (ITEM_ID_INVALID != rightleft)
+ {
+ if (!rightleftseq.empty())
+ rightleftseq += input_seq::or_code;
+ rightleftseq += make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, rightleft);
+ }
+ if (ITEM_ID_INVALID != rightright)
+ {
+ if (!rightrightseq.empty())
+ rightrightseq += input_seq::or_code;
+ rightrightseq += make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, rightright);
+ }
+ if (ITEM_ID_INVALID != rightup)
+ {
+ if (!rightupseq.empty())
+ rightupseq += input_seq::or_code;
+ rightupseq += make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, rightup);
+ }
+ if (ITEM_ID_INVALID != rightdown)
+ {
+ if (!rightdownseq.empty())
+ rightdownseq += input_seq::or_code;
+ rightdownseq += make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, rightdown);
+ }
+ }
+
+ // now add collected assignments
+ if (!leftleftseq.empty())
+ assignments.emplace_back(IPT_JOYSTICKLEFT_LEFT, SEQ_TYPE_STANDARD, leftleftseq);
+ if (!leftrightseq.empty())
+ assignments.emplace_back(IPT_JOYSTICKLEFT_RIGHT, SEQ_TYPE_STANDARD, leftrightseq);
+ if (!leftupseq.empty())
+ assignments.emplace_back(IPT_JOYSTICKLEFT_UP, SEQ_TYPE_STANDARD, leftupseq);
+ if (!leftdownseq.empty())
+ assignments.emplace_back(IPT_JOYSTICKLEFT_DOWN, SEQ_TYPE_STANDARD, leftdownseq);
+ if (!rightleftseq.empty())
+ assignments.emplace_back(IPT_JOYSTICKRIGHT_LEFT, SEQ_TYPE_STANDARD, rightleftseq);
+ if (!rightrightseq.empty())
+ assignments.emplace_back(IPT_JOYSTICKRIGHT_RIGHT, SEQ_TYPE_STANDARD, rightrightseq);
+ if (!rightupseq.empty())
+ assignments.emplace_back(IPT_JOYSTICKRIGHT_UP, SEQ_TYPE_STANDARD, rightupseq);
+ if (!rightdownseq.empty())
+ assignments.emplace_back(IPT_JOYSTICKRIGHT_DOWN, SEQ_TYPE_STANDARD, rightdownseq);
+}
+
+
+void joystick_assignment_helper::choose_primary_stick(
+ input_item_id (&stickaxes)[2][2],
+ input_item_id leftx,
+ input_item_id lefty,
+ input_item_id rightx,
+ input_item_id righty)
+{
+ if ((ITEM_ID_INVALID != leftx) && (ITEM_ID_INVALID != lefty))
+ {
+ // left stick has both axes, make it primary
+ stickaxes[0][0] = leftx;
+ stickaxes[0][1] = lefty;
+ stickaxes[1][0] = rightx;
+ stickaxes[1][1] = righty;
+ }
+ else if ((ITEM_ID_INVALID != rightx) && (ITEM_ID_INVALID != righty))
+ {
+ // right stick has both axes, make it primary
+ stickaxes[0][0] = rightx;
+ stickaxes[0][1] = righty;
+ stickaxes[1][0] = leftx;
+ stickaxes[1][1] = lefty;
+ }
+ else if (ITEM_ID_INVALID != leftx)
+ {
+ // degenerate case - left X and possibly right X or Y
+ stickaxes[0][0] = leftx;
+ stickaxes[0][1] = righty;
+ stickaxes[1][0] = rightx;
+ stickaxes[1][1] = ITEM_ID_INVALID;
+ }
+ else if ((ITEM_ID_INVALID != rightx) || (ITEM_ID_INVALID != lefty))
+ {
+ // degenerate case - right X and possibly left Y, or one or two Y axes
+ stickaxes[0][0] = rightx;
+ stickaxes[0][1] = lefty;
+ stickaxes[1][0] = ITEM_ID_INVALID;
+ stickaxes[1][1] = righty;
+ }
+ else
+ {
+ // degenerate case - one Y axis at most
+ stickaxes[0][0] = ITEM_ID_INVALID;
+ stickaxes[0][1] = righty;
+ stickaxes[1][0] = ITEM_ID_INVALID;
+ stickaxes[1][1] = ITEM_ID_INVALID;
+ }
+}
+
+} // namespace osd
diff --git a/src/osd/modules/input/assignmenthelper.h b/src/osd/modules/input/assignmenthelper.h
new file mode 100644
index 00000000000..ff5a9d34072
--- /dev/null
+++ b/src/osd/modules/input/assignmenthelper.h
@@ -0,0 +1,118 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+//============================================================
+//
+// assignmenthelper.h - input assignment setup helper
+//
+//============================================================
+#ifndef MAME_OSD_INPUT_ASSIGNMENTHELPER_H
+#define MAME_OSD_INPUT_ASSIGNMENTHELPER_H
+
+#pragma once
+
+#include "interface/inputcode.h"
+#include "interface/inputdev.h"
+
+#include <initializer_list>
+
+
+namespace osd {
+
+class joystick_assignment_helper
+{
+protected:
+ static constexpr input_code make_code(
+ input_item_class itemclass,
+ input_item_modifier modifier,
+ input_item_id item)
+ {
+ return input_code(DEVICE_CLASS_JOYSTICK, 0, itemclass, modifier, item);
+ }
+
+ static bool add_assignment(
+ input_device::assignment_vector &assignments,
+ ioport_type fieldtype,
+ input_seq_type seqtype,
+ input_item_class itemclass,
+ input_item_modifier modifier,
+ std::initializer_list<input_item_id> items);
+
+ static bool add_button_assignment(
+ input_device::assignment_vector &assignments,
+ ioport_type field_type,
+ std::initializer_list<input_item_id> items);
+
+ static bool add_button_pair_assignment(
+ input_device::assignment_vector &assignments,
+ ioport_type field1,
+ ioport_type field2,
+ input_item_id button1,
+ input_item_id button2);
+
+ static bool add_axis_inc_dec_assignment(
+ input_device::assignment_vector &assignments,
+ ioport_type field_type,
+ input_item_id button_dec,
+ input_item_id button_inc);
+
+ static bool add_axis_pair_assignment(
+ input_device::assignment_vector &assignments,
+ ioport_type field1,
+ ioport_type field2,
+ input_item_id axis);
+
+ static bool consume_button_pair(
+ input_device::assignment_vector &assignments,
+ ioport_type field1,
+ ioport_type field2,
+ input_item_id &button1,
+ input_item_id &button2);
+
+ static bool consume_trigger_pair(
+ input_device::assignment_vector &assignments,
+ ioport_type field1,
+ ioport_type field2,
+ input_item_id &axis1,
+ input_item_id &axis2);
+
+ static bool consume_axis_pair(
+ input_device::assignment_vector &assignments,
+ ioport_type field1,
+ ioport_type field2,
+ input_item_id &axis);
+
+ static void add_directional_assignments(
+ input_device::assignment_vector &assignments,
+ input_item_id xaxis,
+ input_item_id yaxis,
+ input_item_id leftswitch,
+ input_item_id rightswitch,
+ input_item_id upswitch,
+ input_item_id downswitch);
+
+ static void add_twin_stick_assignments(
+ input_device::assignment_vector &assignments,
+ input_item_id leftx,
+ input_item_id lefty,
+ input_item_id rightx,
+ input_item_id righty,
+ input_item_id leftleft,
+ input_item_id leftright,
+ input_item_id leftup,
+ input_item_id leftdown,
+ input_item_id rightleft,
+ input_item_id rightright,
+ input_item_id rightup,
+ input_item_id rightdown);
+
+ static void choose_primary_stick(
+ input_item_id (&stickaxes)[2][2],
+ input_item_id leftx,
+ input_item_id lefty,
+ input_item_id rightx,
+ input_item_id righty);
+};
+
+} // namespace osd
+
+#endif // MAME_OSD_INPUT_ASSIGNMENTHELPER_H
diff --git a/src/osd/modules/input/input_common.cpp b/src/osd/modules/input/input_common.cpp
index 7127a7878fa..f3de3ca186e 100644
--- a/src/osd/modules/input/input_common.cpp
+++ b/src/osd/modules/input/input_common.cpp
@@ -8,180 +8,182 @@
//
//============================================================
-#include "modules/lib/osdobj_common.h"
-
-// MAME headers
-#include "emu.h"
#include "input_common.h"
-#include "inputdev.h" // FIXME: still using concrete input device class in input_module_base::poll
+#include "modules/lib/osdobj_common.h"
-// winnt.h defines this
-#ifdef DELETE
-#undef DELETE
-#endif
+#include "emu.h" // so we can get an input manager from the running machine
//============================================================
// Keyboard translation table
//============================================================
-#if defined(OSD_WINDOWS)
+#if defined(OSD_WINDOWS) || defined(SDLMAME_WIN32)
#include <windows.h>
-#define KEY_TRANS_ENTRY0(mame, sdlsc, sdlkey, disc, virtual, ascii, UI) { ITEM_ID_##mame, KEY_ ## disc, virtual, ascii, "ITEM_ID_"#mame, (char *) UI }
-#define KEY_TRANS_ENTRY1(mame, sdlsc, sdlkey, disc, virtual, ascii) { ITEM_ID_##mame, KEY_ ## disc, virtual, ascii, "ITEM_ID_"#mame, (char*) #mame }
-#elif defined(OSD_SDL)
-// SDL include
+#include <dinput.h>
+#define DIK_UNKNOWN 0xffff // intentionally impossible
+#define KEY_TRANS_WIN32(disc, virtual) DIK_##disc, virtual,
+#else
+#define KEY_TRANS_WIN32(disc, virtual)
+#endif
+
+#if defined(OSD_SDL) || defined(SDLMAME_WIN32)
#include <SDL2/SDL.h>
-#define KEY_TRANS_ENTRY0(mame, sdlsc, sdlkey, disc, virtual, ascii, UI) { ITEM_ID_##mame, SDL_SCANCODE_ ## sdlsc, ascii, "ITEM_ID_"#mame, (char *) UI }
-#define KEY_TRANS_ENTRY1(mame, sdlsc, sdlkey, disc, virtual, ascii) { ITEM_ID_##mame, SDL_SCANCODE_ ## sdlsc, ascii, "ITEM_ID_"#mame, (char*) #mame }
+#define KEY_TRANS_SDL(sdlsc) SDL_SCANCODE_##sdlsc,
#else
-// osd mini
+#define KEY_TRANS_SDL(sdlsc)
#endif
-// FIXME: sdl_key can be removed from the table below. It is no longer used.
+#define KEY_TRANS_ENTRY0(mame, sdlsc, disc, virtual, ascii, UI) { ITEM_ID_##mame, KEY_TRANS_SDL(sdlsc) KEY_TRANS_WIN32(disc, virtual) ascii, "ITEM_ID_"#mame, UI }
+#define KEY_TRANS_ENTRY1(mame, sdlsc, disc, virtual, ascii) { ITEM_ID_##mame, KEY_TRANS_SDL(sdlsc) KEY_TRANS_WIN32(disc, virtual) ascii, "ITEM_ID_"#mame, #mame }
+
+// winnt.h defines this
+#ifdef DELETE
+#undef DELETE
+#endif
#if defined(OSD_WINDOWS) || defined(OSD_SDL)
+
key_trans_entry keyboard_trans_table::s_default_table[] =
{
- // MAME key sdl scancode sdl key di scancode virtual key ascii ui
- KEY_TRANS_ENTRY0(ESC, ESCAPE, ESCAPE, ESCAPE, VK_ESCAPE, 27, "ESCAPE"),
- KEY_TRANS_ENTRY1(1, 1, 1, 1, '1', '1'),
- KEY_TRANS_ENTRY1(2, 2, 2, 2, '2', '2'),
- KEY_TRANS_ENTRY1(3, 3, 3, 3, '3', '3'),
- KEY_TRANS_ENTRY1(4, 4, 4, 4, '4', '4'),
- KEY_TRANS_ENTRY1(5, 5, 5, 5, '5', '5'),
- KEY_TRANS_ENTRY1(6, 6, 6, 6, '6', '6'),
- KEY_TRANS_ENTRY1(7, 7, 7, 7, '7', '7'),
- KEY_TRANS_ENTRY1(8, 8, 8, 8, '8', '8'),
- KEY_TRANS_ENTRY1(9, 9, 9, 9, '9', '9'),
- KEY_TRANS_ENTRY1(0, 0, 0, 0, '0', '0'),
- KEY_TRANS_ENTRY1(MINUS, MINUS, MINUS, MINUS, VK_OEM_MINUS, '-'),
- KEY_TRANS_ENTRY1(EQUALS, EQUALS, EQUALS, EQUALS, VK_OEM_PLUS, '='),
- KEY_TRANS_ENTRY1(BACKSPACE, BACKSPACE, BACKSPACE, BACK, VK_BACK, 8),
- KEY_TRANS_ENTRY1(TAB, TAB, TAB, TAB, VK_TAB, 9),
- KEY_TRANS_ENTRY1(Q, Q, q, Q, 'Q', 'Q'),
- KEY_TRANS_ENTRY1(W, W, w, W, 'W', 'W'),
- KEY_TRANS_ENTRY1(E, E, e, E, 'E', 'E'),
- KEY_TRANS_ENTRY1(R, R, r, R, 'R', 'R'),
- KEY_TRANS_ENTRY1(T, T, t, T, 'T', 'T'),
- KEY_TRANS_ENTRY1(Y, Y, y, Y, 'Y', 'Y'),
- KEY_TRANS_ENTRY1(U, U, u, U, 'U', 'U'),
- KEY_TRANS_ENTRY1(I, I, i, I, 'I', 'I'),
- KEY_TRANS_ENTRY1(O, O, o, O, 'O', 'O'),
- KEY_TRANS_ENTRY1(P, P, p, P, 'P', 'P'),
- KEY_TRANS_ENTRY1(OPENBRACE, LEFTBRACKET, LEFTBRACKET, LBRACKET, VK_OEM_4, '['),
- KEY_TRANS_ENTRY1(CLOSEBRACE, RIGHTBRACKET, RIGHTBRACKET, RBRACKET, VK_OEM_6, ']'),
- KEY_TRANS_ENTRY0(ENTER, RETURN, RETURN, RETURN, VK_RETURN, 13, "RETURN"),
- KEY_TRANS_ENTRY1(LCONTROL, LCTRL, LCTRL, LCONTROL, VK_LCONTROL, 0),
- KEY_TRANS_ENTRY1(A, A, a, A, 'A', 'A'),
- KEY_TRANS_ENTRY1(S, S, s, S, 'S', 'S'),
- KEY_TRANS_ENTRY1(D, D, d, D, 'D', 'D'),
- KEY_TRANS_ENTRY1(F, F, f, F, 'F', 'F'),
- KEY_TRANS_ENTRY1(G, G, g, G, 'G', 'G'),
- KEY_TRANS_ENTRY1(H, H, h, H, 'H', 'H'),
- KEY_TRANS_ENTRY1(J, J, j, J, 'J', 'J'),
- KEY_TRANS_ENTRY1(K, K, k, K, 'K', 'K'),
- KEY_TRANS_ENTRY1(L, L, l, L, 'L', 'L'),
- KEY_TRANS_ENTRY1(COLON, SEMICOLON, SEMICOLON, SEMICOLON, VK_OEM_1, ';'),
- KEY_TRANS_ENTRY1(QUOTE, APOSTROPHE, QUOTE, APOSTROPHE, VK_OEM_7, '\''),
- KEY_TRANS_ENTRY1(TILDE, GRAVE, BACKQUOTE, GRAVE, VK_OEM_3, '`'),
- KEY_TRANS_ENTRY1(LSHIFT, LSHIFT, LSHIFT, LSHIFT, VK_LSHIFT, 0),
- KEY_TRANS_ENTRY1(BACKSLASH, BACKSLASH, BACKSLASH, BACKSLASH, VK_OEM_5, '\\'),
-// KEY_TRANS_ENTRY1(BACKSLASH2, NONUSHASH, UNKNOWN, OEM_102, VK_OEM_102, '<'),
+ // MAME key SDL scancode DI scancode virtual key ASCII UI
+ KEY_TRANS_ENTRY0(ESC, ESCAPE, ESCAPE, VK_ESCAPE, 27, "ESCAPE"),
+ KEY_TRANS_ENTRY1(1, 1, 1, '1', '1'),
+ KEY_TRANS_ENTRY1(2, 2, 2, '2', '2'),
+ KEY_TRANS_ENTRY1(3, 3, 3, '3', '3'),
+ KEY_TRANS_ENTRY1(4, 4, 4, '4', '4'),
+ KEY_TRANS_ENTRY1(5, 5, 5, '5', '5'),
+ KEY_TRANS_ENTRY1(6, 6, 6, '6', '6'),
+ KEY_TRANS_ENTRY1(7, 7, 7, '7', '7'),
+ KEY_TRANS_ENTRY1(8, 8, 8, '8', '8'),
+ KEY_TRANS_ENTRY1(9, 9, 9, '9', '9'),
+ KEY_TRANS_ENTRY1(0, 0, 0, '0', '0'),
+ KEY_TRANS_ENTRY1(MINUS, MINUS, MINUS, VK_OEM_MINUS, '-'),
+ KEY_TRANS_ENTRY1(EQUALS, EQUALS, EQUALS, VK_OEM_PLUS, '='),
+ KEY_TRANS_ENTRY1(BACKSPACE, BACKSPACE, BACK, VK_BACK, 8),
+ KEY_TRANS_ENTRY1(TAB, TAB, TAB, VK_TAB, 9),
+ KEY_TRANS_ENTRY1(Q, Q, Q, 'Q', 'Q'),
+ KEY_TRANS_ENTRY1(W, W, W, 'W', 'W'),
+ KEY_TRANS_ENTRY1(E, E, E, 'E', 'E'),
+ KEY_TRANS_ENTRY1(R, R, R, 'R', 'R'),
+ KEY_TRANS_ENTRY1(T, T, T, 'T', 'T'),
+ KEY_TRANS_ENTRY1(Y, Y, Y, 'Y', 'Y'),
+ KEY_TRANS_ENTRY1(U, U, U, 'U', 'U'),
+ KEY_TRANS_ENTRY1(I, I, I, 'I', 'I'),
+ KEY_TRANS_ENTRY1(O, O, O, 'O', 'O'),
+ KEY_TRANS_ENTRY1(P, P, P, 'P', 'P'),
+ KEY_TRANS_ENTRY1(OPENBRACE, LEFTBRACKET, LBRACKET, VK_OEM_4, '['),
+ KEY_TRANS_ENTRY1(CLOSEBRACE, RIGHTBRACKET, RBRACKET, VK_OEM_6, ']'),
+ KEY_TRANS_ENTRY0(ENTER, RETURN, RETURN, VK_RETURN, 13, "RETURN"),
+ KEY_TRANS_ENTRY1(LCONTROL, LCTRL, LCONTROL, VK_LCONTROL, 0),
+ KEY_TRANS_ENTRY1(A, A, A, 'A', 'A'),
+ KEY_TRANS_ENTRY1(S, S, S, 'S', 'S'),
+ KEY_TRANS_ENTRY1(D, D, D, 'D', 'D'),
+ KEY_TRANS_ENTRY1(F, F, F, 'F', 'F'),
+ KEY_TRANS_ENTRY1(G, G, G, 'G', 'G'),
+ KEY_TRANS_ENTRY1(H, H, H, 'H', 'H'),
+ KEY_TRANS_ENTRY1(J, J, J, 'J', 'J'),
+ KEY_TRANS_ENTRY1(K, K, K, 'K', 'K'),
+ KEY_TRANS_ENTRY1(L, L, L, 'L', 'L'),
+ KEY_TRANS_ENTRY1(COLON, SEMICOLON, SEMICOLON, VK_OEM_1, ';'),
+ KEY_TRANS_ENTRY1(QUOTE, APOSTROPHE, APOSTROPHE, VK_OEM_7, '\''),
+ KEY_TRANS_ENTRY1(TILDE, GRAVE, GRAVE, VK_OEM_3, '`'),
+ KEY_TRANS_ENTRY1(LSHIFT, LSHIFT, LSHIFT, VK_LSHIFT, 0),
+ KEY_TRANS_ENTRY1(BACKSLASH, BACKSLASH, BACKSLASH, VK_OEM_5, '\\'),
+// KEY_TRANS_ENTRY1(BACKSLASH2, NONUSHASH, UNKNOWN, OEM_102, VK_OEM_102, '<'),
// This is the additional key that ISO keyboards have over ANSI ones, located between left shift and Y.
- KEY_TRANS_ENTRY1(BACKSLASH2, NONUSBACKSLASH, UNKNOWN, OEM_102, VK_OEM_102, '<'),
- KEY_TRANS_ENTRY1(Z, Z, z, Z, 'Z', 'Z'),
- KEY_TRANS_ENTRY1(X, X, x, X, 'X', 'X'),
- KEY_TRANS_ENTRY1(C, C, c, C, 'C', 'C'),
- KEY_TRANS_ENTRY1(V, V, v, V, 'V', 'V'),
- KEY_TRANS_ENTRY1(B, B, b, B, 'B', 'B'),
- KEY_TRANS_ENTRY1(N, N, n, N, 'N', 'N'),
- KEY_TRANS_ENTRY1(M, M, m, M, 'M', 'M'),
- KEY_TRANS_ENTRY1(COMMA, COMMA, COMMA, COMMA, VK_OEM_COMMA, ','),
- KEY_TRANS_ENTRY1(STOP, PERIOD, PERIOD, PERIOD, VK_OEM_PERIOD, '.'),
- KEY_TRANS_ENTRY1(SLASH, SLASH, SLASH, SLASH, VK_OEM_2, '/'),
- KEY_TRANS_ENTRY1(RSHIFT, RSHIFT, RSHIFT, RSHIFT, VK_RSHIFT, 0),
- KEY_TRANS_ENTRY1(ASTERISK, KP_MULTIPLY, KP_MULTIPLY, MULTIPLY, VK_MULTIPLY, '*'),
- KEY_TRANS_ENTRY1(LALT, LALT, LALT, LMENU, VK_LMENU, 0),
- KEY_TRANS_ENTRY1(SPACE, SPACE, SPACE, SPACE, VK_SPACE, ' '),
- KEY_TRANS_ENTRY1(CAPSLOCK, CAPSLOCK, CAPSLOCK, CAPITAL, VK_CAPITAL, 0),
- KEY_TRANS_ENTRY1(F1, F1, F1, F1, VK_F1, 0),
- KEY_TRANS_ENTRY1(F2, F2, F2, F2, VK_F2, 0),
- KEY_TRANS_ENTRY1(F3, F3, F3, F3, VK_F3, 0),
- KEY_TRANS_ENTRY1(F4, F4, F4, F4, VK_F4, 0),
- KEY_TRANS_ENTRY1(F5, F5, F5, F5, VK_F5, 0),
- KEY_TRANS_ENTRY1(F6, F6, F6, F6, VK_F6, 0),
- KEY_TRANS_ENTRY1(F7, F7, F7, F7, VK_F7, 0),
- KEY_TRANS_ENTRY1(F8, F8, F8, F8, VK_F8, 0),
- KEY_TRANS_ENTRY1(F9, F9, F9, F9, VK_F9, 0),
- KEY_TRANS_ENTRY1(F10, F10, F10, F10, VK_F10, 0),
- KEY_TRANS_ENTRY1(NUMLOCK, NUMLOCKCLEAR, NUMLOCKCLEAR, NUMLOCK, VK_NUMLOCK, 0),
- KEY_TRANS_ENTRY1(SCRLOCK, SCROLLLOCK, SCROLLLOCK, SCROLL, VK_SCROLL, 0),
- KEY_TRANS_ENTRY1(7_PAD, KP_7, KP_7, NUMPAD7, VK_NUMPAD7, 0),
- KEY_TRANS_ENTRY1(8_PAD, KP_8, KP_8, NUMPAD8, VK_NUMPAD8, 0),
- KEY_TRANS_ENTRY1(9_PAD, KP_9, KP_9, NUMPAD9, VK_NUMPAD9, 0),
- KEY_TRANS_ENTRY1(MINUS_PAD, KP_MINUS, KP_MINUS, SUBTRACT, VK_SUBTRACT, 0),
- KEY_TRANS_ENTRY1(4_PAD, KP_4, KP_4, NUMPAD4, VK_NUMPAD4, 0),
- KEY_TRANS_ENTRY1(5_PAD, KP_5, KP_5, NUMPAD5, VK_NUMPAD5, 0),
- KEY_TRANS_ENTRY1(6_PAD, KP_6, KP_6, NUMPAD6, VK_NUMPAD6, 0),
- KEY_TRANS_ENTRY1(PLUS_PAD, KP_PLUS, KP_PLUS, ADD, VK_ADD, 0),
- KEY_TRANS_ENTRY1(1_PAD, KP_1, KP_1, NUMPAD1, VK_NUMPAD1, 0),
- KEY_TRANS_ENTRY1(2_PAD, KP_2, KP_2, NUMPAD2, VK_NUMPAD2, 0),
- KEY_TRANS_ENTRY1(3_PAD, KP_3, KP_3, NUMPAD3, VK_NUMPAD3, 0),
- KEY_TRANS_ENTRY1(0_PAD, KP_0, KP_0, NUMPAD0, VK_NUMPAD0, 0),
- KEY_TRANS_ENTRY1(DEL_PAD, KP_PERIOD, KP_PERIOD, DECIMAL, VK_DECIMAL, 0),
- KEY_TRANS_ENTRY1(F11, F11, F11, F11, VK_F11, 0),
- KEY_TRANS_ENTRY1(F12, F12, F12, F12, VK_F12, 0),
- KEY_TRANS_ENTRY1(F13, F13, F13, F13, VK_F13, 0),
- KEY_TRANS_ENTRY1(F14, F14, F14, F14, VK_F14, 0),
- KEY_TRANS_ENTRY1(F15, F15, F15, F15, VK_F15, 0),
- KEY_TRANS_ENTRY1(ENTER_PAD, KP_ENTER, KP_ENTER, NUMPADENTER, VK_RETURN, 0),
- KEY_TRANS_ENTRY1(RCONTROL, RCTRL, RCTRL, RCONTROL, VK_RCONTROL, 0),
- KEY_TRANS_ENTRY1(SLASH_PAD, KP_DIVIDE, KP_DIVIDE, DIVIDE, VK_DIVIDE, 0),
- KEY_TRANS_ENTRY1(PRTSCR, PRINTSCREEN, PRINTSCREEN, SYSRQ, 0, 0),
- KEY_TRANS_ENTRY1(RALT, RALT, RALT, RMENU, VK_RMENU, 0),
- KEY_TRANS_ENTRY1(HOME, HOME, HOME, HOME, VK_HOME, 0),
- KEY_TRANS_ENTRY1(UP, UP, UP, UP, VK_UP, 0),
- KEY_TRANS_ENTRY1(PGUP, PAGEUP, PAGEUP, PRIOR, VK_PRIOR, 0),
- KEY_TRANS_ENTRY1(LEFT, LEFT, LEFT, LEFT, VK_LEFT, 0),
- KEY_TRANS_ENTRY1(RIGHT, RIGHT, RIGHT, RIGHT, VK_RIGHT, 0),
- KEY_TRANS_ENTRY1(END, END, END, END, VK_END, 0),
- KEY_TRANS_ENTRY1(DOWN, DOWN, DOWN, DOWN, VK_DOWN, 0),
- KEY_TRANS_ENTRY1(PGDN, PAGEDOWN, PAGEDOWN, NEXT, VK_NEXT, 0),
- KEY_TRANS_ENTRY1(INSERT, INSERT, INSERT, INSERT, VK_INSERT, 0),
- KEY_TRANS_ENTRY0(DEL, DELETE, DELETE, DELETE, VK_DELETE, 0, "DELETE"),
- KEY_TRANS_ENTRY1(LWIN, LGUI, LGUI, LWIN, VK_LWIN, 0),
- KEY_TRANS_ENTRY1(RWIN, RGUI, RGUI, RWIN, VK_RWIN, 0),
- KEY_TRANS_ENTRY1(MENU, MENU, MENU, APPS, VK_APPS, 0),
- KEY_TRANS_ENTRY1(PAUSE, PAUSE, PAUSE, PAUSE, VK_PAUSE, 0),
- KEY_TRANS_ENTRY0(CANCEL, CANCEL, CANCEL, UNKNOWN, 0, 0, "CANCEL"),
- KEY_TRANS_ENTRY1(BS_PAD, KP_BACKSPACE, KP_BACKSPACE, UNKNOWN, 0, 0),
- KEY_TRANS_ENTRY1(TAB_PAD, KP_TAB, KP_TAB, UNKNOWN, 0, 0),
- KEY_TRANS_ENTRY1(00_PAD, KP_00, KP_00, UNKNOWN, 0, 0),
- KEY_TRANS_ENTRY1(000_PAD, KP_000, KP_000, UNKNOWN, 0, 0),
- KEY_TRANS_ENTRY1(COMMA_PAD, KP_COMMA, KP_COMMA, NUMPADCOMMA, 0, 0),
- KEY_TRANS_ENTRY1(EQUALS_PAD, KP_EQUALS, KP_EQUALS, NUMPADEQUALS, 0, 0),
-
- // New keys introduced in Windows 2000. These have no MAME codes to
- // preserve compatibility with old config files that may refer to them
- // as e.g. FORWARD instead of e.g. KEYCODE_WEBFORWARD. They need table
- // entries anyway because otherwise they aren't recognized when
- // GetAsyncKeyState polling is used (as happens currently when MAME is
- // paused). Some codes are missing because the mapping to vkey codes
- // isn't clear, and MapVirtualKey is no help.
- KEY_TRANS_ENTRY1(OTHER_SWITCH, MUTE, MUTE, MUTE, VK_VOLUME_MUTE, 0),
- KEY_TRANS_ENTRY1(OTHER_SWITCH, VOLUMEDOWN, VOLUMEDOWN, VOLUMEDOWN, VK_VOLUME_DOWN, 0),
- KEY_TRANS_ENTRY1(OTHER_SWITCH, VOLUMEUP, VOLUMEUP, VOLUMEUP, VK_VOLUME_UP, 0),
- KEY_TRANS_ENTRY1(OTHER_SWITCH, AC_HOME, AC_HOME, WEBHOME, VK_BROWSER_HOME, 0),
- KEY_TRANS_ENTRY1(OTHER_SWITCH, AC_SEARCH, AC_SEARCH, WEBSEARCH, VK_BROWSER_SEARCH, 0),
- KEY_TRANS_ENTRY1(OTHER_SWITCH, AC_BOOKMARKS, AC_BOOKMARKS, WEBFAVORITES, VK_BROWSER_FAVORITES, 0),
- KEY_TRANS_ENTRY1(OTHER_SWITCH, AC_REFRESH, AC_REFRESH, WEBREFRESH, VK_BROWSER_REFRESH, 0),
- KEY_TRANS_ENTRY1(OTHER_SWITCH, AC_STOP, AC_STOP, WEBSTOP, VK_BROWSER_STOP, 0),
- KEY_TRANS_ENTRY1(OTHER_SWITCH, AC_FORWARD, AC_FORWARD, WEBFORWARD, VK_BROWSER_FORWARD, 0),
- KEY_TRANS_ENTRY1(OTHER_SWITCH, AC_BACK, AC_BACK, WEBBACK, VK_BROWSER_BACK, 0),
- KEY_TRANS_ENTRY1(OTHER_SWITCH, MAIL, MAIL, MAIL, VK_LAUNCH_MAIL, 0),
- KEY_TRANS_ENTRY1(OTHER_SWITCH, MEDIASELECT, MEDIASELECT, MEDIASELECT, VK_LAUNCH_MEDIA_SELECT, 0),
- KEY_TRANS_ENTRY0(INVALID, UNKNOWN, UNKNOWN, ESCAPE, 0, 0, "INVALID")
+ KEY_TRANS_ENTRY1(BACKSLASH2, NONUSBACKSLASH, OEM_102, VK_OEM_102, '<'),
+ KEY_TRANS_ENTRY1(Z, Z, Z, 'Z', 'Z'),
+ KEY_TRANS_ENTRY1(X, X, X, 'X', 'X'),
+ KEY_TRANS_ENTRY1(C, C, C, 'C', 'C'),
+ KEY_TRANS_ENTRY1(V, V, V, 'V', 'V'),
+ KEY_TRANS_ENTRY1(B, B, B, 'B', 'B'),
+ KEY_TRANS_ENTRY1(N, N, N, 'N', 'N'),
+ KEY_TRANS_ENTRY1(M, M, M, 'M', 'M'),
+ KEY_TRANS_ENTRY1(COMMA, COMMA, COMMA, VK_OEM_COMMA, ','),
+ KEY_TRANS_ENTRY1(STOP, PERIOD, PERIOD, VK_OEM_PERIOD, '.'),
+ KEY_TRANS_ENTRY1(SLASH, SLASH, SLASH, VK_OEM_2, '/'),
+ KEY_TRANS_ENTRY1(RSHIFT, RSHIFT, RSHIFT, VK_RSHIFT, 0),
+ KEY_TRANS_ENTRY1(ASTERISK, KP_MULTIPLY, MULTIPLY, VK_MULTIPLY, '*'),
+ KEY_TRANS_ENTRY1(LALT, LALT, LMENU, VK_LMENU, 0),
+ KEY_TRANS_ENTRY1(SPACE, SPACE, SPACE, VK_SPACE, ' '),
+ KEY_TRANS_ENTRY1(CAPSLOCK, CAPSLOCK, CAPITAL, VK_CAPITAL, 0),
+ KEY_TRANS_ENTRY1(F1, F1, F1, VK_F1, 0),
+ KEY_TRANS_ENTRY1(F2, F2, F2, VK_F2, 0),
+ KEY_TRANS_ENTRY1(F3, F3, F3, VK_F3, 0),
+ KEY_TRANS_ENTRY1(F4, F4, F4, VK_F4, 0),
+ KEY_TRANS_ENTRY1(F5, F5, F5, VK_F5, 0),
+ KEY_TRANS_ENTRY1(F6, F6, F6, VK_F6, 0),
+ KEY_TRANS_ENTRY1(F7, F7, F7, VK_F7, 0),
+ KEY_TRANS_ENTRY1(F8, F8, F8, VK_F8, 0),
+ KEY_TRANS_ENTRY1(F9, F9, F9, VK_F9, 0),
+ KEY_TRANS_ENTRY1(F10, F10, F10, VK_F10, 0),
+ KEY_TRANS_ENTRY1(NUMLOCK, NUMLOCKCLEAR, NUMLOCK, VK_NUMLOCK, 0),
+ KEY_TRANS_ENTRY1(SCRLOCK, SCROLLLOCK, SCROLL, VK_SCROLL, 0),
+ KEY_TRANS_ENTRY1(7_PAD, KP_7, NUMPAD7, VK_NUMPAD7, 0),
+ KEY_TRANS_ENTRY1(8_PAD, KP_8, NUMPAD8, VK_NUMPAD8, 0),
+ KEY_TRANS_ENTRY1(9_PAD, KP_9, NUMPAD9, VK_NUMPAD9, 0),
+ KEY_TRANS_ENTRY1(MINUS_PAD, KP_MINUS, SUBTRACT, VK_SUBTRACT, 0),
+ KEY_TRANS_ENTRY1(4_PAD, KP_4, NUMPAD4, VK_NUMPAD4, 0),
+ KEY_TRANS_ENTRY1(5_PAD, KP_5, NUMPAD5, VK_NUMPAD5, 0),
+ KEY_TRANS_ENTRY1(6_PAD, KP_6, NUMPAD6, VK_NUMPAD6, 0),
+ KEY_TRANS_ENTRY1(PLUS_PAD, KP_PLUS, ADD, VK_ADD, 0),
+ KEY_TRANS_ENTRY1(1_PAD, KP_1, NUMPAD1, VK_NUMPAD1, 0),
+ KEY_TRANS_ENTRY1(2_PAD, KP_2, NUMPAD2, VK_NUMPAD2, 0),
+ KEY_TRANS_ENTRY1(3_PAD, KP_3, NUMPAD3, VK_NUMPAD3, 0),
+ KEY_TRANS_ENTRY1(0_PAD, KP_0, NUMPAD0, VK_NUMPAD0, 0),
+ KEY_TRANS_ENTRY1(DEL_PAD, KP_PERIOD, DECIMAL, VK_DECIMAL, 0),
+ KEY_TRANS_ENTRY1(F11, F11, F11, VK_F11, 0),
+ KEY_TRANS_ENTRY1(F12, F12, F12, VK_F12, 0),
+ KEY_TRANS_ENTRY1(F13, F13, F13, VK_F13, 0),
+ KEY_TRANS_ENTRY1(F14, F14, F14, VK_F14, 0),
+ KEY_TRANS_ENTRY1(F15, F15, F15, VK_F15, 0),
+ KEY_TRANS_ENTRY1(ENTER_PAD, KP_ENTER, NUMPADENTER, VK_RETURN, 0),
+ KEY_TRANS_ENTRY1(RCONTROL, RCTRL, RCONTROL, VK_RCONTROL, 0),
+ KEY_TRANS_ENTRY1(SLASH_PAD, KP_DIVIDE, DIVIDE, VK_DIVIDE, 0),
+ KEY_TRANS_ENTRY1(PRTSCR, PRINTSCREEN, SYSRQ, 0, 0),
+ KEY_TRANS_ENTRY1(RALT, RALT, RMENU, VK_RMENU, 0),
+ KEY_TRANS_ENTRY1(HOME, HOME, HOME, VK_HOME, 0),
+ KEY_TRANS_ENTRY1(UP, UP, UP, VK_UP, 0),
+ KEY_TRANS_ENTRY1(PGUP, PAGEUP, PRIOR, VK_PRIOR, 0),
+ KEY_TRANS_ENTRY1(LEFT, LEFT, LEFT, VK_LEFT, 0),
+ KEY_TRANS_ENTRY1(RIGHT, RIGHT, RIGHT, VK_RIGHT, 0),
+ KEY_TRANS_ENTRY1(END, END, END, VK_END, 0),
+ KEY_TRANS_ENTRY1(DOWN, DOWN, DOWN, VK_DOWN, 0),
+ KEY_TRANS_ENTRY1(PGDN, PAGEDOWN, NEXT, VK_NEXT, 0),
+ KEY_TRANS_ENTRY1(INSERT, INSERT, INSERT, VK_INSERT, 0),
+ KEY_TRANS_ENTRY0(DEL, DELETE, DELETE, VK_DELETE, 0, "DELETE"),
+ KEY_TRANS_ENTRY1(LWIN, LGUI, LWIN, VK_LWIN, 0),
+ KEY_TRANS_ENTRY1(RWIN, RGUI, RWIN, VK_RWIN, 0),
+ KEY_TRANS_ENTRY1(MENU, MENU, APPS, VK_APPS, 0),
+ KEY_TRANS_ENTRY1(PAUSE, PAUSE, PAUSE, VK_PAUSE, 0),
+ KEY_TRANS_ENTRY1(CANCEL, CANCEL, UNKNOWN, 0, 0),
+ KEY_TRANS_ENTRY1(BS_PAD, KP_BACKSPACE, UNKNOWN, 0, 0),
+ KEY_TRANS_ENTRY1(TAB_PAD, KP_TAB, UNKNOWN, 0, 0),
+ KEY_TRANS_ENTRY1(00_PAD, KP_00, UNKNOWN, 0, 0),
+ KEY_TRANS_ENTRY1(000_PAD, KP_000, UNKNOWN, 0, 0),
+ KEY_TRANS_ENTRY1(COMMA_PAD, KP_COMMA, NUMPADCOMMA, VK_SEPARATOR, 0),
+ KEY_TRANS_ENTRY1(EQUALS_PAD, KP_EQUALS, NUMPADEQUALS, VK_OEM_NEC_EQUAL, 0),
+
+ // keys that have no specific MAME input item IDs
+ KEY_TRANS_ENTRY0(OTHER_SWITCH, AUDIONEXT, NEXTTRACK, VK_MEDIA_NEXT_TRACK, 0, "AUDIONEXT"),
+ KEY_TRANS_ENTRY0(OTHER_SWITCH, AUDIOMUTE, MUTE, VK_VOLUME_MUTE, 0, "VOLUMEMUTE"),
+ KEY_TRANS_ENTRY0(OTHER_SWITCH, AUDIOPLAY, PLAYPAUSE, VK_MEDIA_PLAY_PAUSE, 0, "AUDIOPLAY"),
+ KEY_TRANS_ENTRY0(OTHER_SWITCH, AUDIOSTOP, MEDIASTOP, VK_MEDIA_STOP, 0, "AUDIOSTOP"),
+ KEY_TRANS_ENTRY0(OTHER_SWITCH, VOLUMEDOWN, VOLUMEDOWN, VK_VOLUME_DOWN, 0, "VOLUMEDOWN"),
+ KEY_TRANS_ENTRY0(OTHER_SWITCH, VOLUMEUP, VOLUMEUP, VK_VOLUME_UP, 0, "VOLUMEUP"),
+ KEY_TRANS_ENTRY0(OTHER_SWITCH, AC_HOME, WEBHOME, VK_BROWSER_HOME, 0, "NAVHOME"),
+ KEY_TRANS_ENTRY0(OTHER_SWITCH, AC_SEARCH, WEBSEARCH, VK_BROWSER_SEARCH, 0, "NAVSEARCH"),
+ KEY_TRANS_ENTRY0(OTHER_SWITCH, AC_BOOKMARKS, WEBFAVORITES, VK_BROWSER_FAVORITES, 0, "NAVFAVORITES"),
+ KEY_TRANS_ENTRY0(OTHER_SWITCH, AC_REFRESH, WEBREFRESH, VK_BROWSER_REFRESH, 0, "NAVREFRESH"),
+ KEY_TRANS_ENTRY0(OTHER_SWITCH, AC_STOP, WEBSTOP, VK_BROWSER_STOP, 0, "NAVSTOP"),
+ KEY_TRANS_ENTRY0(OTHER_SWITCH, AC_FORWARD, WEBFORWARD, VK_BROWSER_FORWARD, 0, "NAVFORWARD"),
+ KEY_TRANS_ENTRY0(OTHER_SWITCH, AC_BACK, WEBBACK, VK_BROWSER_BACK, 0, "NAVBACK"),
+ KEY_TRANS_ENTRY0(OTHER_SWITCH, MAIL, MAIL, VK_LAUNCH_MAIL, 0, "MAIL"),
+ KEY_TRANS_ENTRY0(OTHER_SWITCH, MEDIASELECT, MEDIASELECT, VK_LAUNCH_MEDIA_SELECT, 0, "MEDIASEL"),
+
+ // sentinel
+ KEY_TRANS_ENTRY0(INVALID, UNKNOWN, UNKNOWN, 0, 0, "INVALID")
};
// The private constructor to create the default instance
@@ -190,14 +192,18 @@ keyboard_trans_table::keyboard_trans_table()
m_table = s_default_table;
m_table_size = std::size(s_default_table);
}
-#else
+
+#else // defined(OSD_WINDOWS) || defined(OSD_SDL)
+
keyboard_trans_table::keyboard_trans_table()
{
m_table = nullptr;
m_table_size = 0;
}
-#endif
+#endif // defined(OSD_WINDOWS) || defined(OSD_SDL)
+
+
// public constructor to allow creation of non-default instances
keyboard_trans_table::keyboard_trans_table(std::unique_ptr<key_trans_entry[]> entries, unsigned int size)
{
@@ -226,14 +232,12 @@ input_item_id keyboard_trans_table::lookup_mame_code(const char *scode) const
}
// Windows specific lookup methods
-#if defined(OSD_WINDOWS)
+#if defined(OSD_WINDOWS) || defined(SDLMAME_WIN32)
input_item_id keyboard_trans_table::map_di_scancode_to_itemid(int scancode) const
{
- int tablenum;
-
// scan the table for a match
- for (tablenum = 0; tablenum < m_table_size; tablenum++)
+ for (int tablenum = 0; tablenum < m_table_size; tablenum++)
if (m_table[tablenum].scan_code == scancode)
return m_table[tablenum].mame_key;
@@ -250,75 +254,53 @@ int keyboard_trans_table::vkey_for_mame_code(input_code code) const
// only works for keyboard switches
if (code.device_class() == DEVICE_CLASS_KEYBOARD && code.item_class() == ITEM_CLASS_SWITCH)
{
- input_item_id id = code.item_id();
- int tablenum;
+ const input_item_id id = code.item_id();
// scan the table for a match
- for (tablenum = 0; tablenum < m_table_size; tablenum++)
+ for (int tablenum = 0; tablenum < m_table_size; tablenum++)
if (m_table[tablenum].mame_key == id)
return m_table[tablenum].virtual_key;
}
return 0;
}
-#endif
+#endif // defined(OSD_WINDOWS) || defined(SDLMAME_WIN32)
-int input_module_base::init(const osd_options &options)
+input_module_base::input_module_base(const char *type, const char* name) :
+ osd_module(type, name),
+ m_clock(),
+ m_last_poll(timepoint_type::min()),
+ m_background_input(false),
+ m_options(nullptr),
+ m_manager(nullptr)
{
- m_options = &options;
-
- m_mouse_enabled = options.mouse();
- m_lightgun_enabled = options.lightgun();
-
- int result = init_internal();
- if (result != 0)
- return result;
-
- m_input_paused = false;
- m_input_enabled = true;
-
- return 0;
}
-void input_module_base::poll(running_machine &machine)
+int input_module_base::init(osd_interface &osd, const osd_options &options)
{
- // ignore if not enabled
- if (m_input_enabled)
- {
- // grab the current time
- m_last_poll = m_clock.now();
-
- before_poll(machine);
+ m_options = &options;
- // track if mouse/lightgun is enabled, for mouse hiding purposes
- m_mouse_enabled = machine.input().device_class(DEVICE_CLASS_MOUSE).enabled();
- m_lightgun_enabled = machine.input().device_class(DEVICE_CLASS_LIGHTGUN).enabled();
- }
+ // don't enable background input when debugging
+ m_background_input = !options.debug() && options.background_input();
- // poll all of the devices
- if (should_poll_devices(machine))
- {
- m_devicelist.poll_devices();
- }
- else
- {
- m_devicelist.reset_devices();
- }
+ return 0;
}
-void input_module_base::pause()
+void input_module_base::input_init(running_machine &machine)
{
- // keep track of the paused state
- m_input_paused = true;
+ m_manager = &machine.input();
}
-void input_module_base::resume()
+void input_module_base::poll_if_necessary(bool relative_reset)
{
- // keep track of the paused state
- m_input_paused = false;
-}
+ timepoint_type const now = m_clock.now();
+ if (relative_reset || (now >= (m_last_poll + std::chrono::milliseconds(MIN_POLLING_INTERVAL))))
+ {
+ // grab the current time
+ m_last_poll = now;
-void input_module_base::exit()
-{
- devicelist().free_all_devices();
+ before_poll();
+
+ poll(relative_reset);
+ }
}
diff --git a/src/osd/modules/input/input_common.h b/src/osd/modules/input/input_common.h
index e220445c266..28e53fb0ccb 100644
--- a/src/osd/modules/input/input_common.h
+++ b/src/osd/modules/input/input_common.h
@@ -14,9 +14,14 @@
#include "input_module.h"
+#include "interface/inputdev.h"
#include "interface/inputman.h"
+#include "modules/osdmodule.h"
+
+#include "util/strformat.h"
#include <algorithm>
+#include <cassert>
#include <chrono>
#include <functional>
#include <memory>
@@ -42,225 +47,66 @@ enum
#define MAX_HATS 8
#define MAX_POV 4
-/****************************************************************************
-* DirectInput compatible keyboard scan codes
-****************************************************************************/
-#define KEY_UNKNOWN 0x00
-#define KEY_ESCAPE 0x01
-#define KEY_1 0x02
-#define KEY_2 0x03
-#define KEY_3 0x04
-#define KEY_4 0x05
-#define KEY_5 0x06
-#define KEY_6 0x07
-#define KEY_7 0x08
-#define KEY_8 0x09
-#define KEY_9 0x0A
-#define KEY_0 0x0B
-#define KEY_MINUS 0x0C /* - on main keyboard */
-#define KEY_EQUALS 0x0D
-#define KEY_BACK 0x0E /* backspace */
-#define KEY_TAB 0x0F
-#define KEY_Q 0x10
-#define KEY_W 0x11
-#define KEY_E 0x12
-#define KEY_R 0x13
-#define KEY_T 0x14
-#define KEY_Y 0x15
-#define KEY_U 0x16
-#define KEY_I 0x17
-#define KEY_O 0x18
-#define KEY_P 0x19
-#define KEY_LBRACKET 0x1A
-#define KEY_RBRACKET 0x1B
-#define KEY_RETURN 0x1C /* Enter on main keyboard */
-#define KEY_LCONTROL 0x1D
-#define KEY_A 0x1E
-#define KEY_S 0x1F
-#define KEY_D 0x20
-#define KEY_F 0x21
-#define KEY_G 0x22
-#define KEY_H 0x23
-#define KEY_J 0x24
-#define KEY_K 0x25
-#define KEY_L 0x26
-#define KEY_SEMICOLON 0x27
-#define KEY_APOSTROPHE 0x28
-#define KEY_GRAVE 0x29 /* accent grave */
-#define KEY_LSHIFT 0x2A
-#define KEY_BACKSLASH 0x2B
-#define KEY_Z 0x2C
-#define KEY_X 0x2D
-#define KEY_C 0x2E
-#define KEY_V 0x2F
-#define KEY_B 0x30
-#define KEY_N 0x31
-#define KEY_M 0x32
-#define KEY_COMMA 0x33
-#define KEY_PERIOD 0x34 /* . on main keyboard */
-#define KEY_SLASH 0x35 /* / on main keyboard */
-#define KEY_RSHIFT 0x36
-#define KEY_MULTIPLY 0x37 /* * on numeric keypad */
-#define KEY_LMENU 0x38 /* left Alt */
-#define KEY_SPACE 0x39
-#define KEY_CAPITAL 0x3A
-#define KEY_F1 0x3B
-#define KEY_F2 0x3C
-#define KEY_F3 0x3D
-#define KEY_F4 0x3E
-#define KEY_F5 0x3F
-#define KEY_F6 0x40
-#define KEY_F7 0x41
-#define KEY_F8 0x42
-#define KEY_F9 0x43
-#define KEY_F10 0x44
-#define KEY_NUMLOCK 0x45
-#define KEY_SCROLL 0x46 /* Scroll Lock */
-#define KEY_NUMPAD7 0x47
-#define KEY_NUMPAD8 0x48
-#define KEY_NUMPAD9 0x49
-#define KEY_SUBTRACT 0x4A /* - on numeric keypad */
-#define KEY_NUMPAD4 0x4B
-#define KEY_NUMPAD5 0x4C
-#define KEY_NUMPAD6 0x4D
-#define KEY_ADD 0x4E /* + on numeric keypad */
-#define KEY_NUMPAD1 0x4F
-#define KEY_NUMPAD2 0x50
-#define KEY_NUMPAD3 0x51
-#define KEY_NUMPAD0 0x52
-#define KEY_DECIMAL 0x53 /* . on numeric keypad */
-#define KEY_OEM_102 0x56 /* <> or \| on RT 102-key keyboard (Non-U.S.) */
-#define KEY_F11 0x57
-#define KEY_F12 0x58
-#define KEY_F13 0x64 /* (NEC PC98) */
-#define KEY_F14 0x65 /* (NEC PC98) */
-#define KEY_F15 0x66 /* (NEC PC98) */
-#define KEY_KANA 0x70 /* (Japanese keyboard) */
-#define KEY_ABNT_C1 0x73 /* /? on Brazilian keyboard */
-#define KEY_CONVERT 0x79 /* (Japanese keyboard) */
-#define KEY_NOCONVERT 0x7B /* (Japanese keyboard) */
-#define KEY_YEN 0x7D /* (Japanese keyboard) */
-#define KEY_ABNT_C2 0x7E /* Numpad . on Brazilian keyboard */
-#define KEY_NUMPADEQUALS 0x8D /* = on numeric keypad (NEC PC98) */
-#define KEY_PREVTRACK 0x90 /* Previous Track (DIK_CIRCUMFLEX on Japanese keyboard) */
-#define KEY_AT 0x91 /* (NEC PC98) */
-#define KEY_COLON 0x92 /* (NEC PC98) */
-#define KEY_UNDERLINE 0x93 /* (NEC PC98) */
-#define KEY_KANJI 0x94 /* (Japanese keyboard) */
-#define KEY_STOP 0x95 /* (NEC PC98) */
-#define KEY_AX 0x96 /* (Japan AX) */
-#define KEY_UNLABELED 0x97 /* (J3100) */
-#define KEY_NEXTTRACK 0x99 /* Next Track */
-#define KEY_NUMPADENTER 0x9C /* Enter on numeric keypad */
-#define KEY_RCONTROL 0x9D
-#define KEY_MUTE 0xA0 /* Mute */
-#define KEY_CALCULATOR 0xA1 /* Calculator */
-#define KEY_PLAYPAUSE 0xA2 /* Play / Pause */
-#define KEY_MEDIASTOP 0xA4 /* Media Stop */
-#define KEY_VOLUMEDOWN 0xAE /* Volume - */
-#define KEY_VOLUMEUP 0xB0 /* Volume + */
-#define KEY_WEBHOME 0xB2 /* Web home */
-#define KEY_NUMPADCOMMA 0xB3 /* , on numeric keypad (NEC PC98) */
-#define KEY_DIVIDE 0xB5 /* / on numeric keypad */
-#define KEY_SYSRQ 0xB7
-#define KEY_RMENU 0xB8 /* right Alt */
-#define KEY_PAUSE 0xC5 /* Pause */
-#define KEY_HOME 0xC7 /* Home on arrow keypad */
-#define KEY_UP 0xC8 /* UpArrow on arrow keypad */
-#define KEY_PRIOR 0xC9 /* PgUp on arrow keypad */
-#define KEY_LEFT 0xCB /* LeftArrow on arrow keypad */
-#define KEY_RIGHT 0xCD /* RightArrow on arrow keypad */
-#define KEY_END 0xCF /* End on arrow keypad */
-#define KEY_DOWN 0xD0 /* DownArrow on arrow keypad */
-#define KEY_NEXT 0xD1 /* PgDn on arrow keypad */
-#define KEY_INSERT 0xD2 /* Insert on arrow keypad */
-#define KEY_DELETE 0xD3 /* Delete on arrow keypad */
-#define KEY_LWIN 0xDB /* Left Windows key */
-#define KEY_RWIN 0xDC /* Right Windows key */
-#define KEY_APPS 0xDD /* AppMenu key */
-#define KEY_POWER 0xDE /* System Power */
-#define KEY_SLEEP 0xDF /* System Sleep */
-#define KEY_WAKE 0xE3 /* System Wake */
-#define KEY_WEBSEARCH 0xE5 /* Web Search */
-#define KEY_WEBFAVORITES 0xE6 /* Web Favorites */
-#define KEY_WEBREFRESH 0xE7 /* Web Refresh */
-#define KEY_WEBSTOP 0xE8 /* Web Stop */
-#define KEY_WEBFORWARD 0xE9 /* Web Forward */
-#define KEY_WEBBACK 0xEA /* Web Back */
-#define KEY_MYCOMPUTER 0xEB /* My Computer */
-#define KEY_MAIL 0xEC /* Mail */
-#define KEY_MEDIASELECT 0xED /* Media Select */
//============================================================
// device_info
//============================================================
-class input_device_list;
-
class device_info
{
- friend input_device_list;
-
private:
const std::string m_name;
const std::string m_id;
- osd::input_device * m_device;
- running_machine & m_machine;
input_module & m_module;
- input_device_class m_deviceclass;
public:
// Constructor
- device_info(running_machine &machine, std::string &&name, std::string &&id, input_device_class deviceclass, input_module &module) :
+ device_info(std::string &&name, std::string &&id, input_module &module) :
m_name(std::move(name)),
m_id(std::move(id)),
- m_device(nullptr),
- m_machine(machine),
- m_module(module),
- m_deviceclass(deviceclass)
+ m_module(module)
{
}
// Destructor
- virtual ~device_info() { }
+ virtual ~device_info() = default;
// Getters
- running_machine & machine() const { return m_machine; }
- const std::string & name() const { return m_name; }
- const std::string & id() const { return m_id; }
- osd::input_device * device() const { return m_device; }
- input_module & module() const { return m_module; }
- input_device_class deviceclass() const { return m_deviceclass; }
+ const std::string &name() const { return m_name; }
+ const std::string &id() const { return m_id; }
+ input_module &module() const { return m_module; }
// Poll and reset methods
- virtual void poll() { }
+ virtual void poll(bool relative_reset) = 0;
virtual void reset() = 0;
+ virtual void configure(osd::input_device &device) = 0;
};
+
//============================================================
// event_based_device
//============================================================
-#define DEFAULT_EVENT_QUEUE_SIZE 20
-
template <class TEvent>
class event_based_device : public device_info
{
private:
- std::queue<TEvent> m_event_queue;
+ static inline constexpr unsigned DEFAULT_EVENT_QUEUE_SIZE = 20;
+
+ std::queue<TEvent> m_event_queue;
protected:
std::mutex m_device_lock;
- virtual void process_event(TEvent &ev) = 0;
+ virtual void process_event(TEvent const &ev) = 0;
public:
- event_based_device(running_machine &machine, std::string &&name, std::string &&id, input_device_class deviceclass, input_module &module) :
- device_info(machine, std::move(name), std::move(id), deviceclass, module)
+ event_based_device(std::string &&name, std::string &&id, input_module &module) :
+ device_info(std::move(name), std::move(id), module)
{
}
- void queue_events(const TEvent *events, int count)
+ void queue_events(TEvent const *events, int count)
{
std::lock_guard<std::mutex> scope_lock(m_device_lock);
for (int i = 0; i < count; i++)
@@ -271,39 +117,40 @@ public:
m_event_queue.pop();
}
- void virtual poll() override
+ void virtual poll(bool relative_reset) override
{
std::lock_guard<std::mutex> scope_lock(m_device_lock);
// Process each event until the queue is empty
while (!m_event_queue.empty())
{
- TEvent &next_event = m_event_queue.front();
- process_event(next_event);
+ process_event(m_event_queue.front());
m_event_queue.pop();
}
}
};
+
//============================================================
// input_device_list class
//============================================================
+template <typename Info>
class input_device_list
{
private:
- std::vector<std::unique_ptr<device_info>> m_list;
+ std::vector<std::unique_ptr<Info> > m_list;
public:
auto size() const { return m_list.size(); }
auto empty() const { return m_list.empty(); }
- auto begin() { return m_list.begin(); }
- auto end() { return m_list.end(); }
+ auto begin() const { return m_list.begin(); }
+ auto end() const { return m_list.end(); }
- void poll_devices()
+ void poll_devices(bool relative_reset)
{
for (auto &device: m_list)
- device->poll();
+ device->poll(relative_reset);
}
void reset_devices()
@@ -312,18 +159,11 @@ public:
device->reset();
}
- void free_device(device_info &devinfo)
- {
- // find the device to remove
- const auto device_matches = [&devinfo] (std::unique_ptr<device_info> &device) { return &devinfo == device.get(); };
- m_list.erase(std::remove_if(std::begin(m_list), std::end(m_list), device_matches), m_list.end());
- }
-
template <typename T>
void for_each_device(T &&action)
{
for (auto &device: m_list)
- action(device.get());
+ action(*device);
}
void free_all_devices()
@@ -332,41 +172,34 @@ public:
m_list.pop_back();
}
- template <typename TActual, typename... TArgs>
- TActual &create_device(running_machine &machine, std::string &&name, std::string &&id, input_module &module, TArgs &&... args)
+ template <typename Actual>
+ Actual &add_device(std::unique_ptr<Actual> &&devinfo)
{
- // allocate the device object
- auto devinfo = std::make_unique<TActual>(machine, std::move(name), std::move(id), module, std::forward<TArgs>(args)...);
-
- return add_device(machine.input(), std::move(devinfo));
- }
-
- template <typename TActual>
- TActual &add_device(osd::input_manager &manager, std::unique_ptr<TActual> &&devinfo)
- {
- // Add the device to the machine
- devinfo->m_device = &manager.add_device(devinfo->deviceclass(), devinfo->name(), devinfo->id(), devinfo.get());
-
- // append us to the list
- return *static_cast<TActual *>(m_list.emplace_back(std::move(devinfo)).get());
+ // append us to the list and return reference
+ Actual &result = *devinfo;
+ m_list.emplace_back(std::move(devinfo));
+ return result;
}
};
+
// keyboard translation table
-struct key_trans_entry {
+struct key_trans_entry
+{
input_item_id mame_key;
-#if defined(OSD_SDL)
+#if defined(OSD_SDL) || defined(SDLMAME_WIN32)
int sdl_scancode;
-#elif defined(OSD_WINDOWS)
- int scan_code;
+#endif
+#if defined(OSD_WINDOWS) || defined(SDLMAME_WIN32)
+ uint16_t scan_code;
unsigned char virtual_key;
#endif
char ascii_key;
- char const * mame_key_name;
- char * ui_name;
+ char const * mame_key_name;
+ char const * ui_name;
};
class keyboard_trans_table
@@ -379,7 +212,7 @@ private:
std::unique_ptr<key_trans_entry[]> m_custom_table;
key_trans_entry * m_table;
- uint32_t m_table_size;
+ uint32_t m_table_size;
public:
// constructor
@@ -392,7 +225,7 @@ public:
input_item_id lookup_mame_code(const char * scode) const;
int lookup_mame_index(const char * scode) const;
-#if defined(OSD_WINDOWS)
+#if defined(OSD_WINDOWS) || defined(SDLMAME_WIN32)
input_item_id map_di_scancode_to_itemid(int di_scancode) const;
int vkey_for_mame_code(input_code code) const;
#endif
@@ -406,97 +239,137 @@ public:
key_trans_entry & operator [](int i) const { return m_table[i]; }
};
+
//============================================================
// input_module_base - base class for input modules
//============================================================
-class osd_options;
+class input_module_base : public osd_module, public input_module
+{
+private:
+ // 10 milliseconds polling interval
+ static constexpr inline unsigned MIN_POLLING_INTERVAL = 2;
-typedef std::chrono::high_resolution_clock clock_type;
-typedef std::chrono::time_point<std::chrono::high_resolution_clock> timepoint_type;
+ using clock_type = std::chrono::high_resolution_clock;
+ using timepoint_type = std::chrono::time_point<std::chrono::high_resolution_clock>;
-// 10 milliseconds polling interval
-#define MIN_POLLING_INTERVAL 10
+ clock_type m_clock;
+ timepoint_type m_last_poll;
+ bool m_background_input;
+ const osd_options * m_options;
+ osd::input_manager * m_manager;
+
+ virtual void poll(bool relative_reset) = 0;
+
+protected:
+ input_module_base(char const *type, char const *name);
+
+ osd::input_manager & manager() { assert(m_manager); return *m_manager; }
+ const osd_options * options() const { return m_options; }
+ bool background_input() const { return m_background_input; }
+
+ virtual void before_poll() { }
+
+public:
+ virtual int init(osd_interface &osd, const osd_options &options) override;
+
+ virtual void input_init(running_machine &machine) override;
+ virtual void poll_if_necessary(bool relative_reset) override;
+
+ virtual void reset_devices() = 0; // SDL OSD uses this to forcibly release keys
+};
-class input_module_base : public input_module
+
+//============================================================
+// input_module_impl - base class for input modules
+//============================================================
+
+template <typename Info, typename OsdImpl>
+class input_module_impl : public input_module_base
{
public:
- input_module_base(const char *type, const char* name) :
- input_module(type, name),
- m_input_enabled(false),
- m_mouse_enabled(false),
- m_lightgun_enabled(false),
- m_input_paused(false),
- m_options(nullptr)
+ virtual void exit() override
{
+ devicelist().free_all_devices();
}
-private:
- bool m_input_enabled;
- bool m_mouse_enabled;
- bool m_lightgun_enabled;
- bool m_input_paused;
- const osd_options * m_options;
- input_device_list m_devicelist;
- clock_type m_clock;
- timepoint_type m_last_poll;
+ virtual int init(osd_interface &osd, const osd_options &options) override
+ {
+ m_osd = dynamic_cast<OsdImpl *>(&osd);
+ if (!m_osd)
+ return -1;
+
+ return input_module_base::init(osd, options);
+ }
+
+ virtual void reset_devices() override { devicelist().reset_devices(); }
protected:
- void set_mouse_enabled(bool value) { m_mouse_enabled = value; }
+ using input_module_base::input_module_base;
-public:
+ input_device_list<Info> &devicelist() { return m_devicelist; }
+ OsdImpl &osd() { assert(m_osd); return *m_osd; }
- const osd_options * options() const { return m_options; }
- input_device_list & devicelist() { return m_devicelist; }
- bool input_enabled() const { return m_input_enabled; }
- bool input_paused() const { return m_input_paused; }
- bool mouse_enabled() const { return m_mouse_enabled; }
- bool lightgun_enabled() const { return m_lightgun_enabled; }
+ virtual void before_poll() override
+ {
+ // periodically process events, in case they're not coming through
+ // this also will make sure the mouse state is up-to-date
+ osd().process_events();
+ }
+
+ virtual bool should_poll_devices()
+ {
+ return background_input() || osd().has_focus();
+ }
- virtual int init(const osd_options &options) override;
+ template <typename Actual, typename... Params>
+ Actual &create_device(input_device_class deviceclass, std::string &&name, std::string &&id, Params &&... args)
+ {
+ // allocate the device object and add it to the input manager
+ return add_device(
+ deviceclass,
+ std::make_unique<Actual>(std::move(name), std::move(id), *this, std::forward<Params>(args)...));
+ }
- virtual void poll_if_necessary(running_machine &machine) override
+ template <typename Actual>
+ Actual &add_device(input_device_class deviceclass, std::unique_ptr<Actual> &&devinfo)
{
- auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(m_clock.now() - m_last_poll);
- if (elapsed.count() >= MIN_POLLING_INTERVAL)
- {
- poll(machine);
- }
+ // add it to the input manager and append it to the list
+ osd::input_device &osddev = manager().add_device(deviceclass, devinfo->name(), devinfo->id(), devinfo.get());
+ devinfo->configure(osddev);
+ return devicelist().add_device(std::move(devinfo));
}
- virtual void pause() override;
- virtual void resume() override;
- virtual void exit() override;
+private:
+ virtual void poll(bool relative_reset) override final
+ {
+ // poll all of the devices
+ if (should_poll_devices())
+ m_devicelist.poll_devices(relative_reset);
+ else
+ m_devicelist.reset_devices();
+ }
-protected:
- virtual int init_internal() { return 0; }
- virtual void poll(running_machine &machine);
- virtual bool should_poll_devices(running_machine &machine) = 0;
- virtual void before_poll(running_machine &machine) { }
+ input_device_list<Info> m_devicelist;
+ OsdImpl *m_osd = nullptr;
};
+
template <class TItem>
int generic_button_get_state(void *device_internal, void *item_internal)
{
- device_info *devinfo = static_cast<device_info *>(device_internal);
- TItem *itemdata = static_cast<TItem*>(item_internal);
-
// return the current state
- devinfo->module().poll_if_necessary(devinfo->machine());
- return *itemdata >> 7;
+ return *reinterpret_cast<TItem const *>(item_internal) >> 7;
}
+
template <class TItem>
int generic_axis_get_state(void *device_internal, void *item_internal)
{
- device_info *devinfo = static_cast<device_info *>(device_internal);
- TItem *axisdata = static_cast<TItem*>(item_internal);
-
- // return the current state
- devinfo->module().poll_if_necessary(devinfo->machine());
- return *axisdata;
+ return *reinterpret_cast<TItem const *>(item_internal);
}
+
//============================================================
// default_button_name
//============================================================
@@ -524,23 +397,22 @@ const char *const default_axis_name[] =
inline int32_t normalize_absolute_axis(double raw, double rawmin, double rawmax)
{
- double center = (rawmax + rawmin) / 2.0;
-
- // make sure we have valid data
+ // make sure we have valid arguments
if (rawmin >= rawmax)
return int32_t(raw);
+ double const center = (rawmax + rawmin) / 2.0;
if (raw >= center)
{
// above center
- double result = (raw - center) * osd::INPUT_ABSOLUTE_MAX / (rawmax - center);
- return std::min(result, (double)osd::INPUT_ABSOLUTE_MAX);
+ double const result = (raw - center) * double(osd::input_device::ABSOLUTE_MAX) / (rawmax - center);
+ return int32_t(std::min(result, double(osd::input_device::ABSOLUTE_MAX)));
}
else
{
// below center
- double result = -((center - raw) * (double)-osd::INPUT_ABSOLUTE_MIN / (center - rawmin));
- return std::max(result, (double)osd::INPUT_ABSOLUTE_MIN);
+ double result = -((center - raw) * double(-osd::input_device::ABSOLUTE_MIN) / (center - rawmin));
+ return int32_t(std::max(result, double(osd::input_device::ABSOLUTE_MIN)));
}
}
diff --git a/src/osd/modules/input/input_dinput.cpp b/src/osd/modules/input/input_dinput.cpp
index 77467f80d59..7732d610bba 100644
--- a/src/osd/modules/input/input_dinput.cpp
+++ b/src/osd/modules/input/input_dinput.cpp
@@ -1,155 +1,354 @@
// license:BSD-3-Clause
-// copyright-holders:Aaron Giles, Brad Hughes
+// copyright-holders:Aaron Giles, Brad Hughes, Vas Crabb
//============================================================
//
// input_dinput.cpp - Windows DirectInput support
//
//============================================================
+/*
+
+DirectInput joystick input is a bit of a mess. It gives eight axes
+called X, Y, Z, Rx, Ry, Rz, slider 0 and slider 1. The driver can
+assign arbitrary physical axes to these axes. Up to four hat switches
+are supported, giving a direction in hundredths of degrees. In theory,
+this supports dial-like controls with an arbitrary number of stops. In
+practice, it just makes dealing with 8-way hat switches more complicated
+and prevents contradictory inputs from being reported altogether.
+
+You may get a vague indication of the type of controller, and you can
+obtain usage information for HID controllers.
+
+The Windows HID driver supposedly uses the following mappings:
+
+0x01 Generic Desktop 0x30 X X
+0x01 Generic Desktop 0x31 Y Y
+0x01 Generic Desktop 0x32 Z Z
+0x01 Generic Desktop 0x33 Rx Rx
+0x01 Generic Desktop 0x34 Ry Ry
+0x01 Generic Desktop 0x35 Rz Rz
+0x01 Generic Desktop 0x36 Slider Slider
+0x01 Generic Desktop 0x37 Dial Slider
+0x01 Generic Desktop 0x39 Hat Switch POV Hat
+0x02 Simulation 0xBA Rudder Rz
+0x02 Simulation 0xBB Throttle Slider
+0x02 Simulation 0xC4 Accelerator Y
+0x02 Simulation 0xC5 Brake Rz
+0x02 Simulation 0xC8 Steering X
+
+Anything without an explicit mapping is treated as a button.
+
+The WinMM driver supposedly uses the following axis mappings:
+
+X X
+Y Y
+Z Slider
+R Rz
+U Slider
+V Slider
+
+The actual mapping used by various controllers doesn't match what you
+might expect from the HID mapping.
+
+Gamepads:
+
+Axis Logitech DS4 Xinput Switch
+X Left X Left X Left X Left X
+Y Left Y Left Y Left Y Left Y
+Z Right X Right X Triggers
+Rx Left trigger Right X Right X
+Ry Right trigger Right Y Right Y
+Rz Right Y Right Y
+
+Thrustmaster controllers:
+
+Axis HOTAS Side stick Throttle/Pedals Dual Throttles Triple Throttles Driving
+X Aileron Aileron Mini Stick X Left Throttle Right Brake Steering
+Y Elevator Elevator Mini stick Y Right Throttle Left Brake Brake
+Z Throttle Throttle Flaps Rudder
+Rx Right Brake Right Brake Right Brake Left Throttle
+Ry Left Brake Left Brake Left Brake Centre Throttle
+Rz Twist Rudder Rocker Air Brake Right Throttle Accelerator
+Slider 0 Rocker Throttle Antenna Rudder Clutch
+Slider 1 Rudder Rudder
+
+Logitech controllers:
+
+Axis Pro Wheels
+X Steering
+Y
+Z
+Rx Accelerator
+Ry Brake
+Rz Clutch
+Slider 0
+Slider 1
+
+MFG Crosswind pedals:
+
+X Left Brake
+Y Right Brake
+Rz Rudder
+
+*/
#include "modules/osdmodule.h"
-#if defined(OSD_WINDOWS)
-
-#include "emu.h"
+#if defined(OSD_WINDOWS) || defined(SDLMAME_WIN32)
#include "input_dinput.h"
-#include "winutil.h"
+#include "interface/inputseq.h"
+#include "windows/winutil.h"
+
+// emu
+#include "inpttype.h"
+
+// lib/util
+#include "util/corestr.h"
+
+#ifdef SDLMAME_WIN32
+#include <SDL2/SDL.h>
+#include <SDL2/SDL_syswm.h>
+#endif
-#include <mutex>
+#include <algorithm>
+#include <cmath>
+#include <iterator>
+#include <memory>
// standard windows headers
#include <initguid.h>
#include <tchar.h>
+namespace osd {
+
namespace {
-using namespace Microsoft::WRL;
+std::string guid_to_string(GUID const &guid)
+{
+ // size of a GUID string with dashes plus NUL terminator
+ char guid_string[37];
+ snprintf(
+ guid_string, std::size(guid_string),
+ "%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ guid.Data1, guid.Data2, guid.Data3,
+ guid.Data4[0], guid.Data4[1], guid.Data4[2],
+ guid.Data4[3], guid.Data4[4], guid.Data4[5],
+ guid.Data4[6], guid.Data4[7]);
+
+ return guid_string;
+}
+
+
//============================================================
-// dinput_joystick_pov_get_state
+// dinput_keyboard_device - DirectInput keyboard device
//============================================================
-int32_t dinput_joystick_pov_get_state(void *device_internal, void *item_internal)
+class dinput_keyboard_device : public dinput_device
{
- auto *devinfo = static_cast<dinput_joystick_device *>(device_internal);
- int povnum = reinterpret_cast<uintptr_t>(item_internal) / 4;
- int povdir = reinterpret_cast<uintptr_t>(item_internal) % 4;
- int32_t result = 0;
+public:
+ dinput_keyboard_device(
+ std::string &&name,
+ std::string &&id,
+ input_module &module,
+ Microsoft::WRL::ComPtr<IDirectInputDevice8> &&device,
+ DIDEVCAPS const &caps,
+ LPCDIDATAFORMAT format);
+
+ virtual void poll(bool relative_reset) override;
+ virtual void reset() override;
+ virtual void configure(input_device &device) override;
+
+private:
+ std::mutex m_device_lock;
+ keyboard_state m_keyboard;
+};
- // get the current state
- devinfo->module().poll_if_necessary(devinfo->machine());
- const DWORD pov = devinfo->joystick.state.rgdwPOV[povnum];
+dinput_keyboard_device::dinput_keyboard_device(
+ std::string &&name,
+ std::string &&id,
+ input_module &module,
+ Microsoft::WRL::ComPtr<IDirectInputDevice8> &&device,
+ DIDEVCAPS const &caps,
+ LPCDIDATAFORMAT format) :
+ dinput_device(std::move(name), std::move(id), module, std::move(device), caps, format),
+ m_keyboard({ { 0 } })
+{
+}
- // if invalid, return 0
- if ((pov & 0xffff) == 0xffff)
- return result;
+void dinput_keyboard_device::poll(bool relative_reset)
+{
+ // poll the DirectInput immediate state
+ std::lock_guard<std::mutex> scope_lock(m_device_lock);
+ poll_dinput(&m_keyboard.state);
+}
- // return the current state
- switch (povdir)
+void dinput_keyboard_device::reset()
+{
+ memset(&m_keyboard.state, 0, sizeof(m_keyboard.state));
+}
+
+void dinput_keyboard_device::configure(input_device &device)
+{
+ // populate it
+ char defname[20];
+ for (unsigned keynum = 0; keynum < MAX_KEYS; keynum++)
{
- case POVDIR_LEFT: result = (pov >= 22500 && pov <= 31500); break;
- case POVDIR_RIGHT: result = (pov >= 4500 && pov <= 13500); break;
- case POVDIR_UP: result = (pov >= 31500 || pov <= 4500); break;
- case POVDIR_DOWN: result = (pov >= 13500 && pov <= 22500); break;
+ input_item_id itemid = keyboard_trans_table::instance().map_di_scancode_to_itemid(keynum);
+
+ // generate/fetch the name
+ snprintf(defname, std::size(defname), "Scan%03d", keynum);
+
+ // add the item to the device
+ device.add_item(
+ item_name(keynum, defname, nullptr),
+ strmakeupper(defname),
+ itemid,
+ generic_button_get_state<uint8_t>,
+ &m_keyboard.state[keynum]);
}
- return result;
}
//============================================================
-// dinput_set_dword_property
+// dinput_mouse_device - DirectInput mouse device
//============================================================
-HRESULT dinput_set_dword_property(ComPtr<IDirectInputDevice8> device, REFGUID property_guid, DWORD object, DWORD how, DWORD value)
+class dinput_mouse_device : public dinput_device
+{
+public:
+ dinput_mouse_device(
+ std::string &&name,
+ std::string &&id,
+ input_module &module,
+ Microsoft::WRL::ComPtr<IDirectInputDevice8> &&device,
+ DIDEVCAPS const &caps,
+ LPCDIDATAFORMAT format);
+
+ void poll(bool relative_reset) override;
+ void reset() override;
+ virtual void configure(input_device &device) override;
+
+private:
+ mouse_state m_mouse;
+};
+
+dinput_mouse_device::dinput_mouse_device(
+ std::string &&name,
+ std::string &&id,
+ input_module &module,
+ Microsoft::WRL::ComPtr<IDirectInputDevice8> &&device,
+ DIDEVCAPS const &caps,
+ LPCDIDATAFORMAT format) :
+ dinput_device(std::move(name), std::move(id), module, std::move(device), caps, format),
+ m_mouse({0})
{
- DIPROPDWORD dipdw;
+ // cap the number of axes and buttons based on the format
+ m_caps.dwAxes = std::min(m_caps.dwAxes, DWORD(3));
+ m_caps.dwButtons = std::min(m_caps.dwButtons, DWORD((m_format == &c_dfDIMouse) ? 4 : 8));
+}
- dipdw.diph.dwSize = sizeof(dipdw);
- dipdw.diph.dwHeaderSize = sizeof(dipdw.diph);
- dipdw.diph.dwObj = object;
- dipdw.diph.dwHow = how;
- dipdw.dwData = value;
+void dinput_mouse_device::poll(bool relative_reset)
+{
+ // poll
+ if (relative_reset && (poll_dinput(&m_mouse) == DI_OK))
+ {
+ // scale the axis data
+ m_mouse.lX *= input_device::RELATIVE_PER_PIXEL;
+ m_mouse.lY *= input_device::RELATIVE_PER_PIXEL;
+ m_mouse.lZ *= input_device::RELATIVE_PER_PIXEL;
+ }
+}
- return device->SetProperty(property_guid, &dipdw.diph);
+void dinput_mouse_device::reset()
+{
+ memset(&m_mouse, 0, sizeof(m_mouse));
+}
+
+void dinput_mouse_device::configure(input_device &device)
+{
+ // populate the axes
+ for (int axisnum = 0; axisnum < m_caps.dwAxes; axisnum++)
+ {
+ // add to the mouse device and optionally to the gun device as well
+ device.add_item(
+ item_name(offsetof(DIMOUSESTATE, lX) + axisnum * sizeof(LONG), default_axis_name[axisnum], nullptr),
+ std::string_view(),
+ input_item_id(ITEM_ID_XAXIS + axisnum),
+ generic_axis_get_state<LONG>,
+ &m_mouse.lX + axisnum);
+ }
+
+ // populate the buttons
+ for (int butnum = 0; butnum < m_caps.dwButtons; butnum++)
+ {
+ auto offset = reinterpret_cast<uintptr_t>(&static_cast<DIMOUSESTATE *>(nullptr)->rgbButtons[butnum]);
+
+ // add to the mouse device
+ device.add_item(
+ item_name(offset, default_button_name(butnum), nullptr),
+ std::string_view(),
+ input_item_id(ITEM_ID_BUTTON1 + butnum),
+ generic_button_get_state<BYTE>,
+ &m_mouse.rgbButtons[butnum]);
+ }
}
//============================================================
-// dinput_module - base directinput module
+// dinput_module - base DirectInput module
//============================================================
-class dinput_module : public wininput_module, public device_enum_interface
+class dinput_module : public input_module_impl<dinput_device, osd_common_t>
{
-protected:
- std::unique_ptr<dinput_api_helper> m_dinput_helper;
-
public:
- dinput_module(const char* type, const char* name)
- : wininput_module(type, name),
- m_dinput_helper(nullptr)
+ dinput_module(const char* type, const char* name) :
+ input_module_impl<dinput_device, osd_common_t>(type, name),
+ m_dinput_helper(nullptr)
{
}
- int init_internal() override
+ virtual int init(osd_interface &osd, osd_options const &options) override
{
m_dinput_helper = std::make_unique<dinput_api_helper>();
- int result = m_dinput_helper->initialize();
- if (result != 0)
+ int const result = m_dinput_helper->initialize();
+ if (result)
+ {
+ m_dinput_helper.reset();
return result;
+ }
- return 0;
+ return input_module_impl<dinput_device, osd_common_t>::init(osd, options);
}
- void exit() override
+ virtual void exit() override
{
- wininput_module::exit();
- m_dinput_helper.reset();
- }
+ input_module_impl<dinput_device, osd_common_t>::exit();
- void input_init(running_machine &machine) override
- {
- HRESULT result = m_dinput_helper->enum_attached_devices(dinput_devclass(), this, &machine);
- if (result != DI_OK)
- fatalerror("DirectInput: Unable to enumerate devices (result=%08X)\n", uint32_t(result));
+ m_dinput_helper.reset();
}
- static std::string device_item_name(dinput_device *devinfo, int offset, const char *defstring, const char *suffix)
+ virtual void input_init(running_machine &machine) override
{
- DIDEVICEOBJECTINSTANCE instance = { 0 };
- HRESULT result;
+ input_module_impl<dinput_device, osd_common_t>::input_init(machine);
- // query the key name
- instance.dwSize = sizeof(instance);
- result = devinfo->dinput.device->GetObjectInfo(&instance, offset, DIPH_BYOFFSET);
-
- // if we got an error and have no default string, just return nullptr
+ HRESULT const result = m_dinput_helper->enum_attached_devices(
+ dinput_devclass(),
+ [this] (LPCDIDEVICEINSTANCE instance) { return device_enum_callback(instance); });
if (result != DI_OK)
- {
- if (defstring == nullptr)
- return nullptr;
-
- // Return the default value
- std::string result(defstring);
- if (suffix)
- result.append(" ").append(suffix);
- return result;
- }
-
- // convert the name to utf8
- std::string namestring = osd::text::from_tstring(instance.tszName);
-
- // if no suffix, return as-is
- if (suffix)
- namestring.append(" ").append(suffix);
- return namestring;
+ fatalerror("DirectInput: Unable to enumerate devices (result=%08X)\n", uint32_t(result));
}
protected:
virtual int dinput_devclass() = 0;
+ virtual BOOL device_enum_callback(LPCDIDEVICEINSTANCE instance) = 0;
+
+ std::unique_ptr<dinput_api_helper> m_dinput_helper;
};
+
class keyboard_input_dinput : public dinput_module
{
public:
@@ -158,42 +357,30 @@ public:
{
}
- int dinput_devclass() override
+protected:
+ virtual int dinput_devclass() override
{
return DI8DEVCLASS_KEYBOARD;
}
- BOOL device_enum_callback(LPCDIDEVICEINSTANCE instance, LPVOID ref) override
+ virtual BOOL device_enum_callback(LPCDIDEVICEINSTANCE instance) override
{
- running_machine &machine = *static_cast<running_machine *>(ref);
- dinput_keyboard_device *devinfo;
- int keynum;
-
// allocate and link in a new device
- devinfo = m_dinput_helper->create_device<dinput_keyboard_device>(machine, *this, instance, &c_dfDIKeyboard, nullptr, dinput_cooperative_level::FOREGROUND);
- if (devinfo == nullptr)
- goto exit;
-
- // populate it
- for (keynum = 0; keynum < MAX_KEYS; keynum++)
- {
- input_item_id itemid = keyboard_trans_table::instance().map_di_scancode_to_itemid(keynum);
- char defname[20];
- std::string name;
-
- // generate/fetch the name
- snprintf(defname, std::size(defname), "Scan%03d", keynum);
- name = device_item_name(devinfo, keynum, defname, nullptr);
-
- // add the item to the device
- devinfo->device()->add_item(name, itemid, generic_button_get_state<std::uint8_t>, &devinfo->keyboard.state[keynum]);
- }
+ auto devinfo = m_dinput_helper->create_device<dinput_keyboard_device>(
+ *this,
+ instance,
+ &c_dfDIKeyboard,
+ nullptr,
+ background_input() ? dinput_cooperative_level::BACKGROUND : dinput_cooperative_level::FOREGROUND,
+ [] (auto...) { return true; });
+ if (devinfo)
+ add_device(DEVICE_CLASS_KEYBOARD, std::move(devinfo));
- exit:
return DIENUM_CONTINUE;
}
};
+
class mouse_input_dinput : public dinput_module
{
public:
@@ -202,68 +389,41 @@ public:
{
}
- int dinput_devclass() override
+protected:
+ virtual int dinput_devclass() override
{
return DI8DEVCLASS_POINTER;
}
- BOOL device_enum_callback(LPCDIDEVICEINSTANCE instance, LPVOID ref) override
+ virtual BOOL device_enum_callback(LPCDIDEVICEINSTANCE instance) override
{
- dinput_mouse_device *devinfo = nullptr;
- running_machine &machine = *static_cast<running_machine *>(ref);
- int axisnum, butnum;
- HRESULT result;
-
// allocate and link in a new device
- devinfo = m_dinput_helper->create_device<dinput_mouse_device>(machine, *this, instance, &c_dfDIMouse2, &c_dfDIMouse, dinput_cooperative_level::FOREGROUND);
- if (!devinfo)
- goto exit;
-
- // set relative mode on the mouse device
- result = dinput_set_dword_property(devinfo->dinput.device, DIPROP_AXISMODE, 0, DIPH_DEVICE, DIPROPAXISMODE_REL);
- if (result != DI_OK && result != DI_PROPNOEFFECT)
- {
- osd_printf_error("DirectInput: Unable to set relative mode for mouse %u (%s)\n", static_cast<unsigned int>(devicelist().size()), devinfo->name());
- goto error;
- }
-
- // cap the number of axes and buttons based on the format
- devinfo->dinput.caps.dwAxes = std::min(devinfo->dinput.caps.dwAxes, DWORD(3));
- devinfo->dinput.caps.dwButtons = std::min(devinfo->dinput.caps.dwButtons, DWORD((devinfo->dinput.format == &c_dfDIMouse) ? 4 : 8));
-
- // populate the axes
- for (axisnum = 0; axisnum < devinfo->dinput.caps.dwAxes; axisnum++)
- {
- // add to the mouse device and optionally to the gun device as well
- std::string name = device_item_name(devinfo, offsetof(DIMOUSESTATE, lX) + axisnum * sizeof(LONG), default_axis_name[axisnum], nullptr);
- devinfo->device()->add_item(
- name,
- static_cast<input_item_id>(ITEM_ID_XAXIS + axisnum),
- generic_axis_get_state<LONG>,
- &devinfo->mouse.lX + axisnum);
- }
-
- // populate the buttons
- for (butnum = 0; butnum < devinfo->dinput.caps.dwButtons; butnum++)
- {
- auto offset = reinterpret_cast<uintptr_t>(&static_cast<DIMOUSESTATE *>(nullptr)->rgbButtons[butnum]);
-
- // add to the mouse device
- std::string name = device_item_name(devinfo, offset, default_button_name(butnum).c_str(), nullptr);
- devinfo->device()->add_item(
- name,
- static_cast<input_item_id>(ITEM_ID_BUTTON1 + butnum),
- generic_button_get_state<BYTE>,
- &devinfo->mouse.rgbButtons[butnum]);
- }
+ auto devinfo = m_dinput_helper->create_device<dinput_mouse_device>(
+ *this,
+ instance,
+ &c_dfDIMouse2,
+ &c_dfDIMouse,
+ background_input() ? dinput_cooperative_level::BACKGROUND : dinput_cooperative_level::FOREGROUND,
+ [] (auto const &device, auto const &format) -> bool
+ {
+ // set relative mode
+ HRESULT const result = dinput_api_helper::set_dword_property(
+ device,
+ DIPROP_AXISMODE,
+ 0,
+ DIPH_DEVICE,
+ DIPROPAXISMODE_REL);
+ if ((result != DI_OK) && (result != DI_PROPNOEFFECT))
+ {
+ osd_printf_error("DirectInput: Unable to set relative mode for mouse.\n");
+ return false;
+ }
+ return true;
+ });
+ if (devinfo)
+ add_device(DEVICE_CLASS_MOUSE, std::move(devinfo));
- exit:
return DIENUM_CONTINUE;
-
- error:
- if (devinfo)
- devicelist().free_device(*devinfo);
- goto exit;
}
};
@@ -276,33 +436,40 @@ public:
{
}
- int dinput_devclass() override
+protected:
+ virtual int dinput_devclass() override
{
return DI8DEVCLASS_GAMECTRL;
}
- BOOL device_enum_callback(LPCDIDEVICEINSTANCE instance, LPVOID ref) override
+ virtual BOOL device_enum_callback(LPCDIDEVICEINSTANCE instance) override
{
- dinput_cooperative_level cooperative_level = dinput_cooperative_level::FOREGROUND;
- running_machine &machine = *static_cast<running_machine *>(ref);
- dinput_joystick_device *devinfo;
- int result = 0;
-
- if (!osd_common_t::s_window_list.empty() && osd_common_t::s_window_list.front()->win_has_menu())
- cooperative_level = dinput_cooperative_level::BACKGROUND;
-
// allocate and link in a new device
- devinfo = m_dinput_helper->create_device<dinput_joystick_device>(machine, *this, instance, &c_dfDIJoystick, nullptr, cooperative_level);
- if (devinfo == nullptr)
- goto exit;
-
- result = devinfo->configure();
- if (result != 0)
- {
- osd_printf_error("Failed to configure DI Joystick device. Error 0x%x\n", static_cast<unsigned int>(result));
- }
+ auto devinfo = m_dinput_helper->create_device<dinput_joystick_device>(
+ *this,
+ instance,
+ &c_dfDIJoystick,
+ nullptr,
+ background_input() ? dinput_cooperative_level::BACKGROUND : dinput_cooperative_level::FOREGROUND,
+ [] (auto const &device, auto const &format) -> bool
+ {
+ // set absolute mode
+ HRESULT const result = dinput_api_helper::set_dword_property(
+ device,
+ DIPROP_AXISMODE,
+ 0,
+ DIPH_DEVICE,
+ DIPROPAXISMODE_ABS);
+ if ((result != DI_OK) && (result != DI_PROPNOEFFECT))
+ {
+ osd_printf_error("DirectInput: Unable to set absolute mode for joystick.\n");
+ return false;
+ }
+ return true;
+ });
+ if (devinfo)
+ add_device(DEVICE_CLASS_JOYSTICK, std::move(devinfo));
- exit:
return DIENUM_CONTINUE;
}
};
@@ -311,92 +478,64 @@ public:
//============================================================
-// dinput_device - base directinput device
+// dinput_device - base DirectInput device
//============================================================
-dinput_device::dinput_device(running_machine &machine, std::string &&name, std::string &&id, input_device_class deviceclass, input_module &module)
- : device_info(machine, std::move(name), std::move(id), deviceclass, module),
- dinput({nullptr})
+dinput_device::dinput_device(
+ std::string &&name,
+ std::string &&id,
+ input_module &module,
+ Microsoft::WRL::ComPtr<IDirectInputDevice8> &&device,
+ DIDEVCAPS const &caps,
+ LPCDIDATAFORMAT format) :
+ device_info(std::move(name), std::move(id), module),
+ m_device(std::move(device)),
+ m_caps(caps),
+ m_format(format)
{
}
-dinput_device::~dinput_device()
-{
- if (dinput.device)
- dinput.device.Reset();
-}
-
HRESULT dinput_device::poll_dinput(LPVOID pState) const
{
HRESULT result;
// first poll the device, then get the state
- dinput.device->Poll();
-
- // GetDeviceState returns the immediate state
- result = dinput.device->GetDeviceState(dinput.format->dwDataSize, pState);
+ result = m_device->Poll();
// handle lost inputs here
- if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED)
+ if ((result == DIERR_INPUTLOST) || (result == DIERR_NOTACQUIRED))
{
- result = dinput.device->Acquire();
- if (result == DI_OK)
- result = dinput.device->GetDeviceState(dinput.format->dwDataSize, pState);
+ result = m_device->Acquire();
+ if ((result == DI_OK) || (result == S_FALSE))
+ result = m_device->Poll();
}
- return result;
-}
-
-
-//============================================================
-// dinput_keyboard_device - directinput keyboard device
-//============================================================
-
-dinput_keyboard_device::dinput_keyboard_device(running_machine &machine, std::string &&name, std::string &&id, input_module &module)
- : dinput_device(machine, std::move(name), std::move(id), DEVICE_CLASS_KEYBOARD, module),
- keyboard({{0}})
-{
-}
-
-// Polls the direct input immediate state
-void dinput_keyboard_device::poll()
-{
- std::lock_guard<std::mutex> scope_lock(m_device_lock);
-
- // Poll the state
- dinput_device::poll_dinput(&keyboard.state);
-}
+ // GetDeviceState returns the immediate state
+ if ((result == DI_OK) || (result == DI_NOEFFECT))
+ result = m_device->GetDeviceState(m_format->dwDataSize, pState);
-void dinput_keyboard_device::reset()
-{
- memset(&keyboard.state, 0, sizeof(keyboard.state));
+ return result;
}
-
-//============================================================
-// dinput_mouse_device - directinput mouse device
-//============================================================
-
-dinput_mouse_device::dinput_mouse_device(running_machine &machine, std::string &&name, std::string &&id, input_module &module)
- : dinput_device(machine, std::move(name), std::move(id), DEVICE_CLASS_MOUSE, module),
- mouse({0})
+std::string dinput_device::item_name(int offset, std::string_view defstring, const char *suffix) const
{
-}
+ // query the key name
+ DIDEVICEOBJECTINSTANCE instance = { 0 };
+ instance.dwSize = sizeof(instance);
+ HRESULT const result = m_device->GetObjectInfo(&instance, offset, DIPH_BYOFFSET);
-void dinput_mouse_device::poll()
-{
- // poll
- dinput_device::poll_dinput(&mouse);
+ // use the default value if it failed
+ std::string name;
+ if (result != DI_OK)
+ name = defstring;
+ else
+ name = text::from_tstring(instance.tszName);
- // scale the axis data
- mouse.lX *= osd::INPUT_RELATIVE_PER_PIXEL;
- mouse.lY *= osd::INPUT_RELATIVE_PER_PIXEL;
- mouse.lZ *= osd::INPUT_RELATIVE_PER_PIXEL;
-}
+ // if no suffix, return as-is
+ if (suffix)
+ name.append(" ").append(suffix);
-void dinput_mouse_device::reset()
-{
- memset(&mouse, 0, sizeof(mouse));
+ return name;
}
@@ -404,63 +543,87 @@ void dinput_mouse_device::reset()
// dinput_joystick_device - directinput joystick device
//============================================================
-dinput_joystick_device::dinput_joystick_device(running_machine &machine, std::string &&name, std::string &&id, input_module &module)
- : dinput_device(machine, std::move(name), std::move(id), DEVICE_CLASS_JOYSTICK, module),
- joystick({{0}})
+dinput_joystick_device::dinput_joystick_device(
+ std::string &&name,
+ std::string &&id,
+ input_module &module,
+ Microsoft::WRL::ComPtr<IDirectInputDevice8> &&device,
+ DIDEVCAPS const &caps,
+ LPCDIDATAFORMAT format) :
+ dinput_device(std::move(name), std::move(id), module, std::move(device), caps, format),
+ m_joystick({ { 0 } })
{
+ // cap the number of axes, POVs, and buttons based on the format
+ m_caps.dwAxes = std::min(m_caps.dwAxes, DWORD(8));
+ m_caps.dwPOVs = std::min(m_caps.dwPOVs, DWORD(4));
+ m_caps.dwButtons = std::min(m_caps.dwButtons, DWORD(128));
}
void dinput_joystick_device::reset()
{
- memset(&joystick.state, 0, sizeof(joystick.state));
+ memset(&m_joystick.state, 0, sizeof(m_joystick.state));
+ std::fill(std::begin(m_joystick.state.rgdwPOV), std::end(m_joystick.state.rgdwPOV), 0xffff);
}
-void dinput_joystick_device::poll()
+void dinput_joystick_device::poll(bool relative_reset)
{
- int axisnum;
-
// poll the device first
- if (dinput_device::poll_dinput(&joystick.state) != ERROR_SUCCESS)
- return;
-
- // normalize axis values
- for (axisnum = 0; axisnum < 8; axisnum++)
+ if (dinput_device::poll_dinput(&m_joystick.state) == DI_OK)
{
- LONG *axis = (&joystick.state.lX) + axisnum;
- *axis = normalize_absolute_axis(*axis, joystick.rangemin[axisnum], joystick.rangemax[axisnum]);
+ // normalize axis values
+ for (int axisnum = 0; axisnum < 8; axisnum++)
+ {
+ auto const range = m_joystick.rangemax[axisnum] - m_joystick.rangemin[axisnum];
+ if (range)
+ {
+ // assumes output range is symmetrical
+ LONG *const axis = &m_joystick.state.lX + axisnum;
+ double const offset = *axis - m_joystick.rangemin[axisnum];
+ double const scaled = offset * double(input_device::ABSOLUTE_MAX - input_device::ABSOLUTE_MIN) / double(range);
+ *axis = lround(std::clamp<double>(scaled + input_device::ABSOLUTE_MIN, input_device::ABSOLUTE_MIN, input_device::ABSOLUTE_MAX));
+ }
+ }
}
}
-int dinput_joystick_device::configure()
+void dinput_joystick_device::configure(input_device &device)
{
+ input_device::assignment_vector assignments;
HRESULT result;
- auto &devicelist = static_cast<input_module_base&>(module()).devicelist();
- // temporary approximation of index
- int devindex = devicelist.size();
-
- // set absolute mode
- result = dinput_set_dword_property(dinput.device, DIPROP_AXISMODE, 0, DIPH_DEVICE, DIPROPAXISMODE_ABS);
- if (result != DI_OK && result != DI_PROPNOEFFECT)
- osd_printf_warning("DirectInput: Unable to set absolute mode for joystick %d (%s)\n", devindex, name());
+ // get device information - it gives clues about axis usage
+ DIDEVICEINSTANCE info;
+ info.dwSize = sizeof(info);
+ result = m_device->GetDeviceInfo(&info);
+ bool hid = false;
+ uint8_t type = DI8DEVTYPE_DEVICE;
+ uint8_t subtype = 0;
+ if (result == DI_OK)
+ {
+ hid = (info.dwDevType & DIDEVTYPE_HID) != 0;
+ type = info.dwDevType & 0x00ff;
+ subtype = (info.dwDevType >> 8) & 0x00ff;
+ osd_printf_verbose(
+ "DirectInput: Device type=0x%02X subtype=0x%02X HID=%u\n",
+ type,
+ subtype,
+ hid ? "yes" : "no");
+ }
// turn off deadzone; we do our own calculations
- result = dinput_set_dword_property(dinput.device, DIPROP_DEADZONE, 0, DIPH_DEVICE, 0);
- if (result != DI_OK && result != DI_PROPNOEFFECT)
- osd_printf_warning("DirectInput: Unable to reset deadzone for joystick %d (%s)\n", devindex, name());
+ result = dinput_api_helper::set_dword_property(m_device, DIPROP_DEADZONE, 0, DIPH_DEVICE, 0);
+ if ((result != DI_OK) && (result != DI_PROPNOEFFECT))
+ osd_printf_warning("DirectInput: Unable to reset deadzone for joystick %s.\n", name());
// turn off saturation; we do our own calculations
- result = dinput_set_dword_property(dinput.device, DIPROP_SATURATION, 0, DIPH_DEVICE, 10000);
- if (result != DI_OK && result != DI_PROPNOEFFECT)
- osd_printf_warning("DirectInput: Unable to reset saturation for joystick %d (%s)\n", devindex, name());
-
- // cap the number of axes, POVs, and buttons based on the format
- dinput.caps.dwAxes = std::min(dinput.caps.dwAxes, DWORD(8));
- dinput.caps.dwPOVs = std::min(dinput.caps.dwPOVs, DWORD(4));
- dinput.caps.dwButtons = std::min(dinput.caps.dwButtons, DWORD(128));
+ result = dinput_api_helper::set_dword_property(m_device, DIPROP_SATURATION, 0, DIPH_DEVICE, 10000);
+ if ((result != DI_OK) && (result != DI_PROPNOEFFECT))
+ osd_printf_warning("DirectInput: Unable to reset saturation for joystick %s.\n", name());
// populate the axes
- for (uint32_t axisnum = 0, axiscount = 0; axiscount < dinput.caps.dwAxes && axisnum < 8; axisnum++)
+ input_item_id axisitems[8];
+ std::fill(std::begin(axisitems), std::end(axisitems), ITEM_ID_INVALID);
+ for (uint32_t axisnum = 0, axiscount = 0; (axiscount < m_caps.dwAxes) && (axisnum < 8); axisnum++)
{
// fetch the range of this axis
DIPROPRANGE dipr;
@@ -468,62 +631,555 @@ int dinput_joystick_device::configure()
dipr.diph.dwHeaderSize = sizeof(dipr.diph);
dipr.diph.dwObj = offsetof(DIJOYSTATE2, lX) + axisnum * sizeof(LONG);
dipr.diph.dwHow = DIPH_BYOFFSET;
- result = dinput.device->GetProperty(DIPROP_RANGE, &dipr.diph);
+ result = m_device->GetProperty(DIPROP_RANGE, &dipr.diph);
if (result != DI_OK)
+ {
+ // this is normal when axes are skipped, e.g. X/Y/Z present, rX/rY absent, rZ present
+ osd_printf_verbose("DirectInput: Unable to get properties for joystick %s axis %u.\n", name(), axisnum);
continue;
+ }
- joystick.rangemin[axisnum] = dipr.lMin;
- joystick.rangemax[axisnum] = dipr.lMax;
+ m_joystick.rangemin[axisnum] = dipr.lMin;
+ m_joystick.rangemax[axisnum] = dipr.lMax;
// populate the item description as well
- std::string name = dinput_module::device_item_name(this, offsetof(DIJOYSTATE2, lX) + axisnum * sizeof(LONG), default_axis_name[axisnum], nullptr);
- device()->add_item(
- name,
- static_cast<input_item_id>(ITEM_ID_XAXIS + axisnum),
- generic_axis_get_state<LONG>,
- &joystick.state.lX + axisnum);
+ axisitems[axisnum] = device.add_item(
+ item_name(offsetof(DIJOYSTATE2, lX) + axisnum * sizeof(LONG), default_axis_name[axisnum], nullptr),
+ std::string_view(),
+ input_item_id(ITEM_ID_XAXIS + axisnum),
+ generic_axis_get_state<LONG>,
+ &m_joystick.state.lX + axisnum);
axiscount++;
}
- // populate the POVs
- for (uint32_t povnum = 0; povnum < dinput.caps.dwPOVs; povnum++)
+ // take a guess at which axes might be pedals depending on type and remap onto negative half of range
+ input_item_id pedalitems[3] = { ITEM_ID_INVALID, ITEM_ID_INVALID, ITEM_ID_INVALID };
+ if (DI8DEVTYPE_FLIGHT == type)
{
- std::string name;
+ // Rx/Ry are often used for brakes
+ bool const rxpedal = (ITEM_ID_INVALID != axisitems[3]) && !m_joystick.rangemin[3] && (0 < m_joystick.rangemax[3]);
+ bool const rypedal = (ITEM_ID_INVALID != axisitems[4]) && !m_joystick.rangemin[4] && (0 < m_joystick.rangemax[4]);
+ if (rxpedal && rypedal)
+ {
+ pedalitems[0] = axisitems[3];
+ m_joystick.rangemin[3] = m_joystick.rangemax[3];
+ m_joystick.rangemax[3] = -m_joystick.rangemax[3];
+ pedalitems[1] = axisitems[4];
+ m_joystick.rangemin[4] = m_joystick.rangemax[4];
+ m_joystick.rangemax[4] = -m_joystick.rangemax[4];
+ }
+ }
+ else if (DI8DEVTYPE_DRIVING == type)
+ {
+ bool const ypedal = (ITEM_ID_INVALID != axisitems[1]) && !m_joystick.rangemin[1] && (0 < m_joystick.rangemax[1]);
+ bool const rxpedal = (ITEM_ID_INVALID != axisitems[3]) && !m_joystick.rangemin[3] && (0 < m_joystick.rangemax[3]);
+ bool const rypedal = (ITEM_ID_INVALID != axisitems[4]) && !m_joystick.rangemin[4] && (0 < m_joystick.rangemax[4]);
+ bool const rzpedal = (ITEM_ID_INVALID != axisitems[5]) && !m_joystick.rangemin[5] && (0 < m_joystick.rangemax[5]);
+ bool const s0pedal = (ITEM_ID_INVALID != axisitems[6]) && !m_joystick.rangemin[6] && (0 < m_joystick.rangemax[6]);
+ if (DI8DEVTYPEDRIVING_DUALPEDALS == subtype)
+ {
+ // dual pedals are usually Y and Rz
+ if (ypedal && rzpedal)
+ {
+ pedalitems[0] = axisitems[1];
+ m_joystick.rangemin[1] = m_joystick.rangemax[1];
+ m_joystick.rangemax[1] = -m_joystick.rangemax[1];
+
+ pedalitems[1] = axisitems[5];
+ m_joystick.rangemin[5] = m_joystick.rangemax[5];
+ m_joystick.rangemax[5] = -m_joystick.rangemax[5];
+ }
+ }
+ else if (DI8DEVTYPEDRIVING_THREEPEDALS == subtype)
+ {
+ // triple pedals may be Y, Rz and slider 0, or Rx, Ry and Rz
+ if (ypedal && rzpedal && s0pedal)
+ {
+ pedalitems[0] = axisitems[1];
+ m_joystick.rangemin[1] = m_joystick.rangemax[1];
+ m_joystick.rangemax[1] = -m_joystick.rangemax[1];
+
+ pedalitems[1] = axisitems[5];
+ m_joystick.rangemin[5] = m_joystick.rangemax[5];
+ m_joystick.rangemax[5] = -m_joystick.rangemax[5];
+
+ pedalitems[2] = axisitems[6];
+ m_joystick.rangemin[6] = m_joystick.rangemax[6];
+ m_joystick.rangemax[6] = -m_joystick.rangemax[6];
+ }
+ else if (rxpedal && rypedal && rzpedal)
+ {
+ pedalitems[0] = axisitems[3];
+ m_joystick.rangemin[3] = m_joystick.rangemax[3];
+ m_joystick.rangemax[3] = -m_joystick.rangemax[3];
+
+ pedalitems[1] = axisitems[4];
+ m_joystick.rangemin[4] = m_joystick.rangemax[4];
+ m_joystick.rangemax[4] = -m_joystick.rangemax[4];
+
+ pedalitems[2] = axisitems[5];
+ m_joystick.rangemin[5] = m_joystick.rangemax[5];
+ m_joystick.rangemax[5] = -m_joystick.rangemax[5];
+ }
+ }
+ }
+
+ // populate the POV hats
+ input_item_id povitems[4][4];
+ for (auto &pov : povitems)
+ std::fill(std::begin(pov), std::end(pov), ITEM_ID_INVALID);
+ for (uint32_t povnum = 0; povnum < m_caps.dwPOVs; povnum++)
+ {
// left
- name = dinput_module::device_item_name(this, offsetof(DIJOYSTATE2, rgdwPOV) + povnum * sizeof(DWORD), default_pov_name(povnum).c_str(), "Left");
- device()->add_item(name, ITEM_ID_OTHER_SWITCH, dinput_joystick_pov_get_state, reinterpret_cast<void *>(static_cast<uintptr_t>(povnum * 4 + POVDIR_LEFT)));
+ povitems[povnum][0] = device.add_item(
+ item_name(offsetof(DIJOYSTATE2, rgdwPOV) + povnum * sizeof(DWORD), default_pov_name(povnum), "Left"),
+ std::string_view(),
+ input_item_id((povnum * 4) + ITEM_ID_HAT1LEFT),
+ &dinput_joystick_device::pov_get_state,
+ reinterpret_cast<void *>(uintptr_t(povnum * 4 + POVDIR_LEFT)));
// right
- name = dinput_module::device_item_name(this, offsetof(DIJOYSTATE2, rgdwPOV) + povnum * sizeof(DWORD), default_pov_name(povnum).c_str(), "Right");
- device()->add_item(name, ITEM_ID_OTHER_SWITCH, dinput_joystick_pov_get_state, reinterpret_cast<void *>(static_cast<uintptr_t>(povnum * 4 + POVDIR_RIGHT)));
+ povitems[povnum][1] = device.add_item(
+ item_name(offsetof(DIJOYSTATE2, rgdwPOV) + povnum * sizeof(DWORD), default_pov_name(povnum), "Right"),
+ std::string_view(),
+ input_item_id((povnum * 4) + ITEM_ID_HAT1RIGHT),
+ &dinput_joystick_device::pov_get_state,
+ reinterpret_cast<void *>(uintptr_t(povnum * 4 + POVDIR_RIGHT)));
// up
- name = dinput_module::device_item_name(this, offsetof(DIJOYSTATE2, rgdwPOV) + povnum * sizeof(DWORD), default_pov_name(povnum).c_str(), "Up");
- device()->add_item(name, ITEM_ID_OTHER_SWITCH, dinput_joystick_pov_get_state, reinterpret_cast<void *>(static_cast<uintptr_t>(povnum * 4 + POVDIR_UP)));
+ povitems[povnum][2] = device.add_item(
+ item_name(offsetof(DIJOYSTATE2, rgdwPOV) + povnum * sizeof(DWORD), default_pov_name(povnum), "Up"),
+ std::string_view(),
+ input_item_id((povnum * 4) + ITEM_ID_HAT1UP),
+ &dinput_joystick_device::pov_get_state,
+ reinterpret_cast<void *>(uintptr_t(povnum * 4 + POVDIR_UP)));
// down
- name = dinput_module::device_item_name(this, offsetof(DIJOYSTATE2, rgdwPOV) + povnum * sizeof(DWORD), default_pov_name(povnum).c_str(), "Down");
- device()->add_item(name, ITEM_ID_OTHER_SWITCH, dinput_joystick_pov_get_state, reinterpret_cast<void *>(static_cast<uintptr_t>(povnum * 4 + POVDIR_DOWN)));
+ povitems[povnum][3] = device.add_item(
+ item_name(offsetof(DIJOYSTATE2, rgdwPOV) + povnum * sizeof(DWORD), default_pov_name(povnum), "Down"),
+ std::string_view(),
+ input_item_id((povnum * 4) + ITEM_ID_HAT1DOWN),
+ &dinput_joystick_device::pov_get_state,
+ reinterpret_cast<void *>(uintptr_t(povnum * 4 + POVDIR_DOWN)));
}
// populate the buttons
- for (uint32_t butnum = 0; butnum < dinput.caps.dwButtons; butnum++)
+ for (uint32_t butnum = 0; butnum < m_caps.dwButtons; butnum++)
{
auto offset = reinterpret_cast<uintptr_t>(&static_cast<DIJOYSTATE2 *>(nullptr)->rgbButtons[butnum]);
- std::string name = dinput_module::device_item_name(this, offset, default_button_name(butnum).c_str(), nullptr);
input_item_id itemid;
-
if (butnum < INPUT_MAX_BUTTONS)
- itemid = static_cast<input_item_id>(ITEM_ID_BUTTON1 + butnum);
+ itemid = input_item_id(ITEM_ID_BUTTON1 + butnum);
else if (butnum < INPUT_MAX_BUTTONS + INPUT_MAX_ADD_SWITCH)
- itemid = static_cast<input_item_id>(ITEM_ID_ADD_SWITCH1 - INPUT_MAX_BUTTONS + butnum);
+ itemid = input_item_id(ITEM_ID_ADD_SWITCH1 - INPUT_MAX_BUTTONS + butnum);
else
itemid = ITEM_ID_OTHER_SWITCH;
- device()->add_item(name, itemid, generic_button_get_state<BYTE>, &joystick.state.rgbButtons[butnum]);
+ input_item_id const actual = device.add_item(
+ item_name(offset, default_button_name(butnum), nullptr),
+ std::string_view(),
+ itemid,
+ generic_button_get_state<BYTE>,
+ &m_joystick.state.rgbButtons[butnum]);
+
+ // there are sixteen action button types
+ if (butnum < 16)
+ {
+ input_seq const seq(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, actual));
+ assignments.emplace_back(ioport_type(IPT_BUTTON1 + butnum), SEQ_TYPE_STANDARD, seq);
+
+ // assign the first few buttons to UI actions and pedals
+ // TODO: don't map pedals for driving controls that have them present
+ switch (butnum)
+ {
+ case 0:
+ assignments.emplace_back(IPT_PEDAL, SEQ_TYPE_INCREMENT, seq);
+ assignments.emplace_back(IPT_UI_SELECT, SEQ_TYPE_STANDARD, seq);
+ break;
+ case 1:
+ assignments.emplace_back(IPT_PEDAL2, SEQ_TYPE_INCREMENT, seq);
+ assignments.emplace_back((3 > m_caps.dwButtons) ? IPT_UI_CLEAR : IPT_UI_BACK, SEQ_TYPE_STANDARD, seq);
+ break;
+ case 2:
+ assignments.emplace_back(IPT_PEDAL3, SEQ_TYPE_INCREMENT, seq);
+ assignments.emplace_back(IPT_UI_CLEAR, SEQ_TYPE_STANDARD, seq);
+ break;
+ case 3:
+ assignments.emplace_back(IPT_UI_HELP, SEQ_TYPE_STANDARD, seq);
+ break;
+ }
+ }
+ }
+
+ // add default assignments depending on type
+ if (DI8DEVTYPE_FLIGHT == type)
+ {
+ if (((ITEM_ID_INVALID == axisitems[0]) || (ITEM_ID_INVALID == axisitems[1])) && (1 <= m_caps.dwPOVs))
+ {
+ // X or Y missing, fall back to using POV hat for navigation
+ add_directional_assignments(
+ assignments,
+ axisitems[0],
+ axisitems[1],
+ povitems[0][0],
+ povitems[0][1],
+ povitems[0][2],
+ povitems[0][3]);
+
+ // try using throttle for zoom/focus
+ if (ITEM_ID_INVALID != axisitems[2])
+ {
+ input_seq const negseq(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NEG, axisitems[2]));
+ input_seq const posseq(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_POS, axisitems[2]));
+ if (ITEM_ID_INVALID != axisitems[5])
+ {
+ assignments.emplace_back(IPT_UI_ZOOM_IN, SEQ_TYPE_STANDARD, posseq);
+ assignments.emplace_back(IPT_UI_ZOOM_OUT, SEQ_TYPE_STANDARD, negseq);
+ assignments.emplace_back(IPT_UI_FOCUS_PREV, SEQ_TYPE_STANDARD, negseq);
+ assignments.emplace_back(IPT_UI_FOCUS_NEXT, SEQ_TYPE_STANDARD, posseq);
+ }
+ else
+ {
+ assignments.emplace_back(IPT_UI_PREV_GROUP, SEQ_TYPE_STANDARD, posseq);
+ assignments.emplace_back(IPT_UI_NEXT_GROUP, SEQ_TYPE_STANDARD, negseq);
+ }
+ }
+
+ // try using twist/rudder for next/previous group
+ if (ITEM_ID_INVALID != axisitems[5])
+ {
+ input_seq const negseq(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NEG, axisitems[5]));
+ input_seq const posseq(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_POS, axisitems[5]));
+ assignments.emplace_back(IPT_UI_PREV_GROUP, SEQ_TYPE_STANDARD, negseq);
+ assignments.emplace_back(IPT_UI_NEXT_GROUP, SEQ_TYPE_STANDARD, posseq);
+ }
+ }
+ else
+ {
+ // only use stick for primary navigation/movement
+ add_directional_assignments(
+ assignments,
+ axisitems[0],
+ axisitems[1],
+ ITEM_ID_INVALID,
+ ITEM_ID_INVALID,
+ ITEM_ID_INVALID,
+ ITEM_ID_INVALID);
+
+ // try using hat for secondary navigation functions
+ if (1 <= m_caps.dwPOVs)
+ {
+ input_seq const leftseq(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, povitems[0][0]));
+ input_seq const rightseq(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, povitems[0][1]));
+ input_seq const upseq(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, povitems[0][2]));
+ input_seq const downseq(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, povitems[0][3]));
+ if ((ITEM_ID_INVALID != axisitems[2]) || (ITEM_ID_INVALID != axisitems[5]))
+ {
+ assignments.emplace_back(IPT_UI_PREV_GROUP, SEQ_TYPE_STANDARD, leftseq);
+ assignments.emplace_back(IPT_UI_NEXT_GROUP, SEQ_TYPE_STANDARD, rightseq);
+ assignments.emplace_back(IPT_UI_PAGE_UP, SEQ_TYPE_STANDARD, upseq);
+ assignments.emplace_back(IPT_UI_PAGE_DOWN, SEQ_TYPE_STANDARD, downseq);
+ }
+ else
+ {
+ assignments.emplace_back(IPT_UI_FOCUS_PREV, SEQ_TYPE_STANDARD, leftseq);
+ assignments.emplace_back(IPT_UI_FOCUS_NEXT, SEQ_TYPE_STANDARD, rightseq);
+ assignments.emplace_back(IPT_UI_ZOOM_OUT, SEQ_TYPE_STANDARD, leftseq);
+ assignments.emplace_back(IPT_UI_ZOOM_IN, SEQ_TYPE_STANDARD, rightseq);
+ assignments.emplace_back(IPT_UI_PREV_GROUP, SEQ_TYPE_STANDARD, upseq);
+ assignments.emplace_back(IPT_UI_NEXT_GROUP, SEQ_TYPE_STANDARD, downseq);
+ }
+ }
+
+ // try using throttle for zoom
+ if (ITEM_ID_INVALID != axisitems[2])
+ {
+ input_seq const negseq(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NEG, axisitems[2]));
+ input_seq const posseq(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_POS, axisitems[2]));
+ if ((1 <= m_caps.dwPOVs) || (ITEM_ID_INVALID != axisitems[5]))
+ {
+ assignments.emplace_back(IPT_UI_ZOOM_IN, SEQ_TYPE_STANDARD, posseq);
+ assignments.emplace_back(IPT_UI_ZOOM_OUT, SEQ_TYPE_STANDARD, negseq);
+ if ((1 > m_caps.dwPOVs) || (ITEM_ID_INVALID == axisitems[5]))
+ {
+ assignments.emplace_back(IPT_UI_FOCUS_PREV, SEQ_TYPE_STANDARD, negseq);
+ assignments.emplace_back(IPT_UI_FOCUS_NEXT, SEQ_TYPE_STANDARD, posseq);
+ }
+ }
+ else
+ {
+ assignments.emplace_back(IPT_UI_PREV_GROUP, SEQ_TYPE_STANDARD, posseq);
+ assignments.emplace_back(IPT_UI_NEXT_GROUP, SEQ_TYPE_STANDARD, negseq);
+ }
+ }
+
+ // try using twist/rudder for focus next/previous
+ if (ITEM_ID_INVALID != axisitems[5])
+ {
+ input_seq const negseq(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NEG, axisitems[5]));
+ input_seq const posseq(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_POS, axisitems[5]));
+ if (1 <= m_caps.dwPOVs)
+ {
+ assignments.emplace_back(IPT_UI_FOCUS_PREV, SEQ_TYPE_STANDARD, negseq);
+ assignments.emplace_back(IPT_UI_FOCUS_NEXT, SEQ_TYPE_STANDARD, posseq);
+ if (ITEM_ID_INVALID == axisitems[2])
+ {
+ assignments.emplace_back(IPT_UI_ZOOM_IN, SEQ_TYPE_STANDARD, posseq);
+ assignments.emplace_back(IPT_UI_ZOOM_OUT, SEQ_TYPE_STANDARD, negseq);
+ }
+ }
+ else
+ {
+ assignments.emplace_back(IPT_UI_PREV_GROUP, SEQ_TYPE_STANDARD, negseq);
+ assignments.emplace_back(IPT_UI_NEXT_GROUP, SEQ_TYPE_STANDARD, posseq);
+ }
+ }
+ }
+
+ // Z or slider 0 is usually the throttle - use one of them for joystick Z
+ add_assignment(
+ assignments,
+ IPT_AD_STICK_Z,
+ SEQ_TYPE_STANDARD,
+ ITEM_CLASS_ABSOLUTE,
+ ITEM_MODIFIER_NONE,
+ { axisitems[2], axisitems[6] });
+
+ // use Z for the first two pedals if present
+ if (ITEM_ID_INVALID != axisitems[2])
+ {
+ // TODO: use Rx/Ry as well if they appear to be brakes
+ input_seq const pedal1seq(make_code(ITEM_CLASS_ABSOLUTE, ITEM_MODIFIER_POS, axisitems[2]));
+ input_seq const pedal2seq(make_code(ITEM_CLASS_ABSOLUTE, ITEM_MODIFIER_NEG, axisitems[2]));
+ assignments.emplace_back(IPT_PEDAL, SEQ_TYPE_STANDARD, pedal1seq);
+ assignments.emplace_back(IPT_PEDAL2, SEQ_TYPE_STANDARD, pedal2seq);
+ }
+ }
+ else if (DI8DEVTYPE_DRIVING == type)
+ {
+ // use the wheel and D-pad for navigation and directional controls
+ add_directional_assignments(
+ assignments,
+ axisitems[0],
+ ITEM_ID_INVALID,
+ povitems[0][0],
+ povitems[0][1],
+ povitems[0][2],
+ povitems[0][3]);
+
+ // check subtype to determine how pedals should be assigned
+ if (DI8DEVTYPEDRIVING_COMBINEDPEDALS == subtype)
+ {
+ if (ITEM_ID_INVALID != axisitems[1])
+ {
+ // put first two pedals on opposite sides of Y axis
+ assignments.emplace_back(
+ IPT_PEDAL,
+ SEQ_TYPE_STANDARD,
+ input_seq(make_code(ITEM_CLASS_ABSOLUTE, ITEM_MODIFIER_POS, axisitems[1])));
+ assignments.emplace_back(
+ IPT_PEDAL2,
+ SEQ_TYPE_STANDARD,
+ input_seq(make_code(ITEM_CLASS_ABSOLUTE, ITEM_MODIFIER_NEG, axisitems[1])));
+
+ // use for previous/next group as well
+ assignments.emplace_back(
+ IPT_UI_NEXT_GROUP,
+ SEQ_TYPE_STANDARD,
+ input_seq(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_POS, axisitems[1])));
+ assignments.emplace_back(
+ IPT_UI_PREV_GROUP,
+ SEQ_TYPE_STANDARD,
+ input_seq(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NEG, axisitems[1])));
+ }
+ }
+ else
+ {
+ // see if we have individual pedals
+ if (ITEM_ID_INVALID != pedalitems[0])
+ {
+ assignments.emplace_back(
+ IPT_PEDAL,
+ SEQ_TYPE_STANDARD,
+ input_seq(make_code(ITEM_CLASS_ABSOLUTE, ITEM_MODIFIER_NEG, pedalitems[0])));
+ assignments.emplace_back(
+ IPT_UI_NEXT_GROUP,
+ SEQ_TYPE_STANDARD,
+ input_seq(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NEG, pedalitems[0])));
+ }
+ if (ITEM_ID_INVALID != pedalitems[1])
+ {
+ assignments.emplace_back(
+ IPT_PEDAL2,
+ SEQ_TYPE_STANDARD,
+ input_seq(make_code(ITEM_CLASS_ABSOLUTE, ITEM_MODIFIER_NEG, pedalitems[1])));
+ assignments.emplace_back(
+ IPT_UI_PREV_GROUP,
+ SEQ_TYPE_STANDARD,
+ input_seq(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NEG, pedalitems[1])));
+ }
+ if (ITEM_ID_INVALID != pedalitems[2])
+ {
+ assignments.emplace_back(
+ IPT_PEDAL3,
+ SEQ_TYPE_STANDARD,
+ input_seq(make_code(ITEM_CLASS_ABSOLUTE, ITEM_MODIFIER_NEG, pedalitems[2])));
+ assignments.emplace_back(
+ IPT_UI_FOCUS_NEXT,
+ SEQ_TYPE_STANDARD,
+ input_seq(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NEG, pedalitems[2])));
+ }
+ }
+ }
+ else
+ {
+ // assume this is a gamepad - see if it looks like it has dual analog sticks
+ input_item_id stickaxes[2][2] = {
+ { axisitems[0], axisitems[1] },
+ { ITEM_ID_INVALID, ITEM_ID_INVALID } };
+ input_item_id pedalaxis = ITEM_ID_INVALID;
+ if ((ITEM_ID_INVALID != axisitems[2]) && (ITEM_ID_INVALID != axisitems[5]))
+ {
+ // assume Z/Rz are right stick
+ stickaxes[1][0] = axisitems[2];
+ stickaxes[1][1] = axisitems[5];
+ add_twin_stick_assignments(
+ assignments,
+ stickaxes[0][0],
+ stickaxes[0][1],
+ stickaxes[1][0],
+ stickaxes[1][1],
+ ITEM_ID_INVALID,
+ ITEM_ID_INVALID,
+ ITEM_ID_INVALID,
+ ITEM_ID_INVALID,
+ ITEM_ID_INVALID,
+ ITEM_ID_INVALID,
+ ITEM_ID_INVALID,
+ ITEM_ID_INVALID);
+ }
+ else if ((ITEM_ID_INVALID != axisitems[3]) && (ITEM_ID_INVALID != axisitems[4]))
+ {
+ // assume Rx/Ry are right stick and Z is triggers if present
+ stickaxes[1][0] = axisitems[3];
+ stickaxes[1][1] = axisitems[4];
+ pedalaxis = axisitems[2];
+ add_twin_stick_assignments(
+ assignments,
+ stickaxes[0][0],
+ stickaxes[0][1],
+ stickaxes[1][0],
+ stickaxes[1][1],
+ ITEM_ID_INVALID,
+ ITEM_ID_INVALID,
+ ITEM_ID_INVALID,
+ ITEM_ID_INVALID,
+ ITEM_ID_INVALID,
+ ITEM_ID_INVALID,
+ ITEM_ID_INVALID,
+ ITEM_ID_INVALID);
+ }
+ else
+ {
+ // if Z is present, use it as secondary Y
+ stickaxes[1][1] = axisitems[2];
+ }
+
+ // try to find a "complete" stick for primary movement controls
+ input_item_id diraxis[2][2];
+ choose_primary_stick(diraxis, stickaxes[0][0], stickaxes[0][1], stickaxes[1][0], stickaxes[1][1]);
+ add_directional_assignments(
+ assignments,
+ diraxis[0][0],
+ diraxis[0][1],
+ povitems[0][0],
+ povitems[0][1],
+ povitems[0][2],
+ povitems[0][3]);
+
+ // assign a secondary stick axis to joystick Z
+ add_assignment(
+ assignments,
+ IPT_AD_STICK_Z,
+ SEQ_TYPE_STANDARD,
+ ITEM_CLASS_ABSOLUTE,
+ ITEM_MODIFIER_NONE,
+ { diraxis[1][1], diraxis[1][0] });
+
+ // try to find a suitable axis to use for the first two pedals
+ add_assignment(
+ assignments,
+ IPT_PEDAL,
+ SEQ_TYPE_STANDARD,
+ ITEM_CLASS_ABSOLUTE,
+ ITEM_MODIFIER_NEG,
+ { pedalaxis, diraxis[1][1], diraxis[0][1] });
+ add_assignment(
+ assignments,
+ IPT_PEDAL2,
+ SEQ_TYPE_STANDARD,
+ ITEM_CLASS_ABSOLUTE,
+ ITEM_MODIFIER_POS,
+ { pedalaxis, diraxis[1][1], diraxis[0][1] });
+
+ // try to choose an axis for previous/next group
+ if (ITEM_ID_INVALID != pedalaxis)
+ {
+ // this is reversed because right trigger is negative direction
+ assignments.emplace_back(
+ IPT_UI_PREV_GROUP,
+ SEQ_TYPE_STANDARD,
+ input_seq(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_POS, pedalaxis)));
+ assignments.emplace_back(
+ IPT_UI_NEXT_GROUP,
+ SEQ_TYPE_STANDARD,
+ input_seq(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NEG, pedalaxis)));
+ pedalaxis = ITEM_ID_INVALID;
+ }
+ else if (consume_axis_pair(assignments, IPT_UI_PREV_GROUP, IPT_UI_NEXT_GROUP, diraxis[1][1]))
+ {
+ // took secondary Y
+ }
+ else if (consume_axis_pair(assignments, IPT_UI_PREV_GROUP, IPT_UI_NEXT_GROUP, diraxis[1][0]))
+ {
+ // took secondary X
+ }
+
+ // use secondary Y for page up/down if available
+ consume_axis_pair(assignments, IPT_UI_PAGE_UP, IPT_UI_PAGE_DOWN, diraxis[1][1]);
+
+ // put focus previous/next and zoom on secondary X if available
+ add_axis_pair_assignment(assignments, IPT_UI_FOCUS_PREV, IPT_UI_FOCUS_NEXT, diraxis[1][0]);
+ add_axis_pair_assignment(assignments, IPT_UI_ZOOM_OUT, IPT_UI_ZOOM_IN, diraxis[1][0]);
+ }
+
+ // set default assignments
+ device.set_default_assignments(std::move(assignments));
+}
+
+int32_t dinput_joystick_device::pov_get_state(void *device_internal, void *item_internal)
+{
+ auto *const devinfo = static_cast<dinput_joystick_device *>(device_internal);
+ int const povnum = uintptr_t(item_internal) / 4;
+ int const povdir = uintptr_t(item_internal) % 4;
+
+ // get the current state
+ DWORD const pov = devinfo->m_joystick.state.rgdwPOV[povnum];
+
+ // if invalid, return 0
+ if ((pov & 0xffff) == 0xffff)
+ return 0;
+
+ // return the current state
+ switch (povdir)
+ {
+ case POVDIR_LEFT: return (pov >= 22500) && (pov <= 31500);
+ case POVDIR_RIGHT: return (pov >= 4500) && (pov <= 13500);
+ case POVDIR_UP: return (pov >= 31500) || (pov <= 4500);
+ case POVDIR_DOWN: return (pov >= 13500) && (pov <= 22500);
}
return 0;
@@ -535,18 +1191,16 @@ int dinput_joystick_device::configure()
//============================================================
dinput_api_helper::dinput_api_helper()
- : m_dinput(nullptr)
{
}
dinput_api_helper::~dinput_api_helper()
{
- m_dinput.Reset();
}
int dinput_api_helper::initialize()
{
- HRESULT result = DirectInput8Create(GetModuleHandleUni(), DIRECTINPUT_VERSION, IID_IDirectInput8, reinterpret_cast<void **>(m_dinput.GetAddressOf()), nullptr);
+ HRESULT result = DirectInput8Create(GetModuleHandleUni(), DIRECTINPUT_VERSION, IID_IDirectInput8, &m_dinput, nullptr);
if (result != DI_OK)
{
return result;
@@ -557,25 +1211,132 @@ int dinput_api_helper::initialize()
}
-HRESULT dinput_api_helper::enum_attached_devices(int devclass, device_enum_interface *enumerate_interface, void *state) const
+std::pair<Microsoft::WRL::ComPtr<IDirectInputDevice8>, LPCDIDATAFORMAT> dinput_api_helper::open_device(
+ LPCDIDEVICEINSTANCE instance,
+ LPCDIDATAFORMAT format1,
+ LPCDIDATAFORMAT format2,
+ dinput_cooperative_level cooperative_level)
{
- device_enum_interface::dinput_callback_context ctx;
- ctx.self = enumerate_interface;
- ctx.state = state;
+ HRESULT result;
- return m_dinput->EnumDevices(devclass, device_enum_interface::enum_callback, &ctx, DIEDFL_ATTACHEDONLY);
+ // attempt to create a device
+ Microsoft::WRL::ComPtr<IDirectInputDevice8> device;
+ result = m_dinput->CreateDevice(instance->guidInstance, &device, nullptr);
+ if (result != DI_OK)
+ {
+ osd_printf_error("DirectInput: Unable to create device.\n");
+ return std::make_pair(nullptr, nullptr);
+ }
+
+ // attempt to set the data format
+ LPCDIDATAFORMAT format = format1;
+ result = device->SetDataFormat(format);
+ if ((result != DI_OK) && format2)
+ {
+ // use the secondary format if available
+ osd_printf_verbose("DirectInput: Error setting primary data format, trying secondary format.\n");
+ format = format2;
+ result = device->SetDataFormat(format);
+ }
+ if (result != DI_OK)
+ {
+ osd_printf_error("DirectInput: Unable to set data format.\n");
+ return std::make_pair(nullptr, nullptr);
+ }
+
+ // default window to the first window in the list
+ // For now, we always use the desktop window due to multiple issues:
+ // * MAME recreates windows on toggling fullscreen. DirectInput really doesn't like this.
+ // * DirectInput doesn't like the window used for D3D fullscreen exclusive mode.
+ // * With multiple windows, the first window needs to have focus when using foreground mode.
+ // This makes it impossible to use force feedback as that requires foreground exclusive mode.
+ // The only way to get around this would be to reopen devices on focus changes.
+ [[maybe_unused]] HWND window_handle;
+ DWORD di_cooperative_level;
+#if defined(OSD_WINDOWS)
+ auto const &window = dynamic_cast<win_window_info &>(*osd_common_t::window_list().front());
+ bool const standalone_window = !window.attached_mode();
+#elif defined(SDLMAME_WIN32)
+ auto const &window = dynamic_cast<sdl_window_info &>(*osd_common_t::window_list().front());
+ bool const standalone_window = true;
+#endif
+ if (!standalone_window)
+ {
+ // in attached mode we have to ignore the caller and hook up to the desktop window
+ window_handle = GetDesktopWindow();
+ di_cooperative_level = DISCL_BACKGROUND | DISCL_NONEXCLUSIVE;
+ }
+ else
+ {
+#if defined(OSD_WINDOWS)
+ window_handle = window.platform_window();
+#elif defined(SDLMAME_WIN32)
+ auto const sdlwindow = window.platform_window();
+ SDL_SysWMinfo info;
+ SDL_VERSION(&info.version);
+ if (!SDL_GetWindowWMInfo(sdlwindow, &info))
+ return std::make_pair(nullptr, nullptr);
+ window_handle = info.info.win.window;
+#endif
+ switch (cooperative_level)
+ {
+ case dinput_cooperative_level::BACKGROUND:
+ di_cooperative_level = DISCL_BACKGROUND | DISCL_NONEXCLUSIVE;
+ break;
+ case dinput_cooperative_level::FOREGROUND:
+ //di_cooperative_level = DISCL_FOREGROUND | DISCL_NONEXCLUSIVE;
+ di_cooperative_level = DISCL_BACKGROUND | DISCL_NONEXCLUSIVE;
+ break;
+ default:
+ throw false;
+ }
+ }
+
+ // set the cooperative level
+ result = device->SetCooperativeLevel(GetDesktopWindow(), di_cooperative_level);
+ if (result != DI_OK)
+ {
+ osd_printf_error("DirectInput: Unable to set cooperative level.\n");
+ return std::make_pair(nullptr, nullptr);
+ }
+
+ // return new device
+ return std::make_pair(std::move(device), format);
+}
+
+
+std::string dinput_api_helper::make_id(LPCDIDEVICEINSTANCE instance)
+{
+ // use name, product GUID and instance GUID as identifier
+ return
+ text::from_tstring(instance->tszInstanceName) +
+ " product_" +
+ guid_to_string(instance->guidProduct) +
+ " instance_" +
+ guid_to_string(instance->guidInstance);
}
-#else // defined(OSD_WINDOWS)
+} // namespace osd
+
+
+#else // defined(OSD_WINDOWS) || defined(SDLMAME_WIN32)
#include "input_module.h"
+namespace osd {
+
+namespace {
+
MODULE_NOT_SUPPORTED(keyboard_input_dinput, OSD_KEYBOARDINPUT_PROVIDER, "dinput")
MODULE_NOT_SUPPORTED(mouse_input_dinput, OSD_MOUSEINPUT_PROVIDER, "dinput")
MODULE_NOT_SUPPORTED(joystick_input_dinput, OSD_JOYSTICKINPUT_PROVIDER, "dinput")
-#endif // defined(OSD_WINDOWS)
+} // anonymous namespace
+
+} // namespace osd
+
+#endif // defined(OSD_WINDOWS) || defined(SDLMAME_WIN32)
-MODULE_DEFINITION(KEYBOARDINPUT_DINPUT, keyboard_input_dinput)
-MODULE_DEFINITION(MOUSEINPUT_DINPUT, mouse_input_dinput)
-MODULE_DEFINITION(JOYSTICKINPUT_DINPUT, joystick_input_dinput)
+MODULE_DEFINITION(KEYBOARDINPUT_DINPUT, osd::keyboard_input_dinput)
+MODULE_DEFINITION(MOUSEINPUT_DINPUT, osd::mouse_input_dinput)
+MODULE_DEFINITION(JOYSTICKINPUT_DINPUT, osd::joystick_input_dinput)
diff --git a/src/osd/modules/input/input_dinput.h b/src/osd/modules/input/input_dinput.h
index c9e84d1f633..98fdfb011bb 100644
--- a/src/osd/modules/input/input_dinput.h
+++ b/src/osd/modules/input/input_dinput.h
@@ -1,5 +1,5 @@
// license:BSD-3-Clause
-// copyright-holders:Aaron Giles, Brad Hughes
+// copyright-holders:Aaron Giles, Brad Hughes, Vas Crabb
//============================================================
//
// input_dinput.h - Windows DirectInput support
@@ -10,7 +10,8 @@
#pragma once
-#include "input_windows.h"
+#include "assignmenthelper.h"
+#include "input_wincommon.h"
#include "modules/lib/osdlib.h"
#include "modules/lib/osdobj_common.h"
@@ -19,40 +20,24 @@
#include "strconv.h"
-#include <dinput.h>
+#include <memory>
+#include <mutex>
+#include <string>
+#include <string_view>
+#include <type_traits>
+#include <utility>
+
#include <windows.h>
+#include <dinput.h>
#include <wrl/client.h>
+namespace osd {
+
//============================================================
// dinput_device - base directinput device
//============================================================
-class device_enum_interface
-{
-public:
- struct dinput_callback_context
- {
- device_enum_interface * self;
- void * state;
- };
-
- virtual ~device_enum_interface()
- {
- }
-
- static BOOL CALLBACK enum_callback(LPCDIDEVICEINSTANCE instance, LPVOID ref)
- {
- auto context = static_cast<dinput_callback_context*>(ref);
- return context->self->device_enum_callback(instance, context->state);
- }
-
- virtual BOOL device_enum_callback(LPCDIDEVICEINSTANCE instance, LPVOID ref) = 0;
-};
-
-// Typedef for dynamically loaded function
-typedef HRESULT (WINAPI *dinput_create_fn)(HINSTANCE, DWORD, LPDIRECTINPUT8 *, LPUNKNOWN);
-
enum class dinput_cooperative_level
{
FOREGROUND,
@@ -61,181 +46,144 @@ enum class dinput_cooperative_level
class dinput_api_helper
{
-private:
- Microsoft::WRL::ComPtr<IDirectInput8> m_dinput;
- osd::dynamic_module::ptr m_dinput_dll;
-
public:
dinput_api_helper();
- virtual ~dinput_api_helper();
+ ~dinput_api_helper();
+
int initialize();
- template <class TDevice>
- TDevice *create_device(
- running_machine &machine,
+ template <typename TDevice, typename TCallback>
+ std::unique_ptr<TDevice> create_device(
input_module_base &module,
LPCDIDEVICEINSTANCE instance,
LPCDIDATAFORMAT format1,
LPCDIDATAFORMAT format2,
- dinput_cooperative_level cooperative_level)
+ dinput_cooperative_level cooperative_level,
+ TCallback &&callback)
{
- HRESULT result;
- std::shared_ptr<win_window_info> window;
- HWND hwnd;
-
- // convert instance name to utf8
- std::string utf8_instance_name = osd::text::from_tstring(instance->tszInstanceName);
-
- // set device id to name + product unique identifier + instance unique identifier
- std::string utf8_instance_id = utf8_instance_name + " product_" + guid_to_string(instance->guidProduct) + " instance_" + guid_to_string(instance->guidInstance);
-
- // allocate memory for the device object
- TDevice &devinfo = module.devicelist().create_device<TDevice>(machine, std::move(utf8_instance_name), std::move(utf8_instance_id), module);
-
- // attempt to create a device
- result = m_dinput->CreateDevice(instance->guidInstance, devinfo.dinput.device.GetAddressOf(), nullptr);
+ auto [device, format] = open_device(instance, format1, format2, cooperative_level);
+ if (!device)
+ return nullptr;
+
+ // get the capabilities
+ DIDEVCAPS caps;
+ caps.dwSize = sizeof(caps);
+ HRESULT const result = device->GetCapabilities(&caps);
if (result != DI_OK)
- goto error;
+ return nullptr;
- // get the caps
- devinfo.dinput.caps.dwSize = sizeof(devinfo.dinput.caps);
- result = devinfo.dinput.device->GetCapabilities(&devinfo.dinput.caps);
- if (result != DI_OK)
- goto error;
+ if (!callback(device, format))
+ return nullptr;
- // attempt to set the data format
- devinfo.dinput.format = format1;
- result = devinfo.dinput.device->SetDataFormat(devinfo.dinput.format);
- if (result != DI_OK)
- {
- // use the secondary format if available
- if (format2)
- {
- devinfo.dinput.format = format2;
- result = devinfo.dinput.device->SetDataFormat(devinfo.dinput.format);
- }
- if (result != DI_OK)
- goto error;
- }
-
- // default window to the first window in the list
- window = std::static_pointer_cast<win_window_info>(osd_common_t::s_window_list.front());
- DWORD di_cooperative_level;
- if (window->attached_mode())
- {
- // in attached mode we have to ignore the caller and hook up to the desktop window
- hwnd = GetDesktopWindow();
- di_cooperative_level = DISCL_BACKGROUND | DISCL_NONEXCLUSIVE;
- }
- else
- {
- hwnd = window->platform_window();
- switch (cooperative_level)
- {
- case dinput_cooperative_level::BACKGROUND:
- di_cooperative_level = DISCL_BACKGROUND | DISCL_NONEXCLUSIVE;
- break;
- case dinput_cooperative_level::FOREGROUND:
- di_cooperative_level = DISCL_FOREGROUND | DISCL_NONEXCLUSIVE;
- break;
- default:
- throw false;
- }
- }
-
- // set the cooperative level
- result = devinfo.dinput.device->SetCooperativeLevel(hwnd, di_cooperative_level);
- if (result != DI_OK)
- goto error;
+ // allocate memory for the device object
+ return std::make_unique<TDevice>(
+ text::from_tstring(instance->tszInstanceName),
+ make_id(instance),
+ module,
+ std::move(device),
+ caps,
+ format);
+ }
- return &devinfo;
+ template <typename T>
+ HRESULT enum_attached_devices(int devclass, T &&callback) const
+ {
+ return m_dinput->EnumDevices(
+ devclass,
+ &di_enum_devices_cb<std::remove_reference_t<T> >,
+ LPVOID(&callback),
+ DIEDFL_ATTACHEDONLY);
+ }
- error:
- module.devicelist().free_device(devinfo);
- return nullptr;
+ template <typename T>
+ static HRESULT set_dword_property(
+ T &&device,
+ REFGUID property_guid,
+ DWORD object,
+ DWORD how,
+ DWORD value)
+ {
+ DIPROPDWORD dipdw;
+ dipdw.diph.dwSize = sizeof(dipdw);
+ dipdw.diph.dwHeaderSize = sizeof(dipdw.diph);
+ dipdw.diph.dwObj = object;
+ dipdw.diph.dwHow = how;
+ dipdw.dwData = value;
+
+ return device->SetProperty(property_guid, &dipdw.diph);
}
- HRESULT enum_attached_devices(int devclass, device_enum_interface *enumerate_interface, void *state) const;
+private:
+ std::pair<Microsoft::WRL::ComPtr<IDirectInputDevice8>, LPCDIDATAFORMAT> open_device(
+ LPCDIDEVICEINSTANCE instance,
+ LPCDIDATAFORMAT format1,
+ LPCDIDATAFORMAT format2,
+ dinput_cooperative_level cooperative_level);
- static std::string guid_to_string(const GUID& guid)
+ static std::string make_id(LPCDIDEVICEINSTANCE instance);
+
+ template <typename T>
+ static BOOL CALLBACK di_enum_devices_cb(LPCDIDEVICEINSTANCE instance, LPVOID ref)
{
- // Size of a GUID string with dashes plus null terminator
- char guid_string[37];
-
- snprintf(
- guid_string, std::size(guid_string),
- "%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
- guid.Data1, guid.Data2, guid.Data3,
- guid.Data4[0], guid.Data4[1], guid.Data4[2],
- guid.Data4[3], guid.Data4[4], guid.Data4[5],
- guid.Data4[6], guid.Data4[7]);
-
- return guid_string;
+ return (*reinterpret_cast<T *>(ref))(instance);
}
+
+ Microsoft::WRL::ComPtr<IDirectInput8> m_dinput;
+ dynamic_module::ptr m_dinput_dll;
};
+
class dinput_device : public device_info
{
-public:
- // DirectInput-specific information about a device
- struct dinput_api_state
- {
- Microsoft::WRL::ComPtr<IDirectInputDevice8> device;
- DIDEVCAPS caps;
- LPCDIDATAFORMAT format;
- };
+protected:
+ dinput_device(
+ std::string &&name,
+ std::string &&id,
+ input_module &module,
+ Microsoft::WRL::ComPtr<IDirectInputDevice8> &&device,
+ DIDEVCAPS const &caps,
+ LPCDIDATAFORMAT format);
- dinput_api_state dinput;
+ HRESULT poll_dinput(LPVOID pState) const;
- dinput_device(running_machine &machine, std::string &&name, std::string &&id, input_device_class deviceclass, input_module &module);
- virtual ~dinput_device();
+ std::string item_name(int offset, std::string_view defstr, char const *suffix) const;
-protected:
- HRESULT poll_dinput(LPVOID pState) const;
+ // DirectInput-specific information about a device
+ Microsoft::WRL::ComPtr<IDirectInputDevice8> const m_device;
+ DIDEVCAPS m_caps;
+ LPCDIDATAFORMAT const m_format;
};
-class dinput_keyboard_device : public dinput_device
-{
-private:
- std::mutex m_device_lock;
+class dinput_joystick_device : public dinput_device, protected joystick_assignment_helper
+{
public:
- keyboard_state keyboard;
-
- dinput_keyboard_device(running_machine &machine, std::string &&name, std::string &&id, input_module &module);
+ dinput_joystick_device(
+ std::string &&name,
+ std::string &&id,
+ input_module &module,
+ Microsoft::WRL::ComPtr<IDirectInputDevice8> &&device,
+ DIDEVCAPS const &caps,
+ LPCDIDATAFORMAT format);
- void poll() override;
void reset() override;
-};
+ void poll(bool relative_reset) override;
+ void configure(input_device &device) override;
-class dinput_mouse_device : public dinput_device
-{
-public:
- mouse_state mouse;
+private:
+ // state information for a joystick; DirectInput state must be first element
+ struct dinput_joystick_state
+ {
+ DIJOYSTATE state;
+ LONG rangemin[8];
+ LONG rangemax[8];
+ };
-public:
- dinput_mouse_device(running_machine &machine, std::string &&name, std::string &&id, input_module &module);
- void poll() override;
- void reset() override;
-};
+ static int32_t pov_get_state(void *device_internal, void *item_internal);
-// state information for a joystick; DirectInput state must be first element
-struct dinput_joystick_state
-{
- DIJOYSTATE state;
- LONG rangemin[8];
- LONG rangemax[8];
+ dinput_joystick_state m_joystick;
};
-class dinput_joystick_device : public dinput_device
-{
-public:
- dinput_joystick_state joystick;
-public:
- dinput_joystick_device(running_machine &machine, std::string &&name, std::string &&id, input_module &module);
- void reset() override;
- void poll() override;
- int configure();
-};
+} // namespace osd
#endif // MAME_OSD_INPUT_INPUT_DINPUT_H
diff --git a/src/osd/modules/input/input_mac.cpp b/src/osd/modules/input/input_mac.cpp
index 85afdaeb9cb..90360adaa3f 100644
--- a/src/osd/modules/input/input_mac.cpp
+++ b/src/osd/modules/input/input_mac.cpp
@@ -31,17 +31,10 @@
#include "../../mac/osdmac.h"
#include "input_common.h"
-extern void MacPollInputs();
-
void mac_osd_interface::customize_input_type_list(std::vector<input_type_entry> &typelist)
{
}
-void mac_osd_interface::poll_inputs(running_machine &machine)
-{
- MacPollInputs();
-}
-
void mac_osd_interface::release_keys()
{
}
diff --git a/src/osd/modules/input/input_module.h b/src/osd/modules/input/input_module.h
index 732b9593a57..64e5ebb2332 100644
--- a/src/osd/modules/input/input_module.h
+++ b/src/osd/modules/input/input_module.h
@@ -15,20 +15,13 @@
#include "modules/osdmodule.h"
-class input_module : public osd_module
+class input_module
{
public:
- input_module(const char *type, const char *name)
- : osd_module(type, name)
- {
- }
-
- virtual ~input_module() { }
+ virtual ~input_module() = default;
virtual void input_init(running_machine &machine) = 0;
- virtual void poll_if_necessary(running_machine &machine) = 0;
- virtual void pause() = 0;
- virtual void resume() = 0;
+ virtual void poll_if_necessary(bool relative_reset) = 0;
};
//============================================================
diff --git a/src/osd/modules/input/input_none.cpp b/src/osd/modules/input/input_none.cpp
index bbe19661ab6..96c3f116868 100644
--- a/src/osd/modules/input/input_none.cpp
+++ b/src/osd/modules/input/input_none.cpp
@@ -7,56 +7,58 @@
//============================================================
#include "input_module.h"
-#include "modules/osdmodule.h"
-class keyboard_input_none : public input_module
+
+namespace osd {
+
+namespace {
+
+class keyboard_input_none : public osd_module, public input_module
{
public:
- keyboard_input_none() : input_module(OSD_KEYBOARDINPUT_PROVIDER, "none") { }
- int init(const osd_options &options) override { return 0; }
- void poll_if_necessary(running_machine &machine) override { }
+ keyboard_input_none() : osd_module(OSD_KEYBOARDINPUT_PROVIDER, "none") { }
+ int init(osd_interface &osd, const osd_options &options) override { return 0; }
void input_init(running_machine &machine) override { }
- void pause() override { }
- void resume() override { }
+ void poll_if_necessary(bool relative_reset) override { }
};
-MODULE_DEFINITION(KEYBOARD_NONE, keyboard_input_none)
-class mouse_input_none : public input_module
+class mouse_input_none : public osd_module, public input_module
{
public:
- mouse_input_none() : input_module(OSD_MOUSEINPUT_PROVIDER, "none") { }
- int init(const osd_options &options) override { return 0; }
+ mouse_input_none() : osd_module(OSD_MOUSEINPUT_PROVIDER, "none") { }
+ int init(osd_interface &osd, const osd_options &options) override { return 0; }
void input_init(running_machine &machine) override { }
- void poll_if_necessary(running_machine &machine) override { }
- void pause() override { }
- void resume() override { }
+ void poll_if_necessary(bool relative_reset) override { }
};
-MODULE_DEFINITION(MOUSE_NONE, mouse_input_none)
-class lightgun_input_none : public input_module
+class lightgun_input_none : public osd_module, public input_module
{
public:
- lightgun_input_none() : input_module(OSD_LIGHTGUNINPUT_PROVIDER, "none") { }
- int init(const osd_options &options) override { return 0; }
+ lightgun_input_none() : osd_module(OSD_LIGHTGUNINPUT_PROVIDER, "none") { }
+ int init(osd_interface &osd, const osd_options &options) override { return 0; }
void input_init(running_machine &machine) override { }
- void poll_if_necessary(running_machine &machine) override { }
- void pause() override { }
- void resume() override { }
+ void poll_if_necessary(bool relative_reset) override { }
};
-MODULE_DEFINITION(LIGHTGUN_NONE, lightgun_input_none)
-class joystick_input_none : public input_module
+class joystick_input_none : public osd_module, public input_module
{
public:
- joystick_input_none() : input_module(OSD_JOYSTICKINPUT_PROVIDER, "none") { }
- int init(const osd_options &options) override { return 0; }
+ joystick_input_none() : osd_module(OSD_JOYSTICKINPUT_PROVIDER, "none") { }
+ int init(osd_interface &osd, const osd_options &options) override { return 0; }
void input_init(running_machine &machine) override { }
- void poll_if_necessary(running_machine &machine) override { }
- void pause() override { }
- void resume() override { }
+ void poll_if_necessary(bool relative_reset) override { }
};
-MODULE_DEFINITION(JOYSTICK_NONE, joystick_input_none)
+} // anonymous namesapce
+
+} // namespace osd
+
+
+
+MODULE_DEFINITION(KEYBOARD_NONE, osd::keyboard_input_none)
+MODULE_DEFINITION(MOUSE_NONE, osd::mouse_input_none)
+MODULE_DEFINITION(LIGHTGUN_NONE, osd::lightgun_input_none)
+MODULE_DEFINITION(JOYSTICK_NONE, osd::joystick_input_none)
diff --git a/src/osd/modules/input/input_rawinput.cpp b/src/osd/modules/input/input_rawinput.cpp
index 94018f9c404..d6b99649c4a 100644
--- a/src/osd/modules/input/input_rawinput.cpp
+++ b/src/osd/modules/input/input_rawinput.cpp
@@ -10,27 +10,34 @@
#if defined(OSD_WINDOWS)
-// MAME headers
-#include "emu.h"
-
#include "input_windows.h"
+#include "input_wincommon.h"
+
#include "winmain.h"
#include "window.h"
#include "modules/lib/osdlib.h"
#include "strconv.h"
+// MAME headers
+#include "inpttype.h"
+
#include <algorithm>
+#include <cassert>
+#include <chrono>
#include <functional>
#include <mutex>
#include <new>
+#include <utility>
// standard windows headers
#include <windows.h>
#include <tchar.h>
+namespace osd {
+
namespace {
class safe_regkey
@@ -222,6 +229,7 @@ std::wstring improve_name_from_usb_path(const std::wstring &regpath)
return trim_prefix(regstring);
}
+
//============================================================
// rawinput_device_improve_name
//============================================================
@@ -262,19 +270,36 @@ std::wstring rawinput_device_improve_name(const std::wstring &name)
class rawinput_device : public event_based_device<RAWINPUT>
{
-private:
- HANDLE m_handle = nullptr;
-
public:
- rawinput_device(running_machine &machine, std::string &&name, std::string &&id, input_device_class deviceclass, input_module &module) :
- event_based_device(machine, std::move(name), std::move(id), deviceclass, module)
+ rawinput_device(std::string &&name, std::string &&id, input_module &module, HANDLE handle) :
+ event_based_device(std::move(name), std::move(id), module),
+ m_handle(handle)
{
}
HANDLE device_handle() const { return m_handle; }
- void set_handle(HANDLE handle) { m_handle = handle; }
+
+ bool reconnect_candidate(std::string_view i) const { return !m_handle && (id() == i); }
+
+ void detach_device()
+ {
+ assert(m_handle);
+ m_handle = nullptr;
+ osd_printf_verbose("RawInput: %s [ID %s] disconnected\n", name(), id());
+ }
+
+ void attach_device(HANDLE handle)
+ {
+ assert(!m_handle);
+ m_handle = handle;
+ osd_printf_verbose("RawInput: %s [ID %s] reconnected\n", name(), id());
+ }
+
+private:
+ HANDLE m_handle;
};
+
//============================================================
// rawinput_keyboard_device
//============================================================
@@ -282,172 +307,329 @@ public:
class rawinput_keyboard_device : public rawinput_device
{
public:
- keyboard_state keyboard;
+ rawinput_keyboard_device(std::string &&name, std::string &&id, input_module &module, HANDLE handle) :
+ rawinput_device(std::move(name), std::move(id), module, handle),
+ m_pause_pressed(std::chrono::steady_clock::time_point::min()),
+ m_e1(0xffff),
+ m_keyboard({ { 0 } })
+ {
+ }
- rawinput_keyboard_device(running_machine &machine, std::string &&name, std::string &&id, input_module &module) :
- rawinput_device(machine, std::move(name), std::move(id), DEVICE_CLASS_KEYBOARD, module),
- keyboard({ { 0 } })
+ virtual void reset() override
{
+ m_pause_pressed = std::chrono::steady_clock::time_point::min();
+ memset(&m_keyboard, 0, sizeof(m_keyboard));
+ m_e1 = 0xffff;
}
- void reset() override
+ virtual void poll(bool relative_reset) override
{
- memset(&keyboard, 0, sizeof(keyboard));
+ rawinput_device::poll(relative_reset);
+
+ if (m_keyboard.state[0x80 | 0x45] && (std::chrono::steady_clock::now() > (m_pause_pressed + std::chrono::milliseconds(30))))
+ m_keyboard.state[0x80 | 0x45] = 0x00;
}
- void process_event(RAWINPUT &rawinput) override
+ virtual void process_event(RAWINPUT const &rawinput) override
{
// determine the full DIK-compatible scancode
- uint8_t scancode = (rawinput.data.keyboard.MakeCode & 0x7f) | ((rawinput.data.keyboard.Flags & RI_KEY_E0) ? 0x80 : 0x00);
+ uint8_t scancode;
- // scancode 0xaa is a special shift code we need to ignore
- if (scancode == 0xaa)
+ // the only thing that uses this is Pause
+ if (rawinput.data.keyboard.Flags & RI_KEY_E1)
+ {
+ m_e1 = rawinput.data.keyboard.MakeCode;
return;
+ }
+ else if (0xffff != m_e1)
+ {
+ auto const e1 = std::exchange(m_e1, 0xffff);
+ if (!(rawinput.data.keyboard.Flags & RI_KEY_E0))
+ {
+ if (((e1 & ~USHORT(0x80)) == 0x1d) && ((rawinput.data.keyboard.MakeCode & ~USHORT(0x80)) == 0x45))
+ {
+ if (rawinput.data.keyboard.Flags & RI_KEY_BREAK)
+ return; // RawInput generates a fake break immediately after the make - ignore it
+
+ m_pause_pressed = std::chrono::steady_clock::now();
+ scancode = 0x80 | 0x45;
+ }
+ else
+ {
+ return; // no idea
+ }
+ }
+ else
+ {
+ return; // shouldn't happen, ignore it
+ }
+ }
+ else
+ {
+ // strip bit 7 of the make code to work around dodgy drivers that set it for key up events
+ if (rawinput.data.keyboard.MakeCode & ~USHORT(0xff))
+ {
+ // won't fit in a byte along with the E0 flag
+ return;
+ }
+ scancode = (rawinput.data.keyboard.MakeCode & 0x7f) | ((rawinput.data.keyboard.Flags & RI_KEY_E0) ? 0x80 : 0x00);
+
+ // fake shift generated with cursor control and Ins/Del for compatibility with very old DOS software
+ if (scancode == 0xaa)
+ return;
+ }
// set or clear the key
- keyboard.state[scancode] = (rawinput.data.keyboard.Flags & RI_KEY_BREAK) ? 0x00 : 0x80;
+ m_keyboard.state[scancode] = (rawinput.data.keyboard.Flags & RI_KEY_BREAK) ? 0x00 : 0x80;
}
+
+ virtual void configure(input_device &device) override
+ {
+ keyboard_trans_table const &table = keyboard_trans_table::instance();
+
+ // FIXME: GetKeyNameTextW is for scan codes from WM_KEYDOWN, which aren't quite the same as DIK_* keycodes
+ // in particular, NumLock and Pause are reversed for US-style keyboard systems
+ for (unsigned keynum = 0; keynum < MAX_KEYS; keynum++)
+ {
+ input_item_id itemid = table.map_di_scancode_to_itemid(keynum);
+ WCHAR keyname[100];
+
+ // generate the name
+ // FIXME: GetKeyNameText gives bogus names for media keys and various other things
+ // in many cases it ignores the "extended" bit and returns the key name corresponding to the scan code alone
+ LONG lparam = ((keynum & 0x7f) << 16) | ((keynum & 0x80) << 17);
+ if ((keynum & 0x7f) == 0x45)
+ lparam ^= 0x0100'0000; // horrid hack
+ if (GetKeyNameTextW(lparam, keyname, std::size(keyname)) == 0)
+ _snwprintf(keyname, std::size(keyname), L"Scan%03d", keynum);
+ std::string name = text::from_wstring(keyname);
+
+ // add the item to the device
+ device.add_item(
+ name,
+ util::string_format("SCAN%03d", keynum),
+ itemid,
+ generic_button_get_state<std::uint8_t>,
+ &m_keyboard.state[keynum]);
+ }
+ }
+
+private:
+ std::chrono::steady_clock::time_point m_pause_pressed;
+ uint16_t m_e1;
+ keyboard_state m_keyboard;
};
+
//============================================================
// rawinput_mouse_device
//============================================================
class rawinput_mouse_device : public rawinput_device
{
-private:
- std::mutex m_device_lock;
public:
- mouse_state mouse;
-
- rawinput_mouse_device(running_machine &machine, std::string &&name, std::string &&id, input_module &module) :
- rawinput_device(machine, std::move(name), std::move(id), DEVICE_CLASS_MOUSE, module),
- mouse({0})
+ rawinput_mouse_device(std::string &&name, std::string &&id, input_module &module, HANDLE handle) :
+ rawinput_device(std::move(name), std::move(id), module, handle),
+ m_mouse({0}),
+ m_x(0),
+ m_y(0),
+ m_z(0)
{
}
- void poll() override
+ virtual void poll(bool relative_reset) override
{
- mouse.lX = 0;
- mouse.lY = 0;
- mouse.lZ = 0;
+ rawinput_device::poll(relative_reset);
+ if (relative_reset)
+ {
+ m_mouse.lX = std::exchange(m_x, 0);
+ m_mouse.lY = std::exchange(m_y, 0);
+ m_mouse.lZ = std::exchange(m_z, 0);
+ }
+ }
- rawinput_device::poll();
+ virtual void reset() override
+ {
+ memset(&m_mouse, 0, sizeof(m_mouse));
+ m_x = m_y = m_z = 0;
}
- void reset() override
+ virtual void configure(input_device &device) override
{
- memset(&mouse, 0, sizeof(mouse));
+ // populate the axes
+ for (int axisnum = 0; axisnum < 3; axisnum++)
+ {
+ device.add_item(
+ default_axis_name[axisnum],
+ std::string_view(),
+ input_item_id(ITEM_ID_XAXIS + axisnum),
+ generic_axis_get_state<LONG>,
+ &m_mouse.lX + axisnum);
+ }
+
+ // populate the buttons
+ for (int butnum = 0; butnum < 5; butnum++)
+ {
+ device.add_item(
+ default_button_name(butnum),
+ std::string_view(),
+ input_item_id(ITEM_ID_BUTTON1 + butnum),
+ generic_button_get_state<BYTE>,
+ &m_mouse.rgbButtons[butnum]);
+ }
}
- void process_event(RAWINPUT &rawinput) override
+ virtual void process_event(RAWINPUT const &rawinput) override
{
// If this data was intended for a rawinput mouse
if (rawinput.data.mouse.usFlags == MOUSE_MOVE_RELATIVE)
{
- mouse.lX += rawinput.data.mouse.lLastX * osd::INPUT_RELATIVE_PER_PIXEL;
- mouse.lY += rawinput.data.mouse.lLastY * osd::INPUT_RELATIVE_PER_PIXEL;
+ m_x += rawinput.data.mouse.lLastX * input_device::RELATIVE_PER_PIXEL;
+ m_y += rawinput.data.mouse.lLastY * input_device::RELATIVE_PER_PIXEL;
- // update zaxis
+ // update Z axis (vertical scroll)
if (rawinput.data.mouse.usButtonFlags & RI_MOUSE_WHEEL)
- mouse.lZ += static_cast<int16_t>(rawinput.data.mouse.usButtonData) * osd::INPUT_RELATIVE_PER_PIXEL;
+ m_z += int16_t(rawinput.data.mouse.usButtonData) * input_device::RELATIVE_PER_PIXEL;
// update the button states; always update the corresponding mouse buttons
- if (rawinput.data.mouse.usButtonFlags & RI_MOUSE_BUTTON_1_DOWN) mouse.rgbButtons[0] = 0x80;
- if (rawinput.data.mouse.usButtonFlags & RI_MOUSE_BUTTON_1_UP) mouse.rgbButtons[0] = 0x00;
- if (rawinput.data.mouse.usButtonFlags & RI_MOUSE_BUTTON_2_DOWN) mouse.rgbButtons[1] = 0x80;
- if (rawinput.data.mouse.usButtonFlags & RI_MOUSE_BUTTON_2_UP) mouse.rgbButtons[1] = 0x00;
- if (rawinput.data.mouse.usButtonFlags & RI_MOUSE_BUTTON_3_DOWN) mouse.rgbButtons[2] = 0x80;
- if (rawinput.data.mouse.usButtonFlags & RI_MOUSE_BUTTON_3_UP) mouse.rgbButtons[2] = 0x00;
- if (rawinput.data.mouse.usButtonFlags & RI_MOUSE_BUTTON_4_DOWN) mouse.rgbButtons[3] = 0x80;
- if (rawinput.data.mouse.usButtonFlags & RI_MOUSE_BUTTON_4_UP) mouse.rgbButtons[3] = 0x00;
- if (rawinput.data.mouse.usButtonFlags & RI_MOUSE_BUTTON_5_DOWN) mouse.rgbButtons[4] = 0x80;
- if (rawinput.data.mouse.usButtonFlags & RI_MOUSE_BUTTON_5_UP) mouse.rgbButtons[4] = 0x00;
+ if (rawinput.data.mouse.usButtonFlags & RI_MOUSE_BUTTON_1_DOWN) m_mouse.rgbButtons[0] = 0x80;
+ if (rawinput.data.mouse.usButtonFlags & RI_MOUSE_BUTTON_1_UP) m_mouse.rgbButtons[0] = 0x00;
+ if (rawinput.data.mouse.usButtonFlags & RI_MOUSE_BUTTON_2_DOWN) m_mouse.rgbButtons[1] = 0x80;
+ if (rawinput.data.mouse.usButtonFlags & RI_MOUSE_BUTTON_2_UP) m_mouse.rgbButtons[1] = 0x00;
+ if (rawinput.data.mouse.usButtonFlags & RI_MOUSE_BUTTON_3_DOWN) m_mouse.rgbButtons[2] = 0x80;
+ if (rawinput.data.mouse.usButtonFlags & RI_MOUSE_BUTTON_3_UP) m_mouse.rgbButtons[2] = 0x00;
+ if (rawinput.data.mouse.usButtonFlags & RI_MOUSE_BUTTON_4_DOWN) m_mouse.rgbButtons[3] = 0x80;
+ if (rawinput.data.mouse.usButtonFlags & RI_MOUSE_BUTTON_4_UP) m_mouse.rgbButtons[3] = 0x00;
+ if (rawinput.data.mouse.usButtonFlags & RI_MOUSE_BUTTON_5_DOWN) m_mouse.rgbButtons[4] = 0x80;
+ if (rawinput.data.mouse.usButtonFlags & RI_MOUSE_BUTTON_5_UP) m_mouse.rgbButtons[4] = 0x00;
}
}
+
+private:
+ mouse_state m_mouse;
+ LONG m_x, m_y, m_z;
};
+
//============================================================
// rawinput_lightgun_device
//============================================================
class rawinput_lightgun_device : public rawinput_device
{
-private:
- std::mutex m_device_lock;
public:
- mouse_state lightgun;
-
- rawinput_lightgun_device(running_machine &machine, std::string &&name, std::string &&id, input_module &module) :
- rawinput_device(machine, std::move(name), std::move(id), DEVICE_CLASS_LIGHTGUN, module),
- lightgun({0})
+ rawinput_lightgun_device(std::string &&name, std::string &&id, input_module &module, HANDLE handle) :
+ rawinput_device(std::move(name), std::move(id), module, handle),
+ m_lightgun({0}),
+ m_z(0)
{
}
- void poll() override
+ virtual void poll(bool relative_reset) override
{
- lightgun.lZ = 0;
+ rawinput_device::poll(relative_reset);
+ if (relative_reset)
+ m_lightgun.lZ = std::exchange(m_z, 0);
+ }
- rawinput_device::poll();
+ virtual void reset() override
+ {
+ memset(&m_lightgun, 0, sizeof(m_lightgun));
+ m_z = 0;
}
- void reset() override
+ virtual void configure(input_device &device) override
{
- memset(&lightgun, 0, sizeof(lightgun));
+ // populate the axes
+ for (int axisnum = 0; axisnum < 2; axisnum++)
+ {
+ device.add_item(
+ default_axis_name[axisnum],
+ std::string_view(),
+ input_item_id(ITEM_ID_XAXIS + axisnum),
+ generic_axis_get_state<LONG>,
+ &m_lightgun.lX + axisnum);
+ }
+
+ // scroll wheel is always relative if present
+ device.add_item(
+ default_axis_name[2],
+ std::string_view(),
+ ITEM_ID_ADD_RELATIVE1,
+ generic_axis_get_state<LONG>,
+ &m_lightgun.lZ);
+
+ // populate the buttons
+ for (int butnum = 0; butnum < 5; butnum++)
+ {
+ device.add_item(
+ default_button_name(butnum),
+ std::string_view(),
+ input_item_id(ITEM_ID_BUTTON1 + butnum),
+ generic_button_get_state<BYTE>,
+ &m_lightgun.rgbButtons[butnum]);
+ }
}
- void process_event(RAWINPUT &rawinput) override
+ virtual void process_event(RAWINPUT const &rawinput) override
{
// If this data was intended for a rawinput lightgun
if (rawinput.data.mouse.usFlags & MOUSE_MOVE_ABSOLUTE)
{
// update the X/Y positions
- lightgun.lX = normalize_absolute_axis(rawinput.data.mouse.lLastX, 0, osd::INPUT_ABSOLUTE_MAX);
- lightgun.lY = normalize_absolute_axis(rawinput.data.mouse.lLastY, 0, osd::INPUT_ABSOLUTE_MAX);
+ m_lightgun.lX = normalize_absolute_axis(rawinput.data.mouse.lLastX, 0, input_device::ABSOLUTE_MAX);
+ m_lightgun.lY = normalize_absolute_axis(rawinput.data.mouse.lLastY, 0, input_device::ABSOLUTE_MAX);
// update zaxis
if (rawinput.data.mouse.usButtonFlags & RI_MOUSE_WHEEL)
- lightgun.lZ += static_cast<int16_t>(rawinput.data.mouse.usButtonData) * osd::INPUT_RELATIVE_PER_PIXEL;
+ m_z += int16_t(rawinput.data.mouse.usButtonData) * input_device::RELATIVE_PER_PIXEL;
// update the button states; always update the corresponding mouse buttons
- if (rawinput.data.mouse.usButtonFlags & RI_MOUSE_BUTTON_1_DOWN) lightgun.rgbButtons[0] = 0x80;
- if (rawinput.data.mouse.usButtonFlags & RI_MOUSE_BUTTON_1_UP) lightgun.rgbButtons[0] = 0x00;
- if (rawinput.data.mouse.usButtonFlags & RI_MOUSE_BUTTON_2_DOWN) lightgun.rgbButtons[1] = 0x80;
- if (rawinput.data.mouse.usButtonFlags & RI_MOUSE_BUTTON_2_UP) lightgun.rgbButtons[1] = 0x00;
- if (rawinput.data.mouse.usButtonFlags & RI_MOUSE_BUTTON_3_DOWN) lightgun.rgbButtons[2] = 0x80;
- if (rawinput.data.mouse.usButtonFlags & RI_MOUSE_BUTTON_3_UP) lightgun.rgbButtons[2] = 0x00;
- if (rawinput.data.mouse.usButtonFlags & RI_MOUSE_BUTTON_4_DOWN) lightgun.rgbButtons[3] = 0x80;
- if (rawinput.data.mouse.usButtonFlags & RI_MOUSE_BUTTON_4_UP) lightgun.rgbButtons[3] = 0x00;
- if (rawinput.data.mouse.usButtonFlags & RI_MOUSE_BUTTON_5_DOWN) lightgun.rgbButtons[4] = 0x80;
- if (rawinput.data.mouse.usButtonFlags & RI_MOUSE_BUTTON_5_UP) lightgun.rgbButtons[4] = 0x00;
+ if (rawinput.data.mouse.usButtonFlags & RI_MOUSE_BUTTON_1_DOWN) m_lightgun.rgbButtons[0] = 0x80;
+ if (rawinput.data.mouse.usButtonFlags & RI_MOUSE_BUTTON_1_UP) m_lightgun.rgbButtons[0] = 0x00;
+ if (rawinput.data.mouse.usButtonFlags & RI_MOUSE_BUTTON_2_DOWN) m_lightgun.rgbButtons[1] = 0x80;
+ if (rawinput.data.mouse.usButtonFlags & RI_MOUSE_BUTTON_2_UP) m_lightgun.rgbButtons[1] = 0x00;
+ if (rawinput.data.mouse.usButtonFlags & RI_MOUSE_BUTTON_3_DOWN) m_lightgun.rgbButtons[2] = 0x80;
+ if (rawinput.data.mouse.usButtonFlags & RI_MOUSE_BUTTON_3_UP) m_lightgun.rgbButtons[2] = 0x00;
+ if (rawinput.data.mouse.usButtonFlags & RI_MOUSE_BUTTON_4_DOWN) m_lightgun.rgbButtons[3] = 0x80;
+ if (rawinput.data.mouse.usButtonFlags & RI_MOUSE_BUTTON_4_UP) m_lightgun.rgbButtons[3] = 0x00;
+ if (rawinput.data.mouse.usButtonFlags & RI_MOUSE_BUTTON_5_DOWN) m_lightgun.rgbButtons[4] = 0x80;
+ if (rawinput.data.mouse.usButtonFlags & RI_MOUSE_BUTTON_5_UP) m_lightgun.rgbButtons[4] = 0x00;
}
}
+
+private:
+ mouse_state m_lightgun;
+ LONG m_z;
};
+
//============================================================
-// rawinput_module - base class for rawinput modules
+// rawinput_module - base class for RawInput modules
//============================================================
-class rawinput_module : public wininput_module
+class rawinput_module : public wininput_module<rawinput_device>
{
private:
std::mutex m_module_lock;
public:
- rawinput_module(const char *type, const char *name) : wininput_module(type, name)
+ rawinput_module(const char *type, const char *name) : wininput_module<rawinput_device>(type, name)
{
}
- bool probe() override
+ virtual bool probe() override
{
return true;
}
- void input_init(running_machine &machine) override
+ virtual void input_init(running_machine &machine) override
{
+ wininput_module<rawinput_device>::input_init(machine);
+
// get initial number of devices
UINT device_count = 0;
if (GetRawInputDeviceList(nullptr, &device_count, sizeof(RAWINPUTDEVICELIST)) != 0)
@@ -479,11 +661,7 @@ public:
// iterate backwards through devices; new devices are added at the head
for (int devnum = retrieved - 1; devnum >= 0; devnum--)
- add_rawinput_device(machine, rawinput_devices[devnum]);
-
- // don't enable global inputs when debugging
- if (!machine.options().debug())
- m_global_inputs_enabled = downcast<windows_options &>(machine.options()).global_inputs();
+ add_rawinput_device(rawinput_devices[devnum]);
// If we added no devices, no need to register for notifications
if (devicelist().empty())
@@ -494,26 +672,21 @@ public:
registration.usUsagePage = usagepage();
registration.usUsage = usage();
registration.dwFlags = RIDEV_DEVNOTIFY;
- if (m_global_inputs_enabled)
+ if (background_input())
registration.dwFlags |= RIDEV_INPUTSINK;
- registration.hwndTarget = std::static_pointer_cast<win_window_info>(osd_common_t::s_window_list.front())->platform_window();
+ registration.hwndTarget = dynamic_cast<win_window_info &>(*osd_common_t::window_list().front()).platform_window();
// register the device
RegisterRawInputDevices(&registration, 1, sizeof(registration));
}
protected:
- virtual void add_rawinput_device(running_machine &machine, RAWINPUTDEVICELIST const &device) = 0;
+ virtual void add_rawinput_device(RAWINPUTDEVICELIST const &device) = 0;
virtual USHORT usagepage() = 0;
virtual USHORT usage() = 0;
- int init_internal() override
- {
- return 0;
- }
-
template<class TDevice>
- TDevice *create_rawinput_device(running_machine &machine, RAWINPUTDEVICELIST const &rawinputdevice)
+ TDevice *create_rawinput_device(input_device_class deviceclass, RAWINPUTDEVICELIST const &rawinputdevice)
{
// determine the length of the device name, allocate it, and fetch it if not nameless
UINT name_length = 0;
@@ -528,38 +701,34 @@ protected:
if (wcsstr(tname.get(), L"Root#RDP_") != nullptr)
return nullptr;
- // improve the name and then allocate a device
- std::string utf8_name = osd::text::from_wstring(rawinput_device_improve_name(tname.get()));
+ // improve the name
+ std::string utf8_name = text::from_wstring(rawinput_device_improve_name(tname.get()));
// set device ID to raw input name
- std::string utf8_id = osd::text::from_wstring(tname.get());
+ std::string utf8_id = text::from_wstring(tname.get());
tname.reset();
- TDevice &devinfo = devicelist().create_device<TDevice>(machine, std::move(utf8_name), std::move(utf8_id), *this);
-
- // Add the handle
- devinfo.set_handle(rawinputdevice.hDevice);
-
- return &devinfo;
+ // allocate a device
+ return &create_device<TDevice>(
+ deviceclass,
+ std::move(utf8_name),
+ std::move(utf8_id),
+ rawinputdevice.hDevice);
}
- bool handle_input_event(input_event eventid, void *eventdata) override
+ virtual bool handle_input_event(input_event eventid, void *eventdata) override
{
switch (eventid)
{
// handle raw input data
case INPUT_EVENT_RAWINPUT:
{
- // ignore if not enabled
- if (!input_enabled())
- return false;
+ HRAWINPUT const rawinputdevice = *static_cast<HRAWINPUT *>(eventdata);
- HRAWINPUT rawinputdevice = *static_cast<HRAWINPUT *>(eventdata);
-
- BYTE small_buffer[4096];
+ union { RAWINPUT r; BYTE b[4096]; } small_buffer;
std::unique_ptr<BYTE []> larger_buffer;
- LPBYTE data = small_buffer;
+ LPVOID data = &small_buffer;
UINT size;
// determine the size of data buffer we need
@@ -569,7 +738,7 @@ protected:
// if necessary, allocate a temporary buffer and fetch the data
if (size > sizeof(small_buffer))
{
- larger_buffer.reset(new (std::nothrow) BYTE [size]);
+ larger_buffer.reset(new (std::align_val_t(alignof(RAWINPUT)), std::nothrow) BYTE [size]);
data = larger_buffer.get();
if (!data)
return false;
@@ -595,13 +764,12 @@ protected:
devicelist().end(),
[input] (auto const &device)
{
- auto devinfo = dynamic_cast<rawinput_device *>(device.get());
- return devinfo && (input->header.hDevice == devinfo->device_handle());
+ return input->header.hDevice == device->device_handle();
});
if (devicelist().end() == target_device)
return false;
- static_cast<rawinput_device *>(target_device->get())->queue_events(input, 1);
+ (*target_device)->queue_events(input, 1);
return true;
}
}
@@ -609,7 +777,7 @@ protected:
case INPUT_EVENT_ARRIVAL:
{
- HRAWINPUT rawinputdevice = *static_cast<HRAWINPUT *>(eventdata);
+ HRAWINPUT const rawinputdevice = *static_cast<HRAWINPUT *>(eventdata);
// determine the length of the device name, allocate it, and fetch it if not nameless
UINT name_length = 0;
@@ -619,7 +787,7 @@ protected:
std::unique_ptr<WCHAR []> tname = std::make_unique<WCHAR []>(name_length + 1);
if (name_length > 1 && GetRawInputDeviceInfoW(rawinputdevice, RIDI_DEVICENAME, tname.get(), &name_length) == UINT(-1))
return false;
- std::string utf8_id = osd::text::from_wstring(tname.get());
+ std::string utf8_id = text::from_wstring(tname.get());
tname.reset();
std::lock_guard<std::mutex> scope_lock(m_module_lock);
@@ -630,20 +798,19 @@ protected:
devicelist().end(),
[&utf8_id] (auto const &device)
{
- auto devinfo = dynamic_cast<rawinput_device *>(device.get());
- return devinfo && !devinfo->device_handle() && (devinfo->id() == utf8_id);
+ return device->reconnect_candidate(utf8_id);
});
if (devicelist().end() == target_device)
return false;
- static_cast<rawinput_device *>(target_device->get())->set_handle(rawinputdevice);
+ (*target_device)->attach_device(rawinputdevice);
return true;
}
break;
case INPUT_EVENT_REMOVAL:
{
- HRAWINPUT rawinputdevice = *static_cast<HRAWINPUT *>(eventdata);
+ HRAWINPUT const rawinputdevice = *static_cast<HRAWINPUT *>(eventdata);
std::lock_guard<std::mutex> scope_lock(m_module_lock);
@@ -653,15 +820,14 @@ protected:
devicelist().end(),
[rawinputdevice] (auto const &device)
{
- auto devinfo = dynamic_cast<rawinput_device *>(device.get());
- return devinfo && (rawinputdevice == devinfo->device_handle());
+ return rawinputdevice == device->device_handle();
});
if (devicelist().end() == target_device)
return false;
(*target_device)->reset();
- static_cast<rawinput_device *>(target_device->get())->set_handle(nullptr);
+ (*target_device)->detach_device();
return true;
}
break;
@@ -675,163 +841,109 @@ protected:
}
};
+
//============================================================
-// keyboard_input_rawinput - rawinput keyboard module
+// keyboard_input_rawinput - RawInput keyboard module
//============================================================
class keyboard_input_rawinput : public rawinput_module
{
public:
- keyboard_input_rawinput()
- : rawinput_module(OSD_KEYBOARDINPUT_PROVIDER, "rawinput")
+ keyboard_input_rawinput() : rawinput_module(OSD_KEYBOARDINPUT_PROVIDER, "rawinput")
{
}
protected:
- USHORT usagepage() override { return 1; }
- USHORT usage() override { return 6; }
+ virtual USHORT usagepage() override { return 1; }
+ virtual USHORT usage() override { return 6; }
- void add_rawinput_device(running_machine &machine, RAWINPUTDEVICELIST const &device) override
+ virtual void add_rawinput_device(RAWINPUTDEVICELIST const &device) override
{
// make sure this is a keyboard
if (device.dwType != RIM_TYPEKEYBOARD)
return;
// allocate and link in a new device
- auto *devinfo = create_rawinput_device<rawinput_keyboard_device>(machine, device);
- if (devinfo == nullptr)
- return;
-
- keyboard_trans_table &table = keyboard_trans_table::instance();
-
- // populate it
- for (int keynum = 0; keynum < MAX_KEYS; keynum++)
- {
- input_item_id itemid = table.map_di_scancode_to_itemid(keynum);
- WCHAR keyname[100];
-
- // generate the name
- if (GetKeyNameTextW(((keynum & 0x7f) << 16) | ((keynum & 0x80) << 17), keyname, std::size(keyname)) == 0)
- _snwprintf(keyname, std::size(keyname), L"Scan%03d", keynum);
- std::string name = osd::text::from_wstring(keyname);
-
- // add the item to the device
- devinfo->device()->add_item(name, itemid, generic_button_get_state<std::uint8_t>, &devinfo->keyboard.state[keynum]);
- }
+ create_rawinput_device<rawinput_keyboard_device>(DEVICE_CLASS_KEYBOARD, device);
}
};
+
//============================================================
-// mouse_input_rawinput - rawinput mouse module
+// mouse_input_rawinput - RawInput mouse module
//============================================================
class mouse_input_rawinput : public rawinput_module
{
public:
- mouse_input_rawinput()
- : rawinput_module(OSD_MOUSEINPUT_PROVIDER, "rawinput")
+ mouse_input_rawinput() : rawinput_module(OSD_MOUSEINPUT_PROVIDER, "rawinput")
{
}
protected:
- USHORT usagepage() override { return 1; }
- USHORT usage() override { return 2; }
+ virtual USHORT usagepage() override { return 1; }
+ virtual USHORT usage() override { return 2; }
- void add_rawinput_device(running_machine &machine, RAWINPUTDEVICELIST const &device) override
+ virtual void add_rawinput_device(RAWINPUTDEVICELIST const &device) override
{
// make sure this is a mouse
if (device.dwType != RIM_TYPEMOUSE)
return;
// allocate and link in a new device
- auto *devinfo = create_rawinput_device<rawinput_mouse_device>(machine, device);
- if (devinfo == nullptr)
- return;
-
- // populate the axes
- for (int axisnum = 0; axisnum < 3; axisnum++)
- {
- devinfo->device()->add_item(
- default_axis_name[axisnum],
- static_cast<input_item_id>(ITEM_ID_XAXIS + axisnum),
- generic_axis_get_state<LONG>,
- &devinfo->mouse.lX + axisnum);
- }
-
- // populate the buttons
- for (int butnum = 0; butnum < 5; butnum++)
- {
- devinfo->device()->add_item(
- default_button_name(butnum),
- static_cast<input_item_id>(ITEM_ID_BUTTON1 + butnum),
- generic_button_get_state<BYTE>,
- &devinfo->mouse.rgbButtons[butnum]);
- }
+ create_rawinput_device<rawinput_mouse_device>(DEVICE_CLASS_MOUSE, device);
}
};
+
//============================================================
-// lightgun_input_rawinput - rawinput lightgun module
+// lightgun_input_rawinput - RawInput lightgun module
//============================================================
class lightgun_input_rawinput : public rawinput_module
{
public:
- lightgun_input_rawinput()
- : rawinput_module(OSD_LIGHTGUNINPUT_PROVIDER, "rawinput")
+ lightgun_input_rawinput() : rawinput_module(OSD_LIGHTGUNINPUT_PROVIDER, "rawinput")
{
}
protected:
- USHORT usagepage() override { return 1; }
- USHORT usage() override { return 2; }
+ virtual USHORT usagepage() override { return 1; }
+ virtual USHORT usage() override { return 2; }
- void add_rawinput_device(running_machine &machine, RAWINPUTDEVICELIST const &device) override
+ virtual void add_rawinput_device(RAWINPUTDEVICELIST const &device) override
{
-
// make sure this is a mouse
if (device.dwType != RIM_TYPEMOUSE)
return;
// allocate and link in a new device
- auto *devinfo = create_rawinput_device<rawinput_lightgun_device>(machine, device);
- if (devinfo == nullptr)
- return;
-
- // populate the axes
- for (int axisnum = 0; axisnum < 3; axisnum++)
- {
- devinfo->device()->add_item(
- default_axis_name[axisnum],
- static_cast<input_item_id>(ITEM_ID_XAXIS + axisnum),
- generic_axis_get_state<LONG>,
- &devinfo->lightgun.lX + axisnum);
- }
-
- // populate the buttons
- for (int butnum = 0; butnum < 5; butnum++)
- {
- devinfo->device()->add_item(
- default_button_name(butnum),
- static_cast<input_item_id>(ITEM_ID_BUTTON1 + butnum),
- generic_button_get_state<BYTE>,
- &devinfo->lightgun.rgbButtons[butnum]);
- }
+ create_rawinput_device<rawinput_lightgun_device>(DEVICE_CLASS_LIGHTGUN, device);
}
};
} // anonymous namespace
+} // namespace osd
+
#else // defined(OSD_WINDOWS)
#include "input_module.h"
+namespace osd {
+
+namespace {
+
MODULE_NOT_SUPPORTED(keyboard_input_rawinput, OSD_KEYBOARDINPUT_PROVIDER, "rawinput")
MODULE_NOT_SUPPORTED(mouse_input_rawinput, OSD_MOUSEINPUT_PROVIDER, "rawinput")
MODULE_NOT_SUPPORTED(lightgun_input_rawinput, OSD_LIGHTGUNINPUT_PROVIDER, "rawinput")
+} // anonymous namespace
+
+} // namespace osd
+
#endif // defined(OSD_WINDOWS)
-MODULE_DEFINITION(KEYBOARDINPUT_RAWINPUT, keyboard_input_rawinput)
-MODULE_DEFINITION(MOUSEINPUT_RAWINPUT, mouse_input_rawinput)
-MODULE_DEFINITION(LIGHTGUNINPUT_RAWINPUT, lightgun_input_rawinput)
+MODULE_DEFINITION(KEYBOARDINPUT_RAWINPUT, osd::keyboard_input_rawinput)
+MODULE_DEFINITION(MOUSEINPUT_RAWINPUT, osd::mouse_input_rawinput)
+MODULE_DEFINITION(LIGHTGUNINPUT_RAWINPUT, osd::lightgun_input_rawinput)
diff --git a/src/osd/modules/input/input_sdl.cpp b/src/osd/modules/input/input_sdl.cpp
index a3bbe494194..cc7cb2f1451 100644
--- a/src/osd/modules/input/input_sdl.cpp
+++ b/src/osd/modules/input/input_sdl.cpp
@@ -1,5 +1,5 @@
// license:BSD-3-Clause
-// copyright-holders:Olivier Galibert, R. Belmont, Brad Hughes
+// copyright-holders:Olivier Galibert, R. Belmont, Brad Hughes, Vas Crabb
//============================================================
//
// input_sdl.cpp - SDL 2.0 implementation of MAME input routines
@@ -12,34 +12,38 @@
//============================================================
#include "input_module.h"
+
#include "modules/osdmodule.h"
-#if defined(SDLMAME_SDL2)
+#if defined(OSD_SDL)
+
+#include "assignmenthelper.h"
+#include "input_common.h"
+
+#include "interface/inputseq.h"
+#include "modules/lib/osdobj_common.h"
+#include "sdl/osdsdl.h"
+
+// emu
+#include "inpttype.h"
-// standard sdl header
+// standard SDL header
#include <SDL2/SDL.h>
-#include <cctype>
-// ReSharper disable once CppUnusedIncludeDirective
+
#include <algorithm>
+#include <cctype>
+#include <chrono>
#include <cstddef>
+#include <cstring>
+#include <initializer_list>
#include <iterator>
+#include <list>
#include <memory>
-#include <mutex>
#include <optional>
-#include <queue>
-
-// MAME headers
-#include "emu.h"
-#include "uiinput.h"
-#include "strconv.h"
-#include "unicode.h"
-
-// MAMEOS headers
-#include "input_common.h"
-#include "../lib/osdobj_common.h"
-#include "input_sdlcommon.h"
-#include "../../sdl/osdsdl.h"
-#include "../../sdl/window.h"
+#include <string>
+#include <string_view>
+#include <tuple>
+#include <utility>
// winnt.h defines this
#ifdef DELETE
@@ -47,11 +51,217 @@
#endif
+namespace osd {
+
namespace {
-// FIXME: sdl does not properly report the window for certain OS.
-#define GET_FOCUS_WINDOW(ev) focus_window()
-//#define GET_FOCUS_WINDOW(ev) window_from_id((ev)->windowID)
+char const *const CONTROLLER_AXIS_XBOX[]{
+ "LSX",
+ "LSY",
+ "RSX",
+ "RSY",
+ "LT",
+ "RT" };
+
+char const *const CONTROLLER_AXIS_PS[]{
+ "LSX",
+ "LSY",
+ "RSX",
+ "RSY",
+ "L2",
+ "R2" };
+
+char const *const CONTROLLER_AXIS_SWITCH[]{
+ "LSX",
+ "LSY",
+ "RSX",
+ "RSY",
+ "ZL",
+ "ZR" };
+
+char const *const CONTROLLER_BUTTON_XBOX360[]{
+ "A",
+ "B",
+ "X",
+ "Y",
+ "Back",
+ "Guide",
+ "Start",
+ "LSB",
+ "RSB",
+ "LB",
+ "RB",
+ "D-pad Up",
+ "D-pad Down",
+ "D-pad Left",
+ "D-pad Right",
+ "Share",
+ "P1",
+ "P2",
+ "P3",
+ "P4",
+ "Touchpad" };
+
+char const *const CONTROLLER_BUTTON_XBOXONE[]{
+ "A",
+ "B",
+ "X",
+ "Y",
+ "View",
+ "Logo",
+ "Menu",
+ "LSB",
+ "RSB",
+ "LB",
+ "RB",
+ "D-pad Up",
+ "D-pad Down",
+ "D-pad Left",
+ "D-pad Right",
+ "Share",
+ "P1",
+ "P2",
+ "P3",
+ "P4",
+ "Touchpad" };
+
+char const *const CONTROLLER_BUTTON_PS3[]{
+ "Cross",
+ "Circle",
+ "Square",
+ "Triangle",
+ "Select",
+ "PS",
+ "Start",
+ "L3",
+ "R3",
+ "L1",
+ "R1",
+ "D-pad Up",
+ "D-pad Down",
+ "D-pad Left",
+ "D-pad Right",
+ "Mute",
+ "P1",
+ "P2",
+ "P3",
+ "P4",
+ "Touchpad" };
+
+char const *const CONTROLLER_BUTTON_PS4[]{
+ "Cross",
+ "Circle",
+ "Square",
+ "Triangle",
+ "Share",
+ "PS",
+ "Options",
+ "L3",
+ "R3",
+ "L1",
+ "R1",
+ "D-pad Up",
+ "D-pad Down",
+ "D-pad Left",
+ "D-pad Right",
+ "Mute",
+ "P1",
+ "P2",
+ "P3",
+ "P4",
+ "Touchpad" };
+
+char const *const CONTROLLER_BUTTON_PS5[]{
+ "Cross",
+ "Circle",
+ "Square",
+ "Triangle",
+ "Create",
+ "PS",
+ "Options",
+ "L3",
+ "R3",
+ "L1",
+ "R1",
+ "D-pad Up",
+ "D-pad Down",
+ "D-pad Left",
+ "D-pad Right",
+ "Mute",
+ "P1",
+ "P2",
+ "P3",
+ "P4",
+ "Touchpad" };
+
+char const *const CONTROLLER_BUTTON_SWITCH[]{
+ "A",
+ "B",
+ "X",
+ "Y",
+ "-",
+ "Home",
+ "+",
+ "LSB",
+ "RSB",
+ "L",
+ "R",
+ "D-pad Up",
+ "D-pad Down",
+ "D-pad Left",
+ "D-pad Right",
+ "Capture",
+ "RSR",
+ "LSL",
+ "RSL",
+ "LSR",
+ "Touchpad" };
+
+[[maybe_unused]] char const *const CONTROLLER_BUTTON_STADIA[]{
+ "A",
+ "B",
+ "X",
+ "Y",
+ "Options",
+ "Logo",
+ "Menu",
+ "L3",
+ "R3",
+ "L1",
+ "R1",
+ "D-pad Up",
+ "D-pad Down",
+ "D-pad Left",
+ "D-pad Right",
+ "Capture",
+ "P1",
+ "P2",
+ "P3",
+ "P4",
+ "Touchpad" };
+
+[[maybe_unused]] char const *const CONTROLLER_BUTTON_SHIELD[]{
+ "A",
+ "B",
+ "X",
+ "Y",
+ "Back",
+ "Logo",
+ "Start",
+ "LSB",
+ "RSB",
+ "LB",
+ "RB",
+ "D-pad Up",
+ "D-pad Down",
+ "D-pad Left",
+ "D-pad Right",
+ "Share",
+ "P1",
+ "P2",
+ "P3",
+ "P4",
+ "Touchpad" };
struct key_lookup_table
{
@@ -60,12 +270,8 @@ struct key_lookup_table
};
#define KE(x) { SDL_SCANCODE_ ## x, "SDL_SCANCODE_" #x },
-#define KE8(A, B, C, D, E, F, G, H) KE(A) KE(B) KE(C) KE(D) KE(E) KE(F) KE(G) KE(H)
-#define KE7(A, B, C, D, E, F, G) KE(A) KE(B) KE(C) KE(D) KE(E) KE(F) KE(G)
-#define KE5(A, B, C, D, E) KE(A) KE(B) KE(C) KE(D) KE(E)
-#define KE3(A, B, C) KE(A) KE(B) KE(C)
-key_lookup_table sdl_lookup_table[] =
+key_lookup_table const sdl_lookup_table[] =
{
KE(UNKNOWN)
@@ -324,48 +530,29 @@ key_lookup_table sdl_lookup_table[] =
KE(APP1)
KE(APP2)
-
-
-{
- -1, ""
-}
};
+
//============================================================
// lookup_sdl_code
//============================================================
-int lookup_sdl_code(const char *scode)
+int lookup_sdl_code(std::string_view scode)
{
- int i = 0;
-
- while (sdl_lookup_table[i].code >= 0)
- {
- if (!strcmp(scode, sdl_lookup_table[i].name))
- return sdl_lookup_table[i].code;
- i++;
- }
- return -1;
+ auto const found = std::find_if(
+ std::begin(sdl_lookup_table),
+ std::end(sdl_lookup_table),
+ [&scode] (auto const &key) { return scode == key.name; });
+ return (std::end(sdl_lookup_table) != found) ? found->code : -1;
}
+
//============================================================
// sdl_device
//============================================================
-class sdl_device : public event_based_device<SDL_Event>
-{
-public:
- sdl_device(running_machine &machine, std::string &&name, std::string &&id, input_device_class devclass, input_module &module) :
- event_based_device(machine, std::move(name), std::move(id), devclass, module)
- {
- }
+using sdl_device = event_based_device<SDL_Event>;
-protected:
- std::shared_ptr<sdl_window_info> focus_window()
- {
- return sdl_event_manager::instance().focus_window();
- }
-};
//============================================================
// sdl_keyboard_device
@@ -374,506 +561,1454 @@ protected:
class sdl_keyboard_device : public sdl_device
{
public:
- // state information for a keyboard
- struct keyboard_state
+ sdl_keyboard_device(
+ std::string &&name,
+ std::string &&id,
+ input_module &module,
+ keyboard_trans_table const &trans_table) :
+ sdl_device(std::move(name), std::move(id), module),
+ m_trans_table(trans_table),
+ m_keyboard({{0}}),
+ m_capslock_pressed(std::chrono::steady_clock::time_point::min())
{
- int32_t state[0x3ff]; // must be int32_t!
- int8_t oldkey[MAX_KEYS];
- int8_t currkey[MAX_KEYS];
- };
-
- keyboard_state keyboard;
-
- sdl_keyboard_device(running_machine &machine, std::string &&name, std::string &&id, input_module &module) :
- sdl_device(machine, std::move(name), std::move(id), DEVICE_CLASS_KEYBOARD, module),
- keyboard({{0}})
- {
- #ifdef __APPLE__
- m_capslock_hack = false;
- machine.add_notifier(MACHINE_NOTIFY_FRAME, machine_notify_delegate(&sdl_keyboard_device::frame_callback, this));
- #endif
}
- #ifdef __APPLE__
- unsigned m_capslock_hack;
- void frame_callback()
+ virtual void poll(bool relative_reset) override
{
- if (m_capslock_hack)
- if (--m_capslock_hack == 0)
- keyboard.state[SDL_SCANCODE_CAPSLOCK] = 0x00;
+ sdl_device::poll(relative_reset);
+
+#ifdef __APPLE__
+ if (m_keyboard.state[SDL_SCANCODE_CAPSLOCK] && (std::chrono::steady_clock::now() > (m_capslock_pressed + std::chrono::milliseconds(30))))
+ m_keyboard.state[SDL_SCANCODE_CAPSLOCK] = 0x00;
+#endif
}
- #endif
- void process_event(SDL_Event &sdlevent) override
+ virtual void process_event(SDL_Event const &event) override
{
- switch (sdlevent.type)
+ switch (event.type)
{
case SDL_KEYDOWN:
+ if (event.key.keysym.scancode == SDL_SCANCODE_CAPSLOCK)
+ m_capslock_pressed = std::chrono::steady_clock::now();
- #ifdef __APPLE__
- if (sdlevent.key.keysym.scancode == SDL_SCANCODE_CAPSLOCK)
- m_capslock_hack = 2;
- #endif
-
- keyboard.state[sdlevent.key.keysym.scancode] = 0x80;
- if (sdlevent.key.keysym.sym < 0x20)
- machine().ui_input().push_char_event(osd_common_t::s_window_list.front()->target(), sdlevent.key.keysym.sym);
- else if (keyboard.state[SDL_SCANCODE_LCTRL] == 0x80 || keyboard.state[SDL_SCANCODE_RCTRL] == 0x80)
- {
- // SDL filters out control characters for text input, so they are decoded here
- if (sdlevent.key.keysym.sym >= 0x40 && sdlevent.key.keysym.sym < 0x7f)
- machine().ui_input().push_char_event(osd_common_t::s_window_list.front()->target(), sdlevent.key.keysym.sym & 0x1f);
- else if (keyboard.state[SDL_SCANCODE_LSHIFT] == 0x80 || keyboard.state[SDL_SCANCODE_RSHIFT] == 0x80)
- {
- if (sdlevent.key.keysym.sym == SDLK_6) // Ctrl-^ (RS)
- machine().ui_input().push_char_event(osd_common_t::s_window_list.front()->target(), 0x1e);
- else if (sdlevent.key.keysym.sym == SDLK_MINUS) // Ctrl-_ (US)
- machine().ui_input().push_char_event(osd_common_t::s_window_list.front()->target(), 0x1f);
- }
- }
+ m_keyboard.state[event.key.keysym.scancode] = 0x80;
break;
case SDL_KEYUP:
- #ifdef __APPLE__
- if (sdlevent.key.keysym.scancode == SDL_SCANCODE_CAPSLOCK)
+#ifdef __APPLE__
+ if (event.key.keysym.scancode == SDL_SCANCODE_CAPSLOCK)
break;
- #endif
-
- keyboard.state[sdlevent.key.keysym.scancode] = 0x00;
- break;
+#endif
- case SDL_TEXTINPUT:
- if (*sdlevent.text.text)
- {
- auto window = GET_FOCUS_WINDOW(&event.text);
- //printf("Focus window is %p - wl %p\n", window, osd_common_t::s_window_list);
- if (window != nullptr)
- {
- auto ptr = sdlevent.text.text;
- auto len = std::strlen(sdlevent.text.text);
- while (len)
- {
- char32_t ch;
- auto chlen = uchar_from_utf8(&ch, ptr, len);
- if (0 > chlen)
- {
- ch = 0x0fffd;
- chlen = 1;
- }
- ptr += chlen;
- len -= chlen;
- machine().ui_input().push_char_event(window->target(), ch);
- }
- }
- }
+ m_keyboard.state[event.key.keysym.scancode] = 0x00;
break;
}
}
- void reset() override
+ virtual void reset() override
{
- memset(&keyboard.state, 0, sizeof(keyboard.state));
- #ifdef __APPLE__
- m_capslock_hack = 0;
- #endif
+ memset(&m_keyboard.state, 0, sizeof(m_keyboard.state));
+ m_capslock_pressed = std::chrono::steady_clock::time_point::min();
}
+
+ virtual void configure(input_device &device) override
+ {
+ // populate it
+ for (int keynum = 0; m_trans_table[keynum].mame_key != ITEM_ID_INVALID; keynum++)
+ {
+ input_item_id itemid = m_trans_table[keynum].mame_key;
+ device.add_item(
+ m_trans_table[keynum].ui_name,
+ std::string_view(),
+ itemid,
+ generic_button_get_state<s32>,
+ &m_keyboard.state[m_trans_table[keynum].sdl_scancode]);
+ }
+ }
+
+private:
+ // state information for a keyboard
+ struct keyboard_state
+ {
+ s32 state[0x3ff]; // must be s32!
+ s8 oldkey[MAX_KEYS];
+ s8 currkey[MAX_KEYS];
+ };
+
+ keyboard_trans_table const &m_trans_table;
+ keyboard_state m_keyboard;
+ std::chrono::steady_clock::time_point m_capslock_pressed;
};
+
//============================================================
// sdl_mouse_device
//============================================================
class sdl_mouse_device : public sdl_device
{
-private:
- const std::chrono::milliseconds double_click_speed = std::chrono::milliseconds(250);
- std::chrono::system_clock::time_point last_click;
- int last_x;
- int last_y;
-
public:
- // state information for a mouse
- struct mouse_state
+ sdl_mouse_device(std::string &&name, std::string &&id, input_module &module) :
+ sdl_device(std::move(name), std::move(id), module),
+ m_mouse({0}),
+ m_x(0),
+ m_y(0),
+ m_v(0),
+ m_h(0)
{
- int32_t lX, lY;
- int32_t buttons[MAX_BUTTONS];
- };
-
- mouse_state mouse;
+ }
- sdl_mouse_device(running_machine &machine, std::string &&name, std::string &&id, input_module &module) :
- sdl_device(machine, std::move(name), std::move(id), DEVICE_CLASS_MOUSE, module),
- last_x(0),
- last_y(0),
- mouse({0})
+ virtual void poll(bool relative_reset) override
{
+ sdl_device::poll(relative_reset);
+ if (relative_reset)
+ {
+ m_mouse.lX = std::exchange(m_x, 0);
+ m_mouse.lY = std::exchange(m_y, 0);
+ m_mouse.lV = std::exchange(m_v, 0);
+ m_mouse.lH = std::exchange(m_h, 0);
+ }
}
- void reset() override
+ virtual void reset() override
{
- memset(&mouse, 0, sizeof(mouse));
+ memset(&m_mouse, 0, sizeof(m_mouse));
+ m_x = m_y = m_v = m_h = 0;
}
- void poll() override
+ virtual void configure(input_device &device) override
{
- mouse.lX = 0;
- mouse.lY = 0;
- sdl_device::poll();
+ // add the axes
+ device.add_item(
+ "X",
+ std::string_view(),
+ ITEM_ID_XAXIS,
+ generic_axis_get_state<s32>,
+ &m_mouse.lX);
+ device.add_item(
+ "Y",
+ std::string_view(),
+ ITEM_ID_YAXIS,
+ generic_axis_get_state<s32>,
+ &m_mouse.lY);
+ device.add_item(
+ "Scroll V",
+ std::string_view(),
+ ITEM_ID_ZAXIS,
+ generic_axis_get_state<s32>,
+ &m_mouse.lV);
+ device.add_item(
+ "Scroll H",
+ std::string_view(),
+ ITEM_ID_RZAXIS,
+ generic_axis_get_state<s32>,
+ &m_mouse.lH);
+
+ // add the buttons
+ for (int button = 0; button < 4; button++)
+ {
+ input_item_id itemid = (input_item_id)(ITEM_ID_BUTTON1 + button);
+ int const offset = button ^ (((1 == button) || (2 == button)) ? 3 : 0);
+ device.add_item(
+ default_button_name(button),
+ std::string_view(),
+ itemid,
+ generic_button_get_state<s32>,
+ &m_mouse.buttons[offset]);
+ }
}
- virtual void process_event(SDL_Event &sdlevent) override
+ virtual void process_event(SDL_Event const &event) override
{
- switch (sdlevent.type)
+ switch (event.type)
{
case SDL_MOUSEMOTION:
- mouse.lX += sdlevent.motion.xrel * osd::INPUT_RELATIVE_PER_PIXEL;
- mouse.lY += sdlevent.motion.yrel * osd::INPUT_RELATIVE_PER_PIXEL;
+ m_x += event.motion.xrel * input_device::RELATIVE_PER_PIXEL;
+ m_y += event.motion.yrel * input_device::RELATIVE_PER_PIXEL;
+ break;
- {
- int cx = -1, cy = -1;
- auto window = GET_FOCUS_WINDOW(&sdlevent.motion);
+ case SDL_MOUSEBUTTONDOWN:
+ m_mouse.buttons[event.button.button - 1] = 0x80;
+ break;
- if (window != nullptr && window->xy_to_render_target(sdlevent.motion.x, sdlevent.motion.y, &cx, &cy))
- machine().ui_input().push_mouse_move_event(window->target(), cx, cy);
- }
+ case SDL_MOUSEBUTTONUP:
+ m_mouse.buttons[event.button.button - 1] = 0;
break;
- case SDL_MOUSEBUTTONDOWN:
- mouse.buttons[sdlevent.button.button - 1] = 0x80;
- //printf("But down %d %d %d %d %s\n", event.button.which, event.button.button, event.button.x, event.button.y, devinfo->name.c_str());
- if (sdlevent.button.button == 1)
- {
- int cx, cy;
- auto click = std::chrono::system_clock::now();
- auto window = GET_FOCUS_WINDOW(&sdlevent.button);
- if (window != nullptr && window->xy_to_render_target(sdlevent.button.x, sdlevent.button.y, &cx, &cy))
- {
- machine().ui_input().push_mouse_down_event(window->target(), cx, cy);
+ case SDL_MOUSEWHEEL:
+#if SDL_VERSION_ATLEAST(2, 0, 18)
+ m_v += event.wheel.preciseY * input_device::RELATIVE_PER_PIXEL;
+ m_h += event.wheel.preciseX * input_device::RELATIVE_PER_PIXEL;
+#else
+ m_v += event.wheel.y * input_device::RELATIVE_PER_PIXEL;
+ m_h += event.wheel.x * input_device::RELATIVE_PER_PIXEL;
+#endif
+ break;
+ }
+ }
- // avoid overflow with std::chrono::time_point::min() by adding rather than subtracting
- if (click < last_click + double_click_speed
- && (cx >= last_x - 4 && cx <= last_x + 4)
- && (cy >= last_y - 4 && cy <= last_y + 4))
- {
- last_click = std::chrono::time_point<std::chrono::system_clock>::min();
- machine().ui_input().push_mouse_double_click_event(window->target(), cx, cy);
- }
- else
- {
- last_click = click;
- last_x = cx;
- last_y = cy;
- }
- }
- }
+private:
+ // state information for a mouse
+ struct mouse_state
+ {
+ s32 lX, lY, lV, lH;
+ s32 buttons[MAX_BUTTONS];
+ };
- else if (sdlevent.button.button == 3)
- {
- int cx, cy;
- auto window = GET_FOCUS_WINDOW(&sdlevent.button);
+ mouse_state m_mouse;
+ s32 m_x, m_y, m_v, m_h;
+};
- if (window != nullptr && window->xy_to_render_target(sdlevent.button.x, sdlevent.button.y, &cx, &cy))
- {
- machine().ui_input().push_mouse_rdown_event(window->target(), cx, cy);
- }
- }
- break;
- case SDL_MOUSEBUTTONUP:
- mouse.buttons[sdlevent.button.button - 1] = 0;
- //printf("But up %d %d %d %d\n", event.button.which, event.button.button, event.button.x, event.button.y);
+//============================================================
+// sdl_joystick_device_base
+//============================================================
- if (sdlevent.button.button == 1)
- {
- int cx, cy;
- auto window = GET_FOCUS_WINDOW(&sdlevent.button);
+class sdl_joystick_device_base : public sdl_device, protected joystick_assignment_helper
+{
+public:
+ std::optional<std::string> const &serial() const { return m_serial; }
+ SDL_JoystickID instance() const { return m_instance; }
- if (window != nullptr && window->xy_to_render_target(sdlevent.button.x, sdlevent.button.y, &cx, &cy))
- {
- machine().ui_input().push_mouse_up_event(window->target(), cx, cy);
- }
- }
- else if (sdlevent.button.button == 3)
- {
- int cx, cy;
- auto window = GET_FOCUS_WINDOW(&sdlevent.button);
+ bool is_instance(SDL_JoystickID instance) const { return m_instance == instance; }
- if (window != nullptr && window->xy_to_render_target(sdlevent.button.x, sdlevent.button.y, &cx, &cy))
- {
- machine().ui_input().push_mouse_rup_event(window->target(), cx, cy);
- }
- }
- break;
+ bool reconnect_match(std::string_view g, char const *s) const
+ {
+ return
+ (0 > m_instance) &&
+ (id() == g) &&
+ ((s && serial() && (*serial() == s)) || (!s && !serial()));
+ }
- case SDL_MOUSEWHEEL:
- auto window = GET_FOCUS_WINDOW(&sdlevent.wheel);
- if (window != nullptr)
- machine().ui_input().push_mouse_wheel_event(window->target(), 0, 0, sdlevent.wheel.y, 3);
- break;
- }
+protected:
+ sdl_joystick_device_base(
+ std::string &&name,
+ std::string &&id,
+ input_module &module,
+ char const *serial) :
+ sdl_device(std::move(name), std::move(id), module),
+ m_instance(-1)
+ {
+ if (serial)
+ m_serial = serial;
}
+
+ void set_instance(SDL_JoystickID instance)
+ {
+ assert(0 > m_instance);
+ assert(0 <= instance);
+
+ m_instance = instance;
+ }
+
+ void clear_instance()
+ {
+ m_instance = -1;
+ }
+
+private:
+ std::optional<std::string> m_serial;
+ SDL_JoystickID m_instance;
};
+
//============================================================
// sdl_joystick_device
//============================================================
-class sdl_joystick_device : public sdl_device
+class sdl_joystick_device : public sdl_joystick_device_base
{
public:
- // state information for a joystick
- struct sdl_joystick_state
+ sdl_joystick_device(
+ std::string &&name,
+ std::string &&id,
+ input_module &module,
+ SDL_Joystick *joy,
+ char const *serial) :
+ sdl_joystick_device_base(
+ std::move(name),
+ std::move(id),
+ module,
+ serial),
+ m_joystick({{0}}),
+ m_joydevice(joy),
+ m_hapdevice(SDL_HapticOpenFromJoystick(joy))
{
- int32_t axes[MAX_AXES];
- int32_t buttons[MAX_BUTTONS];
- int32_t hatsU[MAX_HATS], hatsD[MAX_HATS], hatsL[MAX_HATS], hatsR[MAX_HATS];
- int32_t balls[MAX_AXES];
- };
+ set_instance(SDL_JoystickInstanceID(joy));
+ }
- struct sdl_api_state
+ virtual void configure(input_device &device) override
{
- SDL_Joystick *device = nullptr;
- SDL_Haptic *hapdevice = nullptr;
- SDL_JoystickID joystick_id;
- std::optional<std::string> serial;
- };
+ input_device::assignment_vector assignments;
+ char tempname[32];
- sdl_joystick_state joystick;
- sdl_api_state sdl_state;
+ int const axiscount = SDL_JoystickNumAxes(m_joydevice);
+ int const buttoncount = SDL_JoystickNumButtons(m_joydevice);
+ int const hatcount = SDL_JoystickNumHats(m_joydevice);
+ int const ballcount = SDL_JoystickNumBalls(m_joydevice);
- sdl_joystick_device(running_machine &machine, std::string &&name, std::string &&id, input_module &module) :
- sdl_device(machine, std::move(name), std::move(id), DEVICE_CLASS_JOYSTICK, module),
- joystick({{0}})
- {
+ // loop over all axes
+ input_item_id axisactual[MAX_AXES];
+ for (int axis = 0; (axis < MAX_AXES) && (axis < axiscount); axis++)
+ {
+ input_item_id itemid;
+
+ if (axis < INPUT_MAX_AXIS)
+ itemid = input_item_id(ITEM_ID_XAXIS + axis);
+ else if (axis < (INPUT_MAX_AXIS + INPUT_MAX_ADD_ABSOLUTE))
+ itemid = input_item_id(ITEM_ID_ADD_ABSOLUTE1 + axis - INPUT_MAX_AXIS);
+ else
+ itemid = ITEM_ID_OTHER_AXIS_ABSOLUTE;
+
+ snprintf(tempname, sizeof(tempname), "A%d", axis + 1);
+ axisactual[axis] = device.add_item(
+ tempname,
+ std::string_view(),
+ itemid,
+ generic_axis_get_state<s32>,
+ &m_joystick.axes[axis]);
+ }
+
+ // loop over all buttons
+ for (int button = 0; (button < MAX_BUTTONS) && (button < buttoncount); button++)
+ {
+ input_item_id itemid;
+
+ m_joystick.buttons[button] = 0;
+
+ if (button < INPUT_MAX_BUTTONS)
+ itemid = input_item_id(ITEM_ID_BUTTON1 + button);
+ else if (button < INPUT_MAX_BUTTONS + INPUT_MAX_ADD_SWITCH)
+ itemid = input_item_id(ITEM_ID_ADD_SWITCH1 + button - INPUT_MAX_BUTTONS);
+ else
+ itemid = ITEM_ID_OTHER_SWITCH;
+
+ input_item_id const actual = device.add_item(
+ default_button_name(button),
+ std::string_view(),
+ itemid,
+ generic_button_get_state<s32>,
+ &m_joystick.buttons[button]);
+
+ // there are sixteen action button types
+ if (button < 16)
+ {
+ input_seq const seq(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, actual));
+ assignments.emplace_back(ioport_type(IPT_BUTTON1 + button), SEQ_TYPE_STANDARD, seq);
+
+ // assign the first few buttons to UI actions and pedals
+ switch (button)
+ {
+ case 0:
+ assignments.emplace_back(IPT_PEDAL, SEQ_TYPE_INCREMENT, seq);
+ assignments.emplace_back(IPT_UI_SELECT, SEQ_TYPE_STANDARD, seq);
+ break;
+ case 1:
+ assignments.emplace_back(IPT_PEDAL2, SEQ_TYPE_INCREMENT, seq);
+ assignments.emplace_back((3 > buttoncount) ? IPT_UI_CLEAR : IPT_UI_BACK, SEQ_TYPE_STANDARD, seq);
+ break;
+ case 2:
+ assignments.emplace_back(IPT_PEDAL3, SEQ_TYPE_INCREMENT, seq);
+ assignments.emplace_back(IPT_UI_CLEAR, SEQ_TYPE_STANDARD, seq);
+ break;
+ case 3:
+ assignments.emplace_back(IPT_UI_HELP, SEQ_TYPE_STANDARD, seq);
+ break;
+ }
+ }
+ }
+
+ // loop over all hats
+ input_item_id hatactual[MAX_HATS][4];
+ for (int hat = 0; (hat < MAX_HATS) && (hat < hatcount); hat++)
+ {
+ input_item_id itemid;
+
+ snprintf(tempname, sizeof(tempname), "Hat %d Up", hat + 1);
+ itemid = input_item_id((hat < INPUT_MAX_HATS) ? ITEM_ID_HAT1UP + (4 * hat) : ITEM_ID_OTHER_SWITCH);
+ hatactual[hat][0] = device.add_item(
+ tempname,
+ std::string_view(),
+ itemid,
+ generic_button_get_state<s32>,
+ &m_joystick.hatsU[hat]);
+
+ snprintf(tempname, sizeof(tempname), "Hat %d Down", hat + 1);
+ itemid = input_item_id((hat < INPUT_MAX_HATS) ? ITEM_ID_HAT1DOWN + (4 * hat) : ITEM_ID_OTHER_SWITCH);
+ hatactual[hat][1] = device.add_item(
+ tempname,
+ std::string_view(),
+ itemid,
+ generic_button_get_state<s32>,
+ &m_joystick.hatsD[hat]);
+
+ snprintf(tempname, sizeof(tempname), "Hat %d Left", hat + 1);
+ itemid = input_item_id((hat < INPUT_MAX_HATS) ? ITEM_ID_HAT1LEFT + (4 * hat) : ITEM_ID_OTHER_SWITCH);
+ hatactual[hat][2] = device.add_item(
+ tempname,
+ std::string_view(),
+ itemid,
+ generic_button_get_state<s32>,
+ &m_joystick.hatsL[hat]);
+
+ snprintf(tempname, sizeof(tempname), "Hat %d Right", hat + 1);
+ itemid = input_item_id((hat < INPUT_MAX_HATS) ? ITEM_ID_HAT1RIGHT + (4 * hat) : ITEM_ID_OTHER_SWITCH);
+ hatactual[hat][3] = device.add_item(
+ tempname,
+ std::string_view(),
+ itemid,
+ generic_button_get_state<s32>,
+ &m_joystick.hatsR[hat]);
+ }
+
+ // loop over all (track)balls
+ for (int ball = 0; (ball < (MAX_AXES / 2)) && (ball < ballcount); ball++)
+ {
+ int itemid;
+
+ if (ball * 2 < INPUT_MAX_ADD_RELATIVE)
+ itemid = ITEM_ID_ADD_RELATIVE1 + ball * 2;
+ else
+ itemid = ITEM_ID_OTHER_AXIS_RELATIVE;
+
+ snprintf(tempname, sizeof(tempname), "R%d X", ball + 1);
+ input_item_id const xactual = device.add_item(
+ tempname,
+ std::string_view(),
+ input_item_id(itemid),
+ generic_axis_get_state<s32>,
+ &m_joystick.balls[ball * 2]);
+
+ snprintf(tempname, sizeof(tempname), "R%d Y", ball + 1);
+ input_item_id const yactual = device.add_item(
+ tempname,
+ std::string_view(),
+ input_item_id(itemid + 1),
+ generic_axis_get_state<s32>,
+ &m_joystick.balls[ball * 2 + 1]);
+
+ if (0 == ball)
+ {
+ // assign the first trackball to dial, trackball, mouse and lightgun inputs
+ input_seq const xseq(make_code(ITEM_CLASS_RELATIVE, ITEM_MODIFIER_NONE, xactual));
+ input_seq const yseq(make_code(ITEM_CLASS_RELATIVE, ITEM_MODIFIER_NONE, yactual));
+ assignments.emplace_back(IPT_DIAL, SEQ_TYPE_STANDARD, xseq);
+ assignments.emplace_back(IPT_DIAL_V, SEQ_TYPE_STANDARD, yseq);
+ assignments.emplace_back(IPT_TRACKBALL_X, SEQ_TYPE_STANDARD, xseq);
+ assignments.emplace_back(IPT_TRACKBALL_Y, SEQ_TYPE_STANDARD, yseq);
+ assignments.emplace_back(IPT_LIGHTGUN_X, SEQ_TYPE_STANDARD, xseq);
+ assignments.emplace_back(IPT_LIGHTGUN_Y, SEQ_TYPE_STANDARD, yseq);
+ assignments.emplace_back(IPT_MOUSE_X, SEQ_TYPE_STANDARD, xseq);
+ assignments.emplace_back(IPT_MOUSE_Y, SEQ_TYPE_STANDARD, yseq);
+ if (2 > axiscount)
+ {
+ // use it for joystick inputs if axes are limited
+ assignments.emplace_back(IPT_AD_STICK_X, SEQ_TYPE_STANDARD, xseq);
+ assignments.emplace_back(IPT_AD_STICK_Y, SEQ_TYPE_STANDARD, yseq);
+ }
+ else
+ {
+ // use for non-centring throttle control
+ assignments.emplace_back(IPT_AD_STICK_Z, SEQ_TYPE_STANDARD, yseq);
+ }
+ }
+ else if ((1 == ball) && (2 > axiscount))
+ {
+ // provide a non-centring throttle control
+ input_seq const yseq(make_code(ITEM_CLASS_RELATIVE, ITEM_MODIFIER_NONE, yactual));
+ assignments.emplace_back(IPT_AD_STICK_Z, SEQ_TYPE_STANDARD, yseq);
+ }
+ }
+
+ // set up default assignments for axes and hats
+ add_directional_assignments(
+ assignments,
+ (1 <= axiscount) ? axisactual[0] : ITEM_ID_INVALID, // assume first axis is X
+ (2 <= axiscount) ? axisactual[1] : ITEM_ID_INVALID, // assume second axis is Y
+ (1 <= hatcount) ? hatactual[0][2] : ITEM_ID_INVALID,
+ (1 <= hatcount) ? hatactual[0][3] : ITEM_ID_INVALID,
+ (1 <= hatcount) ? hatactual[0][0] : ITEM_ID_INVALID,
+ (1 <= hatcount) ? hatactual[0][1] : ITEM_ID_INVALID);
+ if (2 <= axiscount)
+ {
+ // put pedals on the last of the second, third or fourth axis
+ input_item_id const pedalitem = axisactual[(std::min)(axiscount, 4) - 1];
+ assignments.emplace_back(
+ IPT_PEDAL,
+ SEQ_TYPE_STANDARD,
+ input_seq(make_code(ITEM_CLASS_ABSOLUTE, ITEM_MODIFIER_NEG, pedalitem)));
+ assignments.emplace_back(
+ IPT_PEDAL2,
+ SEQ_TYPE_STANDARD,
+ input_seq(make_code(ITEM_CLASS_ABSOLUTE, ITEM_MODIFIER_POS, pedalitem)));
+ }
+ if (3 <= axiscount)
+ {
+ // assign X/Y to one of the twin sticks
+ assignments.emplace_back(
+ (4 <= axiscount) ? IPT_JOYSTICKLEFT_LEFT : IPT_JOYSTICKRIGHT_LEFT,
+ SEQ_TYPE_STANDARD,
+ input_seq(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_LEFT, axisactual[0])));
+ assignments.emplace_back(
+ (4 <= axiscount) ? IPT_JOYSTICKLEFT_RIGHT : IPT_JOYSTICKRIGHT_RIGHT,
+ SEQ_TYPE_STANDARD,
+ input_seq(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_RIGHT, axisactual[0])));
+ assignments.emplace_back(
+ (4 <= axiscount) ? IPT_JOYSTICKLEFT_UP : IPT_JOYSTICKRIGHT_UP,
+ SEQ_TYPE_STANDARD,
+ input_seq(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_UP, axisactual[1])));
+ assignments.emplace_back(
+ (4 <= axiscount) ? IPT_JOYSTICKLEFT_DOWN : IPT_JOYSTICKRIGHT_DOWN,
+ SEQ_TYPE_STANDARD,
+ input_seq(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_DOWN, axisactual[1])));
+
+ // use third or fourth axis for Z
+ input_seq const seq(make_code(ITEM_CLASS_ABSOLUTE, ITEM_MODIFIER_NONE, axisactual[(std::min)(axiscount, 4) - 1]));
+ assignments.emplace_back(IPT_AD_STICK_Z, SEQ_TYPE_STANDARD, seq);
+
+ // use this for focus next/previous to make system selection menu practical to navigate
+ input_seq const upseq(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NEG, axisactual[2]));
+ input_seq const downseq(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_POS, axisactual[2]));
+ assignments.emplace_back(IPT_UI_FOCUS_PREV, SEQ_TYPE_STANDARD, upseq);
+ assignments.emplace_back(IPT_UI_FOCUS_NEXT, SEQ_TYPE_STANDARD, downseq);
+ if (4 <= axiscount)
+ {
+ // use for zoom as well if there's another axis to use for previous/next group
+ assignments.emplace_back(IPT_UI_ZOOM_IN, SEQ_TYPE_STANDARD, downseq);
+ assignments.emplace_back(IPT_UI_ZOOM_OUT, SEQ_TYPE_STANDARD, upseq);
+ }
+
+ // use this for twin sticks, too
+ assignments.emplace_back((4 <= axiscount) ? IPT_JOYSTICKRIGHT_LEFT : IPT_JOYSTICKLEFT_UP, SEQ_TYPE_STANDARD, upseq);
+ assignments.emplace_back((4 <= axiscount) ? IPT_JOYSTICKRIGHT_RIGHT : IPT_JOYSTICKLEFT_DOWN, SEQ_TYPE_STANDARD, downseq);
+
+ // put previous/next group on the last of the third or fourth axis
+ input_item_id const groupitem = axisactual[(std::min)(axiscount, 4) - 1];
+ assignments.emplace_back(
+ IPT_UI_PREV_GROUP,
+ SEQ_TYPE_STANDARD,
+ input_seq(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NEG, groupitem)));
+ assignments.emplace_back(
+ IPT_UI_NEXT_GROUP,
+ SEQ_TYPE_STANDARD,
+ input_seq(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_POS, groupitem)));
+ }
+ if (4 <= axiscount)
+ {
+ // use this for twin sticks
+ input_seq const upseq(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NEG, axisactual[3]));
+ input_seq const downseq(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_POS, axisactual[3]));
+ assignments.emplace_back(IPT_JOYSTICKRIGHT_UP, SEQ_TYPE_STANDARD, upseq);
+ assignments.emplace_back(IPT_JOYSTICKRIGHT_DOWN, SEQ_TYPE_STANDARD, downseq);
+ }
+
+ // set default assignments
+ device.set_default_assignments(std::move(assignments));
}
~sdl_joystick_device()
{
- if (sdl_state.device)
+ if (m_joydevice)
{
- if (sdl_state.hapdevice)
+ if (m_hapdevice)
{
- SDL_HapticClose(sdl_state.hapdevice);
- sdl_state.hapdevice = nullptr;
+ SDL_HapticClose(m_hapdevice);
+ m_hapdevice = nullptr;
}
- SDL_JoystickClose(sdl_state.device);
- sdl_state.device = nullptr;
+ SDL_JoystickClose(m_joydevice);
+ m_joydevice = nullptr;
}
}
- void reset() override
+ virtual void reset() override
{
- memset(&joystick, 0, sizeof(joystick));
+ memset(&m_joystick, 0, sizeof(m_joystick));
}
- void process_event(SDL_Event &sdlevent) override
+ virtual void process_event(SDL_Event const &event) override
{
- switch (sdlevent.type)
+ switch (event.type)
{
case SDL_JOYAXISMOTION:
- joystick.axes[sdlevent.jaxis.axis] = (sdlevent.jaxis.value * 2);
+ if (event.jaxis.axis < MAX_AXES)
+ m_joystick.axes[event.jaxis.axis] = (event.jaxis.value * 2);
break;
case SDL_JOYBALLMOTION:
- //printf("Ball %d %d\n", sdlevent.jball.xrel, sdlevent.jball.yrel);
- joystick.balls[sdlevent.jball.ball * 2] = sdlevent.jball.xrel * osd::INPUT_RELATIVE_PER_PIXEL;
- joystick.balls[sdlevent.jball.ball * 2 + 1] = sdlevent.jball.yrel * osd::INPUT_RELATIVE_PER_PIXEL;
+ //printf("Ball %d %d\n", event.jball.xrel, event.jball.yrel);
+ if (event.jball.ball < (MAX_AXES / 2))
+ {
+ m_joystick.balls[event.jball.ball * 2] = event.jball.xrel * input_device::RELATIVE_PER_PIXEL;
+ m_joystick.balls[event.jball.ball * 2 + 1] = event.jball.yrel * input_device::RELATIVE_PER_PIXEL;
+ }
break;
case SDL_JOYHATMOTION:
- joystick.hatsU[sdlevent.jhat.hat] = (sdlevent.jhat.value & SDL_HAT_UP) ? 0x80 : 0;
- joystick.hatsD[sdlevent.jhat.hat] = (sdlevent.jhat.value & SDL_HAT_DOWN) ? 0x80 : 0;
- joystick.hatsL[sdlevent.jhat.hat] = (sdlevent.jhat.value & SDL_HAT_LEFT) ? 0x80 : 0;
- joystick.hatsR[sdlevent.jhat.hat] = (sdlevent.jhat.value & SDL_HAT_RIGHT) ? 0x80 : 0;
+ if (event.jhat.hat < MAX_HATS)
+ {
+ m_joystick.hatsU[event.jhat.hat] = (event.jhat.value & SDL_HAT_UP) ? 0x80 : 0;
+ m_joystick.hatsD[event.jhat.hat] = (event.jhat.value & SDL_HAT_DOWN) ? 0x80 : 0;
+ m_joystick.hatsL[event.jhat.hat] = (event.jhat.value & SDL_HAT_LEFT) ? 0x80 : 0;
+ m_joystick.hatsR[event.jhat.hat] = (event.jhat.value & SDL_HAT_RIGHT) ? 0x80 : 0;
+ }
break;
case SDL_JOYBUTTONDOWN:
case SDL_JOYBUTTONUP:
- if (sdlevent.jbutton.button < MAX_BUTTONS)
- joystick.buttons[sdlevent.jbutton.button] = (sdlevent.jbutton.state == SDL_PRESSED) ? 0x80 : 0;
+ if (event.jbutton.button < MAX_BUTTONS)
+ m_joystick.buttons[event.jbutton.button] = (event.jbutton.state == SDL_PRESSED) ? 0x80 : 0;
break;
case SDL_JOYDEVICEREMOVED:
- osd_printf_verbose("Joystick: %s [GUID %s] disconnected\n", name(), id());
+ osd_printf_verbose("Joystick: %s [ID %s] disconnected\n", name(), id());
+ clear_instance();
reset();
- if (sdl_state.device)
+ if (m_joydevice)
{
- if (sdl_state.hapdevice)
+ if (m_hapdevice)
{
- SDL_HapticClose(sdl_state.hapdevice);
- sdl_state.hapdevice = nullptr;
+ SDL_HapticClose(m_hapdevice);
+ m_hapdevice = nullptr;
}
- SDL_JoystickClose(sdl_state.device);
- sdl_state.device = nullptr;
+ SDL_JoystickClose(m_joydevice);
+ m_joydevice = nullptr;
}
break;
}
}
+
+ bool has_haptic() const
+ {
+ return m_hapdevice != nullptr;
+ }
+
+ void attach_device(SDL_Joystick *joy)
+ {
+ assert(joy);
+ assert(!m_joydevice);
+
+ set_instance(SDL_JoystickInstanceID(joy));
+ m_joydevice = joy;
+ m_hapdevice = SDL_HapticOpenFromJoystick(joy);
+
+ osd_printf_verbose("Joystick: %s [ID %s] reconnected\n", name(), id());
+ }
+
+protected:
+ // state information for a joystick
+ struct sdl_joystick_state
+ {
+ s32 axes[MAX_AXES];
+ s32 buttons[MAX_BUTTONS];
+ s32 hatsU[MAX_HATS], hatsD[MAX_HATS], hatsL[MAX_HATS], hatsR[MAX_HATS];
+ s32 balls[MAX_AXES];
+ };
+
+ sdl_joystick_state m_joystick;
+
+private:
+ SDL_Joystick *m_joydevice;
+ SDL_Haptic *m_hapdevice;
};
+
+//============================================================
+// sdl_sixaxis_joystick_device
+//============================================================
+
class sdl_sixaxis_joystick_device : public sdl_joystick_device
{
public:
- sdl_sixaxis_joystick_device(running_machine &machine, std::string &&name, std::string &&id, input_module &module) :
- sdl_joystick_device(machine, std::move(name), std::move(id), module)
- {
- }
+ using sdl_joystick_device::sdl_joystick_device;
- void process_event(SDL_Event &sdlevent) override
+ virtual void process_event(SDL_Event const &event) override
{
- switch (sdlevent.type)
+ switch (event.type)
{
case SDL_JOYAXISMOTION:
{
- int const axis = sdlevent.jaxis.axis;
+ int const axis = event.jaxis.axis;
if (axis <= 3)
{
- joystick.axes[sdlevent.jaxis.axis] = (sdlevent.jaxis.value * 2);
+ m_joystick.axes[event.jaxis.axis] = (event.jaxis.value * 2);
}
else
{
- int const magic = (sdlevent.jaxis.value / 2) + 16384;
- joystick.axes[sdlevent.jaxis.axis] = magic;
+ int const magic = (event.jaxis.value / 2) + 16384;
+ m_joystick.axes[event.jaxis.axis] = magic;
}
}
break;
default:
// Call the base for other events
- sdl_joystick_device::process_event(sdlevent);
+ sdl_joystick_device::process_event(event);
break;
}
}
};
+
//============================================================
-// sdl_input_module
+// sdl_game_controller_device
//============================================================
-class sdl_input_module : public input_module_base, public sdl_event_subscriber
+class sdl_game_controller_device : public sdl_joystick_device_base
{
public:
- sdl_input_module(const char *type) : input_module_base(type, "sdl")
+ sdl_game_controller_device(
+ std::string &&name,
+ std::string &&id,
+ input_module &module,
+ SDL_GameController *ctrl,
+ char const *serial) :
+ sdl_joystick_device_base(
+ std::move(name),
+ std::move(id),
+ module,
+ serial),
+ m_controller({{0}}),
+ m_ctrldevice(ctrl)
{
+ set_instance(SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(ctrl)));
}
- void input_init(running_machine &machine) override
+ ~sdl_game_controller_device()
{
- if (machine.debug_flags & DEBUG_FLAG_OSD_ENABLED)
+ if (m_ctrldevice)
{
- osd_printf_warning("Debug Build: Disabling input grab for -debug\n");
- set_mouse_enabled(false);
+ SDL_GameControllerClose(m_ctrldevice);
+ m_ctrldevice = nullptr;
}
}
- void exit() override
+ virtual void configure(input_device &device) override
{
- // unsubscribe for events
- sdl_event_manager::instance().unsubscribe(this);
+ input_device::assignment_vector assignments;
+ char const *const *axisnames = CONTROLLER_AXIS_XBOX;
+ char const *const *buttonnames = CONTROLLER_BUTTON_XBOX360;
+ bool digitaltriggers = false;
+ bool avoidpaddles = false;
+ auto const ctrltype = SDL_GameControllerGetType(m_ctrldevice);
+ switch (ctrltype)
+ {
+ case SDL_CONTROLLER_TYPE_UNKNOWN:
+ osd_printf_verbose("Game Controller: ... unknown type\n", int(ctrltype));
+ break;
+ case SDL_CONTROLLER_TYPE_XBOX360:
+ osd_printf_verbose("Game Controller: ... Xbox 360 type\n");
+ axisnames = CONTROLLER_AXIS_XBOX;
+ buttonnames = CONTROLLER_BUTTON_XBOX360;
+ break;
+ case SDL_CONTROLLER_TYPE_XBOXONE:
+ osd_printf_verbose("Game Controller: ... Xbox One type\n");
+ axisnames = CONTROLLER_AXIS_XBOX;
+ buttonnames = CONTROLLER_BUTTON_XBOXONE;
+ break;
+ case SDL_CONTROLLER_TYPE_PS3:
+ osd_printf_verbose("Game Controller: ... PlayStation 3 type\n");
+ axisnames = CONTROLLER_AXIS_PS;
+ buttonnames = CONTROLLER_BUTTON_PS3;
+ break;
+ case SDL_CONTROLLER_TYPE_PS4:
+ osd_printf_verbose("Game Controller: ... PlayStation 4 type\n");
+ axisnames = CONTROLLER_AXIS_PS;
+ buttonnames = CONTROLLER_BUTTON_PS4;
+ break;
+ case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO:
+ osd_printf_verbose("Game Controller: ... Switch Pro Controller type\n");
+ axisnames = CONTROLLER_AXIS_SWITCH;
+ buttonnames = CONTROLLER_BUTTON_SWITCH;
+ digitaltriggers = true;
+ break;
+ //case SDL_CONTROLLER_TYPE_VIRTUAL:
+ case SDL_CONTROLLER_TYPE_PS5:
+ osd_printf_verbose("Game Controller: ... PlayStation 5 type\n");
+ axisnames = CONTROLLER_AXIS_PS;
+ buttonnames = CONTROLLER_BUTTON_PS5;
+ break;
+#if SDL_VERSION_ATLEAST(2, 0, 16)
+ //case SDL_CONTROLLER_TYPE_AMAZON_LUNA:
+ case SDL_CONTROLLER_TYPE_GOOGLE_STADIA:
+ osd_printf_verbose("Game Controller: ... Google Stadia type\n");
+ axisnames = CONTROLLER_AXIS_PS;
+ buttonnames = CONTROLLER_BUTTON_STADIA;
+ break;
+#endif
+#if SDL_VERSION_ATLEAST(2, 24, 0)
+ case SDL_CONTROLLER_TYPE_NVIDIA_SHIELD:
+ osd_printf_verbose("Game Controller: ... NVIDIA Shield type\n");
+ axisnames = CONTROLLER_AXIS_XBOX;
+ buttonnames = CONTROLLER_BUTTON_SHIELD;
+ break;
+ //case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_LEFT:
+ //case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT:
+ case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_PAIR:
+ osd_printf_verbose("Game Controller: ... Joy-Con pair type\n");
+ axisnames = CONTROLLER_AXIS_SWITCH;
+ buttonnames = CONTROLLER_BUTTON_SWITCH;
+ digitaltriggers = true;
+ avoidpaddles = true;
+ break;
+#endif
+ default: // default to Xbox 360 names
+ osd_printf_verbose("Game Controller: ... unrecognized type (%d)\n", int(ctrltype));
+ break;
+ }
+
+ // keep track of item numbers as we add controls
+ std::pair<input_item_id, input_item_id> axisitems[SDL_CONTROLLER_AXIS_MAX];
+ input_item_id buttonitems[SDL_CONTROLLER_BUTTON_MAX];
+ std::tuple<input_item_id, SDL_GameControllerButton, SDL_GameControllerAxis> numberedbuttons[16];
+ std::fill(
+ std::begin(axisitems),
+ std::end(axisitems),
+ std::make_pair(ITEM_ID_INVALID, ITEM_ID_INVALID));
+ std::fill(
+ std::begin(buttonitems),
+ std::end(buttonitems),
+ ITEM_ID_INVALID);
+ std::fill(
+ std::begin(numberedbuttons),
+ std::end(numberedbuttons),
+ std::make_tuple(ITEM_ID_INVALID, SDL_CONTROLLER_BUTTON_INVALID, SDL_CONTROLLER_AXIS_INVALID));
+
+ // add axes
+ std::tuple<SDL_GameControllerAxis, input_item_id, bool> const axes[]{
+ { SDL_CONTROLLER_AXIS_LEFTX, ITEM_ID_XAXIS, false },
+ { SDL_CONTROLLER_AXIS_LEFTY, ITEM_ID_YAXIS, false },
+ { SDL_CONTROLLER_AXIS_RIGHTX, ITEM_ID_ZAXIS, false },
+ { SDL_CONTROLLER_AXIS_RIGHTY, ITEM_ID_RZAXIS, false },
+ { SDL_CONTROLLER_AXIS_TRIGGERLEFT, ITEM_ID_SLIDER1, true },
+ { SDL_CONTROLLER_AXIS_TRIGGERRIGHT, ITEM_ID_SLIDER2, true } };
+ for (auto [axis, item, buttontest] : axes)
+ {
+ bool avail = !buttontest || !digitaltriggers;
+ avail = avail && SDL_GameControllerHasAxis(m_ctrldevice, axis);
+ if (avail)
+ {
+ auto const binding = SDL_GameControllerGetBindForAxis(m_ctrldevice, axis);
+ switch (binding.bindType)
+ {
+ case SDL_CONTROLLER_BINDTYPE_NONE:
+ avail = false;
+ break;
+ case SDL_CONTROLLER_BINDTYPE_BUTTON:
+ if (buttontest)
+ avail = false;
+ break;
+ default:
+ break;
+ }
+ }
+ if (avail)
+ {
+ axisitems[axis].first = device.add_item(
+ axisnames[axis],
+ std::string_view(),
+ item,
+ generic_axis_get_state<s32>,
+ &m_controller.axes[axis]);
+ }
+ }
+
+ // add automatically numbered buttons
+ std::tuple<SDL_GameControllerButton, SDL_GameControllerAxis, bool> const generalbuttons[]{
+ { SDL_CONTROLLER_BUTTON_A, SDL_CONTROLLER_AXIS_INVALID, true },
+ { SDL_CONTROLLER_BUTTON_B, SDL_CONTROLLER_AXIS_INVALID, true },
+ { SDL_CONTROLLER_BUTTON_X, SDL_CONTROLLER_AXIS_INVALID, true },
+ { SDL_CONTROLLER_BUTTON_Y, SDL_CONTROLLER_AXIS_INVALID, true },
+ { SDL_CONTROLLER_BUTTON_LEFTSHOULDER, SDL_CONTROLLER_AXIS_INVALID, true },
+ { SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, SDL_CONTROLLER_AXIS_INVALID, true },
+ { SDL_CONTROLLER_BUTTON_INVALID, SDL_CONTROLLER_AXIS_TRIGGERLEFT, true },
+ { SDL_CONTROLLER_BUTTON_INVALID, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, true },
+ { SDL_CONTROLLER_BUTTON_LEFTSTICK, SDL_CONTROLLER_AXIS_INVALID, true },
+ { SDL_CONTROLLER_BUTTON_RIGHTSTICK, SDL_CONTROLLER_AXIS_INVALID, true },
+ { SDL_CONTROLLER_BUTTON_PADDLE1, SDL_CONTROLLER_AXIS_INVALID, true },
+ { SDL_CONTROLLER_BUTTON_PADDLE2, SDL_CONTROLLER_AXIS_INVALID, true },
+ { SDL_CONTROLLER_BUTTON_PADDLE3, SDL_CONTROLLER_AXIS_INVALID, true },
+ { SDL_CONTROLLER_BUTTON_PADDLE4, SDL_CONTROLLER_AXIS_INVALID, true },
+ { SDL_CONTROLLER_BUTTON_GUIDE, SDL_CONTROLLER_AXIS_INVALID, false },
+ { SDL_CONTROLLER_BUTTON_MISC1, SDL_CONTROLLER_AXIS_INVALID, false },
+ { SDL_CONTROLLER_BUTTON_TOUCHPAD, SDL_CONTROLLER_AXIS_INVALID, false },
+ };
+ input_item_id button_item = ITEM_ID_BUTTON1;
+ unsigned buttoncount = 0;
+ for (auto [button, axis, field] : generalbuttons)
+ {
+ bool avail = true;
+ input_item_id actual = ITEM_ID_INVALID;
+ if (SDL_CONTROLLER_BUTTON_INVALID != button)
+ {
+ avail = SDL_GameControllerHasButton(m_ctrldevice, button);
+ if (avail)
+ {
+ auto const binding = SDL_GameControllerGetBindForButton(m_ctrldevice, button);
+ switch (binding.bindType)
+ {
+ case SDL_CONTROLLER_BINDTYPE_NONE:
+ avail = false;
+ break;
+ default:
+ break;
+ }
+ }
+ if (avail)
+ {
+ actual = buttonitems[button] = device.add_item(
+ buttonnames[button],
+ std::string_view(),
+ button_item++,
+ generic_button_get_state<s32>,
+ &m_controller.buttons[button]);
+ if (field && (std::size(numberedbuttons) > buttoncount))
+ std::get<1>(numberedbuttons[buttoncount]) = button;
+ }
+ }
+ else
+ {
+ avail = SDL_GameControllerHasAxis(m_ctrldevice, axis);
+ if (avail)
+ {
+ auto const binding = SDL_GameControllerGetBindForAxis(m_ctrldevice, axis);
+ switch (binding.bindType)
+ {
+ case SDL_CONTROLLER_BINDTYPE_NONE:
+ avail = false;
+ break;
+ case SDL_CONTROLLER_BINDTYPE_BUTTON:
+ break;
+ default:
+ avail = digitaltriggers;
+ }
+ }
+ if (avail)
+ {
+ actual = axisitems[axis].second = device.add_item(
+ axisnames[axis],
+ std::string_view(),
+ button_item++,
+ [] (void *device_internal, void *item_internal) -> int
+ {
+ return (*reinterpret_cast<s32 const *>(item_internal) <= -16'384) ? 1 : 0;
+ },
+ &m_controller.axes[axis]);
+ if (field && (std::size(numberedbuttons) > buttoncount))
+ std::get<2>(numberedbuttons[buttoncount]) = axis;
+ }
+ }
+
+ // add default button assignments
+ if (field && avail && (std::size(numberedbuttons) > buttoncount))
+ {
+ std::get<0>(numberedbuttons[buttoncount]) = actual;
+ add_button_assignment(assignments, ioport_type(IPT_BUTTON1 + buttoncount++), { actual });
+ }
+ }
+
+ // add buttons with fixed item IDs
+ std::pair<SDL_GameControllerButton, input_item_id> const fixedbuttons[]{
+ { SDL_CONTROLLER_BUTTON_BACK, ITEM_ID_SELECT },
+ { SDL_CONTROLLER_BUTTON_START, ITEM_ID_START },
+ { SDL_CONTROLLER_BUTTON_DPAD_UP, ITEM_ID_HAT1UP },
+ { SDL_CONTROLLER_BUTTON_DPAD_DOWN, ITEM_ID_HAT1DOWN },
+ { SDL_CONTROLLER_BUTTON_DPAD_LEFT, ITEM_ID_HAT1LEFT },
+ { SDL_CONTROLLER_BUTTON_DPAD_RIGHT, ITEM_ID_HAT1RIGHT } };
+ for (auto [button, item] : fixedbuttons)
+ {
+ bool avail = true;
+ avail = SDL_GameControllerHasButton(m_ctrldevice, button);
+ if (avail)
+ {
+ auto const binding = SDL_GameControllerGetBindForButton(m_ctrldevice, button);
+ switch (binding.bindType)
+ {
+ case SDL_CONTROLLER_BINDTYPE_NONE:
+ avail = false;
+ break;
+ default:
+ break;
+ }
+ }
+ if (avail)
+ {
+ buttonitems[button] = device.add_item(
+ buttonnames[button],
+ std::string_view(),
+ item,
+ generic_button_get_state<s32>,
+ &m_controller.buttons[button]);
+ }
+ }
+
+ // try to get a "complete" joystick for primary movement controls
+ input_item_id diraxis[2][2];
+ choose_primary_stick(
+ diraxis,
+ axisitems[SDL_CONTROLLER_AXIS_LEFTX].first,
+ axisitems[SDL_CONTROLLER_AXIS_LEFTY].first,
+ axisitems[SDL_CONTROLLER_AXIS_RIGHTX].first,
+ axisitems[SDL_CONTROLLER_AXIS_RIGHTY].first);
+
+ // now set up controls using the primary joystick
+ add_directional_assignments(
+ assignments,
+ diraxis[0][0],
+ diraxis[0][1],
+ buttonitems[SDL_CONTROLLER_BUTTON_DPAD_LEFT],
+ buttonitems[SDL_CONTROLLER_BUTTON_DPAD_RIGHT],
+ buttonitems[SDL_CONTROLLER_BUTTON_DPAD_UP],
+ buttonitems[SDL_CONTROLLER_BUTTON_DPAD_DOWN]);
+
+ // assign a secondary stick axis to joystick Z if available
+ bool const zaxis = add_assignment(
+ assignments,
+ IPT_AD_STICK_Z,
+ SEQ_TYPE_STANDARD,
+ ITEM_CLASS_ABSOLUTE,
+ ITEM_MODIFIER_NONE,
+ { diraxis[1][1], diraxis[1][0] });
+ if (!zaxis)
+ {
+ // if both triggers are present, combine them, or failing that, fall back to a pair of buttons
+ if ((ITEM_ID_INVALID != axisitems[SDL_CONTROLLER_AXIS_TRIGGERLEFT].first) && (ITEM_ID_INVALID != axisitems[SDL_CONTROLLER_AXIS_TRIGGERRIGHT].first))
+ {
+ assignments.emplace_back(
+ IPT_AD_STICK_Z,
+ SEQ_TYPE_STANDARD,
+ input_seq(
+ make_code(ITEM_CLASS_ABSOLUTE, ITEM_MODIFIER_NONE, axisitems[SDL_CONTROLLER_AXIS_TRIGGERLEFT].first),
+ make_code(ITEM_CLASS_ABSOLUTE, ITEM_MODIFIER_REVERSE, axisitems[SDL_CONTROLLER_AXIS_TRIGGERRIGHT].first)));
+ }
+ else if (add_axis_inc_dec_assignment(assignments, IPT_AD_STICK_Z, buttonitems[SDL_CONTROLLER_BUTTON_LEFTSHOULDER], buttonitems[SDL_CONTROLLER_BUTTON_RIGHTSHOULDER]))
+ {
+ // took shoulder buttons
+ }
+ else if (add_axis_inc_dec_assignment(assignments, IPT_AD_STICK_Z, axisitems[SDL_CONTROLLER_AXIS_TRIGGERLEFT].second, axisitems[SDL_CONTROLLER_AXIS_TRIGGERRIGHT].second))
+ {
+ // took trigger buttons
+ }
+ else if (add_axis_inc_dec_assignment(assignments, IPT_AD_STICK_Z, buttonitems[SDL_CONTROLLER_BUTTON_PADDLE1], buttonitems[SDL_CONTROLLER_BUTTON_PADDLE2]))
+ {
+ // took P1/P2
+ }
+ else if (add_axis_inc_dec_assignment(assignments, IPT_AD_STICK_Z, buttonitems[SDL_CONTROLLER_BUTTON_PADDLE3], buttonitems[SDL_CONTROLLER_BUTTON_PADDLE4]))
+ {
+ // took P3/P4
+ }
+ }
+
+ // prefer trigger axes for pedals, otherwise take half axes and buttons
+ unsigned pedalbutton = 0;
+ if (!add_assignment(assignments, IPT_PEDAL, SEQ_TYPE_STANDARD, ITEM_CLASS_ABSOLUTE, ITEM_MODIFIER_NEG, { axisitems[SDL_CONTROLLER_AXIS_TRIGGERRIGHT].first }))
+ {
+ add_assignment(
+ assignments,
+ IPT_PEDAL,
+ SEQ_TYPE_STANDARD,
+ ITEM_CLASS_ABSOLUTE,
+ ITEM_MODIFIER_NEG,
+ { diraxis[1][1], diraxis[0][1] });
+ bool const incbutton = add_assignment(
+ assignments,
+ IPT_PEDAL,
+ SEQ_TYPE_INCREMENT,
+ ITEM_CLASS_SWITCH,
+ ITEM_MODIFIER_NONE,
+ { axisitems[SDL_CONTROLLER_AXIS_TRIGGERRIGHT].second, buttonitems[SDL_CONTROLLER_BUTTON_RIGHTSHOULDER] });
+ if (!incbutton)
+ {
+ if (add_assignment(assignments, IPT_PEDAL, SEQ_TYPE_INCREMENT, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, { std::get<0>(numberedbuttons[pedalbutton]) }))
+ ++pedalbutton;
+ }
+ }
+ if (!add_assignment(assignments, IPT_PEDAL2, SEQ_TYPE_STANDARD, ITEM_CLASS_ABSOLUTE, ITEM_MODIFIER_NEG, { axisitems[SDL_CONTROLLER_AXIS_TRIGGERLEFT].first }))
+ {
+ add_assignment(
+ assignments,
+ IPT_PEDAL2,
+ SEQ_TYPE_STANDARD,
+ ITEM_CLASS_ABSOLUTE,
+ ITEM_MODIFIER_POS,
+ { diraxis[1][1], diraxis[0][1] });
+ bool const incbutton = add_assignment(
+ assignments,
+ IPT_PEDAL2,
+ SEQ_TYPE_INCREMENT,
+ ITEM_CLASS_SWITCH,
+ ITEM_MODIFIER_NONE,
+ { axisitems[SDL_CONTROLLER_AXIS_TRIGGERLEFT].second, buttonitems[SDL_CONTROLLER_BUTTON_LEFTSHOULDER] });
+ if (!incbutton)
+ {
+ if (add_assignment(assignments, IPT_PEDAL2, SEQ_TYPE_INCREMENT, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, { std::get<0>(numberedbuttons[pedalbutton]) }))
+ ++pedalbutton;
+ }
+ }
+ add_assignment(assignments, IPT_PEDAL3, SEQ_TYPE_INCREMENT, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, { std::get<0>(numberedbuttons[pedalbutton]) });
+
+ // potentially use thumb sticks and/or D-pad and A/B/X/Y diamond for twin sticks
+ add_twin_stick_assignments(
+ assignments,
+ axisitems[SDL_CONTROLLER_AXIS_LEFTX].first,
+ axisitems[SDL_CONTROLLER_AXIS_LEFTY].first,
+ axisitems[SDL_CONTROLLER_AXIS_RIGHTX].first,
+ axisitems[SDL_CONTROLLER_AXIS_RIGHTY].first,
+ buttonitems[SDL_CONTROLLER_BUTTON_DPAD_LEFT],
+ buttonitems[SDL_CONTROLLER_BUTTON_DPAD_RIGHT],
+ buttonitems[SDL_CONTROLLER_BUTTON_DPAD_UP],
+ buttonitems[SDL_CONTROLLER_BUTTON_DPAD_DOWN],
+ buttonitems[SDL_CONTROLLER_BUTTON_X],
+ buttonitems[SDL_CONTROLLER_BUTTON_B],
+ buttonitems[SDL_CONTROLLER_BUTTON_Y],
+ buttonitems[SDL_CONTROLLER_BUTTON_A]);
+
+ // add assignments for buttons with fixed functions
+ add_button_assignment(assignments, IPT_SELECT, { buttonitems[SDL_CONTROLLER_BUTTON_BACK] });
+ add_button_assignment(assignments, IPT_START, { buttonitems[SDL_CONTROLLER_BUTTON_START] });
+ add_button_assignment(assignments, IPT_UI_MENU, { buttonitems[SDL_CONTROLLER_BUTTON_GUIDE] });
+
+ // the first button is always UI select
+ if (add_button_assignment(assignments, IPT_UI_SELECT, { std::get<0>(numberedbuttons[0]) }))
+ {
+ if (SDL_CONTROLLER_BUTTON_INVALID != std::get<1>(numberedbuttons[0]))
+ buttonitems[std::get<1>(numberedbuttons[0])] = ITEM_ID_INVALID;
+ if (SDL_CONTROLLER_AXIS_INVALID != std::get<2>(numberedbuttons[0]))
+ axisitems[std::get<2>(numberedbuttons[0])].second = ITEM_ID_INVALID;
+ }
+
+ // try to get a matching pair of buttons for previous/next group
+ if (consume_button_pair(assignments, IPT_UI_PREV_GROUP, IPT_UI_NEXT_GROUP, axisitems[SDL_CONTROLLER_AXIS_TRIGGERLEFT].second, axisitems[SDL_CONTROLLER_AXIS_TRIGGERRIGHT].second))
+ {
+ // took digital triggers
+ }
+ else if (!avoidpaddles && consume_button_pair(assignments, IPT_UI_PREV_GROUP, IPT_UI_NEXT_GROUP, buttonitems[SDL_CONTROLLER_BUTTON_PADDLE1], buttonitems[SDL_CONTROLLER_BUTTON_PADDLE2]))
+ {
+ // took upper paddles
+ }
+ else if (consume_trigger_pair(assignments, IPT_UI_PREV_GROUP, IPT_UI_NEXT_GROUP, axisitems[SDL_CONTROLLER_AXIS_TRIGGERLEFT].first, axisitems[SDL_CONTROLLER_AXIS_TRIGGERRIGHT].first))
+ {
+ // took analog triggers
+ }
+ else if (!avoidpaddles && consume_button_pair(assignments, IPT_UI_PREV_GROUP, IPT_UI_NEXT_GROUP, buttonitems[SDL_CONTROLLER_BUTTON_PADDLE3], buttonitems[SDL_CONTROLLER_BUTTON_PADDLE4]))
+ {
+ // took lower paddles
+ }
+ else if (consume_axis_pair(assignments, IPT_UI_PREV_GROUP, IPT_UI_NEXT_GROUP, diraxis[1][1]))
+ {
+ // took secondary Y
+ }
+ else if (consume_axis_pair(assignments, IPT_UI_PREV_GROUP, IPT_UI_NEXT_GROUP, diraxis[1][0]))
+ {
+ // took secondary X
+ }
+
+ // try to get a matching pair of buttons for page up/down
+ if (!avoidpaddles && consume_button_pair(assignments, IPT_UI_PAGE_UP, IPT_UI_PAGE_DOWN, buttonitems[SDL_CONTROLLER_BUTTON_PADDLE1], buttonitems[SDL_CONTROLLER_BUTTON_PADDLE2]))
+ {
+ // took upper paddles
+ }
+ else if (!avoidpaddles && consume_button_pair(assignments, IPT_UI_PAGE_UP, IPT_UI_PAGE_DOWN, buttonitems[SDL_CONTROLLER_BUTTON_PADDLE3], buttonitems[SDL_CONTROLLER_BUTTON_PADDLE4]))
+ {
+ // took lower paddles
+ }
+ else
+ if (consume_trigger_pair(assignments, IPT_UI_PAGE_UP, IPT_UI_PAGE_DOWN, axisitems[SDL_CONTROLLER_AXIS_TRIGGERLEFT].first, axisitems[SDL_CONTROLLER_AXIS_TRIGGERRIGHT].first))
+ {
+ // took analog triggers
+ }
+ else if (consume_axis_pair(assignments, IPT_UI_PAGE_UP, IPT_UI_PAGE_DOWN, diraxis[1][1]))
+ {
+ // took secondary Y
+ }
- input_module_base::exit();
+ // try to assign X button to UI clear
+ if (add_button_assignment(assignments, IPT_UI_CLEAR, { buttonitems[SDL_CONTROLLER_BUTTON_X] }))
+ {
+ buttonitems[SDL_CONTROLLER_BUTTON_X] = ITEM_ID_INVALID;
+ }
+ else
+ {
+ // otherwise try to find an unassigned button
+ for (auto [item, button, axis] : numberedbuttons)
+ {
+ if ((SDL_CONTROLLER_BUTTON_INVALID != button) && (ITEM_ID_INVALID != buttonitems[button]))
+ {
+ add_button_assignment(assignments, IPT_UI_CLEAR, { item });
+ buttonitems[button] = ITEM_ID_INVALID;
+ break;
+ }
+ else if ((SDL_CONTROLLER_AXIS_INVALID != axis) && (ITEM_ID_INVALID != axisitems[axis].second))
+ {
+ add_button_assignment(assignments, IPT_UI_CLEAR, { item });
+ axisitems[axis].second = ITEM_ID_INVALID;
+ break;
+ }
+ }
+ }
+
+ // try to assign B button to UI back
+ if (add_button_assignment(assignments, IPT_UI_BACK, { buttonitems[SDL_CONTROLLER_BUTTON_B] }))
+ {
+ buttonitems[SDL_CONTROLLER_BUTTON_X] = ITEM_ID_INVALID;
+ }
+ else
+ {
+ // otherwise try to find an unassigned button
+ for (auto [item, button, axis] : numberedbuttons)
+ {
+ if ((SDL_CONTROLLER_BUTTON_INVALID != button) && (ITEM_ID_INVALID != buttonitems[button]))
+ {
+ add_button_assignment(assignments, IPT_UI_CLEAR, { item });
+ buttonitems[button] = ITEM_ID_INVALID;
+ break;
+ }
+ else if ((SDL_CONTROLLER_AXIS_INVALID != axis) && (ITEM_ID_INVALID != axisitems[axis].second))
+ {
+ add_button_assignment(assignments, IPT_UI_CLEAR, { item });
+ axisitems[axis].second = ITEM_ID_INVALID;
+ break;
+ }
+ }
+ }
+
+ // try to assign Y button to UI help
+ if (add_button_assignment(assignments, IPT_UI_HELP, { buttonitems[SDL_CONTROLLER_BUTTON_Y] }))
+ {
+ buttonitems[SDL_CONTROLLER_BUTTON_Y] = ITEM_ID_INVALID;
+ }
+ else
+ {
+ // otherwise try to find an unassigned button
+ for (auto [item, button, axis] : numberedbuttons)
+ {
+ if ((SDL_CONTROLLER_BUTTON_INVALID != button) && (ITEM_ID_INVALID != buttonitems[button]))
+ {
+ add_button_assignment(assignments, IPT_UI_HELP, { item });
+ buttonitems[button] = ITEM_ID_INVALID;
+ break;
+ }
+ else if ((SDL_CONTROLLER_AXIS_INVALID != axis) && (ITEM_ID_INVALID != axisitems[axis].second))
+ {
+ add_button_assignment(assignments, IPT_UI_HELP, { item });
+ axisitems[axis].second = ITEM_ID_INVALID;
+ break;
+ }
+ }
+ }
+
+ // put focus previous/next on the shoulder buttons if available - this can be overloaded with zoom
+ if (add_button_pair_assignment(assignments, IPT_UI_FOCUS_PREV, IPT_UI_FOCUS_NEXT, buttonitems[SDL_CONTROLLER_BUTTON_LEFTSHOULDER], buttonitems[SDL_CONTROLLER_BUTTON_RIGHTSHOULDER]))
+ {
+ // took shoulder buttons
+ }
+ else if (add_axis_pair_assignment(assignments, IPT_UI_FOCUS_PREV, IPT_UI_FOCUS_NEXT, diraxis[1][0]))
+ {
+ // took secondary X
+ }
+ else if (add_axis_pair_assignment(assignments, IPT_UI_FOCUS_PREV, IPT_UI_FOCUS_NEXT, diraxis[1][1]))
+ {
+ // took secondary Y
+ }
+
+ // put zoom on the secondary stick if available, or fall back to shoulder buttons
+ if (add_axis_pair_assignment(assignments, IPT_UI_ZOOM_OUT, IPT_UI_ZOOM_IN, diraxis[1][0]))
+ {
+ // took secondary X
+ if (axisitems[SDL_CONTROLLER_AXIS_LEFTX].first == diraxis[1][0])
+ add_button_assignment(assignments, IPT_UI_ZOOM_DEFAULT, { buttonitems[SDL_CONTROLLER_BUTTON_LEFTSTICK] });
+ else if (axisitems[SDL_CONTROLLER_AXIS_RIGHTX].first == diraxis[1][0])
+ add_button_assignment(assignments, IPT_UI_ZOOM_DEFAULT, { buttonitems[SDL_CONTROLLER_BUTTON_RIGHTSTICK] });
+ diraxis[1][0] = ITEM_ID_INVALID;
+ }
+ else if (add_axis_pair_assignment(assignments, IPT_UI_ZOOM_IN, IPT_UI_ZOOM_OUT, diraxis[1][1]))
+ {
+ // took secondary Y
+ if (axisitems[SDL_CONTROLLER_AXIS_LEFTY].first == diraxis[1][1])
+ add_button_assignment(assignments, IPT_UI_ZOOM_DEFAULT, { buttonitems[SDL_CONTROLLER_BUTTON_LEFTSTICK] });
+ else if (axisitems[SDL_CONTROLLER_AXIS_RIGHTY].first == diraxis[1][1])
+ add_button_assignment(assignments, IPT_UI_ZOOM_DEFAULT, { buttonitems[SDL_CONTROLLER_BUTTON_RIGHTSTICK] });
+ diraxis[1][1] = ITEM_ID_INVALID;
+ }
+ else if (consume_button_pair(assignments, IPT_UI_ZOOM_OUT, IPT_UI_ZOOM_IN, buttonitems[SDL_CONTROLLER_BUTTON_LEFTSHOULDER], buttonitems[SDL_CONTROLLER_BUTTON_RIGHTSHOULDER]))
+ {
+ // took shoulder buttons
+ }
+
+ // set default assignments
+ device.set_default_assignments(std::move(assignments));
}
- void before_poll(running_machine& machine) override
+ virtual void reset() override
{
- // Tell the event manager to process events and push them to the devices
- sdl_event_manager::instance().process_events(machine);
+ memset(&m_controller, 0, sizeof(m_controller));
+ }
+
+ virtual void process_event(SDL_Event const &event) override
+ {
+ switch (event.type)
+ {
+ case SDL_CONTROLLERAXISMOTION:
+ if (event.caxis.axis < SDL_CONTROLLER_AXIS_MAX)
+ {
+ switch (event.caxis.axis)
+ {
+ case SDL_CONTROLLER_AXIS_TRIGGERLEFT: // MAME wants negative values for triggers
+ case SDL_CONTROLLER_AXIS_TRIGGERRIGHT:
+ m_controller.axes[event.caxis.axis] = -normalize_absolute_axis(event.caxis.value, -32'767, 32'767);
+ break;
+ default:
+ m_controller.axes[event.caxis.axis] = normalize_absolute_axis(event.caxis.value, -32'767, 32'767);
+ }
+ }
+ break;
+
+ case SDL_CONTROLLERBUTTONDOWN:
+ case SDL_CONTROLLERBUTTONUP:
+ if (event.cbutton.button < SDL_CONTROLLER_BUTTON_MAX)
+ m_controller.buttons[event.cbutton.button] = (event.cbutton.state == SDL_PRESSED) ? 0x80 : 0x00;
+ break;
+
+ case SDL_CONTROLLERDEVICEREMOVED:
+ osd_printf_verbose("Game Controller: %s [ID %s] disconnected\n", name(), id());
+ clear_instance();
+ reset();
+ if (m_ctrldevice)
+ {
+ SDL_GameControllerClose(m_ctrldevice);
+ m_ctrldevice = nullptr;
+ }
+ break;
+ }
}
- bool should_poll_devices(running_machine& machine) override
+ void attach_device(SDL_GameController *ctrl)
{
- return sdl_event_manager::instance().has_focus() && input_enabled();
+ assert(ctrl);
+ assert(!m_ctrldevice);
+
+ set_instance(SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(ctrl)));
+ m_ctrldevice = ctrl;
+
+ osd_printf_verbose("Game Controller: %s [ID %s] reconnected\n", name(), id());
}
- void handle_event(SDL_Event &sdlevent) override
+private:
+ // state information for a game controller
+ struct sdl_controller_state
+ {
+ s32 axes[SDL_CONTROLLER_AXIS_MAX];
+ s32 buttons[SDL_CONTROLLER_BUTTON_MAX];
+ };
+
+ sdl_controller_state m_controller;
+ SDL_GameController *m_ctrldevice;
+};
+
+
+//============================================================
+// sdl_input_module
+//============================================================
+
+template <typename Info>
+class sdl_input_module :
+ public input_module_impl<Info, sdl_osd_interface>,
+ protected sdl_event_manager::subscriber
+{
+public:
+ sdl_input_module(char const *type, char const *name) :
+ input_module_impl<Info, sdl_osd_interface>(type, name)
{
- // By default dispatch event to every device
- devicelist().for_each_device(
- [&sdlevent](auto device) {
- downcast<sdl_device*>(device)->queue_events(&sdlevent, 1);
- });
+ }
+
+ virtual void exit() override
+ {
+ // unsubscribe for events
+ unsubscribe();
+
+ input_module_impl<Info, sdl_osd_interface>::exit();
+ }
+
+protected:
+ virtual void handle_event(SDL_Event const &event) override
+ {
+ // dispatch event to every device by default
+ this->devicelist().for_each_device(
+ [&event] (auto &device) { device.queue_events(&event, 1); });
}
};
+
//============================================================
// sdl_keyboard_module
//============================================================
-class sdl_keyboard_module : public sdl_input_module
+class sdl_keyboard_module : public sdl_input_module<sdl_keyboard_device>
{
- keyboard_trans_table * m_key_trans_table;
public:
sdl_keyboard_module() :
- sdl_input_module(OSD_KEYBOARDINPUT_PROVIDER),
- m_key_trans_table(nullptr)
+ sdl_input_module<sdl_keyboard_device>(OSD_KEYBOARDINPUT_PROVIDER, "sdl")
{
}
- void input_init(running_machine &machine) override
+ virtual void input_init(running_machine &machine) override
{
- sdl_input_module::input_init(machine);
+ sdl_input_module<sdl_keyboard_device>::input_init(machine);
static int const event_types[] = {
int(SDL_KEYDOWN),
- int(SDL_KEYUP),
- int(SDL_TEXTINPUT) };
+ int(SDL_KEYUP) };
- sdl_event_manager::instance().subscribe(event_types, this);
+ subscribe(osd(), event_types);
// Read our keymap and store a pointer to our table
- m_key_trans_table = sdlinput_read_keymap(machine);
-
- keyboard_trans_table& local_table = *m_key_trans_table;
+ sdlinput_read_keymap();
osd_printf_verbose("Keyboard: Start initialization\n");
// SDL only has 1 keyboard add it now
- auto &devinfo = devicelist().create_device<sdl_keyboard_device>(machine, "System keyboard", "System keyboard", *this);
-
- // populate it
- for (int keynum = 0; local_table[keynum].mame_key != ITEM_ID_INVALID; keynum++)
- {
- input_item_id itemid = local_table[keynum].mame_key;
-
- // generate the default / modified name
- char defname[20];
- snprintf(defname, sizeof(defname) - 1, "%s", local_table[keynum].ui_name);
-
- devinfo.device()->add_item(defname, itemid, generic_button_get_state<std::int32_t>, &devinfo.keyboard.state[local_table[keynum].sdl_scancode]);
- }
+ auto &devinfo = create_device<sdl_keyboard_device>(
+ DEVICE_CLASS_KEYBOARD,
+ "System keyboard",
+ "System keyboard",
+ *m_key_trans_table);
osd_printf_verbose("Keyboard: Registered %s\n", devinfo.name());
osd_printf_verbose("Keyboard: End initialization\n");
}
private:
- keyboard_trans_table *sdlinput_read_keymap(running_machine &machine)
+ void sdlinput_read_keymap()
{
keyboard_trans_table &default_table = keyboard_trans_table::instance();
- if (!machine.options().bool_value(SDLOPTION_KEYMAP))
- return &default_table;
+ // Allocate a block of translation entries big enough to hold what's in the default table
+ auto key_trans_entries = std::make_unique<key_trans_entry []>(default_table.size());
+
+ // copy the elements from the default table and ask SDL for key names
+ for (int i = 0; i < default_table.size(); i++)
+ {
+ key_trans_entries[i] = default_table[i];
+ char const *const name = SDL_GetScancodeName(SDL_Scancode(default_table[i].sdl_scancode));
+ if (name && *name)
+ key_trans_entries[i].ui_name = name;
+ }
+
+ // Allocate the trans table to be associated with the machine so we don't have to free it
+ m_key_trans_table = std::make_unique<keyboard_trans_table>(std::move(key_trans_entries), default_table.size());
+
+ if (!options()->bool_value(SDLOPTION_KEYMAP))
+ return;
- const char *const keymap_filename = downcast<sdl_options &>(machine.options()).keymap_file();
+ const char *const keymap_filename = dynamic_cast<sdl_options const &>(*options()).keymap_file();
osd_printf_verbose("Keymap: Start reading keymap_file %s\n", keymap_filename);
FILE *const keymap_file = fopen(keymap_filename, "r");
if (!keymap_file)
{
osd_printf_warning("Keymap: Unable to open keymap %s, using default\n", keymap_filename);
- return &default_table;
+ return;
}
- // Allocate a block of translation entries big enough to hold what's in the default table
- auto key_trans_entries = std::make_unique<key_trans_entry[]>(default_table.size());
-
- // copy the elements from the default table
- for (int i = 0; i < default_table.size(); i++)
- key_trans_entries[i] = default_table[i];
-
- // Allocate the trans table to be associated with the machine so we don't have to free it
- m_custom_table = std::make_unique<keyboard_trans_table>(std::move(key_trans_entries), default_table.size());
-
int line = 1;
int sdl2section = 0;
while (!feof(keymap_file))
@@ -906,7 +2041,7 @@ private:
if (sk >= 0 && index >= 0)
{
- key_trans_entry &entry = (*m_custom_table)[index];
+ key_trans_entry &entry = (*m_key_trans_table)[index];
entry.sdl_scancode = sk;
entry.ui_name = const_cast<char *>(m_ui_names.emplace_back(kns).c_str());
osd_printf_verbose("Keymap: Mapped <%s> to <%s> with ui-text <%s>\n", sks, mks, kns);
@@ -921,22 +2056,21 @@ private:
}
fclose(keymap_file);
osd_printf_verbose("Keymap: Processed %d lines\n", line);
-
- return m_custom_table.get();
}
- std::unique_ptr<keyboard_trans_table> m_custom_table;
+ std::unique_ptr<keyboard_trans_table> m_key_trans_table;
std::list<std::string> m_ui_names;
};
+
//============================================================
// sdl_mouse_module
//============================================================
-class sdl_mouse_module : public sdl_input_module
+class sdl_mouse_module : public sdl_input_module<sdl_mouse_device>
{
public:
- sdl_mouse_module() : sdl_input_module(OSD_MOUSEINPUT_PROVIDER)
+ sdl_mouse_module() : sdl_input_module<sdl_mouse_device>(OSD_MOUSEINPUT_PROVIDER, "sdl")
{
}
@@ -950,22 +2084,15 @@ public:
int(SDL_MOUSEBUTTONUP),
int(SDL_MOUSEWHEEL) };
- sdl_event_manager::instance().subscribe(event_types, this);
+ subscribe(osd(), event_types);
osd_printf_verbose("Mouse: Start initialization\n");
// SDL currently only supports one mouse
- auto &devinfo = devicelist().create_device<sdl_mouse_device>(machine, "System mouse", "System mouse", *this);
-
- // add the axes
- devinfo.device()->add_item("X", ITEM_ID_XAXIS, generic_axis_get_state<std::int32_t>, &devinfo.mouse.lX);
- devinfo.device()->add_item("Y", ITEM_ID_YAXIS, generic_axis_get_state<std::int32_t>, &devinfo.mouse.lY);
-
- for (int button = 0; button < 4; button++)
- {
- input_item_id itemid = (input_item_id)(ITEM_ID_BUTTON1 + button);
- devinfo.device()->add_item(default_button_name(button), itemid, generic_button_get_state<std::int32_t>, &devinfo.mouse.buttons[button]);
- }
+ auto &devinfo = create_device<sdl_mouse_device>(
+ DEVICE_CLASS_MOUSE,
+ "System mouse",
+ "System mouse");
osd_printf_verbose("Mouse: Registered %s\n", devinfo.name());
osd_printf_verbose("Mouse: End initialization\n");
@@ -974,181 +2101,310 @@ public:
//============================================================
-// sdl_joystick_module
+// sdl_joystick_module_base
//============================================================
-class sdl_joystick_module : public sdl_input_module
+class sdl_joystick_module_base : public sdl_input_module<sdl_joystick_device_base>
{
-private:
- bool m_initialized_joystick;
- bool m_initialized_haptic;
- bool m_sixaxis_mode;
-public:
- sdl_joystick_module() :
- sdl_input_module(OSD_JOYSTICKINPUT_PROVIDER),
+protected:
+ sdl_joystick_module_base(char const *name) :
+ sdl_input_module<sdl_joystick_device_base>(OSD_JOYSTICKINPUT_PROVIDER, name),
m_initialized_joystick(false),
- m_initialized_haptic(false),
- m_sixaxis_mode(false)
+ m_initialized_haptic(false)
{
}
- virtual void exit() override
+ virtual ~sdl_joystick_module_base()
+ {
+ assert(!m_initialized_joystick);
+ assert(!m_initialized_haptic);
+ }
+
+ bool have_joystick() const { return m_initialized_joystick; }
+ bool have_haptic() const { return m_initialized_haptic; }
+
+ void init_joystick()
{
- sdl_input_module::exit();
+ assert(!m_initialized_joystick);
+ assert(!m_initialized_haptic);
+
+ m_initialized_joystick = !SDL_InitSubSystem(SDL_INIT_JOYSTICK);
+ if (!m_initialized_joystick)
+ {
+ osd_printf_error("Could not initialize SDL Joystick subsystem: %s.\n", SDL_GetError());
+ return;
+ }
+
+ m_initialized_haptic = !SDL_InitSubSystem(SDL_INIT_HAPTIC);
+ if (!m_initialized_haptic)
+ osd_printf_verbose("Could not initialize SDL Haptic subsystem: %s.\n", SDL_GetError());
+ }
+ void quit_joystick()
+ {
if (m_initialized_joystick)
{
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
+ m_initialized_joystick = false;
}
if (m_initialized_haptic)
{
SDL_QuitSubSystem(SDL_INIT_HAPTIC);
+ m_initialized_haptic = false;
}
}
- virtual void input_init(running_machine &machine) override
+ sdl_joystick_device *create_joystick_device(int index, bool sixaxis)
{
- SDL_SetHint(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, "0");
-
- m_initialized_joystick = !SDL_InitSubSystem(SDL_INIT_JOYSTICK);
- if (!m_initialized_joystick)
+ // open the joystick device
+ SDL_Joystick *const joy = SDL_JoystickOpen(index);
+ if (!joy)
{
- osd_printf_error("Could not initialize SDL Joystick: %s.\n", SDL_GetError());
- return;
+ osd_printf_error("Joystick: Could not open SDL joystick %d: %s.\n", index, SDL_GetError());
+ return nullptr;
}
- m_initialized_haptic = !SDL_InitSubSystem(SDL_INIT_HAPTIC);
- if (!m_initialized_haptic)
+ // get basic info
+ char const *const name = SDL_JoystickName(joy);
+ SDL_JoystickGUID guid = SDL_JoystickGetGUID(joy);
+ char guid_str[256];
+ guid_str[0] = '\0';
+ SDL_JoystickGetGUIDString(guid, guid_str, sizeof(guid_str) - 1);
+ char const *const serial = SDL_JoystickGetSerial(joy);
+ std::string id(guid_str);
+ if (serial)
+ id.append(1, '-').append(serial);
+
+ // print some diagnostic info
+ osd_printf_verbose("Joystick: %s [GUID %s] Vendor ID %04X, Product ID %04X, Revision %04X, Serial %s\n",
+ name ? name : "<nullptr>",
+ guid_str,
+ SDL_JoystickGetVendor(joy),
+ SDL_JoystickGetProduct(joy),
+ SDL_JoystickGetProductVersion(joy),
+ serial ? serial : "<nullptr>");
+ osd_printf_verbose("Joystick: ... %d axes, %d buttons %d hats %d balls\n",
+ SDL_JoystickNumAxes(joy),
+ SDL_JoystickNumButtons(joy),
+ SDL_JoystickNumHats(joy),
+ SDL_JoystickNumBalls(joy));
+ if (SDL_JoystickNumButtons(joy) > MAX_BUTTONS)
+ osd_printf_verbose("Joystick: ... Has %d buttons which exceeds supported %d buttons\n", SDL_JoystickNumButtons(joy), MAX_BUTTONS);
+
+ // instantiate device
+ sdl_joystick_device &devinfo = sixaxis
+ ? create_device<sdl_sixaxis_joystick_device>(DEVICE_CLASS_JOYSTICK, name ? name : guid_str, guid_str, joy, serial)
+ : create_device<sdl_joystick_device>(DEVICE_CLASS_JOYSTICK, name ? name : guid_str, guid_str, joy, serial);
+
+ if (devinfo.has_haptic())
+ osd_printf_verbose("Joystick: ... Has haptic capability\n");
+ else
+ osd_printf_verbose("Joystick: ... Does not have haptic capability\n");
+
+ return &devinfo;
+ }
+
+ void dispatch_joystick_event(SDL_Event const &event)
+ {
+ // figure out which joystick this event is destined for
+ sdl_joystick_device_base *const target_device = find_joystick(event.jdevice.which); // FIXME: this depends on SDL_JoystickID being the same size as Sint32
+
+ // if we find a matching joystick, dispatch the event to the joystick
+ if (target_device)
+ target_device->queue_events(&event, 1);
+ }
+
+ device_info *find_reconnect_match(SDL_JoystickGUID const &guid, char const *serial)
+ {
+ char guid_str[256];
+ guid_str[0] = '\0';
+ SDL_JoystickGetGUIDString(guid, guid_str, sizeof(guid_str) - 1);
+ auto target_device = std::find_if(
+ devicelist().begin(),
+ devicelist().end(),
+ [&guid_str, &serial] (auto const &device)
+ {
+ return device->reconnect_match(guid_str, serial);
+ });
+ return (devicelist().end() != target_device) ? target_device->get() : nullptr;
+ }
+
+ sdl_joystick_device_base *find_joystick(SDL_JoystickID instance)
+ {
+ for (auto &device : devicelist())
{
- osd_printf_verbose("Could not initialize SDL Haptic subsystem: %s.\n", SDL_GetError());
+ if (device->is_instance(instance))
+ return device.get();
}
+ return nullptr;
+ }
- sdl_input_module::input_init(machine);
+private:
+ bool m_initialized_joystick;
+ bool m_initialized_haptic;
+};
+
+
+//============================================================
+// sdl_joystick_module
+//============================================================
+
+class sdl_joystick_module : public sdl_joystick_module_base
+{
+public:
+ sdl_joystick_module() : sdl_joystick_module_base("sdljoy")
+ {
+ }
+
+ virtual void exit() override
+ {
+ sdl_joystick_module_base::exit();
- char tempname[512];
+ quit_joystick();
+ }
- m_sixaxis_mode = downcast<const sdl_options *>(options())->sixaxis();
+ virtual void input_init(running_machine &machine) override
+ {
+ auto &sdlopts = dynamic_cast<sdl_options const &>(*options());
+ bool const sixaxis_mode = sdlopts.sixaxis();
+
+ if (!sdlopts.debug() && sdlopts.background_input())
+ SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1");
+ SDL_SetHint(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, "0");
+
+ init_joystick();
+ if (!have_joystick())
+ return;
+
+ sdl_joystick_module_base::input_init(machine);
osd_printf_verbose("Joystick: Start initialization\n");
for (int physical_stick = 0; physical_stick < SDL_NumJoysticks(); physical_stick++)
+ create_joystick_device(physical_stick, sixaxis_mode);
+
+ static int const event_types[] = {
+ int(SDL_JOYAXISMOTION),
+ int(SDL_JOYBALLMOTION),
+ int(SDL_JOYHATMOTION),
+ int(SDL_JOYBUTTONDOWN),
+ int(SDL_JOYBUTTONUP),
+ int(SDL_JOYDEVICEADDED),
+ int(SDL_JOYDEVICEREMOVED) };
+ subscribe(osd(), event_types);
+
+ osd_printf_verbose("Joystick: End initialization\n");
+ }
+
+ virtual void handle_event(SDL_Event const &event) override
+ {
+ if (SDL_JOYDEVICEADDED == event.type)
{
- SDL_Joystick *const joy = SDL_JoystickOpen(physical_stick);
- char const *const name = SDL_JoystickName(joy);
- SDL_JoystickGUID guid = SDL_JoystickGetGUID(joy);
- char guid_str[256];
- guid_str[0] = '\0';
- SDL_JoystickGetGUIDString(guid, guid_str, sizeof(guid_str) - 1);
-
- sdl_joystick_device *const devinfo = m_sixaxis_mode
- ? &devicelist().create_device<sdl_sixaxis_joystick_device>(machine, name ? name : guid_str, guid_str, *this)
- : &devicelist().create_device<sdl_joystick_device>(machine, name ? name : guid_str, guid_str, *this);
-
- if (!devinfo)
+ SDL_Joystick *const joy = SDL_JoystickOpen(event.jdevice.which);
+ if (!joy)
{
- SDL_JoystickClose(joy);
- continue;
+ osd_printf_error("Joystick: Could not open SDL joystick %d: %s.\n", event.jdevice.which, SDL_GetError());
}
-
- devinfo->sdl_state.device = joy;
- devinfo->sdl_state.joystick_id = SDL_JoystickInstanceID(joy);
- devinfo->sdl_state.hapdevice = SDL_HapticOpenFromJoystick(joy);
-#if SDL_VERSION_ATLEAST(2, 0, 14)
- char const *const serial = SDL_JoystickGetSerial(joy);
- if (serial)
- devinfo->sdl_state.serial = serial;
else
-#endif // SDL_VERSION_ATLEAST(2, 0, 14)
- devinfo->sdl_state.serial = std::nullopt;
-
- osd_printf_verbose("Joystick: %s [GUID %s] Vendor ID %04X, Product ID %04X, Revision %04X\n",
- name ? name : "<nullptr>",
- guid_str,
- SDL_JoystickGetVendor(joy),
- SDL_JoystickGetProduct(joy),
- SDL_JoystickGetProductVersion(joy));
- osd_printf_verbose("Joystick: ... %d axes, %d buttons %d hats %d balls\n",
- SDL_JoystickNumAxes(joy),
- SDL_JoystickNumButtons(joy),
- SDL_JoystickNumHats(joy),
- SDL_JoystickNumBalls(joy));
- if (devinfo->sdl_state.hapdevice)
- osd_printf_verbose("Joystick: ... Has haptic capability\n");
- else
- osd_printf_verbose("Joystick: ... Does not have haptic capability\n");
-
- // loop over all axes
- for (int axis = 0; axis < SDL_JoystickNumAxes(joy); axis++)
{
- input_item_id itemid;
-
- if (axis < INPUT_MAX_AXIS)
- itemid = (input_item_id)(ITEM_ID_XAXIS + axis);
- else if (axis < INPUT_MAX_AXIS + INPUT_MAX_ADD_ABSOLUTE)
- itemid = (input_item_id)(ITEM_ID_ADD_ABSOLUTE1 - INPUT_MAX_AXIS + axis);
+ SDL_JoystickGUID guid = SDL_JoystickGetGUID(joy);
+ char const *const serial = SDL_JoystickGetSerial(joy);
+ auto *const target_device = find_reconnect_match(guid, serial);
+ if (target_device)
+ {
+ auto &devinfo = dynamic_cast<sdl_joystick_device &>(*target_device);
+ devinfo.attach_device(joy);
+ }
else
- itemid = ITEM_ID_OTHER_AXIS_ABSOLUTE;
-
- snprintf(tempname, sizeof(tempname), "A%d", axis + 1);
- devinfo->device()->add_item(tempname, itemid, generic_axis_get_state<std::int32_t>, &devinfo->joystick.axes[axis]);
+ {
+ SDL_JoystickClose(joy);
+ }
}
+ }
+ else
+ {
+ dispatch_joystick_event(event);
+ }
+ }
+};
- // loop over all buttons
- if (SDL_JoystickNumButtons(joy) > MAX_BUTTONS)
- osd_printf_verbose("Joystick: ... Has %d buttons which exceeds supported %d buttons\n", SDL_JoystickNumButtons(joy), MAX_BUTTONS);
- for (int button = 0; (button < MAX_BUTTONS) && (button < SDL_JoystickNumButtons(joy)); button++)
- {
- input_item_id itemid;
- devinfo->joystick.buttons[button] = 0;
+//============================================================
+// sdl_game_controller_module
+//============================================================
- if (button < INPUT_MAX_BUTTONS)
- itemid = (input_item_id)(ITEM_ID_BUTTON1 + button);
- else if (button < INPUT_MAX_BUTTONS + INPUT_MAX_ADD_SWITCH)
- itemid = (input_item_id)(ITEM_ID_ADD_SWITCH1 - INPUT_MAX_BUTTONS + button);
- else
- itemid = ITEM_ID_OTHER_SWITCH;
+class sdl_game_controller_module : public sdl_joystick_module_base
+{
+public:
+ sdl_game_controller_module() :
+ sdl_joystick_module_base("sdlgame"),
+ m_initialized_game_controller(false)
+ {
+ }
- devinfo->device()->add_item(default_button_name(button), itemid, generic_button_get_state<std::int32_t>, &devinfo->joystick.buttons[button]);
- }
+ virtual void exit() override
+ {
+ sdl_joystick_module_base::exit();
- // loop over all hats
- for (int hat = 0; hat < SDL_JoystickNumHats(joy); hat++)
- {
- input_item_id itemid;
-
- snprintf(tempname, sizeof(tempname), "Hat %d Up", hat + 1);
- itemid = (input_item_id)((hat < INPUT_MAX_HATS) ? ITEM_ID_HAT1UP + 4 * hat : ITEM_ID_OTHER_SWITCH);
- devinfo->device()->add_item(tempname, itemid, generic_button_get_state<std::int32_t>, &devinfo->joystick.hatsU[hat]);
- snprintf(tempname, sizeof(tempname), "Hat %d Down", hat + 1);
- itemid = (input_item_id)((hat < INPUT_MAX_HATS) ? ITEM_ID_HAT1DOWN + 4 * hat : ITEM_ID_OTHER_SWITCH);
- devinfo->device()->add_item(tempname, itemid, generic_button_get_state<std::int32_t>, &devinfo->joystick.hatsD[hat]);
- snprintf(tempname, sizeof(tempname), "Hat %d Left", hat + 1);
- itemid = (input_item_id)((hat < INPUT_MAX_HATS) ? ITEM_ID_HAT1LEFT + 4 * hat : ITEM_ID_OTHER_SWITCH);
- devinfo->device()->add_item(tempname, itemid, generic_button_get_state<std::int32_t>, &devinfo->joystick.hatsL[hat]);
- snprintf(tempname, sizeof(tempname), "Hat %d Right", hat + 1);
- itemid = (input_item_id)((hat < INPUT_MAX_HATS) ? ITEM_ID_HAT1RIGHT + 4 * hat : ITEM_ID_OTHER_SWITCH);
- devinfo->device()->add_item(tempname, itemid, generic_button_get_state<std::int32_t>, &devinfo->joystick.hatsR[hat]);
- }
+ if (m_initialized_game_controller)
+ SDL_QuitSubSystem(SDL_INIT_GAMECONTROLLER);
- // loop over all (track)balls
- for (int ball = 0; ball < SDL_JoystickNumBalls(joy); ball++)
- {
- int itemid;
+ quit_joystick();
+ }
- if (ball * 2 < INPUT_MAX_ADD_RELATIVE)
- itemid = ITEM_ID_ADD_RELATIVE1 + ball * 2;
+ virtual void input_init(running_machine &machine) override
+ {
+ auto &sdlopts = dynamic_cast<sdl_options const &>(*options());
+ bool const sixaxis_mode = sdlopts.sixaxis();
+
+ if (!sdlopts.debug() && sdlopts.background_input())
+ SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1");
+ SDL_SetHint(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, "0");
+
+ init_joystick();
+ if (!have_joystick())
+ return;
+
+ m_initialized_game_controller = !SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER);
+ if (m_initialized_game_controller)
+ {
+ char const *const mapfile = sdlopts.controller_mapping_file();
+ if (mapfile && *mapfile && std::strcmp(mapfile, OSDOPTVAL_NONE))
+ {
+ auto const count = SDL_GameControllerAddMappingsFromFile(mapfile);
+ if (0 <= count)
+ osd_printf_verbose("Game Controller: %d controller mapping(s) added from file [%s].\n", count, mapfile);
else
- itemid = ITEM_ID_OTHER_AXIS_RELATIVE;
+ osd_printf_error("Game Controller: Error adding mappings from file [%s]: %s.\n", mapfile, SDL_GetError());
+ }
+ }
+ else
+ {
+ osd_printf_warning("Could not initialize SDL Game Controller: %s.\n", SDL_GetError());
+ }
+
+ sdl_joystick_module_base::input_init(machine);
- snprintf(tempname, sizeof(tempname), "R%d X", ball + 1);
- devinfo->device()->add_item(tempname, (input_item_id)itemid, generic_axis_get_state<std::int32_t>, &devinfo->joystick.balls[ball * 2]);
- snprintf(tempname, sizeof(tempname), "R%d Y", ball + 1);
- devinfo->device()->add_item(tempname, (input_item_id)(itemid + 1), generic_axis_get_state<std::int32_t>, &devinfo->joystick.balls[ball * 2 + 1]);
+ osd_printf_verbose("Game Controller: Start initialization\n");
+ for (int physical_stick = 0; physical_stick < SDL_NumJoysticks(); physical_stick++)
+ {
+ // try to open as a game controller
+ SDL_GameController *ctrl = nullptr;
+ if (m_initialized_game_controller && SDL_IsGameController(physical_stick))
+ {
+ ctrl = SDL_GameControllerOpen(physical_stick);
+ if (!ctrl)
+ osd_printf_warning("Game Controller: Could not open SDL game controller %d: %s.\n", physical_stick, SDL_GetError());
}
+
+ // fall back to joystick API if necessary
+ if (!ctrl)
+ create_joystick_device(physical_stick, sixaxis_mode);
+ else
+ create_game_controller_device(physical_stick, ctrl);
}
- static int const event_types[] = {
+ static int const joy_event_types[] = {
int(SDL_JOYAXISMOTION),
int(SDL_JOYBALLMOTION),
int(SDL_JOYHATMOTION),
@@ -1156,88 +2412,175 @@ public:
int(SDL_JOYBUTTONUP),
int(SDL_JOYDEVICEADDED),
int(SDL_JOYDEVICEREMOVED) };
+ static int const event_types[] = {
+ int(SDL_JOYAXISMOTION),
+ int(SDL_JOYBALLMOTION),
+ int(SDL_JOYHATMOTION),
+ int(SDL_JOYBUTTONDOWN),
+ int(SDL_JOYBUTTONUP),
+ int(SDL_JOYDEVICEADDED),
+ int(SDL_JOYDEVICEREMOVED),
+ int(SDL_CONTROLLERAXISMOTION),
+ int(SDL_CONTROLLERBUTTONDOWN),
+ int(SDL_CONTROLLERBUTTONUP),
+ int(SDL_CONTROLLERDEVICEADDED),
+ int(SDL_CONTROLLERDEVICEREMOVED) };
+ if (m_initialized_game_controller)
+ subscribe(osd(), event_types);
+ else
+ subscribe(osd(), joy_event_types);
- sdl_event_manager::instance().subscribe(event_types, this);
-
- osd_printf_verbose("Joystick: End initialization\n");
+ osd_printf_verbose("Game Controller: End initialization\n");
}
- virtual void handle_event(SDL_Event &sdlevent) override
+ virtual void handle_event(SDL_Event const &event) override
{
- if (SDL_JOYDEVICEADDED == sdlevent.type)
+ switch (event.type)
{
- SDL_Joystick *const joy = SDL_JoystickOpen(sdlevent.jdevice.which);
- if (joy)
+ case SDL_JOYDEVICEADDED:
{
+ // make sure this isn't an event for a reconnected game controller
+ auto const controller = find_joystick(SDL_JoystickGetDeviceInstanceID(event.jdevice.which));
+ if (find_joystick(SDL_JoystickGetDeviceInstanceID(event.jdevice.which)))
+ {
+ osd_printf_verbose(
+ "Game Controller: Got SDL joystick added event for reconnected game controller %s [ID %s]\n",
+ controller->name(),
+ controller->id());
+ break;
+ }
+
+ SDL_Joystick *const joy = SDL_JoystickOpen(event.jdevice.which);
+ if (!joy)
+ {
+ osd_printf_error("Joystick: Could not open SDL joystick %d: %s.\n", event.jdevice.which, SDL_GetError());
+ break;
+ }
+
SDL_JoystickGUID guid = SDL_JoystickGetGUID(joy);
- char guid_str[256];
- guid_str[0] = '\0';
- SDL_JoystickGetGUIDString(guid, guid_str, sizeof(guid_str) - 1);
- char const *serial = nullptr;
-#if SDL_VERSION_ATLEAST(2, 0, 14)
- serial = SDL_JoystickGetSerial(joy);
-#endif
- auto target_device = std::find_if(
- devicelist().begin(),
- devicelist().end(),
- [&guid_str, &serial] (auto const &device)
- {
- auto &devinfo = downcast<sdl_joystick_device &>(*device);
- return
- !devinfo.sdl_state.device &&
- (devinfo.id() == guid_str) &&
- ((serial && devinfo.sdl_state.serial && (*devinfo.sdl_state.serial == serial)) || (!serial && !devinfo.sdl_state.serial));
- });
- if (devicelist().end() != target_device)
+ char const *const serial = SDL_JoystickGetSerial(joy);
+ auto *const target_device = find_reconnect_match(guid, serial);
+ if (target_device)
{
- auto &devinfo = downcast<sdl_joystick_device &>(**target_device);
- devinfo.sdl_state.device = joy;
- devinfo.sdl_state.joystick_id = SDL_JoystickInstanceID(joy);
- devinfo.sdl_state.hapdevice = SDL_HapticOpenFromJoystick(joy);
- osd_printf_verbose("Joystick: %s [GUID %s] reconnected\n", devinfo.name(), guid_str);
+ // if this downcast fails, opening as a game controller worked initially but failed on reconnection
+ auto *const devinfo = dynamic_cast<sdl_joystick_device *>(target_device);
+ if (devinfo)
+ devinfo->attach_device(joy);
+ else
+ SDL_JoystickClose(joy);
}
else
{
SDL_JoystickClose(joy);
}
}
- }
- else
- {
- // Figure out which joystick this event id destined for
- sdl_joystick_device *const target_device = find_joystick(sdlevent.jdevice.which); // FIXME: this depends on SDL_JoystickID being the same size as Sint32
+ break;
+
+ // for devices supported by the game controller API, this is received before the corresponding SDL_JOYDEVICEADDED
+ case SDL_CONTROLLERDEVICEADDED:
+ if (m_initialized_game_controller)
+ {
+ SDL_GameController *const ctrl = SDL_GameControllerOpen(event.cdevice.which);
+ if (!ctrl)
+ {
+ osd_printf_error("Game Controller: Could not open SDL game controller %d: %s.\n", event.cdevice.which, SDL_GetError());
+ break;
+ }
+
+ SDL_JoystickGUID guid = SDL_JoystickGetDeviceGUID(event.cdevice.which);
+ char const *const serial = SDL_GameControllerGetSerial(ctrl);
+ auto *const target_device = find_reconnect_match(guid, serial);
+ if (target_device)
+ {
+ // downcast can fail if there was an error opening the device as a game controller the first time
+ auto *const devinfo = dynamic_cast<sdl_game_controller_device *>(target_device);
+ if (devinfo)
+ devinfo->attach_device(ctrl);
+ else
+ SDL_GameControllerClose(ctrl);
+ }
+ else
+ {
+ SDL_GameControllerClose(ctrl);
+ }
+ }
+ break;
- // If we find a matching joystick, dispatch the event to the joystick
- if (target_device)
- target_device->queue_events(&sdlevent, 1);
+ default:
+ dispatch_joystick_event(event);
}
}
private:
- sdl_joystick_device *find_joystick(SDL_JoystickID instance)
+ sdl_game_controller_device *create_game_controller_device(int index, SDL_GameController *ctrl)
{
- for (auto &ptr : devicelist())
+ // get basic info
+ char const *const name = SDL_GameControllerName(ctrl);
+ SDL_JoystickGUID guid = SDL_JoystickGetDeviceGUID(index);
+ char guid_str[256];
+ guid_str[0] = '\0';
+ SDL_JoystickGetGUIDString(guid, guid_str, sizeof(guid_str) - 1);
+ char const *const serial = SDL_GameControllerGetSerial(ctrl);
+ std::string id(guid_str);
+ if (serial)
+ id.append(1, '-').append(serial);
+
+ // print some diagnostic info
+ osd_printf_verbose("Game Controller: %s [GUID %s] Vendor ID %04X, Product ID %04X, Revision %04X, Serial %s\n",
+ name ? name : "<nullptr>",
+ guid_str,
+ SDL_GameControllerGetVendor(ctrl),
+ SDL_GameControllerGetProduct(ctrl),
+ SDL_GameControllerGetProductVersion(ctrl),
+ serial ? serial : "<nullptr>");
+ char *const mapping = SDL_GameControllerMapping(ctrl);
+ if (mapping)
{
- sdl_joystick_device *const device = downcast<sdl_joystick_device *>(ptr.get());
- if (device->sdl_state.device && (device->sdl_state.joystick_id == instance))
- return device;
+ osd_printf_verbose("Game Controller: ... mapping [%s]\n", mapping);
+ SDL_free(mapping);
}
- return nullptr;
+ else
+ {
+ osd_printf_verbose("Game Controller: ... no mapping\n");
+ }
+
+ // instantiate device
+ sdl_game_controller_device &devinfo = create_device<sdl_game_controller_device>(
+ DEVICE_CLASS_JOYSTICK,
+ name ? name : guid_str,
+ guid_str,
+ ctrl,
+ serial);
+ return &devinfo;
}
+
+ bool m_initialized_game_controller;
};
} // anonymous namespace
+} // namespace osd
+
+
#else // defined(SDLMAME_SDL2)
-#include "input_module.h"
+namespace osd {
+
+namespace {
MODULE_NOT_SUPPORTED(sdl_keyboard_module, OSD_KEYBOARDINPUT_PROVIDER, "sdl")
MODULE_NOT_SUPPORTED(sdl_mouse_module, OSD_MOUSEINPUT_PROVIDER, "sdl")
-MODULE_NOT_SUPPORTED(sdl_joystick_module, OSD_JOYSTICKINPUT_PROVIDER, "sdl")
+MODULE_NOT_SUPPORTED(sdl_joystick_module, OSD_JOYSTICKINPUT_PROVIDER, "sdljoy")
+MODULE_NOT_SUPPORTED(sdl_game_controller_module, OSD_JOYSTICKINPUT_PROVIDER, "sdlgame")
+
+} // anonymous namespace
+
+} // namespace osd
#endif // defined(SDLMAME_SDL2)
-MODULE_DEFINITION(KEYBOARDINPUT_SDL, sdl_keyboard_module)
-MODULE_DEFINITION(MOUSEINPUT_SDL, sdl_mouse_module)
-MODULE_DEFINITION(JOYSTICKINPUT_SDL, sdl_joystick_module)
+
+MODULE_DEFINITION(KEYBOARDINPUT_SDL, osd::sdl_keyboard_module)
+MODULE_DEFINITION(MOUSEINPUT_SDL, osd::sdl_mouse_module)
+MODULE_DEFINITION(JOYSTICKINPUT_SDLJOY, osd::sdl_joystick_module)
+MODULE_DEFINITION(JOYSTICKINPUT_SDLGAME, osd::sdl_game_controller_module)
diff --git a/src/osd/modules/input/input_sdlcommon.cpp b/src/osd/modules/input/input_sdlcommon.cpp
deleted file mode 100644
index 659add8dc79..00000000000
--- a/src/osd/modules/input/input_sdlcommon.cpp
+++ /dev/null
@@ -1,337 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Olivier Galibert, R. Belmont, Brad Hughes
-//============================================================
-//
-// input_sdlcommon.cpp - SDL Common code shared by SDL modules
-//
-// Note: this code is also used by the X11 input modules
-//
-//============================================================
-
-#include "input_module.h"
-#include "modules/osdmodule.h"
-
-#if defined(OSD_SDL)
-
-#include "input_sdlcommon.h"
-
-#include <cctype>
-#include <cstddef>
-#include <memory>
-#include <algorithm>
-
-// MAME headers
-#include "emu.h"
-
-#include "ui/uimain.h"
-#include "uiinput.h"
-
-#include "window.h"
-
-#include "util/language.h"
-
-#include "osdepend.h"
-#include "strconv.h"
-
-#include "../../sdl/osdsdl.h"
-#include "input_common.h"
-
-
-#define GET_WINDOW(ev) window_from_id((ev)->windowID)
-//#define GET_WINDOW(ev) ((ev)->windowID)
-
-
-static std::shared_ptr<sdl_window_info> window_from_id(Uint32 windowID)
-{
- SDL_Window *sdl_window = SDL_GetWindowFromID(windowID);
-
- auto& windows = osd_common_t::s_window_list;
- auto window = std::find_if(windows.begin(), windows.end(), [sdl_window](std::shared_ptr<osd_window> w)
- {
- return std::static_pointer_cast<sdl_window_info>(w)->platform_window() == sdl_window;
- });
-
- if (window == windows.end())
- return nullptr;
-
- return std::static_pointer_cast<sdl_window_info>(*window);
-}
-
-void sdl_event_manager::process_events(running_machine &machine)
-{
- std::lock_guard<std::mutex> scope_lock(m_lock);
- SDL_Event sdlevent;
- while (SDL_PollEvent(&sdlevent))
- {
- // process window events if they come in
- if (sdlevent.type == SDL_WINDOWEVENT)
- process_window_event(machine, sdlevent);
-
- // Find all subscribers for the event type
- auto subscribers = m_subscription_index.equal_range(sdlevent.type);
-
- // Dispatch the events
- std::for_each(subscribers.first, subscribers.second, [&sdlevent](auto sub)
- {
- sub.second->handle_event(sdlevent);
- });
- }
-}
-
-void sdl_event_manager::process_window_event(running_machine &machine, SDL_Event &sdlevent)
-{
- std::shared_ptr<sdl_window_info> window = GET_WINDOW(&sdlevent.window);
-
- if (window == nullptr)
- {
- // This condition may occur when the fullscreen toggle is used
- osd_printf_verbose("Skipped window event due to missing window param from SDL\n");
- return;
- }
-
- switch (sdlevent.window.event)
- {
- case SDL_WINDOWEVENT_MOVED:
- window->notify_changed();
- m_focus_window = window;
- break;
-
- case SDL_WINDOWEVENT_RESIZED:
-#ifdef SDLMAME_LINUX
- /* FIXME: SDL2 sends some spurious resize events on Ubuntu
- * while in fullscreen mode. Ignore them for now.
- */
- if (!window->fullscreen())
-#endif
- {
- //printf("event data1,data2 %d x %d %ld\n", event.window.data1, event.window.data2, sizeof(SDL_Event));
- window->resize(sdlevent.window.data1, sdlevent.window.data2);
- }
- break;
-
- case SDL_WINDOWEVENT_ENTER:
- m_mouse_over_window = 1;
- break;
-
- case SDL_WINDOWEVENT_LEAVE:
- machine.ui_input().push_mouse_leave_event(window->target());
- m_mouse_over_window = 0;
- break;
-
- case SDL_WINDOWEVENT_FOCUS_GAINED:
- m_focus_window = window;
- machine.ui_input().push_window_focus_event(window->target());
- break;
-
- case SDL_WINDOWEVENT_FOCUS_LOST:
- machine.ui_input().push_window_defocus_event(window->target());
- break;
-
- case SDL_WINDOWEVENT_CLOSE:
- machine.schedule_exit();
- break;
- }
-}
-
-//============================================================
-// customize_input_type_list
-//============================================================
-
-void sdl_osd_interface::customize_input_type_list(std::vector<input_type_entry> &typelist)
-{
- input_item_id mameid_code;
- input_code ui_code;
- const char* uimode;
- char fullmode[64];
-
- // loop over the defaults
- for (input_type_entry &entry : typelist)
- {
- switch (entry.type())
- {
- // configurable UI mode switch
- case IPT_UI_TOGGLE_UI:
- uimode = options().ui_mode_key();
- if (!strcmp(uimode, "auto"))
- {
-#if defined(__APPLE__) && defined(__MACH__)
- mameid_code = keyboard_trans_table::instance().lookup_mame_code("ITEM_ID_INSERT");
-#else
- mameid_code = keyboard_trans_table::instance().lookup_mame_code("ITEM_ID_SCRLOCK");
-#endif
- }
- else
- {
- snprintf(fullmode, 63, "ITEM_ID_%s", uimode);
- mameid_code = keyboard_trans_table::instance().lookup_mame_code(fullmode);
- }
- ui_code = input_code(DEVICE_CLASS_KEYBOARD, 0, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, input_item_id(mameid_code));
- entry.defseq(SEQ_TYPE_STANDARD).set(ui_code);
- break;
- // alt-enter for fullscreen
- case IPT_OSD_1:
- entry.configure_osd("TOGGLE_FULLSCREEN", N_p("input-name", "Toggle Fullscreen"));
- entry.defseq(SEQ_TYPE_STANDARD).set(KEYCODE_ENTER, KEYCODE_LALT);
- break;
-
- // page down for fastforward (must be OSD_3 as per src/emu/ui.c)
- case IPT_UI_FAST_FORWARD:
- entry.defseq(SEQ_TYPE_STANDARD).set(KEYCODE_PGDN);
- break;
-
- // OSD hotkeys use LCTRL and start at F3, they start at
- // F3 because F1-F2 are hardcoded into many drivers to
- // various dipswitches, and pressing them together with
- // LCTRL will still press/toggle these dipswitches.
-
- // add a Not lcrtl condition to the reset key
- case IPT_UI_SOFT_RESET:
- entry.defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F3, input_seq::not_code, KEYCODE_LCONTROL, input_seq::not_code, KEYCODE_LSHIFT);
- break;
-
- // add a Not lcrtl condition to the show gfx key
- case IPT_UI_SHOW_GFX:
- entry.defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F4, input_seq::not_code, KEYCODE_LCONTROL);
- break;
-
- // LCTRL-F5 to toggle OpenGL filtering
- case IPT_OSD_5:
- entry.configure_osd("TOGGLE_FILTER", N_p("input-name", "Toggle Filter"));
- entry.defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F5, KEYCODE_LCONTROL);
- break;
-
- // LCTRL-F6 to decrease OpenGL prescaling
- case IPT_OSD_6:
- entry.configure_osd("DECREASE_PRESCALE", N_p("input-name", "Decrease Prescaling"));
- entry.defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F6, KEYCODE_LCONTROL);
- break;
- // add a Not lcrtl condition to the toggle cheat key
- case IPT_UI_TOGGLE_CHEAT:
- entry.defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F6, input_seq::not_code, KEYCODE_LCONTROL);
- break;
-
- // LCTRL-F7 to increase OpenGL prescaling
- case IPT_OSD_7:
- entry.configure_osd("INCREASE_PRESCALE", N_p("input-name", "Increase Prescaling"));
- entry.defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F7, KEYCODE_LCONTROL);
- break;
-
- // lshift-lalt-F12 for fullscreen video (BGFX)
- case IPT_OSD_8:
- entry.configure_osd("RENDER_AVI", N_p("input-name", "Record Rendered Video"));
- entry.defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F12, KEYCODE_LSHIFT, KEYCODE_LALT);
- break;
-
- // add a Not lcrtl condition to the load state key
- case IPT_UI_LOAD_STATE:
- entry.defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F7, input_seq::not_code, KEYCODE_LCONTROL, input_seq::not_code, KEYCODE_LSHIFT);
- break;
-
- // add a Not lcrtl condition to the throttle key
- case IPT_UI_THROTTLE:
- entry.defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F10, input_seq::not_code, KEYCODE_LCONTROL);
- break;
-
- // disable the config menu if the ALT key is down
- // (allows ALT-TAB to switch between apps)
- case IPT_UI_CONFIGURE:
- entry.defseq(SEQ_TYPE_STANDARD).set(KEYCODE_TAB, input_seq::not_code, KEYCODE_LALT, input_seq::not_code, KEYCODE_RALT);
- break;
-
-#if defined(__APPLE__) && defined(__MACH__)
- // 78-key Apple MacBook & Bluetooth keyboards have no right control key
- case IPT_MAHJONG_SCORE:
- if (entry.player() == 0)
- entry.defseq(SEQ_TYPE_STANDARD).set(KEYCODE_SLASH);
- break;
-#endif
-
- // leave everything else alone
- default:
- break;
- }
- }
-}
-
-void sdl_osd_interface::poll_inputs(running_machine &machine)
-{
- m_keyboard_input->poll_if_necessary(machine);
- m_mouse_input->poll_if_necessary(machine);
- m_lightgun_input->poll_if_necessary(machine);
- m_joystick_input->poll_if_necessary(machine);
-}
-
-void sdl_osd_interface::release_keys()
-{
- auto keybd = dynamic_cast<input_module_base*>(m_keyboard_input);
- if (keybd != nullptr)
- keybd->devicelist().reset_devices();
-}
-
-bool sdl_osd_interface::should_hide_mouse()
-{
- // if we are paused, no
- if (machine().paused())
- return false;
-
- // if neither mice nor lightguns enabled in the core, then no
- if (!options().mouse() && !options().lightgun())
- return false;
-
- if (!sdl_event_manager::instance().mouse_over_window())
- return false;
-
- // otherwise, yes
- return true;
-}
-
-void sdl_osd_interface::process_events_buf()
-{
- SDL_PumpEvents();
-}
-
-//============================================================
-// devmap_init - initializes a device_map based on
-// an input option prefix and max number of devices
-//============================================================
-
-void device_map_t::init(running_machine &machine, const char *opt, int max_devices, const char *label)
-{
- int dev;
- char defname[20];
-
- // The max devices the user specified, better not be bigger than the max the arrays can old
- assert(max_devices <= MAX_DEVMAP_ENTRIES);
-
- // Initialize the map to default uninitialized values
- for (dev = 0; dev < MAX_DEVMAP_ENTRIES; dev++)
- {
- map[dev].name.clear();
- map[dev].physical = -1;
- logical[dev] = -1;
- }
- initialized = 0;
-
- // populate the device map up to the max number of devices
- for (dev = 0; dev < max_devices; dev++)
- {
- const char *dev_name;
-
- // derive the parameter name from the option name and index. For instance: lightgun_index1 to lightgun_index8
- sprintf(defname, "%s%d", opt, dev + 1);
-
- // Get the user-specified name that matches the parameter
- dev_name = machine.options().value(defname);
-
- // If they've specified a name and it's not "auto", treat it as a custom mapping
- if (dev_name && *dev_name && strcmp(dev_name, OSDOPTVAL_AUTO))
- {
- // remove the spaces from the name store it in the index
- map[dev].name = remove_spaces(dev_name);
- osd_printf_verbose("%s: Logical id %d: %s\n", label, dev + 1, map[dev].name);
- initialized = 1;
- }
- }
-}
-
-#endif
diff --git a/src/osd/modules/input/input_sdlcommon.h b/src/osd/modules/input/input_sdlcommon.h
deleted file mode 100644
index ca71b508f24..00000000000
--- a/src/osd/modules/input/input_sdlcommon.h
+++ /dev/null
@@ -1,142 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Olivier Galibert, R. Belmont, Brad Hughes
-//============================================================
-//
-// input_sdlcommon.h - SDL Common code shared by SDL modules
-//
-// Note: this code is also used by the X11 input modules
-//
-//============================================================
-
-#ifndef MAME_OSD_INPUT_INPUT_SDLCOMMON_H
-#define MAME_OSD_INPUT_INPUT_SDLCOMMON_H
-
-#pragma once
-
-// standard sdl header
-#include <SDL2/SDL.h>
-
-#include <algorithm>
-#include <memory>
-#include <mutex>
-#include <string>
-#include <unordered_map>
-
-#define MAX_DEVMAP_ENTRIES 16
-#define SDL_MODULE_EVENT_BUFFER_SIZE 5
-
-
-struct device_map_t
-{
- struct {
- std::string name;
- int physical;
- } map[MAX_DEVMAP_ENTRIES];
- int logical[MAX_DEVMAP_ENTRIES];
- int initialized;
-
- void init(running_machine &machine, const char *opt, int max_devices, const char *label);
-};
-
-//============================================================
-// event_manager_t
-//============================================================
-
-class sdl_event_subscriber
-{
-public:
- virtual ~sdl_event_subscriber() {}
- virtual void handle_event(SDL_Event &sdlevent) = 0;
-};
-
-template <class TSubscriber>
-class event_manager_t
-{
-protected:
- std::mutex m_lock;
- std::unordered_multimap<int, TSubscriber*> m_subscription_index;
- event_manager_t()
- {
- }
-
-public:
- virtual ~event_manager_t()
- {
- }
-
- template <size_t N>
- void subscribe(int const (&event_types)[N], TSubscriber *subscriber)
- {
- std::lock_guard<std::mutex> scope_lock(m_lock);
-
- // Add the subscription
- for (int i : event_types)
- m_subscription_index.emplace(i, subscriber);
- }
-
- void unsubscribe(TSubscriber *subscriber)
- {
- std::lock_guard<std::mutex> scope_lock(m_lock);
-
- // Remove the events that match the subscriber
- for (auto it = begin(m_subscription_index); it != end(m_subscription_index);)
- {
- if (it->second == subscriber)
- {
- it = m_subscription_index.erase(it);
- }
- else
- {
- ++it;
- }
- }
- }
-
- virtual void process_events(running_machine &machine) = 0;
-};
-
-class sdl_window_info;
-
-class sdl_event_manager : public event_manager_t<sdl_event_subscriber>
-{
-private:
- bool m_mouse_over_window;
- std::shared_ptr<sdl_window_info> m_focus_window;
-
- sdl_event_manager()
- : m_mouse_over_window(true),
- m_focus_window(nullptr)
- {
- }
-
-public:
- bool mouse_over_window() const { return m_mouse_over_window; }
- bool has_focus() const { return m_focus_window != nullptr; }
- std::shared_ptr<sdl_window_info> focus_window() const { return m_focus_window; }
-
- static sdl_event_manager& instance()
- {
- static sdl_event_manager s_instance;
- return s_instance;
- }
-
- void process_events(running_machine &machine) override;
-
-private:
- void process_window_event(running_machine &machine, SDL_Event &sdlevent);
-};
-
-//============================================================
-// INLINE FUNCTIONS
-//============================================================
-
-static inline std::string remove_spaces(const char *s)
-{
- // Remove the spaces
- auto output = std::string(s);
- output.erase(std::remove_if(output.begin(), output.end(), isspace), output.end());
-
- return output;
-}
-
-#endif // MAME_OSD_INPUT_INPUT_SDLCOMMON_H
diff --git a/src/osd/modules/input/input_win32.cpp b/src/osd/modules/input/input_win32.cpp
index 459e624fcfa..3803bc2a180 100644
--- a/src/osd/modules/input/input_win32.cpp
+++ b/src/osd/modules/input/input_win32.cpp
@@ -10,16 +10,24 @@
#if defined(OSD_WINDOWS)
-#include "emu.h"
-
#include "input_windows.h"
+#include "input_wincommon.h"
+
+// osd/windows
+#include "window.h"
+
+// emu
+#include "inpttype.h"
+
#include "strconv.h"
// standard windows headers
#include <tchar.h>
+namespace osd {
+
namespace {
//============================================================
@@ -30,115 +38,113 @@ namespace {
class win32_keyboard_device : public event_based_device<KeyPressEventArgs>
{
public:
- keyboard_state keyboard;
+ win32_keyboard_device(std::string &&name, std::string &&id, input_module &module) :
+ event_based_device(std::move(name), std::move(id), module),
+ m_keyboard({{0}})
+ {
+ }
- win32_keyboard_device(running_machine& machine, std::string &&name, std::string &&id, input_module &module)
- : event_based_device(machine, std::move(name), std::move(id), DEVICE_CLASS_KEYBOARD, module),
- keyboard({{0}})
+ virtual void reset() override
{
+ memset(&m_keyboard, 0, sizeof(m_keyboard));
}
- void reset() override
+ virtual void configure(input_device &device) override
{
- memset(&keyboard, 0, sizeof(keyboard));
+ keyboard_trans_table const &table = keyboard_trans_table::instance();
+
+ for (int keynum = 0; keynum < MAX_KEYS; keynum++)
+ {
+ input_item_id itemid = table.map_di_scancode_to_itemid(keynum);
+ TCHAR keyname[100];
+
+ // generate the name
+ // FIXME: GetKeyNameText gives bogus names for media keys and various other things
+ // in many cases it ignores the "extended" bit and returns the key name corresponding to the scan code alone
+ if (GetKeyNameText(((keynum & 0x7f) << 16) | ((keynum & 0x80) << 17), keyname, std::size(keyname)) == 0)
+ _sntprintf(keyname, std::size(keyname), TEXT("Scan%03d"), keynum);
+ std::string name = text::from_tstring(keyname);
+
+ // add the item to the device
+ device.add_item(
+ name,
+ util::string_format("SCAN%03d", keynum),
+ itemid,
+ generic_button_get_state<std::uint8_t>,
+ &m_keyboard.state[keynum]);
+ }
}
protected:
- void process_event(KeyPressEventArgs &args) override
+ virtual void process_event(KeyPressEventArgs const &args) override
{
- keyboard.state[args.scancode] = args.event_id == INPUT_EVENT_KEYDOWN ? 0x80 : 0x00;
+ m_keyboard.state[args.scancode] = args.event_id == INPUT_EVENT_KEYDOWN ? 0x80 : 0x00;
}
+
+private:
+ keyboard_state m_keyboard;
};
+
//============================================================
// keyboard_input_win32 - win32 keyboard input module
//============================================================
-class keyboard_input_win32 : public wininput_module
+class keyboard_input_win32 : public wininput_module<win32_keyboard_device>
{
-private:
-
public:
- keyboard_input_win32()
- : wininput_module(OSD_KEYBOARDINPUT_PROVIDER, "win32")
+ keyboard_input_win32() : wininput_module<win32_keyboard_device>(OSD_KEYBOARDINPUT_PROVIDER, "win32")
{
}
virtual void input_init(running_machine &machine) override
{
- // Add a single win32 keyboard device that we'll monitor using Win32
- auto &devinfo = devicelist().create_device<win32_keyboard_device>(machine, "Win32 Keyboard 1", "Win32 Keyboard 1", *this);
-
- keyboard_trans_table &table = keyboard_trans_table::instance();
-
- // populate it
- for (int keynum = 0; keynum < MAX_KEYS; keynum++)
- {
- input_item_id itemid = table.map_di_scancode_to_itemid(keynum);
- TCHAR keyname[100];
+ wininput_module<win32_keyboard_device>::input_init(machine);
- // generate the name
- if (GetKeyNameText(((keynum & 0x7f) << 16) | ((keynum & 0x80) << 17), keyname, std::size(keyname)) == 0)
- _sntprintf(keyname, std::size(keyname), TEXT("Scan%03d"), keynum);
- std::string name = osd::text::from_tstring(keyname);
-
- // add the item to the device
- devinfo.device()->add_item(name, itemid, generic_button_get_state<std::uint8_t>, &devinfo.keyboard.state[keynum]);
- }
+ // Add a single win32 keyboard device that we'll monitor using Win32
+ create_device<win32_keyboard_device>(DEVICE_CLASS_KEYBOARD, "Win32 Keyboard 1", "Win32 Keyboard 1");
}
- bool handle_input_event(input_event eventid, void *eventdata) override
+ virtual bool handle_input_event(input_event eventid, void *eventdata) override
{
- if (!input_enabled())
- return false;
-
- KeyPressEventArgs *args;
-
switch (eventid)
{
- case INPUT_EVENT_KEYDOWN:
- case INPUT_EVENT_KEYUP:
- args = static_cast<KeyPressEventArgs*>(eventdata);
- devicelist().for_each_device([args](auto device)
- {
- auto keyboard = dynamic_cast<win32_keyboard_device*>(device);
- if (keyboard != nullptr)
- keyboard->queue_events(args, 1);
- });
-
- return true;
-
- default:
- return false;
+ case INPUT_EVENT_KEYDOWN:
+ case INPUT_EVENT_KEYUP:
+ devicelist().for_each_device(
+ [args = static_cast<KeyPressEventArgs const *>(eventdata)] (auto &device)
+ {
+ device.queue_events(args, 1);
+ });
+ return false; // we still want text input events to be generated
+
+ default:
+ return false;
}
}
};
+
//============================================================
// win32_mouse_device
//============================================================
-struct win32_mouse_state
-{
- POINT last_point;
-};
-
class win32_mouse_device : public event_based_device<MouseButtonEventArgs>
{
public:
- mouse_state mouse;
- win32_mouse_state win32_mouse;
-
- win32_mouse_device(running_machine& machine, std::string &&name, std::string &&id, input_module &module)
- : event_based_device(machine, std::move(name), std::move(id), DEVICE_CLASS_MOUSE, module),
- mouse({0}),
- win32_mouse({{0}})
+ win32_mouse_device(std::string &&name, std::string &&id, input_module &module) :
+ event_based_device(std::move(name), std::move(id), module),
+ m_mouse({0}),
+ m_win32_mouse({{0}})
{
}
- void poll() override
+ virtual void poll(bool relative_reset) override
{
- event_based_device::poll();
+ event_based_device::poll(relative_reset);
+
+ if (!relative_reset)
+ return;
CURSORINFO cursor_info = {0};
cursor_info.cbSize = sizeof(CURSORINFO);
@@ -149,140 +155,188 @@ public:
if (!(cursor_info.flags & CURSOR_SHOWING))
{
// We measure the position change from the previously set center position
- mouse.lX = (cursor_info.ptScreenPos.x - win32_mouse.last_point.x) * osd::INPUT_RELATIVE_PER_PIXEL;
- mouse.lY = (cursor_info.ptScreenPos.y - win32_mouse.last_point.y) * osd::INPUT_RELATIVE_PER_PIXEL;
+ m_mouse.lX = (cursor_info.ptScreenPos.x - m_win32_mouse.last_point.x) * input_device::RELATIVE_PER_PIXEL;
+ m_mouse.lY = (cursor_info.ptScreenPos.y - m_win32_mouse.last_point.y) * input_device::RELATIVE_PER_PIXEL;
RECT window_pos = {0};
- GetWindowRect(std::static_pointer_cast<win_window_info>(osd_common_t::s_window_list.front())->platform_window(), &window_pos);
+ GetWindowRect(
+ dynamic_cast<win_window_info &>(*osd_common_t::window_list().front()).platform_window(),
+ &window_pos);
// We reset the cursor position to the middle of the window each frame
- win32_mouse.last_point.x = window_pos.left + (window_pos.right - window_pos.left) / 2;
- win32_mouse.last_point.y = window_pos.top + (window_pos.bottom - window_pos.top) / 2;
+ m_win32_mouse.last_point.x = window_pos.left + (window_pos.right - window_pos.left) / 2;
+ m_win32_mouse.last_point.y = window_pos.top + (window_pos.bottom - window_pos.top) / 2;
- SetCursorPos(win32_mouse.last_point.x, win32_mouse.last_point.y);
+ SetCursorPos(m_win32_mouse.last_point.x, m_win32_mouse.last_point.y);
}
}
- void reset() override
+ virtual void configure(input_device &device) override
{
- memset(&mouse, 0, sizeof(mouse));
- memset(&win32_mouse, 0, sizeof(win32_mouse));
+ // populate the axes
+ for (int axisnum = 0; axisnum < 2; axisnum++)
+ {
+ device.add_item(
+ default_axis_name[axisnum],
+ std::string_view(),
+ input_item_id(ITEM_ID_XAXIS + axisnum),
+ generic_axis_get_state<LONG>,
+ &m_mouse.lX + axisnum);
+ }
+
+ // populate the buttons
+ for (int butnum = 0; butnum < 2; butnum++)
+ {
+ device.add_item(
+ default_button_name(butnum),
+ std::string_view(),
+ input_item_id(ITEM_ID_BUTTON1 + butnum),
+ generic_button_get_state<BYTE>,
+ &m_mouse.rgbButtons[butnum]);
+ }
+ }
+
+ virtual void reset() override
+ {
+ memset(&m_mouse, 0, sizeof(m_mouse));
+ memset(&m_win32_mouse, 0, sizeof(m_win32_mouse));
}
protected:
- void process_event(MouseButtonEventArgs &args) override
+ virtual void process_event(MouseButtonEventArgs const &args) override
{
// set the button state
- mouse.rgbButtons[args.button] = args.keydown ? 0x80 : 0x00;
-
- // Make sure we have a fresh mouse position on button down
- if (args.keydown)
- module().poll_if_necessary(machine());
+ m_mouse.rgbButtons[args.button] = args.keydown ? 0x80 : 0x00;
}
+
+private:
+ struct win32_mouse_state
+ {
+ POINT last_point;
+ };
+
+ mouse_state m_mouse;
+ win32_mouse_state m_win32_mouse;
};
+
//============================================================
// mouse_input_win32 - win32 mouse input module
//============================================================
-class mouse_input_win32 : public wininput_module
+class mouse_input_win32 : public wininput_module<win32_mouse_device>
{
public:
- mouse_input_win32()
- : wininput_module(OSD_MOUSEINPUT_PROVIDER, "win32")
+ mouse_input_win32() : wininput_module<win32_mouse_device>(OSD_MOUSEINPUT_PROVIDER, "win32")
{
}
virtual void input_init(running_machine &machine) override
{
- if (!input_enabled() || !mouse_enabled())
+ wininput_module<win32_mouse_device>::input_init(machine);
+
+ if (!options()->mouse())
return;
// allocate a device
- auto &devinfo = devicelist().create_device<win32_mouse_device>(machine, "Win32 Mouse 1", "Win32 Mouse 1", *this);
+ create_device<win32_mouse_device>(DEVICE_CLASS_MOUSE, "Win32 Mouse 1", "Win32 Mouse 1");
+ }
+
+ virtual bool handle_input_event(input_event eventid, void *eventdata) override
+ {
+ if (!manager().class_enabled(DEVICE_CLASS_MOUSE) || eventid != INPUT_EVENT_MOUSE_BUTTON)
+ return false;
+
+ auto const *const args = static_cast<MouseButtonEventArgs *>(eventdata);
+ devicelist().for_each_device(
+ [args] (auto &device) { device.queue_events(args, 1); });
+
+ return true;
+ }
+};
+
+//============================================================
+// win32_lightgun_device_base
+//============================================================
+
+class win32_lightgun_device_base : public event_based_device<MouseButtonEventArgs>
+{
+public:
+ virtual void reset() override
+ {
+ memset(&m_mouse, 0, sizeof(m_mouse));
+ }
+
+ virtual void configure(input_device &device) override
+ {
// populate the axes
for (int axisnum = 0; axisnum < 2; axisnum++)
{
- devinfo.device()->add_item(
- default_axis_name[axisnum],
- static_cast<input_item_id>(ITEM_ID_XAXIS + axisnum),
- generic_axis_get_state<LONG>,
- &devinfo.mouse.lX + axisnum);
+ device.add_item(
+ default_axis_name[axisnum],
+ std::string_view(),
+ input_item_id(ITEM_ID_XAXIS + axisnum),
+ generic_axis_get_state<LONG>,
+ &m_mouse.lX + axisnum);
}
// populate the buttons
for (int butnum = 0; butnum < 2; butnum++)
{
- devinfo.device()->add_item(
- default_button_name(butnum),
- static_cast<input_item_id>(ITEM_ID_BUTTON1 + butnum),
- generic_button_get_state<BYTE>,
- &devinfo.mouse.rgbButtons[butnum]);
+ device.add_item(
+ default_button_name(butnum),
+ std::string_view(),
+ input_item_id(ITEM_ID_BUTTON1 + butnum),
+ generic_button_get_state<BYTE>,
+ &m_mouse.rgbButtons[butnum]);
}
}
- bool handle_input_event(input_event eventid, void *eventdata) override
+protected:
+ win32_lightgun_device_base(
+ std::string &&name,
+ std::string &&id,
+ input_module &module) :
+ event_based_device(std::move(name), std::move(id), module),
+ m_mouse({ 0 })
{
- if (!input_enabled() || !mouse_enabled() || eventid != INPUT_EVENT_MOUSE_BUTTON)
- return false;
-
- auto args = static_cast<MouseButtonEventArgs*>(eventdata);
- devicelist().for_each_device([args](auto device)
- {
- auto mouse = dynamic_cast<win32_mouse_device*>(device);
- if (mouse != nullptr)
- mouse->queue_events(args, 1);
- });
-
- return true;
}
+
+ mouse_state m_mouse;
};
+
+
//============================================================
// win32_lightgun_device
//============================================================
-class win32_lightgun_device : public event_based_device<MouseButtonEventArgs>
+class win32_lightgun_device : public win32_lightgun_device_base
{
-private:
- BOOL m_lightgun_shared_axis_mode;
- int m_gun_index;
-
public:
- mouse_state mouse;
-
- win32_lightgun_device(running_machine& machine, std::string &&name, std::string &&id, input_module &module)
- : event_based_device(machine, std::move(name), std::move(id), DEVICE_CLASS_LIGHTGUN, module),
- m_lightgun_shared_axis_mode(FALSE),
- m_gun_index(0),
- mouse({0})
+ win32_lightgun_device(
+ std::string &&name,
+ std::string &&id,
+ input_module &module) :
+ win32_lightgun_device_base(std::move(name), std::move(id), module)
{
- m_lightgun_shared_axis_mode = downcast<windows_options &>(machine.options()).dual_lightgun();
-
- // Since we are about to be added to the list, the current size is the zero-based index of where we will be
- m_gun_index = downcast<wininput_module&>(module).devicelist().size();
}
- void poll() override
+ virtual void poll(bool relative_reset) override
{
- event_based_device::poll();
+ event_based_device::poll(relative_reset);
int32_t xpos = 0, ypos = 0;
- POINT mousepos;
-
- // if we are using the shared axis hack, the data is updated via Windows messages only
- if (m_lightgun_shared_axis_mode)
- return;
// get the cursor position and transform into final results
+ POINT mousepos;
GetCursorPos(&mousepos);
- if (!osd_common_t::s_window_list.empty())
+ if (!osd_common_t::window_list().empty())
{
- RECT client_rect;
-
// get the position relative to the window
- HWND hwnd = std::static_pointer_cast<win_window_info>(osd_common_t::s_window_list.front())->platform_window();
+ HWND const hwnd = dynamic_cast<win_window_info &>(*osd_common_t::window_list().front()).platform_window();
+ RECT client_rect;
GetClientRect(hwnd, &client_rect);
ScreenToClient(hwnd, &mousepos);
@@ -292,91 +346,93 @@ public:
}
// update the X/Y positions
- mouse.lX = xpos;
- mouse.lY = ypos;
+ m_mouse.lX = xpos;
+ m_mouse.lY = ypos;
}
- void reset() override
+protected:
+ virtual void process_event(MouseButtonEventArgs const &args) override
{
- memset(&mouse, 0, sizeof(mouse));
+ // In non-shared axis mode, just update the button state
+ m_mouse.rgbButtons[args.button] = args.keydown ? 0x80 : 0x00;
}
+};
-protected:
- void process_event(MouseButtonEventArgs &args) override
+
+//============================================================
+// win32_dual_lightgun_device
+//============================================================
+
+class win32_dual_lightgun_device : public win32_lightgun_device_base
+{
+public:
+ win32_dual_lightgun_device(
+ std::string &&name,
+ std::string &&id,
+ input_module &module,
+ int index) :
+ win32_lightgun_device_base(std::move(name), std::move(id), module),
+ m_gun_index(index)
{
- // Are we in shared axis mode?
- if (m_lightgun_shared_axis_mode)
- {
- handle_shared_axis_mode(args);
- }
- else
- {
- // In non-shared axis mode, just update the button state
- mouse.rgbButtons[args.button] = args.keydown ? 0x80 : 0x00;
- }
}
-private:
- void handle_shared_axis_mode(MouseButtonEventArgs &args)
+protected:
+ virtual void process_event(MouseButtonEventArgs const &args) override
{
- int button = args.button;
+ int const button = args.button;
- // We only handle the first four buttons in shared axis mode
if (button > 3)
- return;
-
- // First gun doesn't handle buttons 2 & 3
- if (button >= 2 && m_gun_index == 0)
- return;
-
- // Second gun doesn't handle buttons 0 & 1
- if (button < 2 && m_gun_index == 1)
- return;
+ return; // We only handle the first four buttons in shared axis mode
+ else if (button >= 2 && m_gun_index == 0)
+ return; // First gun doesn't handle buttons 2 and 3
+ else if (button < 2 && m_gun_index == 1)
+ return; // Second gun doesn't handle buttons 0 and 1
// Adjust the button if we're the second lightgun
- int logical_button = m_gun_index == 1 ? button - 2 : button;
+ int const logical_button = (m_gun_index == 1) ? (button - 2) : button;
// set the button state
- mouse.rgbButtons[logical_button] = args.keydown ? 0x80 : 0x00;
+ m_mouse.rgbButtons[logical_button] = args.keydown ? 0x80 : 0x00;
if (args.keydown)
{
- RECT client_rect;
- POINT mousepos;
-
// get the position relative to the window
- HWND hwnd = std::static_pointer_cast<win_window_info>(osd_common_t::s_window_list.front())->platform_window();
+ HWND const hwnd = dynamic_cast<win_window_info &>(*osd_common_t::window_list().front()).platform_window();
+ RECT client_rect;
GetClientRect(hwnd, &client_rect);
+
+ POINT mousepos;
mousepos.x = args.xpos;
mousepos.y = args.ypos;
ScreenToClient(hwnd, &mousepos);
// convert to absolute coordinates
- mouse.lX = normalize_absolute_axis(mousepos.x, client_rect.left, client_rect.right);
- mouse.lY = normalize_absolute_axis(mousepos.y, client_rect.top, client_rect.bottom);
+ m_mouse.lX = normalize_absolute_axis(mousepos.x, client_rect.left, client_rect.right);
+ m_mouse.lY = normalize_absolute_axis(mousepos.y, client_rect.top, client_rect.bottom);
}
}
+
+private:
+ int const m_gun_index;
};
+
//============================================================
// lightgun_input_win32 - win32 lightgun input module
//============================================================
-class lightgun_input_win32 : public wininput_module
+class lightgun_input_win32 : public wininput_module<win32_lightgun_device_base>
{
public:
- lightgun_input_win32()
- : wininput_module(OSD_LIGHTGUNINPUT_PROVIDER, "win32")
- {
- }
-
- int init_internal() override
+ lightgun_input_win32() : wininput_module<win32_lightgun_device_base>(OSD_LIGHTGUNINPUT_PROVIDER, "win32")
{
- return 0;
}
virtual void input_init(running_machine &machine) override
{
- int max_guns = downcast<windows_options&>(machine.options()).dual_lightgun() ? 2 : 1;
+ wininput_module<win32_lightgun_device_base>::input_init(machine);
+
+ bool const shared_axis_mode = dynamic_cast<windows_options const &>(*options()).dual_lightgun();
+ int const max_guns = shared_axis_mode ? 2 : 1;
// allocate the lightgun devices
for (int gunnum = 0; gunnum < max_guns; gunnum++)
@@ -384,42 +440,21 @@ public:
static const char *const gun_names[] = { "Win32 Gun 1", "Win32 Gun 2" };
// allocate a device
- auto &devinfo = devicelist().create_device<win32_lightgun_device>(machine, gun_names[gunnum], gun_names[gunnum], *this);
-
- // populate the axes
- for (int axisnum = 0; axisnum < 2; axisnum++)
- {
- devinfo.device()->add_item(
- default_axis_name[axisnum],
- static_cast<input_item_id>(ITEM_ID_XAXIS + axisnum),
- generic_axis_get_state<LONG>,
- &devinfo.mouse.lX + axisnum);
- }
-
- // populate the buttons
- for (int butnum = 0; butnum < 2; butnum++)
- {
- devinfo.device()->add_item(
- default_button_name(butnum),
- static_cast<input_item_id>(ITEM_ID_BUTTON1 + butnum),
- generic_button_get_state<BYTE>,
- &devinfo.mouse.rgbButtons[butnum]);
- }
+ if (shared_axis_mode)
+ create_device<win32_dual_lightgun_device>(DEVICE_CLASS_LIGHTGUN, gun_names[gunnum], gun_names[gunnum], gunnum);
+ else
+ create_device<win32_lightgun_device>(DEVICE_CLASS_LIGHTGUN, gun_names[gunnum], gun_names[gunnum]);
}
}
- bool handle_input_event(input_event eventid, void* eventdata) override
+ virtual bool handle_input_event(input_event eventid, void *eventdata) override
{
- if (!input_enabled() || !lightgun_enabled() || eventid != INPUT_EVENT_MOUSE_BUTTON)
+ if (!manager().class_enabled(DEVICE_CLASS_LIGHTGUN) || eventid != INPUT_EVENT_MOUSE_BUTTON)
return false;
- auto args = static_cast<MouseButtonEventArgs*>(eventdata);
- devicelist().for_each_device([args](auto device)
- {
- auto lightgun = dynamic_cast<win32_lightgun_device*>(device);
- if (lightgun != nullptr)
- lightgun->queue_events(args, 1);
- });
+ auto const *const args = static_cast<MouseButtonEventArgs *>(eventdata);
+ devicelist().for_each_device(
+ [args] (auto &device) { device.queue_events(args, 1); });
return true;
}
@@ -427,14 +462,24 @@ public:
} // anonymous namespace
+} // namespace osd
+
#else // defined(OSD_WINDOWS)
+namespace osd {
+
+namespace {
+
MODULE_NOT_SUPPORTED(keyboard_input_win32, OSD_KEYBOARDINPUT_PROVIDER, "win32")
MODULE_NOT_SUPPORTED(mouse_input_win32, OSD_MOUSEINPUT_PROVIDER, "win32")
MODULE_NOT_SUPPORTED(lightgun_input_win32, OSD_LIGHTGUNINPUT_PROVIDER, "win32")
+} // anonymous namespace
+
+} // namespace osd
+
#endif // defined(OSD_WINDOWS)
-MODULE_DEFINITION(KEYBOARDINPUT_WIN32, keyboard_input_win32)
-MODULE_DEFINITION(MOUSEINPUT_WIN32, mouse_input_win32)
-MODULE_DEFINITION(LIGHTGUNINPUT_WIN32, lightgun_input_win32)
+MODULE_DEFINITION(KEYBOARDINPUT_WIN32, osd::keyboard_input_win32)
+MODULE_DEFINITION(MOUSEINPUT_WIN32, osd::mouse_input_win32)
+MODULE_DEFINITION(LIGHTGUNINPUT_WIN32, osd::lightgun_input_win32)
diff --git a/src/osd/modules/input/input_wincommon.h b/src/osd/modules/input/input_wincommon.h
new file mode 100644
index 00000000000..d77ab8dce9a
--- /dev/null
+++ b/src/osd/modules/input/input_wincommon.h
@@ -0,0 +1,39 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles
+//============================================================
+//
+// input_wincommon.h - Common code used by Windows input modules
+//
+//============================================================
+#ifndef MAME_OSD_INPUT_INPUT_WINCOMMON_H
+#define MAME_OSD_INPUT_INPUT_WINCOMMON_H
+
+#pragma once
+
+#include "input_common.h"
+
+#include <windows.h>
+
+
+namespace osd {
+
+// state information for a keyboard
+struct keyboard_state
+{
+ uint8_t state[MAX_KEYS];
+ int8_t oldkey[MAX_KEYS];
+ int8_t currkey[MAX_KEYS];
+};
+
+// state information for a mouse (matches DIMOUSESTATE exactly)
+struct mouse_state
+{
+ LONG lX;
+ LONG lY;
+ LONG lZ;
+ BYTE rgbButtons[8];
+};
+
+} // namespace osd
+
+#endif // MAME_OSD_INPUT_INPUT_WINCOMMON_H
diff --git a/src/osd/modules/input/input_windows.cpp b/src/osd/modules/input/input_windows.cpp
index 60306765f72..c635ff0b553 100644
--- a/src/osd/modules/input/input_windows.cpp
+++ b/src/osd/modules/input/input_windows.cpp
@@ -25,82 +25,76 @@
bool windows_osd_interface::should_hide_mouse() const
{
- bool hidemouse = false;
- wininput_module *mod;
+ if (!winwindow_has_focus())
+ return false;
- mod = dynamic_cast<wininput_module *>(m_keyboard_input);
- if (mod) hidemouse |= mod->should_hide_mouse();
+ if (machine().paused())
+ return false;
- mod = dynamic_cast<wininput_module *>(m_mouse_input);
- if (mod) hidemouse |= mod->should_hide_mouse();
+ // track if mouse/lightgun is enabled, for mouse hiding purposes
+ bool const mouse_enabled = machine().input().class_enabled(DEVICE_CLASS_MOUSE);
+ bool const lightgun_enabled = machine().input().class_enabled(DEVICE_CLASS_LIGHTGUN);
+ if (!mouse_enabled && !lightgun_enabled)
+ return false;
- mod = dynamic_cast<wininput_module *>(m_lightgun_input);
- if (mod) hidemouse |= mod->should_hide_mouse();
-
- mod = dynamic_cast<wininput_module *>(m_joystick_input);
- if (mod) hidemouse |= mod->should_hide_mouse();
-
- return hidemouse;
+ return true;
}
bool windows_osd_interface::handle_input_event(input_event eventid, void *eventdata) const
{
bool handled = false;
- wininput_module *mod;
+ wininput_event_handler *mod;
- mod = dynamic_cast<wininput_module *>(m_keyboard_input);
- if (mod) handled |= mod->handle_input_event(eventid, eventdata);
+ mod = dynamic_cast<wininput_event_handler *>(m_keyboard_input);
+ if (mod)
+ handled |= mod->handle_input_event(eventid, eventdata);
- mod = dynamic_cast<wininput_module *>(m_mouse_input);
- if (mod) handled |= mod->handle_input_event(eventid, eventdata);
+ mod = dynamic_cast<wininput_event_handler *>(m_mouse_input);
+ if (mod)
+ handled |= mod->handle_input_event(eventid, eventdata);
- mod = dynamic_cast<wininput_module *>(m_lightgun_input);
- if (mod) handled |= mod->handle_input_event(eventid, eventdata);
+ mod = dynamic_cast<wininput_event_handler *>(m_lightgun_input);
+ if (mod)
+ handled |= mod->handle_input_event(eventid, eventdata);
- mod = dynamic_cast<wininput_module *>(m_joystick_input);
- if (mod) handled |= mod->handle_input_event(eventid, eventdata);
+ mod = dynamic_cast<wininput_event_handler *>(m_joystick_input);
+ if (mod)
+ handled |= mod->handle_input_event(eventid, eventdata);
return handled;
}
-void windows_osd_interface::poll_input(running_machine &machine) const
-{
- m_keyboard_input->poll_if_necessary(machine);
- m_mouse_input->poll_if_necessary(machine);
- m_lightgun_input->poll_if_necessary(machine);
- m_joystick_input->poll_if_necessary(machine);
-}
-
//============================================================
// customize_input_type_list
//============================================================
void windows_osd_interface::customize_input_type_list(std::vector<input_type_entry> &typelist)
{
- const char* uimode;
-
// loop over the defaults
for (input_type_entry &entry : typelist)
switch (entry.type())
{
// disable the config menu if the ALT key is down
// (allows ALT-TAB to switch between windows apps)
- case IPT_UI_CONFIGURE:
+ case IPT_UI_MENU:
entry.defseq(SEQ_TYPE_STANDARD).set(KEYCODE_TAB, input_seq::not_code, KEYCODE_LALT, input_seq::not_code, KEYCODE_RALT);
break;
+
// configurable UI mode switch
case IPT_UI_TOGGLE_UI:
- uimode = options().ui_mode_key();
- if (strcmp(uimode, "auto"))
{
- std::string fullmode = "ITEM_ID_";
- fullmode += uimode;
- input_item_id const mameid_code = keyboard_trans_table::instance().lookup_mame_code(fullmode.c_str());
- if (ITEM_ID_INVALID != mameid_code)
+ char const *const uimode = options().ui_mode_key();
+ if (uimode && *uimode && strcmp(uimode, "auto"))
{
- input_code const ui_code = input_code(DEVICE_CLASS_KEYBOARD, 0, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, input_item_id(mameid_code));
- entry.defseq(SEQ_TYPE_STANDARD).set(ui_code);
+ std::string fullmode("ITEM_ID_");
+ fullmode.append(uimode);
+ input_item_id const mameid_code = keyboard_trans_table::instance().lookup_mame_code(fullmode.c_str());
+ if (ITEM_ID_INVALID != mameid_code)
+ {
+ input_code const ui_code = input_code(DEVICE_CLASS_KEYBOARD, 0, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, input_item_id(mameid_code));
+ entry.defseq(SEQ_TYPE_STANDARD).set(ui_code);
+ }
}
}
break;
@@ -138,10 +132,15 @@ void windows_osd_interface::customize_input_type_list(std::vector<input_type_ent
entry.defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F12, KEYCODE_LSHIFT, KEYCODE_LCONTROL, input_seq::not_code, KEYCODE_LALT);
break;
- // lctrl-lalt-F5 to toggle post-processing
+ // lalt-F10 to toggle post-processing
case IPT_OSD_4:
entry.configure_osd("POST_PROCESS", N_p("input-name", "Toggle Post-Processing"));
- entry.defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F5, KEYCODE_LALT, KEYCODE_LCONTROL);
+ entry.defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F10, KEYCODE_LALT);
+ break;
+
+ // add a Not LALT condition to the throttle key
+ case IPT_UI_THROTTLE:
+ entry.defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F10, input_seq::not_code, KEYCODE_LALT);
break;
// leave everything else alone
diff --git a/src/osd/modules/input/input_windows.h b/src/osd/modules/input/input_windows.h
index 7acf8586876..175151cb4e5 100644
--- a/src/osd/modules/input/input_windows.h
+++ b/src/osd/modules/input/input_windows.h
@@ -23,64 +23,26 @@
// TYPEDEFS
//============================================================
-// state information for a keyboard
-struct keyboard_state
-{
- uint8_t state[MAX_KEYS];
- int8_t oldkey[MAX_KEYS];
- int8_t currkey[MAX_KEYS];
-};
-
-// state information for a mouse (matches DIMOUSESTATE exactly)
-struct mouse_state
-{
- LONG lX;
- LONG lY;
- LONG lZ;
- BYTE rgbButtons[8];
-};
-class wininput_module : public input_module_base
+class wininput_event_handler
{
protected:
- bool m_global_inputs_enabled = false;
+ wininput_event_handler() = default;
+ virtual ~wininput_event_handler() = default;
public:
- wininput_module(const char *type, const char *name) : input_module_base(type, name) { }
-
- virtual ~wininput_module() { }
-
- virtual bool should_hide_mouse()
+ virtual bool handle_input_event(input_event eventid, void *data)
{
- if (winwindow_has_focus() // has focus
- && (!video_config.windowed || !osd_common_t::s_window_list.front()->win_has_menu()) // not windowed or doesn't have a menu
- && (input_enabled() && !input_paused()) // input enabled and not paused
- && (mouse_enabled() || lightgun_enabled())) // either mouse or lightgun enabled in the core
- {
- return true;
- }
-
return false;
}
+};
- virtual bool handle_input_event(input_event eventid, void* data)
- {
- return false;
- }
+template <typename Info>
+class wininput_module : public input_module_impl<Info, osd_common_t>, public wininput_event_handler
+{
protected:
-
- void before_poll(running_machine& machine) override
- {
- // periodically process events, in case they're not coming through
- // this also will make sure the mouse state is up-to-date
- winwindow_process_events_periodic(machine);
- }
-
- bool should_poll_devices(running_machine &machine) override
- {
- return input_enabled() && (m_global_inputs_enabled || winwindow_has_focus());
- }
+ using input_module_impl<Info, osd_common_t>::input_module_impl;
};
#endif // MAME_OSD_INPUT_INPUT_WINDOWS_H
diff --git a/src/osd/modules/input/input_winhybrid.cpp b/src/osd/modules/input/input_winhybrid.cpp
index 52d991a9674..2f1023e24fb 100644
--- a/src/osd/modules/input/input_winhybrid.cpp
+++ b/src/osd/modules/input/input_winhybrid.cpp
@@ -8,23 +8,20 @@
#include "modules/osdmodule.h"
-#if defined(OSD_WINDOWS)
-
-#include "emu.h"
+#if defined(OSD_WINDOWS) || defined(SDLMAME_WIN32)
#include "input_dinput.h"
#include "input_xinput.h"
-#include <list>
#include <vector>
#include <oleauto.h>
#include <wbemcli.h>
-namespace {
+namespace osd {
-using namespace Microsoft::WRL;
+namespace {
template <class TCom>
class ComArray
@@ -42,7 +39,7 @@ public:
Release();
}
- TCom** ReleaseAndGetAddressOf()
+ TCom **ReleaseAndGetAddressOf()
{
Release();
@@ -50,7 +47,7 @@ public:
return &m_entries[0];
}
- TCom* operator [] (int i)
+ TCom *operator[](int i)
{
return m_entries[i];
}
@@ -64,7 +61,7 @@ public:
{
for (auto &entry : m_entries)
{
- if (entry != nullptr)
+ if (entry)
{
entry->Release();
entry = nullptr;
@@ -119,28 +116,24 @@ public:
typedef std::unique_ptr<OLECHAR, bstr_deleter> bstr_ptr;
+
//============================================================
// winhybrid_joystick_module
//============================================================
-class winhybrid_joystick_module : public wininput_module, public device_enum_interface
+class winhybrid_joystick_module : public input_module_impl<device_info, osd_common_t>
{
private:
- std::shared_ptr<xinput_api_helper> m_xinput_helper;
+ std::unique_ptr<xinput_api_helper> m_xinput_helper;
std::unique_ptr<dinput_api_helper> m_dinput_helper;
- std::list<DWORD> m_xinput_deviceids;
- bool m_xinput_detect_failed;
public:
winhybrid_joystick_module() :
- wininput_module(OSD_JOYSTICKINPUT_PROVIDER, "winhybrid"),
- m_xinput_helper(nullptr),
- m_dinput_helper(nullptr),
- m_xinput_detect_failed(false)
+ input_module_impl<device_info, osd_common_t>(OSD_JOYSTICKINPUT_PROVIDER, "winhybrid")
{
}
- bool probe() override
+ virtual bool probe() override
{
int status = init_helpers();
if (status != 0)
@@ -152,10 +145,12 @@ public:
return true;
}
- int init(const osd_options &options) override
+ virtual int init(osd_interface &osd, const osd_options &options) override
{
+ int status;
+
// Call the base
- int status = wininput_module::init(options);
+ status = input_module_impl<device_info, osd_common_t>::init(osd, options);
if (status != 0)
return status;
@@ -170,98 +165,100 @@ public:
return 0;
}
- BOOL device_enum_callback(LPCDIDEVICEINSTANCE instance, LPVOID ref) override
- {
- dinput_cooperative_level cooperative_level = dinput_cooperative_level::FOREGROUND;
- running_machine &machine = *static_cast<running_machine *>(ref);
- dinput_joystick_device *devinfo;
- int result = 0;
-
- // First check if this device is XInput Compatible. If so, don't add it here
- // as it'll be picked up by Xinput
- if (!m_xinput_detect_failed && is_xinput_device(&instance->guidProduct))
- {
- osd_printf_verbose("Skipping DirectInput for XInput compatible joystick %S.\n", instance->tszInstanceName);
- goto exit;
- }
-
- if (!osd_common_t::s_window_list.empty() && osd_common_t::s_window_list.front()->win_has_menu())
- cooperative_level = dinput_cooperative_level::BACKGROUND;
-
- // allocate and link in a new device
- devinfo = m_dinput_helper->create_device<dinput_joystick_device>(machine, *this, instance, &c_dfDIJoystick, nullptr, cooperative_level);
- if (devinfo == nullptr)
- goto exit;
-
- result = devinfo->configure();
- if (result != 0)
- {
- osd_printf_error("Failed to configure DI Joystick device. Error 0x%x\n", static_cast<unsigned int>(result));
- }
-
- exit:
- return DIENUM_CONTINUE;
- }
-
- void exit() override
- {
- m_xinput_helper.reset();
- m_dinput_helper.reset();
-
- wininput_module::exit();
- }
-
-protected:
virtual void input_init(running_machine &machine) override
{
- HRESULT result = get_xinput_devices(m_xinput_deviceids);
+ input_module_impl<device_info, osd_common_t>::input_init(machine);
+
+ bool xinput_detect_failed = false;
+ std::vector<DWORD> xinput_deviceids;
+ HRESULT result = get_xinput_devices(xinput_deviceids);
if (result != 0)
{
- m_xinput_detect_failed = true;
+ xinput_detect_failed = true;
+ xinput_deviceids.clear();
osd_printf_warning("XInput device detection failed. XInput won't be used. Error: 0x%X\n", uint32_t(result));
}
- // Enumerate all the directinput joysticks and add them if they aren't xinput compatible
- result = m_dinput_helper->enum_attached_devices(DI8DEVCLASS_GAMECTRL, this, &machine);
- if (result != DI_OK)
- fatalerror("DirectInput: Unable to enumerate game controllers (result=%08X)\n", uint32_t(result));
+ // Enumerate all the DirectInput joysticks and add them if they aren't XInput compatible
+ result = m_dinput_helper->enum_attached_devices(
+ DI8DEVCLASS_GAMECTRL,
+ [this, &xinput_deviceids] (LPCDIDEVICEINSTANCE instance)
+ {
+ // First check if this device is XInput compatible.
+ // If so, don't add it here as it'll be picked up by Xinput.
+ auto const found = std::find(
+ xinput_deviceids.begin(),
+ xinput_deviceids.end(),
+ instance->guidProduct.Data1);
+ if (xinput_deviceids.end() != found)
+ {
+ osd_printf_verbose("Skipping DirectInput for XInput compatible joystick %S.\n", instance->tszInstanceName);
+ return DIENUM_CONTINUE;
+ }
- xinput_joystick_device *devinfo;
+ // allocate and link in a new device
+ auto devinfo = m_dinput_helper->create_device<dinput_joystick_device>(
+ *this,
+ instance,
+ &c_dfDIJoystick,
+ nullptr,
+ background_input() ? dinput_cooperative_level::BACKGROUND : dinput_cooperative_level::FOREGROUND,
+ [] (auto const &device, auto const &format) -> bool
+ {
+ // set absolute mode
+ HRESULT const result = dinput_api_helper::set_dword_property(
+ device,
+ DIPROP_AXISMODE,
+ 0,
+ DIPH_DEVICE,
+ DIPROPAXISMODE_ABS);
+ if ((result != DI_OK) && (result != DI_PROPNOEFFECT))
+ {
+ osd_printf_error("DirectInput: Unable to set absolute mode for joystick.\n");
+ return false;
+ }
+ return true;
+ });
+ if (devinfo)
+ add_device(DEVICE_CLASS_JOYSTICK, std::move(devinfo));
+
+ return DIENUM_CONTINUE;
+ });
+ if (result != DI_OK)
+ fatalerror("DirectInput: Unable to enumerate game controllers (result=%08X).\n", uint32_t(result));
// now add all xinput devices
- if (!m_xinput_detect_failed)
+ if (!xinput_detect_failed)
{
// Loop through each gamepad to determine if they are connected
for (UINT i = 0; i < XUSER_MAX_COUNT; i++)
{
- XINPUT_STATE state = { 0 };
-
- if (m_xinput_helper->xinput_get_state(i, &state) == ERROR_SUCCESS)
- {
- // allocate and link in a new device
- devinfo = m_xinput_helper->create_xinput_device(machine, i, *this);
- if (!devinfo)
- continue;
-
- // Configure each gamepad to add buttons and Axes, etc.
- devinfo->configure();
- }
+ // allocate and link in a new device
+ auto devinfo = m_xinput_helper->create_xinput_device(i, *this);
+ if (devinfo)
+ add_device(DEVICE_CLASS_JOYSTICK, std::move(devinfo));
}
}
}
+ virtual void exit() override
+ {
+ input_module_impl<device_info, osd_common_t>::exit();
+
+ m_xinput_helper.reset();
+ m_dinput_helper.reset();
+ }
+
private:
int init_helpers()
{
- int status = 0;
-
if (!m_xinput_helper)
{
- m_xinput_helper = std::make_shared<xinput_api_helper>();
- status = m_xinput_helper->initialize();
+ m_xinput_helper = std::make_unique<xinput_api_helper>();
+ int const status = m_xinput_helper->initialize();
if (status != 0)
{
- osd_printf_verbose("xinput_api_helper failed to initialize! Error: %u\n", static_cast<unsigned int>(status));
+ osd_printf_verbose("Failed to initialize XInput API! Error: %u\n", static_cast<unsigned int>(status));
return -1;
}
}
@@ -269,30 +266,15 @@ private:
if (!m_dinput_helper)
{
m_dinput_helper = std::make_unique<dinput_api_helper>();
- status = m_dinput_helper->initialize();
+ int const status = m_dinput_helper->initialize();
if (status != DI_OK)
{
- osd_printf_verbose("dinput_api_helper failed to initialize! Error: %u\n", static_cast<unsigned int>(status));
+ osd_printf_verbose("Failed to initialize DirectInput API! Error: %u\n", static_cast<unsigned int>(status));
return -1;
}
}
- return status;
- }
-
- //-----------------------------------------------------------------------------
- // Returns true if the DirectInput device is also an XInput device.
- //-----------------------------------------------------------------------------
- bool is_xinput_device(const GUID* pGuidProductFromDirectInput)
- {
- // Check each xinput device to see if this device's vid/pid matches
- for (auto devid = m_xinput_deviceids.begin(); devid != m_xinput_deviceids.end(); ++devid)
- {
- if (*devid == pGuidProductFromDirectInput->Data1)
- return true;
- }
-
- return false;
+ return 0;
}
//-----------------------------------------------------------------------------
@@ -302,54 +284,43 @@ private:
// Checking against a VID/PID of 0x028E/0x045E won't find 3rd party or future
// XInput devices.
//-----------------------------------------------------------------------------
- HRESULT get_xinput_devices(std::list<DWORD> &xinput_id_list) const
+ HRESULT get_xinput_devices(std::vector<DWORD> &xinput_deviceids)
{
- ComPtr<IWbemServices> pIWbemServices;
- ComPtr<IEnumWbemClassObject> pEnumDevices;
- ComPtr<IWbemLocator> pIWbemLocator;
- ComArray<IWbemClassObject> pDevices(20);
- bstr_ptr bstrDeviceID;
- bstr_ptr bstrClassName;
- bstr_ptr bstrNamespace;
- DWORD uReturned = 0;
- UINT iDevice;
- variant_wrapper var;
- HRESULT hr;
+ xinput_deviceids.clear();
- // CoInit if needed
- CoInitialize(nullptr);
+ HRESULT hr;
// Create WMI
+ Microsoft::WRL::ComPtr<IWbemLocator> pIWbemLocator;
hr = CoCreateInstance(
- __uuidof(WbemLocator),
- nullptr,
- CLSCTX_INPROC_SERVER,
- __uuidof(IWbemLocator),
- reinterpret_cast<void**>(pIWbemLocator.GetAddressOf()));
-
- if (FAILED(hr) || pIWbemLocator == nullptr)
+ __uuidof(WbemLocator),
+ nullptr,
+ CLSCTX_INPROC_SERVER,
+ __uuidof(IWbemLocator),
+ reinterpret_cast<void **>(pIWbemLocator.GetAddressOf()));
+ if (FAILED(hr) || !pIWbemLocator)
{
osd_printf_error("Creating WbemLocator failed. Error: 0x%X\n", static_cast<unsigned int>(hr));
return hr;
}
// Create BSTRs for WMI
- bstrNamespace = bstr_ptr(SysAllocString(L"\\\\.\\root\\cimv2"));
- bstrDeviceID = bstr_ptr(SysAllocString(L"DeviceID"));
- bstrClassName = bstr_ptr(SysAllocString(L"Win32_PNPEntity"));
+ bstr_ptr bstrNamespace = bstr_ptr(SysAllocString(L"\\\\.\\root\\cimv2"));
+ bstr_ptr bstrDeviceID = bstr_ptr(SysAllocString(L"DeviceID"));
+ bstr_ptr bstrClassName = bstr_ptr(SysAllocString(L"Win32_PNPEntity"));
// Connect to WMI
+ Microsoft::WRL::ComPtr<IWbemServices> pIWbemServices;
hr = pIWbemLocator->ConnectServer(
- bstrNamespace.get(),
- nullptr,
- nullptr,
- nullptr,
- 0L,
- nullptr,
- nullptr,
- pIWbemServices.GetAddressOf());
-
- if (FAILED(hr) || pIWbemServices == nullptr)
+ bstrNamespace.get(),
+ nullptr,
+ nullptr,
+ nullptr,
+ 0L,
+ nullptr,
+ nullptr,
+ pIWbemServices.GetAddressOf());
+ if (FAILED(hr) || !pIWbemServices)
{
osd_printf_error("Connecting to WMI Server failed. Error: 0x%X\n", static_cast<unsigned int>(hr));
return hr;
@@ -357,38 +328,41 @@ private:
// Switch security level to IMPERSONATE
(void)CoSetProxyBlanket(
- pIWbemServices.Get(),
- RPC_C_AUTHN_WINNT,
- RPC_C_AUTHZ_NONE,
- nullptr,
- RPC_C_AUTHN_LEVEL_CALL,
- RPC_C_IMP_LEVEL_IMPERSONATE,
- nullptr,
- 0);
+ pIWbemServices.Get(),
+ RPC_C_AUTHN_WINNT,
+ RPC_C_AUTHZ_NONE,
+ nullptr,
+ RPC_C_AUTHN_LEVEL_CALL,
+ RPC_C_IMP_LEVEL_IMPERSONATE,
+ nullptr,
+ 0);
// Get list of Win32_PNPEntity devices
+ Microsoft::WRL::ComPtr<IEnumWbemClassObject> pEnumDevices;
hr = pIWbemServices->CreateInstanceEnum(bstrClassName.get(), 0, nullptr, pEnumDevices.GetAddressOf());
- if (FAILED(hr) || pEnumDevices == nullptr)
+ if (FAILED(hr) || !pEnumDevices)
{
osd_printf_error("Getting list of Win32_PNPEntity devices failed. Error: 0x%X\n", static_cast<unsigned int>(hr));
return hr;
}
// Loop over all devices
- for (; ; )
+ ComArray<IWbemClassObject> pDevices(20);
+ variant_wrapper var;
+ for ( ; ; )
{
// Get a few at a time
+ DWORD uReturned = 0;
hr = pEnumDevices->Next(10000, pDevices.Size(), pDevices.ReleaseAndGetAddressOf(), &uReturned);
if (FAILED(hr))
{
osd_printf_error("Enumerating WMI classes failed. Error: 0x%X\n", static_cast<unsigned int>(hr));
return hr;
}
-
if (uReturned == 0)
break;
- for (iDevice = 0; iDevice < uReturned; iDevice++)
+ for (UINT iDevice = 0; iDevice < uReturned; iDevice++)
{
if (!pDevices[iDevice])
continue;
@@ -402,19 +376,18 @@ private:
if (wcsstr(var.Get().bstrVal, L"IG_"))
{
// If it does, then get the VID/PID from var.bstrVal
- DWORD dwPid = 0, dwVid = 0;
- WCHAR* strVid = wcsstr(var.Get().bstrVal, L"VID_");
+ DWORD dwVid = 0;
+ WCHAR const *const strVid = wcsstr(var.Get().bstrVal, L"VID_");
if (strVid && swscanf(strVid, L"VID_%4X", &dwVid) != 1)
dwVid = 0;
- WCHAR* strPid = wcsstr(var.Get().bstrVal, L"PID_");
+ DWORD dwPid = 0;
+ WCHAR const *const strPid = wcsstr(var.Get().bstrVal, L"PID_");
if (strPid && swscanf(strPid, L"PID_%4X", &dwPid) != 1)
dwPid = 0;
- DWORD dwVidPid = MAKELONG(dwVid, dwPid);
-
- // Add the VID/PID to a linked list
- xinput_id_list.push_back(dwVidPid);
+ // Add the VID/PID to a list
+ xinput_deviceids.push_back(MAKELONG(dwVid, dwPid));
}
}
}
@@ -429,12 +402,14 @@ private:
} // anonymous namespace
-#else // defined(OSD_WINDOWS)
+} // namespace osd
+
+#else // defined(OSD_WINDOWS) || defined(SDLMAME_WIN32)
#include "input_module.h"
-MODULE_NOT_SUPPORTED(winhybrid_joystick_module, OSD_JOYSTICKINPUT_PROVIDER, "winhybrid")
+namespace osd { namespace { MODULE_NOT_SUPPORTED(winhybrid_joystick_module, OSD_JOYSTICKINPUT_PROVIDER, "winhybrid") } }
-#endif // defined(OSD_WINDOWS)
+#endif // defined(OSD_WINDOWS) || defined(SDLMAME_WIN32)
-MODULE_DEFINITION(JOYSTICKINPUT_WINHYBRID, winhybrid_joystick_module)
+MODULE_DEFINITION(JOYSTICKINPUT_WINHYBRID, osd::winhybrid_joystick_module)
diff --git a/src/osd/modules/input/input_x11.cpp b/src/osd/modules/input/input_x11.cpp
index 0cd0caa64df..5230dfd7164 100644
--- a/src/osd/modules/input/input_x11.cpp
+++ b/src/osd/modules/input/input_x11.cpp
@@ -9,35 +9,39 @@
//============================================================
#include "input_module.h"
+
#include "modules/osdmodule.h"
#if defined(SDLMAME_SDL2) && !defined(SDLMAME_WIN32) && defined(USE_XINPUT) && USE_XINPUT
+#include "input_common.h"
+
+#include "sdl/osdsdl.h"
+
+// MAME headers
+#include "inpttype.h"
+
+// standard SDL header
+#include <SDL2/SDL.h>
+
// for X11 xinput
#include <X11/Xlib.h>
#include <X11/extensions/XInput.h>
#include <X11/Xutil.h>
-// standard sdl header
-#include <SDL2/SDL.h>
+#include <algorithm>
#include <cctype>
#include <cstddef>
-#include <mutex>
+#include <cstdio>
+#include <cstring>
#include <memory>
+#include <mutex>
#include <queue>
#include <string>
-#include <algorithm>
-
-// MAME headers
-#include "emu.h"
-#include "osdepend.h"
+#include <unordered_map>
-// MAMEOS headers
-#include "../lib/osdobj_common.h"
-#include "input_common.h"
-#include "../../sdl/osdsdl.h"
-#include "input_sdlcommon.h"
+namespace osd {
namespace {
@@ -52,20 +56,6 @@ static int key_release_type = INVALID_EVENT_TYPE;
static int proximity_in_type = INVALID_EVENT_TYPE;
static int proximity_out_type = INVALID_EVENT_TYPE;
-// state information for a lightgun
-struct lightgun_state
-{
- int32_t lX, lY;
- int32_t buttons[MAX_BUTTONS];
-};
-
-struct x11_api_state
-{
- XID deviceid; // X11 device id
- int32_t maxx, maxy;
- int32_t minx, miny;
-};
-
//============================================================
// DEBUG MACROS
//============================================================
@@ -74,56 +64,64 @@ struct x11_api_state
#define XI_DBG(format, ...) osd_printf_verbose(format, __VA_ARGS__)
#define print_motion_event(motion) print_motion_event_impl(motion)
-inline void print_motion_event_impl(XDeviceMotionEvent *motion)
+inline void print_motion_event_impl(XDeviceMotionEvent const *motion)
{
/*
* print a lot of debug informations of the motion event(s).
*/
osd_printf_verbose(
- "XDeviceMotionEvent:\n"
- " type: %d\n"
- " serial: %lu\n"
- " send_event: %d\n"
- " display: %p\n"
- " window: --\n"
- " deviceid: %lu\n"
- " root: --\n"
- " subwindow: --\n"
- " time: --\n"
- " x: %d, y: %d\n"
- " x_root: %d, y_root: %d\n"
- " state: %u\n"
- " is_hint: %2.2X\n"
- " same_screen: %d\n"
- " device_state: %u\n"
- " axes_count: %2.2X\n"
- " first_axis: %2.2X\n"
- " axis_data[6]: {%d,%d,%d,%d,%d,%d}\n",
- motion->type,
- motion->serial,
- motion->send_event,
- motion->display,
- /* motion->window, */
- motion->deviceid,
- /* motion->root */
- /* motion->subwindow */
- /* motion->time, */
- motion->x, motion->y,
- motion->x_root, motion->y_root,
- motion->state,
- motion->is_hint,
- motion->same_screen,
- motion->device_state,
- motion->axes_count,
- motion->first_axis,
- motion->axis_data[0], motion->axis_data[1], motion->axis_data[2], motion->axis_data[3], motion->axis_data[4], motion->axis_data[5]
- );
+ "XDeviceMotionEvent:\n"
+ " type: %d\n"
+ " serial: %lu\n"
+ " send_event: %d\n"
+ " display: %p\n"
+ " window: --\n"
+ " deviceid: %lu\n"
+ " root: --\n"
+ " subwindow: --\n"
+ " time: --\n"
+ " x: %d, y: %d\n"
+ " x_root: %d, y_root: %d\n"
+ " state: %u\n"
+ " is_hint: %2.2X\n"
+ " same_screen: %d\n"
+ " device_state: %u\n"
+ " axes_count: %2.2X\n"
+ " first_axis: %2.2X\n"
+ " axis_data[6]: {%d,%d,%d,%d,%d,%d}\n",
+ motion->type,
+ motion->serial,
+ motion->send_event,
+ motion->display,
+ /* motion->window, */
+ motion->deviceid,
+ /* motion->root */
+ /* motion->subwindow */
+ /* motion->time, */
+ motion->x, motion->y,
+ motion->x_root, motion->y_root,
+ motion->state,
+ motion->is_hint,
+ motion->same_screen,
+ motion->device_state,
+ motion->axes_count,
+ motion->first_axis,
+ motion->axis_data[0], motion->axis_data[1], motion->axis_data[2], motion->axis_data[3], motion->axis_data[4], motion->axis_data[5]);
}
#else
-#define XI_DBG(format, ...) while(0) {}
-#define print_motion_event(motion) while(0) {}
+#define XI_DBG(format, ...) do { } while (false)
+#define print_motion_event(motion) do { } while (false)
#endif
+
+inline std::string remove_spaces(const char *s)
+{
+ std::string output(s);
+ output.erase(std::remove_if(output.begin(), output.end(), isspace), output.end());
+ return output;
+}
+
+
//============================================================
// lightgun helpers: copy-past from xinfo
//============================================================
@@ -141,7 +139,7 @@ find_device_info(Display *display,
bool is_id = true;
XID id = static_cast<XID>(-1);
- for(loop = 0; loop < len; loop++)
+ for (loop = 0; loop < len; loop++)
{
if (!isdigit(name[loop]))
{
@@ -157,7 +155,7 @@ find_device_info(Display *display,
devices = XListInputDevices(display, &num_devices);
- for(loop = 0; loop < num_devices; loop++)
+ for (loop = 0; loop < num_devices; loop++)
{
osd_printf_verbose("Evaluating device with name: %s\n", devices[loop].name);
@@ -255,19 +253,64 @@ register_events(
return number;
}
-//============================================================
-// x11_event_manager
-//============================================================
-class x11_event_handler
+struct device_map
{
-public:
- virtual ~x11_event_handler() {}
+ static inline constexpr unsigned MAX_ENTRIES = 16;
+
+ struct {
+ std::string name;
+ int physical;
+ } map[MAX_ENTRIES];
+ int logical[MAX_ENTRIES];
+ int initialized;
+
+ void init(osd_options const &options, const char *opt, int max_devices, const char *label)
+ {
+ // initialize based on an input option prefix and max number of devices
+ char defname[20];
+
+ // The max devices the user specified, better not be bigger than the max the arrays can old
+ assert(max_devices <= MAX_ENTRIES);
+
+ // Initialize the map to default uninitialized values
+ for (int dev = 0; dev < MAX_ENTRIES; dev++)
+ {
+ map[dev].name.clear();
+ map[dev].physical = -1;
+ logical[dev] = -1;
+ }
+ initialized = 0;
+
+ // populate the device map up to the max number of devices
+ for (int dev = 0; dev < max_devices; dev++)
+ {
+ const char *dev_name;
+
+ // derive the parameter name from the option name and index. For instance: lightgun_index1 to lightgun_index8
+ sprintf(defname, "%s%d", opt, dev + 1);
+
+ // Get the user-specified name that matches the parameter
+ dev_name = options.value(defname);
- virtual void handle_event(XEvent &xevent) = 0;
+ // If they've specified a name and it's not "auto", treat it as a custom mapping
+ if (dev_name && *dev_name && strcmp(dev_name, OSDOPTVAL_AUTO))
+ {
+ // remove the spaces from the name store it in the index
+ map[dev].name = remove_spaces(dev_name);
+ osd_printf_verbose("%s: Logical id %d: %s\n", label, dev + 1, map[dev].name);
+ initialized = 1;
+ }
+ }
+ }
};
-class x11_event_manager : public event_manager_t<x11_event_handler>
+
+//============================================================
+// x11_event_manager
+//============================================================
+
+class x11_event_manager : public event_subscription_manager<XEvent, int>
{
private:
struct x_cleanup
@@ -288,14 +331,12 @@ private:
x_ptr<Display> m_display;
- x11_event_manager() : event_manager_t()
- {
- }
+ x11_event_manager() = default;
public:
- Display * display() const { return m_display.get(); }
+ Display *display() const { return m_display.get(); }
- static x11_event_manager& instance()
+ static x11_event_manager &instance()
{
static x11_event_manager s_instance;
return s_instance;
@@ -303,7 +344,7 @@ public:
int initialize()
{
- std::lock_guard<std::mutex> scope_lock(m_lock);
+ std::lock_guard<std::mutex> scope_lock(subscription_mutex());
if (m_display)
return 0;
@@ -325,31 +366,24 @@ public:
return 0;
}
- void process_events(running_machine &machine) override
+ void process_events()
{
- std::lock_guard<std::mutex> scope_lock(m_lock);
- XEvent xevent;
+ std::lock_guard<std::mutex> scope_lock(subscription_mutex());
// If X11 has become invalid for some reason, XPending will crash. Assert instead.
assert(m_display);
- //Get XInput events
+ // Get XInput events
while (XPending(m_display.get()) != 0)
{
- XNextEvent(m_display.get(), &xevent);
-
- // Find all subscribers for the event type
- auto const subscribers = m_subscription_index.equal_range(xevent.type);
-
- // Dispatch the events
- std::for_each(
- subscribers.first,
- subscribers.second,
- [&xevent] (auto &pair) { pair.second->handle_event(xevent); });
+ XEvent event;
+ XNextEvent(m_display.get(), &event);
+ dispatch_event(event.type, event);
}
}
};
+
//============================================================
// x11_input_device
//============================================================
@@ -357,15 +391,23 @@ public:
class x11_input_device : public event_based_device<XEvent>
{
public:
- x11_api_state x11_state;
-
- x11_input_device(running_machine &machine, std::string &&name, std::string &&id, input_device_class devclass, input_module &module) :
- event_based_device(machine, std::move(name), std::move(id), devclass, module),
- x11_state({0})
+ x11_input_device(
+ std::string &&name,
+ std::string &&id,
+ input_module &module,
+ XDeviceInfo const *info) :
+ event_based_device(std::move(name), std::move(id), module),
+ m_device_id(info ? info->id : 0)
{
}
+
+ XID const &device_id() const { return m_device_id; }
+
+protected:
+ XID const m_device_id; // X11 device ID
};
+
//============================================================
// x11_lightgun_device
//============================================================
@@ -373,55 +415,124 @@ public:
class x11_lightgun_device : public x11_input_device
{
public:
- lightgun_state lightgun;
+ x11_lightgun_device(
+ std::string &&name,
+ std::string &&id,
+ input_module
+ &module,
+ XDeviceInfo *info) :
+ x11_input_device(std::move(name), std::move(id), module, info),
+ m_axis_count(0),
+ m_button_count(0),
+ m_maxx(0),
+ m_maxy(0),
+ m_minx(0),
+ m_miny(0),
+ m_lightgun({ 0 })
+ {
+ if (info && (info->num_classes > 0))
+ {
+ // Grab device info and translate to stuff MAME can use
+ XAnyClassPtr any = static_cast<XAnyClassPtr>(info->inputclassinfo);
+ for (int i = 0; i < info->num_classes; i++)
+ {
+ switch (any->c_class)
+ {
+ // Set the axis min/max ranges if we got them
+ case ValuatorClass:
+ {
+ auto const valuator_info = reinterpret_cast<XValuatorInfoPtr>(any);
+ auto axis_info = reinterpret_cast<XAxisInfoPtr>(reinterpret_cast<char *>(valuator_info) + sizeof(XValuatorInfo));
+ for (int j = 0; (j < valuator_info->num_axes) && (j < 2); j++, axis_info++)
+ {
+ if (j == 0)
+ {
+ XI_DBG("Set minx=%d, maxx=%d\n", axis_info->min_value, axis_info->max_value);
+ m_axis_count = 1;
+ m_maxx = axis_info->max_value;
+ m_minx = axis_info->min_value;
+ }
+
+ if (j == 1)
+ {
+ XI_DBG("Set miny=%d, maxy=%d\n", axis_info->min_value, axis_info->max_value);
+ m_axis_count = 2;
+ m_maxy = axis_info->max_value;
+ m_miny = axis_info->min_value;
+ }
+ }
+ }
+ break;
+
+ // Count the lightgun buttons based on what we read
+ case ButtonClass:
+ {
+ XButtonInfoPtr b = reinterpret_cast<XButtonInfoPtr>(any);
+ if (b->num_buttons < 0)
+ m_button_count = 0;
+ else if (b->num_buttons <= MAX_BUTTONS)
+ m_button_count = b->num_buttons;
+ else
+ m_button_count = MAX_BUTTONS;
+ }
+ break;
+ }
- x11_lightgun_device(running_machine &machine, std::string &&name, std::string &&id, input_module &module) :
- x11_input_device(machine, std::move(name), std::move(id), DEVICE_CLASS_LIGHTGUN, module),
- lightgun({0})
+ any = reinterpret_cast<XAnyClassPtr>(reinterpret_cast<char *>(any) + any->length);
+ }
+ }
+ }
+
+ virtual void reset() override
+ {
+ memset(&m_lightgun, 0, sizeof(m_lightgun));
+ }
+
+ virtual void configure(input_device &device) override
{
+ // Add buttons
+ for (int button = 0; button < m_button_count; button++)
+ {
+ input_item_id const itemid = input_item_id(ITEM_ID_BUTTON1 + button);
+ device.add_item(default_button_name(button), std::string_view(), itemid, generic_button_get_state<std::int32_t>, &m_lightgun.buttons[button]);
+ }
+
+ // Add X and Y axis
+ if (1 <= m_axis_count)
+ device.add_item("X", std::string_view(), ITEM_ID_XAXIS, generic_axis_get_state<std::int32_t>, &m_lightgun.lX);
+ if (2 <= m_axis_count)
+ device.add_item("Y", std::string_view(), ITEM_ID_YAXIS, generic_axis_get_state<std::int32_t>, &m_lightgun.lY);
}
- void process_event(XEvent &xevent) override
+ virtual void process_event(XEvent const &xevent) override
{
if (xevent.type == motion_type)
{
- XDeviceMotionEvent *motion = reinterpret_cast<XDeviceMotionEvent *>(&xevent);
+ auto const motion = reinterpret_cast<XDeviceMotionEvent const *>(&xevent);
print_motion_event(motion);
- /*
- * We have to check with axis will start on array index 0.
- * We have also to check the number of axes that are stored in the array.
- */
+ // We have to check with axis will start on array index 0.
+ // We also have to check the number of axes that are stored in the array.
switch (motion->first_axis)
{
- /*
- * Starting with x, check number of axis, if there is also the y axis stored.
- */
+ // Starting with x, check number of axes, if there is also the y axis stored.
case 0:
if (motion->axes_count >= 1)
- {
- lightgun.lX = normalize_absolute_axis(motion->axis_data[0], x11_state.minx, x11_state.maxx);
- if (motion->axes_count >= 2)
- {
- lightgun.lY = normalize_absolute_axis(motion->axis_data[1], x11_state.miny, x11_state.maxy);
- }
- }
+ m_lightgun.lX = normalize_absolute_axis(motion->axis_data[0], m_minx, m_maxx);
+ if (motion->axes_count >= 2)
+ m_lightgun.lY = normalize_absolute_axis(motion->axis_data[1], m_miny, m_maxy);
break;
- /*
- * Starting with y, ...
- */
+ // Starting with y, ...
case 1:
if (motion->axes_count >= 1)
- {
- lightgun.lY = normalize_absolute_axis(motion->axis_data[0], x11_state.miny, x11_state.maxy);
- }
+ m_lightgun.lY = normalize_absolute_axis(motion->axis_data[0], m_miny, m_maxy);
break;
}
}
else if (xevent.type == button_press_type || xevent.type == button_release_type)
{
- XDeviceButtonEvent *button = reinterpret_cast<XDeviceButtonEvent *>(&xevent);
+ auto const button = reinterpret_cast<XDeviceButtonEvent const *>(&xevent);
/*
* SDL/X11 Number the buttons 1,2,3, while windows and other parts of MAME
@@ -429,37 +540,50 @@ public:
* -1 the button number to align the numbering schemes.
*/
int button_number = button->button;
- switch (button_number)
+ if (button_number <= MAX_BUTTONS)
{
+ switch (button_number)
+ {
case 2:
- button_number = 3;
- break;
case 3:
- button_number = 2;
+ button_number ^= 1;
break;
+ }
+ m_lightgun.buttons[button_number - 1] = (xevent.type == button_press_type) ? 0x80 : 0;
}
- lightgun.buttons[button_number - 1] = (xevent.type == button_press_type) ? 0x80 : 0;
}
}
- void reset() override
+private:
+ struct lightgun_state
{
- memset(&lightgun, 0, sizeof(lightgun));
- }
+ int32_t lX, lY;
+ int32_t buttons[MAX_BUTTONS];
+ };
+
+ int m_axis_count;
+ int m_button_count;
+ int32_t m_maxx;
+ int32_t m_maxy;
+ int32_t m_minx;
+ int32_t m_miny;
+ lightgun_state m_lightgun;
};
+
//============================================================
// x11_lightgun_module
//============================================================
-class x11_lightgun_module : public input_module_base, public x11_event_handler
+class x11_lightgun_module : public input_module_impl<x11_input_device, osd_common_t>, public x11_event_manager::subscriber
{
private:
- device_map_t m_lightgun_map;
- Display * m_display;
+ device_map m_lightgun_map;
+ Display *m_display;
+
public:
x11_lightgun_module() :
- input_module_base(OSD_LIGHTGUNINPUT_PROVIDER, "x11"),
+ input_module_impl<x11_input_device, osd_common_t>(OSD_LIGHTGUNINPUT_PROVIDER, "x11"),
m_display(nullptr)
{
}
@@ -467,113 +591,109 @@ public:
virtual bool probe() override
{
// If there is no X server, X11 lightguns cannot be supported
- if (!XOpenDisplay(nullptr))
- {
+ Display *const display = XOpenDisplay(nullptr);
+ if (!display)
return false;
- }
+ XCloseDisplay(display);
return true;
}
- void input_init(running_machine &machine) override
+ virtual int init(osd_interface &osd, osd_options const &options) override
{
- osd_printf_verbose("Lightgun: Begin initialization\n");
-
- m_lightgun_map.init(machine, SDLOPTION_LIGHTGUNINDEX, 8, "Lightgun mapping");
-
+ // If the X server has become invalid, a crash can occur
x11_event_manager::instance().initialize();
m_display = x11_event_manager::instance().display();
+ if (!m_display)
+ return -1;
- // If the X server has become invalid, a crash can occur
- assert(m_display != nullptr);
+ return input_module_impl<x11_input_device, osd_common_t>::init(osd, options);
+ }
+
+ virtual void input_init(running_machine &machine) override
+ {
+ assert(m_display);
+
+ input_module_impl<x11_input_device, osd_common_t>::input_init(machine);
+
+ osd_printf_verbose("Lightgun: Begin initialization\n");
+
+ m_lightgun_map.init(*options(), SDLOPTION_LIGHTGUNINDEX, 8, "Lightgun mapping");
// Loop through all 8 possible devices
for (int index = 0; index < 8; index++)
{
- XDeviceInfo *info;
-
// Skip if the name is empty
- if (m_lightgun_map.map[index].name.length() == 0)
+ if (m_lightgun_map.map[index].name.empty())
continue;
+ // Find the device info associated with the name
std::string const &name = m_lightgun_map.map[index].name;
- char defname[512];
-
- // Register and add the device
- auto *devinfo = create_lightgun_device(machine, index);
osd_printf_verbose("%i: %s\n", index, name);
+ XDeviceInfo *const info = find_device_info(m_display, name.c_str(), 0);
+ if (!info)
+ osd_printf_verbose("Lightgun: Can't find device %s!\n", name);
- // Find the device info associated with the name
- info = find_device_info(m_display, name.c_str(), 0);
+ // previously had code to use "NC%d" format if name was empty
+ // but that couldn't happen because device creation would be skipped
- // If we couldn't find the device, skip
- if (!info)
- {
- osd_printf_verbose("Can't find device %s!\n", name);
- continue;
- }
+ // Register and add the device
+ create_device<x11_lightgun_device>(
+ DEVICE_CLASS_LIGHTGUN,
+ std::string(name),
+ std::string(name),
+ info);
- //Grab device info and translate to stuff mame can use
- if (info->num_classes > 0)
+ // Register this device to receive event notifications
+ if (info)
{
- // Add the lightgun buttons based on what we read
- add_lightgun_buttons(static_cast<XAnyClassPtr>(info->inputclassinfo), info->num_classes, *devinfo);
-
- // Also, set the axix min/max ranges if we got them
- set_lightgun_axis_props(static_cast<XAnyClassPtr>(info->inputclassinfo), info->num_classes, *devinfo);
+ int const events_registered = register_events(m_display, info, name.c_str(), 0);
+ osd_printf_verbose("Device %i: Registered %i events.\n", int(info->id), events_registered);
}
+ }
- // Add X and Y axis
- sprintf(defname, "X %s", devinfo->name().c_str());
- devinfo->device()->add_item(defname, ITEM_ID_XAXIS, generic_axis_get_state<std::int32_t>, &devinfo->lightgun.lX);
-
- sprintf(defname, "Y %s", devinfo->name().c_str());
- devinfo->device()->add_item(defname, ITEM_ID_YAXIS, generic_axis_get_state<std::int32_t>, &devinfo->lightgun.lY);
-
- // Save the device id
- devinfo->x11_state.deviceid = info->id;
+ // register ourself to handle events from event manager
+ int const event_types[] = { motion_type, button_press_type, button_release_type };
+ osd_printf_verbose("Events types to register: motion:%d, press:%d, release:%d\n", motion_type, button_press_type, button_release_type);
+ subscribe(x11_event_manager::instance(), event_types);
- // Register this device to receive event notifications
- int events_registered = register_events(m_display, info, m_lightgun_map.map[index].name.c_str(), 0);
- osd_printf_verbose("Device %i: Registered %i events.\n", static_cast<int>(info->id), events_registered);
+ osd_printf_verbose("Lightgun: End initialization\n");
+ }
- // register ourself to handle events from event manager
- int const event_types[] = { motion_type, button_press_type, button_release_type };
- osd_printf_verbose("Events types to register: motion:%d, press:%d, release:%d\n", motion_type, button_press_type, button_release_type);
- x11_event_manager::instance().subscribe(event_types, this);
- }
+ virtual void exit() override
+ {
+ // unsubscribe from events
+ unsubscribe();
- osd_printf_verbose("Lightgun: End initialization\n");
+ input_module_impl<x11_input_device, osd_common_t>::exit();
}
- bool should_poll_devices(running_machine &machine) override
+ virtual bool should_poll_devices() override
{
- return sdl_event_manager::instance().has_focus();
+ return osd().has_focus();
}
- void before_poll(running_machine &machine) override
+ virtual void before_poll() override
{
- if (!should_poll_devices(machine))
- return;
+ // trigger the SDL event manager so it can process window events
+ input_module_impl<x11_input_device, osd_common_t>::before_poll();
// Tell the event manager to process events and push them to the devices
- x11_event_manager::instance().process_events(machine);
-
- // Also trigger the SDL event manager so it can process window events
- sdl_event_manager::instance().process_events(machine);
+ if (should_poll_devices())
+ x11_event_manager::instance().process_events();
}
- void handle_event(XEvent &xevent) override
+ virtual void handle_event(XEvent const &xevent) override
{
XID deviceid;
if (xevent.type == motion_type)
{
- XDeviceMotionEvent *motion = reinterpret_cast<XDeviceMotionEvent *>(&xevent);
+ auto const motion = reinterpret_cast<XDeviceMotionEvent const *>(&xevent);
deviceid = motion->deviceid;
}
else if (xevent.type == button_press_type || xevent.type == button_release_type)
{
- XDeviceButtonEvent *button = reinterpret_cast<XDeviceButtonEvent *>(&xevent);
+ auto const button = reinterpret_cast<XDeviceButtonEvent const *>(&xevent);
deviceid = button->deviceid;
}
else
@@ -582,102 +702,27 @@ public:
}
// Figure out which lightgun this event id destined for
- auto target_device = std::find_if(devicelist().begin(), devicelist().end(), [deviceid](auto &device)
- {
- std::unique_ptr<device_info> &ptr = device;
- return downcast<x11_input_device*>(ptr.get())->x11_state.deviceid == deviceid;
- });
+ auto target_device = std::find_if(
+ devicelist().begin(),
+ devicelist().end(),
+ [&deviceid] (auto &device) { return device->device_id() == deviceid; });
// If we find a matching lightgun, dispatch the event to the lightgun
if (target_device != devicelist().end())
- {
- downcast<x11_input_device*>((*target_device).get())->queue_events(&xevent, 1);
- }
- }
-
-private:
- x11_lightgun_device *create_lightgun_device(running_machine &machine, int index)
- {
- if (m_lightgun_map.map[index].name.length() == 0)
- {
- if (m_lightgun_map.initialized)
- {
- char tempname[20];
- snprintf(tempname, std::size(tempname), "NC%d", index);
- return &devicelist().create_device<x11_lightgun_device>(machine, tempname, tempname, *this);
- }
- else
- {
- return nullptr;
- }
- }
-
- return &devicelist().create_device<x11_lightgun_device>(machine, std::string(m_lightgun_map.map[index].name), std::string(m_lightgun_map.map[index].name), *this);
- }
-
- void add_lightgun_buttons(XAnyClassPtr first_info_class, int num_classes, x11_lightgun_device &devinfo) const
- {
- XAnyClassPtr any = first_info_class;
-
- for (int i = 0; i < num_classes; i++)
- {
- switch (any->c_class)
- {
- case ButtonClass:
- XButtonInfoPtr b = reinterpret_cast<XButtonInfoPtr>(any);
- for (int button = 0; button < b->num_buttons; button++)
- {
- input_item_id itemid = static_cast<input_item_id>(ITEM_ID_BUTTON1 + button);
- devinfo.device()->add_item(default_button_name(button), itemid, generic_button_get_state<std::int32_t>, &devinfo.lightgun.buttons[button]);
- }
- break;
- }
-
- any = reinterpret_cast<XAnyClassPtr>(reinterpret_cast<char *>(any) + any->length);
- }
- }
-
- void set_lightgun_axis_props(XAnyClassPtr first_info_class, int num_classes, x11_lightgun_device &devinfo) const
- {
- XAnyClassPtr any = first_info_class;
-
- for (int i = 0; i < num_classes; i++)
- {
- switch (any->c_class)
- {
- case ValuatorClass:
- XValuatorInfoPtr valuator_info = reinterpret_cast<XValuatorInfoPtr>(any);
- XAxisInfoPtr axis_info = reinterpret_cast<XAxisInfoPtr>(reinterpret_cast<char *>(valuator_info) + sizeof(XValuatorInfo));
- for (int j = 0; j < valuator_info->num_axes; j++, axis_info++)
- {
- if (j == 0)
- {
- XI_DBG("Set minx=%d, maxx=%d\n", axis_info->min_value, axis_info->max_value);
- devinfo.x11_state.maxx = axis_info->max_value;
- devinfo.x11_state.minx = axis_info->min_value;
- }
-
- if (j == 1)
- {
- XI_DBG("Set miny=%d, maxy=%d\n", axis_info->min_value, axis_info->max_value);
- devinfo.x11_state.maxy = axis_info->max_value;
- devinfo.x11_state.miny = axis_info->min_value;
- }
- }
- break;
- }
-
- any = reinterpret_cast<XAnyClassPtr>(reinterpret_cast<char *>(any) + any->length);
- }
+ (*target_device)->queue_events(&xevent, 1);
}
};
} // anonymous namespace
+} // namespace osd
+
+
#else // defined(SDLMAME_SDL2) && !defined(SDLMAME_WIN32) && defined(USE_XINPUT) && USE_XINPUT
-MODULE_NOT_SUPPORTED(x11_lightgun_module, OSD_LIGHTGUNINPUT_PROVIDER, "x11")
+namespace osd { namespace { MODULE_NOT_SUPPORTED(x11_lightgun_module, OSD_LIGHTGUNINPUT_PROVIDER, "x11") } }
#endif // defined(SDLMAME_SDL2) && !defined(SDLMAME_WIN32) && defined(USE_XINPUT) && USE_XINPUT
-MODULE_DEFINITION(LIGHTGUN_X11, x11_lightgun_module)
+
+MODULE_DEFINITION(LIGHTGUN_X11, osd::x11_lightgun_module)
diff --git a/src/osd/modules/input/input_xinput.cpp b/src/osd/modules/input/input_xinput.cpp
index 22171895c97..474ef6fe7ff 100644
--- a/src/osd/modules/input/input_xinput.cpp
+++ b/src/osd/modules/input/input_xinput.cpp
@@ -1,307 +1,3141 @@
// license:BSD-3-Clause
-// copyright-holders:Brad Hughes
+// copyright-holders:Brad Hughes, Vas Crabb
//============================================================
//
// input_xinput.cpp - XInput API input support for Windows
//
//============================================================
+/*
-#include "modules/osdmodule.h"
+XInput is infamously inflexible. It currently only supports a single
+controller type (game controller) with a fixed report format. The
+report format includes:
+* 16-bit field for single-bit buttons and D-pad directions (two bits
+ undefined)
+* Two 8-bit axis values, used for triggers, pedals, buttons or throttle
+ and rudder controls, depending on the controller
+* Four 16-bit axis values, used for joysticks, steering wheels or hat
+ switches, depending on the controller
+
+Some button names have changed at various times:
+* Face buttons White and Black became shoulder buttons LB and RB,
+ respectively.
+* Navigation buttons Start and Back became Menu and View, respectively.
+
+Subtype Gamepad Wheel Arcade stick Arcade pad Flight stick Dance pad Guitar Drum kit
+
+D-pad D-pad D-pad Joystick D-pad Foot switch D-Pad/Strum D-pad
+L trigger Trigger Brake Button Button Rudder Pickup select^
+R trigger Trigger Accelerator Button Button Throttle ^
+L stick X Stick Wheel Roll
+L stick Y Stick Pitch
+R stick X Stick Hat left/right Whammy bar
+R stick Y Stick Hat up/down Orientation
+
+A Button Button Button Button Primary fire Foot switch Fret 1 Floor tom
+B Button Button Button Button Secondary fire Foot switch Fret 2 Snare
+X Button Button Button Button Button Foot switch Fret 4 Low tom
+Y Button Button Button Button Button Foot switch Fret 3 High tom
+LB Button Button Button^ Button Button^ Fret 5 Bass drum
+RB Button Button Button^ Button Button^ Button^ Button^
+LSB Button Button^ Button^ Button^ Button^ Fret modifier^ Button^
+RSB Button Button^ Button^ Button^ Button^ Button^ Button^
+
+^ optional
+
+
+At least the vast majority of controllers report 8-bit trigger
+resolution and 10-bit stick resolution, even when the physical controls
+use digital switches. Resolution can't be used to reliably detect
+nominal analog axes controlled by switches.
+
+Some arcade sticks report unknown or gamepad subtype, but have a single
+digital joystick with a switch to select between controlling the D-pad,
+left stick and right stick. You can't assume that all three can be
+controlled at the same time.
+
+Many controllers don't correctly report the absence of analog sticks.
+
+
+Some controllers use capabilities to indicate extended controller type
+information:
+
+ Type Sub LSX LSY RSX
+Band Hero Wireless Guitar 0x01 0x07 0x1430 0x0705 0x0001
+Band Hero Wireless Drum Kit 0x01 0x08 0x1430 0x0805 0x0001
+DJ Hero 2 Turntable 0x01 0x17 0x1430 0x1705 0x0001
+Rock Band 3 Wireless Keyboard 0x01 0x0f 0x1bad 0x1330 0x0004
+
+
+There are multiple physical button layouts for arcade sticks, for
+example:
+
+Gamester Xbox Arcade Stick, Hori Real Arcade Pro EX
+LT X Y LB
+RT A B RB
+
+PXN 0082 Arcade Stick
+LB X Y RB
+LT A B RT
+
+Mortal Kombat Tournament Edition Arcade Stick
+ X Y
+ RT
+LB A B
+
+Hori Fighting Stick EX2
+ B X Y
+A LT RT
+
+Hori Real Arcade Pro VX-SA Kai, Razer Atrox
+ B X Y LB
+A LT RT RB
+
+Hori Real Arcade Pro.V Kai, Mad Catz EGO Arcade Stick, Mayflash F300, Mayflash F500
+ X Y RB LB
+A B RT LT
+
+Mad Catz WWE All Stars Brawl Stick
+ X Y LB LT
+A B RB RT
+
+Arcade pads typically have six face buttons, and come with different
+layouts corresponding to the latter two arcade stick layouts, with the
+rightmost column on the shoulder buttons. Examples of face button
+layouts:
+
+Hori Fighting Commander OCTA, Mad Catz Street Fighter IV FightPad, PowerA FUSION Wired FightPad
+X Y RB
+A B RT
+
+Hori Pad EX Turbo 2, Mad Catz WWE All Stars BrawlPad, Mortal Kombat X Fight Pad, PDP Versus Fighting Pad
+X Y LB
+A B RB
-#if defined(OSD_WINDOWS)
-#include "emu.h"
+Dance mats usually have this layout:
+BK ST
+B U A
+L R
+Y D X
+
+This layout seems somewhat unusual:
+BK ST
+A U B
+L R
+X D Y
+
+This layout is also available but rare:
+BK ST
+A U B
+L R
+Y D X
+
+
+Drum kits also have multiple layouts.
+
+Rock Band:
+B Y X A
+ LB
+
+Guitar Hero:
+ Y RB
+A X B
+ LB
+
+
+Rock Band keyboards use axes as bit fields:
+
+LT 7 C
+LT 6 C#
+LT 5 D
+LT 4 D#
+LT 3 E
+LT 2 F
+LT 1 F#
+LT 0 G
+RT 7 G#
+RT 6 A
+RT 5 A#
+RT 4 B
+RT 3 C
+RT 2 C#
+RT 1 D
+RT 0 D#
+LSX 7 E
+LSX 6 F
+LSX 5 F#
+LSX 4 G
+LSX 3 G#
+LSX 2 A
+LSX 1 A#
+LSX 0 B
+LSX 15 C
+
+*/
+
+#include "modules/osdmodule.h"
+
+#if defined(OSD_WINDOWS) || defined(SDLMAME_WIN32)
#include "input_xinput.h"
-// standard windows headers
-#include <windows.h>
+#include "assignmenthelper.h"
+
+#include "interface/inputseq.h"
+#include "modules/lib/osdobj_common.h"
+
+// emu
+#include "inpttype.h"
+
+// lib/util
+#include "util/coretmpl.h"
+
+#include "eminline.h"
+
+#include <algorithm>
+#include <cstdint>
+#include <iterator>
+#include <string>
+#include <tuple>
+#include <utility>
#define XINPUT_LIBRARIES { "xinput1_4.dll", "xinput9_1_0.dll" }
-#define XINPUT_AXIS_MINVALUE -32767
-#define XINPUT_AXIS_MAXVALUE 32767
+#define XINPUT_AXIS_MINVALUE (-32'767)
+#define XINPUT_AXIS_MAXVALUE (32'767)
+
+namespace osd {
namespace {
-// default axis names
-const char *const xinput_axis_name[] =
+using util::BIT;
+
+
+char const *const AXIS_NAMES_GAMEPAD[]{
+ "LSX",
+ "LSY",
+ "RSX",
+ "RSY",
+ "LT",
+ "RT" };
+
+char const *const AXIS_NAMES_WHEEL[]{
+ "Wheel",
+ "LSY",
+ "RSX",
+ "RSY",
+ "Brake",
+ "Accelerator" };
+
+char const *const AXIS_NAMES_GUITAR[]{
+ "LSX",
+ "LSY",
+ "Whammy Bar",
+ "Orientation",
+ "Pickup Selector",
+ "RT" };
+
+input_item_id const AXIS_IDS_GAMEPAD[]{
+ ITEM_ID_XAXIS,
+ ITEM_ID_YAXIS,
+ ITEM_ID_ZAXIS,
+ ITEM_ID_RZAXIS,
+ ITEM_ID_SLIDER1,
+ ITEM_ID_SLIDER2 };
+
+char const *const HAT_NAMES_GAMEPAD[]{
+ "D-pad Up",
+ "D-pad Down",
+ "D-pad Left",
+ "D-pad Right",
+ "POV Hat Up",
+ "POV Hat Down",
+ "POV Hat Left",
+ "POV Hat Right" };
+
+char const *const HAT_NAMES_ARCADE_STICK[]{
+ "Joystick Up",
+ "Joystick Down",
+ "Joystick Left",
+ "Joystick Right",
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr };
+
+char const *const HAT_NAMES_GUITAR[]{
+ "Strum/D-pad Up",
+ "Strum/D-pad Down",
+ "D-pad Left",
+ "D-pad Right" };
+
+char const *const BUTTON_NAMES_GAMEPAD[]{
+ "A",
+ "B",
+ "X",
+ "Y",
+ "LT",
+ "RT",
+ "LB",
+ "RB",
+ "LSB",
+ "RSB" };
+
+char const *const BUTTON_NAMES_FLIGHT_STICK[]{
+ "A",
+ "B",
+ "X",
+ "Y",
+ "LB",
+ "RB",
+ "LSB",
+ "RSB" };
+
+char const *const BUTTON_NAMES_GUITAR[]{
+ "Fret 1",
+ "Fret 2",
+ "Fret 3",
+ "Fret 4",
+ "Fret 5",
+ "Fret Modifier",
+ "RB",
+ "RSB" };
+
+char const *const BUTTON_NAMES_DRUMKIT[]{
+ "Green", // floor tom
+ "Red", // snare
+ "Blue", // low tom
+ "Yellow", // Rock Band high tom, Guitar Hero hi-hat
+ "Orange", // Guitar Hero crash cymbal
+ "Bass Drum",
+ "LSB",
+ "RSB" };
+
+char const *const BUTTON_NAMES_KEYBOARD[]{
+ "A",
+ "B",
+ "X",
+ "Y",
+ "LB",
+ "RB",
+ "LSB",
+ "RSB" };
+
+
+
+//============================================================
+// base class for XInput controller handlers
+//============================================================
+
+class xinput_device_base : public device_info, protected joystick_assignment_helper
{
- "LSX",
- "LSY",
- "RSX",
- "RSY"
+protected:
+ xinput_device_base(
+ std::string &&name,
+ std::string &&id,
+ input_module &module,
+ u32 player,
+ XINPUT_CAPABILITIES const &caps,
+ xinput_api_helper const &helper);
+
+ // capabilities
+ BYTE device_type() const { return m_capabilities.Type; }
+ BYTE device_subtype() const { return m_capabilities.SubType; }
+ bool has_button(WORD mask) const { return (m_capabilities.Gamepad.wButtons & mask) != 0; }
+ bool has_trigger_left() const { return m_capabilities.Gamepad.bLeftTrigger != 0; }
+ bool has_trigger_right() const { return m_capabilities.Gamepad.bRightTrigger != 0; }
+ bool has_thumb_left_x() const { return m_capabilities.Gamepad.sThumbLX != 0; }
+ bool has_thumb_left_y() const { return m_capabilities.Gamepad.sThumbLY != 0; }
+ bool has_thumb_right_x() const { return m_capabilities.Gamepad.sThumbRX != 0; }
+ bool has_thumb_right_y() const { return m_capabilities.Gamepad.sThumbRY != 0; }
+
+ // device state
+ WORD buttons() const { return m_xinput_state.Gamepad.wButtons; }
+ BYTE trigger_left() const { return m_xinput_state.Gamepad.bLeftTrigger; }
+ BYTE trigger_right() const { return m_xinput_state.Gamepad.bRightTrigger; }
+ SHORT thumb_left_x() const { return m_xinput_state.Gamepad.sThumbLX; }
+ SHORT thumb_left_y() const { return m_xinput_state.Gamepad.sThumbLY; }
+ SHORT thumb_right_x() const { return m_xinput_state.Gamepad.sThumbRX; }
+ SHORT thumb_right_y() const { return m_xinput_state.Gamepad.sThumbRY; }
+
+ bool read_state();
+ bool is_reset() const { return m_reset; }
+ void set_reset() { m_reset = true; }
+
+protected:
+ template <unsigned M, unsigned N>
+ static bool assign_ui_button(
+ input_device::assignment_vector &assignments,
+ ioport_type type,
+ unsigned preferred,
+ input_item_id (&switch_ids)[M],
+ unsigned const (&numbered_buttons)[N],
+ unsigned button_count);
+
+ template <unsigned M, unsigned N>
+ static void assign_ui_actions(
+ input_device::assignment_vector &assignments,
+ unsigned preferred_back,
+ unsigned preferred_clear,
+ unsigned preferred_help,
+ unsigned start,
+ unsigned back,
+ input_item_id (&switch_ids)[M],
+ unsigned const (&numbered_buttons)[N],
+ unsigned button_count);
+
+private:
+ bool probe_extended_type();
+
+ u32 const m_player_index;
+ XINPUT_CAPABILITIES m_capabilities;
+ XINPUT_STATE m_xinput_state;
+ bool m_reset;
+
+ xinput_api_helper const &m_xinput_helper;
};
-const input_item_id xinput_axis_ids[] =
+
+xinput_device_base::xinput_device_base(
+ std::string &&name,
+ std::string &&id,
+ input_module &module,
+ u32 player,
+ XINPUT_CAPABILITIES const &caps,
+ xinput_api_helper const &helper) :
+ device_info(std::move(name), std::move(id), module),
+ m_player_index(player),
+ m_capabilities(caps),
+ m_xinput_state{ 0 },
+ m_reset(true),
+ m_xinput_helper(helper)
{
- ITEM_ID_XAXIS,
- ITEM_ID_YAXIS,
- ITEM_ID_RXAXIS,
- ITEM_ID_RYAXIS
-};
+ // get friendly names for controller type and subtype
+ char const *type_name = "unsupported";
+ char const *subtype_name = "unsupported";
+ switch (m_capabilities.Type)
+ {
+ case XINPUT_DEVTYPE_GAMEPAD:
+ type_name = "game controller";
+ switch (m_capabilities.SubType)
+ {
+ case 0x00: // XINPUT_DEVSUBTYPE_UNKNOWN: work around MinGW header issues
+ subtype_name = "unknown";
+ break;
+ case XINPUT_DEVSUBTYPE_GAMEPAD:
+ subtype_name = "gamepad";
+ break;
+ case XINPUT_DEVSUBTYPE_WHEEL:
+ subtype_name = "wheel";
+ break;
+ case XINPUT_DEVSUBTYPE_ARCADE_STICK:
+ subtype_name = "arcade stick";
+ break;
+ case 0x04: // XINPUT_DEVSUBTYPE_FLIGHT_STICK: work around MinGW header issues
+ subtype_name = "flight stick";
+ break;
+ case XINPUT_DEVSUBTYPE_DANCE_PAD:
+ subtype_name = "dance pad";
+ break;
+ case XINPUT_DEVSUBTYPE_GUITAR:
+ subtype_name = "guitar";
+ break;
+ case XINPUT_DEVSUBTYPE_GUITAR_ALTERNATE:
+ subtype_name = "alternate guitar";
+ break;
+ case XINPUT_DEVSUBTYPE_DRUM_KIT:
+ subtype_name = "drum kit";
+ break;
+ case XINPUT_DEVSUBTYPE_GUITAR_BASS:
+ subtype_name = "bass guitar";
+ break;
+ case XINPUT_DEVSUBTYPE_ARCADE_PAD:
+ subtype_name = "arcade pad";
+ break;
+ }
+ break;
+ }
-const USHORT xinput_pov_dir[] = {
- XINPUT_GAMEPAD_DPAD_UP,
- XINPUT_GAMEPAD_DPAD_DOWN,
- XINPUT_GAMEPAD_DPAD_LEFT,
- XINPUT_GAMEPAD_DPAD_RIGHT
-};
+ // detect invalid axis resolutions
+ bool const ltcap_bad = m_capabilities.Gamepad.bLeftTrigger && count_leading_zeros_32(m_capabilities.Gamepad.bLeftTrigger << 24);
+ bool const rtcap_bad = m_capabilities.Gamepad.bRightTrigger && count_leading_zeros_32(m_capabilities.Gamepad.bRightTrigger << 24);
+ bool const lsxcap_bad = m_capabilities.Gamepad.sThumbLX && count_leading_zeros_32(m_capabilities.Gamepad.sThumbLX << 16);
+ bool const lsycap_bad = m_capabilities.Gamepad.sThumbLY && count_leading_zeros_32(m_capabilities.Gamepad.sThumbLY << 16);
+ bool const rsxcap_bad = m_capabilities.Gamepad.sThumbRX && count_leading_zeros_32(m_capabilities.Gamepad.sThumbRX << 16);
+ bool const rsycap_bad = m_capabilities.Gamepad.sThumbRY && count_leading_zeros_32(m_capabilities.Gamepad.sThumbRY << 16);
-const char *const xinput_pov_names[] = {
- "DPAD Up",
- "DPAD Down",
- "DPAD Left",
- "DPAD Right"
-};
+ // log some diagnostic information
+ osd_printf_verbose(
+ "XInput: Configuring player %d type 0x%02X (%s) sub type 0x%02X (%s).\n",
+ m_player_index + 1,
+ m_capabilities.Type,
+ type_name,
+ m_capabilities.SubType,
+ subtype_name);
+ osd_printf_verbose(
+ "XInput: Switch capabilities A=%d B=%d X=%d Y=%d LB=%d RB=%d LSB=%d RSB=%d Start=%d Back=%d Up=%d Down=%d Left=%d Right=%d.\n",
+ (m_capabilities.Gamepad.wButtons & XINPUT_GAMEPAD_A) ? 1 : 0,
+ (m_capabilities.Gamepad.wButtons & XINPUT_GAMEPAD_B) ? 1 : 0,
+ (m_capabilities.Gamepad.wButtons & XINPUT_GAMEPAD_X) ? 1 : 0,
+ (m_capabilities.Gamepad.wButtons & XINPUT_GAMEPAD_Y) ? 1 : 0,
+ (m_capabilities.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER) ? 1 : 0,
+ (m_capabilities.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER) ? 1 : 0,
+ (m_capabilities.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB) ? 1 : 0,
+ (m_capabilities.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB) ? 1 : 0,
+ (m_capabilities.Gamepad.wButtons & XINPUT_GAMEPAD_START) ? 1 : 0,
+ (m_capabilities.Gamepad.wButtons & XINPUT_GAMEPAD_BACK) ? 1 : 0,
+ (m_capabilities.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP) ? 1 : 0,
+ (m_capabilities.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN) ? 1 : 0,
+ (m_capabilities.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT) ? 1 : 0,
+ (m_capabilities.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT) ? 1 : 0);
+ osd_printf_verbose(
+ "XInput: Axis capabilities LT=0x%02X (%d-bit%s) RT=0x%02X (%d-bit%s) LSX=0x%04X (%d-bit%s) LSY=0x%04X (%d-bit%s) RSX=0x%04X (%d-bit%s) RSY=0x%04X (%d-bit%s).\n",
+ m_capabilities.Gamepad.bLeftTrigger,
+ count_leading_ones_32(u32(m_capabilities.Gamepad.bLeftTrigger) << 24),
+ ltcap_bad ? ", invalid" : "",
+ m_capabilities.Gamepad.bRightTrigger,
+ count_leading_ones_32(u32(m_capabilities.Gamepad.bRightTrigger) << 24),
+ rtcap_bad ? ", invalid" : "",
+ m_capabilities.Gamepad.sThumbLX,
+ count_leading_ones_32(u32(u16(m_capabilities.Gamepad.sThumbLX)) << 16),
+ lsxcap_bad ? ", invalid" : "",
+ m_capabilities.Gamepad.sThumbLY,
+ count_leading_ones_32(u32(u16(m_capabilities.Gamepad.sThumbLY)) << 16),
+ lsycap_bad ? ", invalid" : "",
+ m_capabilities.Gamepad.sThumbRX,
+ count_leading_ones_32(u32(u16(m_capabilities.Gamepad.sThumbRX)) << 16),
+ rsxcap_bad ? ", invalid" : "",
+ m_capabilities.Gamepad.sThumbRY,
+ count_leading_ones_32(u32(u16(m_capabilities.Gamepad.sThumbRY)) << 16),
+ rsycap_bad ? ", invalid" : "");
+
+ // ignore capabilities if invalid
+ if (!probe_extended_type())
+ {
+ bool ignore_caps = false;
+ if (ltcap_bad || rtcap_bad || lsxcap_bad || lsycap_bad || rsxcap_bad || rsycap_bad)
+ {
+ // Retro-Bit Sega Saturn Control Pad reports garbage for axis resolutions and absence of several buttons
+ osd_printf_verbose("XInput: Ignoring invalid capabilities (invalid axis resolution).\n");
+ ignore_caps = true;
+ }
+ else if (!m_capabilities.Gamepad.wButtons && !m_capabilities.Gamepad.bLeftTrigger && !m_capabilities.Gamepad.bRightTrigger && !m_capabilities.Gamepad.sThumbLX && !m_capabilities.Gamepad.sThumbLY && !m_capabilities.Gamepad.sThumbRX && !m_capabilities.Gamepad.sThumbRY)
+ {
+ // 8BitDo SN30 Pro V1 reports no controls at all, which would be completely useless
+ osd_printf_verbose("XInput: Ignoring invalid capabilities (no controls reported).\n");
+ ignore_caps = true;
+ }
+ if (ignore_caps)
+ {
+ m_capabilities.Gamepad.wButtons = 0xf3ff;
+ m_capabilities.Gamepad.bLeftTrigger = 0xff;
+ m_capabilities.Gamepad.bRightTrigger = 0xff;
+ m_capabilities.Gamepad.sThumbLX = s16(u16(0xffc0));
+ m_capabilities.Gamepad.sThumbLY = s16(u16(0xffc0));
+ m_capabilities.Gamepad.sThumbRX = s16(u16(0xffc0));
+ m_capabilities.Gamepad.sThumbRY = s16(u16(0xffc0));
+ }
+ }
+}
-const USHORT xinput_buttons[] = {
- XINPUT_GAMEPAD_A,
- XINPUT_GAMEPAD_B,
- XINPUT_GAMEPAD_X,
- XINPUT_GAMEPAD_Y,
- XINPUT_GAMEPAD_LEFT_SHOULDER,
- XINPUT_GAMEPAD_RIGHT_SHOULDER,
- XINPUT_GAMEPAD_START,
- XINPUT_GAMEPAD_BACK,
- XINPUT_GAMEPAD_LEFT_THUMB,
- XINPUT_GAMEPAD_RIGHT_THUMB,
-};
-const char *const xinput_button_names[] = {
- "A",
- "B",
- "X",
- "Y",
- "LB",
- "RB",
- "Start",
- "Back",
- "LS",
- "RS"
+bool xinput_device_base::read_state()
+{
+ // save previous packet number and try to read peripheral state
+ DWORD const prevpacket = m_xinput_state.dwPacketNumber;
+ HRESULT const result = m_xinput_helper.xinput_get_state(m_player_index, &m_xinput_state);
+
+ // only update if it succeeded and the packed number changed
+ if (FAILED(result))
+ {
+ return false;
+ }
+ else if (m_reset)
+ {
+ m_reset = false;
+ return true;
+ }
+ else
+ {
+ return prevpacket != m_xinput_state.dwPacketNumber;
+ }
+}
+
+
+template <unsigned M, unsigned N>
+bool xinput_device_base::assign_ui_button(
+ input_device::assignment_vector &assignments,
+ ioport_type type,
+ unsigned preferred,
+ input_item_id (&switch_ids)[M],
+ unsigned const (&numbered_buttons)[N],
+ unsigned button_count)
+{
+ assert(N >= button_count);
+
+ // use preferred button if available
+ if (add_button_assignment(assignments, type, { switch_ids[preferred] }))
+ {
+ switch_ids[preferred] = ITEM_ID_INVALID;
+ return true;
+ }
+
+ // otherwise find next available button
+ for (unsigned i = 0; button_count > i; ++i)
+ {
+ if (add_button_assignment(assignments, type, { switch_ids[numbered_buttons[i]] }))
+ {
+ switch_ids[numbered_buttons[i]] = ITEM_ID_INVALID;
+ return true;
+ }
+ }
+
+ // didn't find a suitable button
+ return false;
+}
+
+
+template <unsigned M, unsigned N>
+void xinput_device_base::assign_ui_actions(
+ input_device::assignment_vector &assignments,
+ unsigned preferred_back,
+ unsigned preferred_clear,
+ unsigned preferred_help,
+ unsigned start,
+ unsigned back,
+ input_item_id (&switch_ids)[M],
+ unsigned const (&numbered_buttons)[N],
+ unsigned button_count)
+{
+ // the first button is always UI select if present, or we can fall back to start
+ if (1U <= button_count)
+ {
+ add_button_assignment(assignments, IPT_UI_SELECT, { switch_ids[numbered_buttons[0]] });
+ switch_ids[numbered_buttons[0]] = ITEM_ID_INVALID;
+ }
+ else if (add_button_assignment(assignments, IPT_UI_SELECT, { switch_ids[start] }))
+ {
+ switch_ids[start] = ITEM_ID_INVALID;
+ }
+
+ // UI clear is usually X
+ assign_ui_button(
+ assignments,
+ IPT_UI_CLEAR,
+ preferred_clear,
+ switch_ids,
+ numbered_buttons,
+ button_count);
+
+ // UI back can fall back from B to the back button
+ bool const assigned_back = assign_ui_button(
+ assignments,
+ IPT_UI_BACK,
+ preferred_back,
+ switch_ids,
+ numbered_buttons,
+ button_count);
+ if (!assigned_back)
+ {
+ if (add_button_assignment(assignments, IPT_UI_BACK, { switch_ids[back] }))
+ switch_ids[back] = ITEM_ID_INVALID;
+ }
+
+ // help takes Y if present
+ assign_ui_button(
+ assignments,
+ IPT_UI_HELP,
+ preferred_help,
+ switch_ids,
+ numbered_buttons,
+ button_count);
+}
+
+
+bool xinput_device_base::probe_extended_type()
+{
+ switch (m_capabilities.Gamepad.sThumbLX)
+ {
+ case 0x1430:
+ switch (m_capabilities.Gamepad.sThumbLY)
+ {
+ case 0x0705:
+ osd_printf_verbose("XInput: Detected Band Hero guitar controller.\n");
+ m_capabilities.Gamepad.sThumbLX = s16(u16(0xffc0)); // neck slider
+ m_capabilities.Gamepad.sThumbLY = 0;
+ m_capabilities.Gamepad.sThumbRX = s16(u16(0xffc0)); // whammy bar
+ return true;
+ case 0x0805:
+ osd_printf_verbose("XInput: Detected Band Hero drum kit controller.\n");
+ m_capabilities.Gamepad.sThumbLX = 0;
+ m_capabilities.Gamepad.sThumbLY = s16(u16(0xffc0)); // green/red velocity
+ m_capabilities.Gamepad.sThumbRX = s16(u16(0xffc0)); // blue/yellow velocity
+ return true;
+ case 0x1705:
+ osd_printf_verbose("XInput: Detected DJ Hero turntable controller.\n");
+ m_capabilities.Gamepad.sThumbLX = 0;
+ m_capabilities.Gamepad.sThumbLY = s16(u16(0xffc0)); // turntable
+ m_capabilities.Gamepad.sThumbRX = s16(u16(0xffc0)); // effects dial
+ return true;
+ }
+ break;
+ case 0x1bad:
+ switch (m_capabilities.Gamepad.sThumbLY)
+ {
+ case 0x1330:
+ osd_printf_verbose("XInput: Detected Rock Band keyboard controller.\n");
+ m_capabilities.Gamepad.sThumbLX = 0; // keys, velocity
+ m_capabilities.Gamepad.sThumbLY = 0; // not present?
+ m_capabilities.Gamepad.sThumbRX = 0; // not present?
+ return true;
+ }
+ break;
+ }
+ return false;
+}
+
+
+
+//============================================================
+// general XInput controller handler
+//============================================================
+
+class xinput_joystick_device : public xinput_device_base
+{
+public:
+ xinput_joystick_device(
+ std::string &&name,
+ std::string &&id,
+ input_module &module,
+ u32 player,
+ XINPUT_CAPABILITIES const &caps,
+ xinput_api_helper const &helper);
+
+ virtual void poll(bool relative_reset) override;
+ virtual void reset() override;
+ virtual void configure(input_device &device) override;
+
+private:
+ static inline constexpr USHORT SWITCH_BITS[] =
+ {
+ XINPUT_GAMEPAD_A,
+ XINPUT_GAMEPAD_B,
+ XINPUT_GAMEPAD_X,
+ XINPUT_GAMEPAD_Y,
+ XINPUT_GAMEPAD_LEFT_SHOULDER,
+ XINPUT_GAMEPAD_RIGHT_SHOULDER,
+ XINPUT_GAMEPAD_LEFT_THUMB,
+ XINPUT_GAMEPAD_RIGHT_THUMB,
+ XINPUT_GAMEPAD_START,
+ XINPUT_GAMEPAD_BACK,
+
+ XINPUT_GAMEPAD_DPAD_UP,
+ XINPUT_GAMEPAD_DPAD_DOWN,
+ XINPUT_GAMEPAD_DPAD_LEFT,
+ XINPUT_GAMEPAD_DPAD_RIGHT
+ };
+
+ enum
+ {
+ SWITCH_A, // button bits
+ SWITCH_B,
+ SWITCH_X,
+ SWITCH_Y,
+ SWITCH_LB,
+ SWITCH_RB,
+ SWITCH_LSB,
+ SWITCH_RSB,
+ SWITCH_START,
+ SWITCH_BACK,
+
+ SWITCH_DPAD_UP, // D-pad bits
+ SWITCH_DPAD_DOWN,
+ SWITCH_DPAD_LEFT,
+ SWITCH_DPAD_RIGHT,
+
+ SWITCH_LT, // for arcade stick/pad with LT/RT buttons
+ SWITCH_RT,
+
+ SWITCH_TOTAL
+ };
+
+ enum
+ {
+ AXIS_LT, // half-axes for triggers
+ AXIS_RT,
+
+ AXIS_LSX, // full-precision axes
+ AXIS_LSY,
+ AXIS_RSX,
+ AXIS_RSY,
+
+ AXIS_TOTAL
+ };
+
+ static bool assign_pedal(
+ input_device::assignment_vector &assignments,
+ bool fallback_shoulder,
+ ioport_type type,
+ input_item_id preferred_axis,
+ input_item_id fallback_axis1,
+ input_item_id fallback_axis2,
+ input_item_modifier fallback_axis_modifier,
+ input_item_id trigger_button,
+ input_item_id shoulder_button,
+ input_item_id numbered_button);
+
+ u8 m_switches[SWITCH_TOTAL];
+ s32 m_axes[AXIS_TOTAL];
};
+xinput_joystick_device::xinput_joystick_device(
+ std::string &&name,
+ std::string &&id,
+ input_module &module,
+ u32 player,
+ XINPUT_CAPABILITIES const &caps,
+ xinput_api_helper const &helper) :
+ xinput_device_base(std::move(name), std::move(id), module, player, caps, helper)
+{
+ std::fill(std::begin(m_switches), std::end(m_switches), 0);
+ std::fill(std::begin(m_axes), std::end(m_axes), 0);
+}
+
+
+void xinput_joystick_device::poll(bool relative_reset)
+{
+ // poll the device first, and skip if nothing changed
+ if (!read_state())
+ return;
+
+ // translate button bits
+ for (unsigned i = 0; std::size(SWITCH_BITS) > i; ++i)
+ m_switches[SWITCH_A + i] = (buttons() & SWITCH_BITS[i]) ? 0xff : 0x00;
+
+ // translate the triggers onto the negative side of the axes
+ m_axes[AXIS_LT] = -normalize_absolute_axis(trigger_left(), -255, 255);
+ m_axes[AXIS_RT] = -normalize_absolute_axis(trigger_right(), -255, 255);
+
+ // translate full-precision axes - Y direction is opposite to what MAME uses
+ m_axes[AXIS_LSX] = normalize_absolute_axis(thumb_left_x(), XINPUT_AXIS_MINVALUE, XINPUT_AXIS_MAXVALUE);
+ m_axes[AXIS_LSY] = normalize_absolute_axis(-thumb_left_y(), XINPUT_AXIS_MINVALUE, XINPUT_AXIS_MAXVALUE);
+ m_axes[AXIS_RSX] = normalize_absolute_axis(thumb_right_x(), XINPUT_AXIS_MINVALUE, XINPUT_AXIS_MAXVALUE);
+ m_axes[AXIS_RSY] = normalize_absolute_axis(-thumb_right_y(), XINPUT_AXIS_MINVALUE, XINPUT_AXIS_MAXVALUE);
+
+ // translate LT/RT switches for arcade sticks/pads
+ m_switches[SWITCH_LT] = (0x80 <= trigger_left()) ? 0xff : 0x00;
+ m_switches[SWITCH_RT] = (0x80 <= trigger_right()) ? 0xff : 0x00;
+}
+
+
+void xinput_joystick_device::reset()
+{
+ set_reset();
+ std::fill(std::begin(m_switches), std::end(m_switches), 0);
+ std::fill(std::begin(m_axes), std::end(m_axes), 0);
+}
+
+
+void xinput_joystick_device::configure(input_device &device)
+{
+ // TODO: proper support for dance mat controllers
+
+ // default characteristics for a gamepad
+ bool button_diamond = true;
+ bool pedal_fallback_shoulder = true;
+ bool lt_rt_button = false;
+ char const *const *axis_names = AXIS_NAMES_GAMEPAD;
+ input_item_id const *preferred_axis_ids = AXIS_IDS_GAMEPAD;
+ char const *const *hat_names = HAT_NAMES_GAMEPAD;
+ char const *const *button_names = BUTTON_NAMES_GAMEPAD;
+
+ // consider the device type to decide how to map controls
+ switch (device_type())
+ {
+ case XINPUT_DEVTYPE_GAMEPAD:
+ switch (device_subtype())
+ {
+ case XINPUT_DEVSUBTYPE_WHEEL:
+ pedal_fallback_shoulder = false;
+ axis_names = AXIS_NAMES_WHEEL;
+ break;
+ case XINPUT_DEVSUBTYPE_ARCADE_STICK:
+ button_diamond = false;
+ lt_rt_button = true;
+ hat_names = HAT_NAMES_ARCADE_STICK;
+ break;
+ case XINPUT_DEVSUBTYPE_DANCE_PAD:
+ // TODO: proper support
+ button_diamond = false;
+ break;
+ case XINPUT_DEVSUBTYPE_ARCADE_PAD:
+ button_diamond = false;
+ lt_rt_button = true;
+ break;
+ }
+ break;
+ }
+
+ // track item IDs for setting up default assignments
+ input_device::assignment_vector assignments;
+ input_item_id axis_ids[AXIS_TOTAL];
+ input_item_id switch_ids[SWITCH_TOTAL];
+ std::fill(std::begin(switch_ids), std::end(switch_ids), ITEM_ID_INVALID);
+
+ // add bidirectional axes
+ bool const axis_caps[]{
+ has_thumb_left_x(),
+ has_thumb_left_y(),
+ has_thumb_right_x(),
+ has_thumb_right_y() };
+ for (unsigned i = 0; std::size(axis_caps) > i; ++i)
+ {
+ if (axis_caps[i])
+ {
+ axis_ids[AXIS_LSX + i] = device.add_item(
+ axis_names[i],
+ std::string_view(),
+ preferred_axis_ids[i],
+ generic_axis_get_state<s32>,
+ &m_axes[AXIS_LSX + i]);
+ }
+ else
+ {
+ axis_ids[AXIS_LSX + i] = ITEM_ID_INVALID;
+ }
+ }
+
+ // add hats
+ bool const hat_caps[]{
+ has_button(XINPUT_GAMEPAD_DPAD_UP),
+ has_button(XINPUT_GAMEPAD_DPAD_DOWN),
+ has_button(XINPUT_GAMEPAD_DPAD_LEFT),
+ has_button(XINPUT_GAMEPAD_DPAD_RIGHT) };
+ for (unsigned i = 0; (SWITCH_DPAD_RIGHT - SWITCH_DPAD_UP) >= i; ++i)
+ {
+ if (hat_caps[i])
+ {
+ switch_ids[SWITCH_DPAD_UP + i] = device.add_item(
+ hat_names[i],
+ std::string_view(),
+ input_item_id(ITEM_ID_HAT1UP + i), // matches up/down/left/right order
+ generic_button_get_state<u8>,
+ &m_switches[SWITCH_DPAD_UP + i]);
+ }
+ }
+
+ // add buttons
+ std::pair<unsigned, bool> const button_caps[]{
+ { SWITCH_A, has_button(XINPUT_GAMEPAD_A) },
+ { SWITCH_B, has_button(XINPUT_GAMEPAD_B) },
+ { SWITCH_X, has_button(XINPUT_GAMEPAD_X) },
+ { SWITCH_Y, has_button(XINPUT_GAMEPAD_Y) },
+ { SWITCH_LT, lt_rt_button && has_trigger_left() },
+ { SWITCH_RT, lt_rt_button && has_trigger_right() },
+ { SWITCH_LB, has_button(XINPUT_GAMEPAD_LEFT_SHOULDER) },
+ { SWITCH_RB, has_button(XINPUT_GAMEPAD_RIGHT_SHOULDER) },
+ { SWITCH_LSB, has_button(XINPUT_GAMEPAD_LEFT_THUMB) },
+ { SWITCH_RSB, has_button(XINPUT_GAMEPAD_RIGHT_THUMB) } };
+ input_item_id button_id = ITEM_ID_BUTTON1;
+ unsigned button_count = 0;
+ unsigned numbered_buttons[SWITCH_RSB - SWITCH_A + 1];
+ for (unsigned i = 0; std::size(button_caps) > i; ++i)
+ {
+ auto const [offset, supported] = button_caps[i];
+ if (supported)
+ {
+ switch_ids[offset] = device.add_item(
+ button_names[i],
+ std::string_view(),
+ button_id++,
+ generic_button_get_state<u8>,
+ &m_switches[offset]);
+ numbered_buttons[button_count] = offset;
+
+ // use these for automatically numbered buttons
+ assignments.emplace_back(
+ ioport_type(IPT_BUTTON1 + button_count++),
+ SEQ_TYPE_STANDARD,
+ input_seq(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, switch_ids[offset])));
+ }
+ }
+
+ // add start/back
+ if (has_button(XINPUT_GAMEPAD_START))
+ {
+ switch_ids[SWITCH_START] = device.add_item(
+ "Start",
+ std::string_view(),
+ ITEM_ID_START,
+ generic_button_get_state<u8>,
+ &m_switches[SWITCH_START]);
+ add_button_assignment(assignments, IPT_START, { switch_ids[SWITCH_START] });
+ }
+ if (has_button(XINPUT_GAMEPAD_BACK))
+ {
+ switch_ids[SWITCH_BACK] = device.add_item(
+ "Back",
+ std::string_view(),
+ ITEM_ID_SELECT,
+ generic_button_get_state<u8>,
+ &m_switches[SWITCH_BACK]);
+ add_button_assignment(assignments, IPT_SELECT, { switch_ids[SWITCH_BACK] });
+ }
+
+ // add triggers/pedals
+ if (!lt_rt_button)
+ {
+ for (unsigned i = 0; (AXIS_RT - AXIS_LT) >= i; ++i)
+ {
+ if (i ? has_trigger_right() : has_trigger_left())
+ {
+ axis_ids[AXIS_LT + i] = device.add_item(
+ axis_names[std::size(axis_caps) + i],
+ std::string_view(),
+ preferred_axis_ids[std::size(axis_caps) + i],
+ generic_axis_get_state<s32>,
+ &m_axes[AXIS_LT + i]);
+ }
+ else
+ {
+ axis_ids[AXIS_LT + i] = ITEM_ID_INVALID;
+ }
+ }
+ }
+
+ // try to get a "complete" joystick for primary movement controls
+ input_item_id directional_axes[2][2];
+ choose_primary_stick(
+ directional_axes,
+ axis_ids[AXIS_LSX],
+ axis_ids[AXIS_LSY],
+ axis_ids[AXIS_RSX],
+ axis_ids[AXIS_RSY]);
+
+ // now set up controls using the primary joystick
+ add_directional_assignments(
+ assignments,
+ directional_axes[0][0],
+ directional_axes[0][1],
+ switch_ids[SWITCH_DPAD_LEFT],
+ switch_ids[SWITCH_DPAD_RIGHT],
+ switch_ids[SWITCH_DPAD_UP],
+ switch_ids[SWITCH_DPAD_DOWN]);
+
+ // assign a secondary stick axis to joystick Z if available
+ bool const stick_z = add_assignment(
+ assignments,
+ IPT_AD_STICK_Z,
+ SEQ_TYPE_STANDARD,
+ ITEM_CLASS_ABSOLUTE,
+ ITEM_MODIFIER_NONE,
+ { directional_axes[1][1], directional_axes[1][0] });
+ if (!stick_z)
+ {
+ // if both triggers are present, combine them, or failing that, fall back to a pair of buttons
+ if ((ITEM_ID_INVALID != axis_ids[AXIS_LT]) && (ITEM_ID_INVALID != axis_ids[AXIS_RT]))
+ {
+ assignments.emplace_back(
+ IPT_AD_STICK_Z,
+ SEQ_TYPE_STANDARD,
+ input_seq(
+ make_code(ITEM_CLASS_ABSOLUTE, ITEM_MODIFIER_NONE, axis_ids[AXIS_LT]),
+ make_code(ITEM_CLASS_ABSOLUTE, ITEM_MODIFIER_REVERSE, axis_ids[AXIS_RT])));
+ }
+ else if (add_axis_inc_dec_assignment(assignments, IPT_AD_STICK_Z, switch_ids[SWITCH_LB], switch_ids[SWITCH_RB]))
+ {
+ // took shoulder buttons
+ }
+ else if (add_axis_inc_dec_assignment(assignments, IPT_AD_STICK_Z, switch_ids[SWITCH_LT], switch_ids[SWITCH_RT]))
+ {
+ // took trigger buttons
+ }
+ }
+
+ // prefer trigger axes for pedals, otherwise take half axes and buttons
+ unsigned pedal_button = 0;
+ bool const pedal1_numbered_button = assign_pedal(
+ assignments,
+ pedal_fallback_shoulder,
+ IPT_PEDAL,
+ axis_ids[AXIS_RT],
+ directional_axes[1][1],
+ directional_axes[0][1],
+ ITEM_MODIFIER_NEG,
+ switch_ids[SWITCH_RT],
+ switch_ids[SWITCH_RB],
+ (pedal_button < button_count)
+ ? switch_ids[numbered_buttons[pedal_button]]
+ : ITEM_ID_INVALID);
+ if (pedal1_numbered_button)
+ ++pedal_button;
+ bool const pedal2_numbered_button = assign_pedal(
+ assignments,
+ pedal_fallback_shoulder,
+ IPT_PEDAL2,
+ axis_ids[AXIS_LT],
+ directional_axes[1][1],
+ directional_axes[0][1],
+ ITEM_MODIFIER_POS,
+ switch_ids[SWITCH_LT],
+ switch_ids[SWITCH_LB],
+ (pedal_button < button_count)
+ ? switch_ids[numbered_buttons[pedal_button]]
+ : ITEM_ID_INVALID);
+ if (pedal2_numbered_button)
+ ++pedal_button;
+ if (pedal_button < button_count)
+ {
+ input_item_id const pedal_button_id = switch_ids[numbered_buttons[pedal_button]];
+ assignments.emplace_back(
+ IPT_PEDAL3,
+ SEQ_TYPE_INCREMENT,
+ input_seq(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, pedal_button_id)));
+ }
+
+ // potentially use thumb sticks and/or D-pad and A/B/X/Y diamond for twin sticks
+ add_twin_stick_assignments(
+ assignments,
+ axis_ids[AXIS_LSX],
+ axis_ids[AXIS_LSY],
+ axis_ids[AXIS_RSX],
+ axis_ids[AXIS_RSY],
+ button_diamond ? switch_ids[SWITCH_DPAD_LEFT] : ITEM_ID_INVALID,
+ button_diamond ? switch_ids[SWITCH_DPAD_RIGHT] : ITEM_ID_INVALID,
+ button_diamond ? switch_ids[SWITCH_DPAD_UP] : ITEM_ID_INVALID,
+ button_diamond ? switch_ids[SWITCH_DPAD_DOWN] : ITEM_ID_INVALID,
+ button_diamond ? switch_ids[SWITCH_X] : ITEM_ID_INVALID,
+ button_diamond ? switch_ids[SWITCH_B] : ITEM_ID_INVALID,
+ button_diamond ? switch_ids[SWITCH_Y] : ITEM_ID_INVALID,
+ button_diamond ? switch_ids[SWITCH_A] : ITEM_ID_INVALID);
+
+ // assign UI select/back/clear/help
+ assign_ui_actions(
+ assignments,
+ SWITCH_B,
+ SWITCH_X,
+ SWITCH_Y,
+ SWITCH_START,
+ SWITCH_BACK,
+ switch_ids,
+ numbered_buttons,
+ button_count);
+
+ // try to get a matching pair of buttons for previous/next group
+ if (consume_button_pair(assignments, IPT_UI_PREV_GROUP, IPT_UI_NEXT_GROUP, switch_ids[SWITCH_LT], switch_ids[SWITCH_RT]))
+ {
+ // took digital triggers
+ }
+ else if (consume_trigger_pair(assignments, IPT_UI_PREV_GROUP, IPT_UI_NEXT_GROUP, axis_ids[AXIS_LT], axis_ids[AXIS_RT]))
+ {
+ // took analog triggers
+ }
+ else if (consume_axis_pair(assignments, IPT_UI_PREV_GROUP, IPT_UI_NEXT_GROUP, directional_axes[1][1]))
+ {
+ // took secondary Y
+ }
+ else if (consume_axis_pair(assignments, IPT_UI_PREV_GROUP, IPT_UI_NEXT_GROUP, directional_axes[1][0]))
+ {
+ // took secondary X
+ }
+
+ // try to assign secondary stick to page up/down
+ consume_axis_pair(assignments, IPT_UI_PAGE_UP, IPT_UI_PAGE_DOWN, directional_axes[1][1]);
+
+ // put focus previous/next on the shoulder buttons if available - this can be overloaded with zoom
+ if (add_button_pair_assignment(assignments, IPT_UI_FOCUS_PREV, IPT_UI_FOCUS_NEXT, switch_ids[SWITCH_LB], switch_ids[SWITCH_RB]))
+ {
+ // took shoulder buttons
+ }
+ else if (add_axis_pair_assignment(assignments, IPT_UI_FOCUS_PREV, IPT_UI_FOCUS_NEXT, directional_axes[1][0]))
+ {
+ // took secondary X
+ }
+
+ // put zoom on the secondary stick if available, or fall back to shoulder buttons
+ if (add_axis_pair_assignment(assignments, IPT_UI_ZOOM_OUT, IPT_UI_ZOOM_IN, directional_axes[1][0]))
+ {
+ // took secondary X
+ if (axis_ids[AXIS_LSX] == directional_axes[1][0])
+ add_button_assignment(assignments, IPT_UI_ZOOM_DEFAULT, { switch_ids[SWITCH_LSB] });
+ else if (axis_ids[AXIS_RSX] == directional_axes[1][0])
+ add_button_assignment(assignments, IPT_UI_ZOOM_DEFAULT, { switch_ids[SWITCH_RSB] });
+ directional_axes[1][0] = ITEM_ID_INVALID;
+ }
+ else if (consume_button_pair(assignments, IPT_UI_ZOOM_OUT, IPT_UI_ZOOM_IN, switch_ids[SWITCH_LB], switch_ids[SWITCH_RB]))
+ {
+ // took shoulder buttons
+ }
+
+ // set default assignments
+ device.set_default_assignments(std::move(assignments));
+}
+
+
+bool xinput_joystick_device::assign_pedal(
+ input_device::assignment_vector &assignments,
+ bool fallback_shoulder,
+ ioport_type type,
+ input_item_id preferred_axis,
+ input_item_id fallback_axis1,
+ input_item_id fallback_axis2,
+ input_item_modifier fallback_axis_modifier,
+ input_item_id trigger_button,
+ input_item_id shoulder_button,
+ input_item_id numbered_button)
+{
+ // first try the preferred trigger/pedal axis
+ if (ITEM_ID_INVALID != preferred_axis)
+ {
+ assignments.emplace_back(
+ type,
+ SEQ_TYPE_STANDARD,
+ input_seq(make_code(ITEM_CLASS_ABSOLUTE, ITEM_MODIFIER_NEG, preferred_axis)));
+ return false;
+ }
+
+ // try adding half a joystick axis
+ add_assignment(
+ assignments,
+ type,
+ SEQ_TYPE_STANDARD,
+ ITEM_CLASS_ABSOLUTE,
+ fallback_axis_modifier,
+ { fallback_axis1, fallback_axis2 });
+
+ // try a trigger button
+ if (ITEM_ID_INVALID != trigger_button)
+ {
+ assignments.emplace_back(
+ type,
+ SEQ_TYPE_INCREMENT,
+ input_seq(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, trigger_button)));
+ return false;
+ }
+
+ // try a shoulder button if appropriate
+ if (fallback_shoulder && (ITEM_ID_INVALID != shoulder_button))
+ {
+ assignments.emplace_back(
+ type,
+ SEQ_TYPE_INCREMENT,
+ input_seq(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, shoulder_button)));
+ return false;
+ }
+
+ // if no numbered button, nothing can be done
+ if (ITEM_ID_INVALID == numbered_button)
+ return false;
+
+ // last resort
+ assignments.emplace_back(
+ type,
+ SEQ_TYPE_INCREMENT,
+ input_seq(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, numbered_button)));
+ return true;
+}
+
+
+
//============================================================
-// xinput_joystick_module
+// XInput flight stick handler
//============================================================
-class xinput_joystick_module : public wininput_module
+class xinput_flight_stick_device : public xinput_device_base
{
public:
- xinput_joystick_module() : wininput_module(OSD_JOYSTICKINPUT_PROVIDER, "xinput")
+ xinput_flight_stick_device(
+ std::string &&name,
+ std::string &&id,
+ input_module &module,
+ u32 player,
+ XINPUT_CAPABILITIES const &caps,
+ xinput_api_helper const &helper);
+
+ virtual void poll(bool relative_reset) override;
+ virtual void reset() override;
+ virtual void configure(input_device &device) override;
+
+private:
+ static inline constexpr USHORT SWITCH_BITS[] =
+ {
+ XINPUT_GAMEPAD_A,
+ XINPUT_GAMEPAD_B,
+ XINPUT_GAMEPAD_X,
+ XINPUT_GAMEPAD_Y,
+ XINPUT_GAMEPAD_LEFT_SHOULDER,
+ XINPUT_GAMEPAD_RIGHT_SHOULDER,
+ XINPUT_GAMEPAD_LEFT_THUMB,
+ XINPUT_GAMEPAD_RIGHT_THUMB,
+ XINPUT_GAMEPAD_START,
+ XINPUT_GAMEPAD_BACK,
+
+ XINPUT_GAMEPAD_DPAD_UP,
+ XINPUT_GAMEPAD_DPAD_DOWN,
+ XINPUT_GAMEPAD_DPAD_LEFT,
+ XINPUT_GAMEPAD_DPAD_RIGHT
+ };
+
+ enum
+ {
+ SWITCH_A, // button bits
+ SWITCH_B,
+ SWITCH_X,
+ SWITCH_Y,
+ SWITCH_LB,
+ SWITCH_RB,
+ SWITCH_LSB,
+ SWITCH_RSB,
+ SWITCH_START,
+ SWITCH_BACK,
+
+ SWITCH_DPAD_UP, // D-pad bits
+ SWITCH_DPAD_DOWN,
+ SWITCH_DPAD_LEFT,
+ SWITCH_DPAD_RIGHT,
+
+ SWITCH_HAT_UP, // for POV hat as right stick
+ SWITCH_HAT_DOWN,
+ SWITCH_HAT_LEFT,
+ SWITCH_HAT_RIGHT,
+
+ SWITCH_TOTAL
+ };
+
+ enum
+ {
+ AXIS_RUDDER, // LT/RT mapped as bidirectional axes
+ AXIS_THROTTLE,
+
+ AXIS_X, // full-precision axes
+ AXIS_Y,
+
+ AXIS_TOTAL
+ };
+
+ u8 m_switches[SWITCH_TOTAL];
+ s32 m_axes[AXIS_TOTAL];
+};
+
+
+xinput_flight_stick_device::xinput_flight_stick_device(
+ std::string &&name,
+ std::string &&id,
+ input_module &module,
+ u32 player,
+ XINPUT_CAPABILITIES const &caps,
+ xinput_api_helper const &helper) :
+ xinput_device_base(std::move(name), std::move(id), module, player, caps, helper)
+{
+ std::fill(std::begin(m_switches), std::end(m_switches), 0);
+ std::fill(std::begin(m_axes), std::end(m_axes), 0);
+}
+
+
+void xinput_flight_stick_device::poll(bool relative_reset)
+{
+ // poll the device first, and skip if nothing changed
+ if (!read_state())
+ return;
+
+ // translate button bits
+ for (unsigned i = 0; std::size(SWITCH_BITS) > i; ++i)
+ m_switches[SWITCH_A + i] = (buttons() & SWITCH_BITS[i]) ? 0xff : 0x00;
+
+ // translate rudder and throttle
+ m_axes[AXIS_RUDDER] = normalize_absolute_axis(trigger_left(), 0, 255);
+ m_axes[AXIS_THROTTLE] = normalize_absolute_axis(trigger_right(), 0, 255);
+
+ // translate full-precision axes - Y direction is opposite to what MAME uses
+ m_axes[AXIS_X] = normalize_absolute_axis(thumb_left_x(), XINPUT_AXIS_MINVALUE, XINPUT_AXIS_MAXVALUE);
+ m_axes[AXIS_Y] = normalize_absolute_axis(-thumb_left_y(), XINPUT_AXIS_MINVALUE, XINPUT_AXIS_MAXVALUE);
+
+ // translate right stick as POV hat
+ m_switches[SWITCH_HAT_UP] = (16'384 <= thumb_right_y()) ? 0xff : 0x00;
+ m_switches[SWITCH_HAT_DOWN] = (-16'384 >= thumb_right_y()) ? 0xff : 0x00;
+ m_switches[SWITCH_HAT_LEFT] = (-16'384 >= thumb_right_x()) ? 0xff : 0x00;
+ m_switches[SWITCH_HAT_RIGHT] = (16'384 <= thumb_right_x()) ? 0xff : 0x00;
+}
+
+
+void xinput_flight_stick_device::reset()
+{
+ set_reset();
+ std::fill(std::begin(m_switches), std::end(m_switches), 0);
+ std::fill(std::begin(m_axes), std::end(m_axes), 0);
+}
+
+
+void xinput_flight_stick_device::configure(input_device &device)
+{
+ // track item IDs for setting up default assignments
+ input_device::assignment_vector assignments;
+ input_item_id switch_ids[SWITCH_TOTAL];
+ std::fill(std::begin(switch_ids), std::end(switch_ids), ITEM_ID_INVALID);
+
+ // add bidirectional axes
+ std::tuple<input_item_id, char const *, bool> const axis_caps[]{
+ { ITEM_ID_RZAXIS, "Rudder", has_trigger_left() },
+ { ITEM_ID_ZAXIS, "Throttle", has_trigger_right() },
+ { ITEM_ID_XAXIS, "Joystick X", has_thumb_left_x() },
+ { ITEM_ID_YAXIS, "Joystick Y", has_thumb_left_y() } };
+ input_item_id axis_ids[AXIS_TOTAL];
+ for (unsigned i = 0; AXIS_TOTAL > i; ++i)
{
+ auto const [id, name, supported] = axis_caps[i];
+ if (supported)
+ {
+ axis_ids[i] = device.add_item(
+ name,
+ std::string_view(),
+ id,
+ generic_axis_get_state<s32>,
+ &m_axes[i]);
+ }
+ else
+ {
+ axis_ids[i] = ITEM_ID_INVALID;
+ }
}
- int init(const osd_options &options) override
+ // add hats
+ bool const hat_caps[]{
+ has_button(XINPUT_GAMEPAD_DPAD_UP),
+ has_button(XINPUT_GAMEPAD_DPAD_DOWN),
+ has_button(XINPUT_GAMEPAD_DPAD_LEFT),
+ has_button(XINPUT_GAMEPAD_DPAD_RIGHT),
+ has_thumb_right_x(),
+ has_thumb_right_x(),
+ has_thumb_right_y(),
+ has_thumb_right_y() };
+ for (unsigned i = 0; (SWITCH_HAT_RIGHT - SWITCH_DPAD_UP) >= i; ++i)
{
- // Call the base
- int status = wininput_module::init(options);
- if (status != 0)
- return status;
+ if (hat_caps[i])
+ {
+ switch_ids[SWITCH_DPAD_UP + i] = device.add_item(
+ HAT_NAMES_GAMEPAD[i],
+ std::string_view(),
+ input_item_id(ITEM_ID_HAT1UP + i), // matches up/down/left/right order
+ generic_button_get_state<u8>,
+ &m_switches[SWITCH_DPAD_UP + i]);
+ }
+ }
- // Create and initialize our helper
- m_xinput_helper = std::make_shared<xinput_api_helper>();
- status = m_xinput_helper->initialize();
- if (status != 0)
+ // add buttons
+ input_item_id button_id = ITEM_ID_BUTTON1;
+ unsigned button_count = 0;
+ unsigned numbered_buttons[SWITCH_RSB - SWITCH_A + 1];
+ for (unsigned i = 0; (SWITCH_RSB - SWITCH_A) >= i; ++i)
+ {
+ if (has_button(SWITCH_BITS[i]))
{
- osd_printf_error("xinput_joystick_module failed to get XInput interface! Error: %u\n", static_cast<unsigned int>(status));
- return -1;
+ switch_ids[SWITCH_A + i] = device.add_item(
+ BUTTON_NAMES_FLIGHT_STICK[i],
+ std::string_view(),
+ button_id++,
+ generic_button_get_state<u8>,
+ &m_switches[SWITCH_A + i]);
+ numbered_buttons[button_count] = SWITCH_A + i;
+
+ // use these for automatically numbered buttons and pedals
+ input_seq const seq(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, switch_ids[SWITCH_A + i]));
+ assignments.emplace_back(ioport_type(IPT_BUTTON1 + button_count), SEQ_TYPE_STANDARD, seq);
+ if (3 > button_count)
+ assignments.emplace_back(ioport_type(IPT_PEDAL + button_count), SEQ_TYPE_INCREMENT, seq);
+ ++button_count;
}
+ }
- return 0;
+ // add start/back
+ if (has_button(XINPUT_GAMEPAD_START))
+ {
+ switch_ids[SWITCH_START] = device.add_item(
+ "Start",
+ std::string_view(),
+ ITEM_ID_START,
+ generic_button_get_state<u8>,
+ &m_switches[SWITCH_START]);
+ add_button_assignment(assignments, IPT_START, { switch_ids[SWITCH_START] });
+ }
+ if (has_button(XINPUT_GAMEPAD_BACK))
+ {
+ switch_ids[SWITCH_BACK] = device.add_item(
+ "Back",
+ std::string_view(),
+ ITEM_ID_SELECT,
+ generic_button_get_state<u8>,
+ &m_switches[SWITCH_BACK]);
+ add_button_assignment(assignments, IPT_SELECT, { switch_ids[SWITCH_BACK] });
}
-protected:
- virtual void input_init(running_machine &machine) override
+ // use throttle for joystick Z, or rudder if it isn't available
+ add_assignment(
+ assignments,
+ IPT_AD_STICK_Z,
+ SEQ_TYPE_STANDARD,
+ ITEM_CLASS_ABSOLUTE,
+ ITEM_MODIFIER_NONE,
+ { axis_ids[AXIS_THROTTLE], axis_ids[AXIS_RUDDER] });
+
+ // if throttle is available, use it for first two pedals, too
+ if (ITEM_ID_INVALID != axis_ids[AXIS_THROTTLE])
{
- // Loop through each gamepad to determine if they are connected
- for (UINT i = 0; i < XUSER_MAX_COUNT; i++)
+ assignments.emplace_back(
+ IPT_PEDAL,
+ SEQ_TYPE_STANDARD,
+ input_seq(make_code(ITEM_CLASS_ABSOLUTE, ITEM_MODIFIER_NEG, axis_ids[AXIS_THROTTLE])));
+ assignments.emplace_back(
+ IPT_PEDAL2,
+ SEQ_TYPE_STANDARD,
+ input_seq(make_code(ITEM_CLASS_ABSOLUTE, ITEM_MODIFIER_POS, axis_ids[AXIS_THROTTLE])));
+ }
+
+ // find something to use for directional controls and navigation
+ bool const axis_missing = (ITEM_ID_INVALID == axis_ids[AXIS_X]) || (ITEM_ID_INVALID == axis_ids[AXIS_Y]);
+ bool const hat_complete = has_thumb_right_x() && has_thumb_right_y();
+ if (axis_missing && hat_complete)
+ {
+ // X or Y missing - rely on POV hat
+ add_directional_assignments(
+ assignments,
+ axis_ids[AXIS_X],
+ axis_ids[AXIS_Y],
+ switch_ids[SWITCH_HAT_LEFT],
+ switch_ids[SWITCH_HAT_RIGHT],
+ switch_ids[SWITCH_HAT_UP],
+ switch_ids[SWITCH_HAT_DOWN]);
+
+ // choose something for previous/next group
+ if (consume_button_pair(assignments, IPT_UI_PREV_GROUP, IPT_UI_NEXT_GROUP, switch_ids[SWITCH_DPAD_UP], switch_ids[SWITCH_DPAD_DOWN]))
+ {
+ // took D-pad up/down
+ }
+ else if (consume_button_pair(assignments, IPT_UI_PREV_GROUP, IPT_UI_NEXT_GROUP, switch_ids[SWITCH_DPAD_LEFT], switch_ids[SWITCH_DPAD_RIGHT]))
+ {
+ // took D-pad left/right
+ }
+ else if (consume_axis_pair(assignments, IPT_UI_PREV_GROUP, IPT_UI_NEXT_GROUP, axis_ids[AXIS_RUDDER]))
+ {
+ // took rudder
+ }
+ else if (consume_axis_pair(assignments, IPT_UI_PREV_GROUP, IPT_UI_NEXT_GROUP, axis_ids[AXIS_THROTTLE]))
+ {
+ // took throttle
+ }
+
+ // choose something for zoom and focus previous/next
+ if (add_axis_pair_assignment(assignments, IPT_UI_ZOOM_OUT, IPT_UI_ZOOM_IN, axis_ids[AXIS_THROTTLE]))
+ {
+ if (!add_axis_pair_assignment(assignments, IPT_UI_FOCUS_PREV, IPT_UI_FOCUS_NEXT, axis_ids[AXIS_RUDDER]))
+ add_axis_pair_assignment(assignments, IPT_UI_FOCUS_PREV, IPT_UI_FOCUS_NEXT, axis_ids[AXIS_THROTTLE]);
+ }
+ else if (add_axis_pair_assignment(assignments, IPT_UI_ZOOM_OUT, IPT_UI_ZOOM_IN, axis_ids[AXIS_RUDDER]))
+ {
+ add_axis_pair_assignment(assignments, IPT_UI_FOCUS_PREV, IPT_UI_FOCUS_NEXT, axis_ids[AXIS_RUDDER]);
+ }
+ else if (add_button_pair_assignment(assignments, IPT_UI_ZOOM_OUT, IPT_UI_ZOOM_IN, switch_ids[SWITCH_DPAD_LEFT], switch_ids[SWITCH_DPAD_RIGHT]))
+ {
+ consume_button_pair(assignments, IPT_UI_FOCUS_PREV, IPT_UI_FOCUS_NEXT, switch_ids[SWITCH_DPAD_LEFT], switch_ids[SWITCH_DPAD_RIGHT]);
+ }
+ }
+ else
+ {
+ // only use stick for the primary directional controls
+ add_directional_assignments(
+ assignments,
+ axis_ids[AXIS_X],
+ axis_ids[AXIS_Y],
+ ITEM_ID_INVALID,
+ ITEM_ID_INVALID,
+ ITEM_ID_INVALID,
+ ITEM_ID_INVALID);
+
+ // assign the POV hat differently depending on whether rudder and/or throttle are present
+ if ((ITEM_ID_INVALID != axis_ids[AXIS_RUDDER]) || (ITEM_ID_INVALID != axis_ids[AXIS_THROTTLE]))
+ {
+ // previous/next group
+ if (consume_button_pair(assignments, IPT_UI_PREV_GROUP, IPT_UI_NEXT_GROUP, switch_ids[SWITCH_HAT_LEFT], switch_ids[SWITCH_HAT_RIGHT]))
+ {
+ // took hat left/right
+ }
+ else if (consume_button_pair(assignments, IPT_UI_PREV_GROUP, IPT_UI_NEXT_GROUP, switch_ids[SWITCH_DPAD_LEFT], switch_ids[SWITCH_DPAD_RIGHT]))
+ {
+ // took D-pad left/right
+ }
+ else if (consume_button_pair(assignments, IPT_UI_PREV_GROUP, IPT_UI_NEXT_GROUP, switch_ids[SWITCH_HAT_UP], switch_ids[SWITCH_HAT_DOWN]))
+ {
+ // took hat up/down
+ }
+ else if (consume_button_pair(assignments, IPT_UI_PREV_GROUP, IPT_UI_NEXT_GROUP, switch_ids[SWITCH_DPAD_UP], switch_ids[SWITCH_DPAD_DOWN]))
+ {
+ // took D-pad up/down
+ }
+ else if (consume_axis_pair(assignments, IPT_UI_PREV_GROUP, IPT_UI_NEXT_GROUP, axis_ids[AXIS_RUDDER]))
+ {
+ // took rudder
+ }
+ else if (consume_axis_pair(assignments, IPT_UI_PREV_GROUP, IPT_UI_NEXT_GROUP, axis_ids[AXIS_THROTTLE]))
+ {
+ // took throttle
+ }
+
+ // page up/down
+ if (consume_button_pair(assignments, IPT_UI_PAGE_UP, IPT_UI_PAGE_DOWN, switch_ids[SWITCH_HAT_UP], switch_ids[SWITCH_HAT_DOWN]))
+ {
+ // took hat up/down
+ }
+ else if (consume_button_pair(assignments, IPT_UI_PAGE_UP, IPT_UI_PAGE_DOWN, switch_ids[SWITCH_DPAD_UP], switch_ids[SWITCH_DPAD_DOWN]))
+ {
+ // took D-pad up/down
+ }
+ else if (consume_button_pair(assignments, IPT_UI_PAGE_UP, IPT_UI_PAGE_DOWN, switch_ids[SWITCH_DPAD_LEFT], switch_ids[SWITCH_DPAD_RIGHT]))
+ {
+ // took D-pad left/right
+ }
+
+ // home/end
+ if (consume_button_pair(assignments, IPT_UI_HOME, IPT_UI_END, switch_ids[SWITCH_DPAD_UP], switch_ids[SWITCH_DPAD_DOWN]))
+ {
+ // took D-pad up/down
+ }
+ else if (consume_button_pair(assignments, IPT_UI_HOME, IPT_UI_END, switch_ids[SWITCH_DPAD_LEFT], switch_ids[SWITCH_DPAD_RIGHT]))
+ {
+ // took D-pad left/right
+ }
+
+ // assign something for zoom - this can overlap with focus previous/next
+ if (add_axis_pair_assignment(assignments, IPT_UI_ZOOM_OUT, IPT_UI_ZOOM_IN, axis_ids[AXIS_THROTTLE]))
+ {
+ // took throttle
+ }
+ else if (add_button_pair_assignment(assignments, IPT_UI_ZOOM_OUT, IPT_UI_ZOOM_IN, switch_ids[SWITCH_DPAD_LEFT], switch_ids[SWITCH_DPAD_RIGHT]))
+ {
+ // took D-pad left/right
+ }
+ else if (add_axis_pair_assignment(assignments, IPT_UI_ZOOM_OUT, IPT_UI_ZOOM_IN, axis_ids[AXIS_RUDDER]))
+ {
+ // took rudder
+ }
+
+ // assign something for focus previous/next
+ if (add_axis_pair_assignment(assignments, IPT_UI_FOCUS_PREV, IPT_UI_FOCUS_NEXT, axis_ids[AXIS_RUDDER]))
+ {
+ // took rudder
+ }
+ else if (add_button_pair_assignment(assignments, IPT_UI_FOCUS_PREV, IPT_UI_FOCUS_NEXT, switch_ids[SWITCH_DPAD_LEFT], switch_ids[SWITCH_DPAD_RIGHT]))
+ {
+ // took D-pad left/right
+ }
+ else if (add_axis_pair_assignment(assignments, IPT_UI_FOCUS_PREV, IPT_UI_FOCUS_NEXT, axis_ids[AXIS_THROTTLE]))
+ {
+ // took throttle
+ }
+ }
+ else
{
- XINPUT_STATE state = {0};
+ // previous/next group
+ if (consume_button_pair(assignments, IPT_UI_PREV_GROUP, IPT_UI_NEXT_GROUP, switch_ids[SWITCH_HAT_UP], switch_ids[SWITCH_HAT_DOWN]))
+ {
+ // took hat up/down
+ }
+ else if (consume_button_pair(assignments, IPT_UI_PREV_GROUP, IPT_UI_NEXT_GROUP, switch_ids[SWITCH_DPAD_UP], switch_ids[SWITCH_DPAD_DOWN]))
+ {
+ // took D-pad up/down
+ }
+ else if (consume_button_pair(assignments, IPT_UI_PREV_GROUP, IPT_UI_NEXT_GROUP, switch_ids[SWITCH_HAT_LEFT], switch_ids[SWITCH_HAT_RIGHT]))
+ {
+ // took hat left/right
+ }
+ else if (consume_button_pair(assignments, IPT_UI_PREV_GROUP, IPT_UI_NEXT_GROUP, switch_ids[SWITCH_DPAD_LEFT], switch_ids[SWITCH_DPAD_RIGHT]))
+ {
+ // took D-pad left/right
+ }
- if (m_xinput_helper->xinput_get_state(i, &state) == ERROR_SUCCESS)
+ // try to choose something for focus previous/next
+ if (add_button_pair_assignment(assignments, IPT_UI_FOCUS_PREV, IPT_UI_FOCUS_NEXT, switch_ids[SWITCH_HAT_LEFT], switch_ids[SWITCH_HAT_RIGHT]))
{
- // allocate and link in a new device
- auto *devinfo = m_xinput_helper->create_xinput_device(machine, i, *this);
- if (!devinfo)
- continue;
+ // took hat left/right - use it for zoom as well
+ consume_button_pair(assignments, IPT_UI_ZOOM_OUT, IPT_UI_ZOOM_IN, switch_ids[SWITCH_HAT_LEFT], switch_ids[SWITCH_HAT_RIGHT]);
+ }
+ else if (add_button_pair_assignment(assignments, IPT_UI_FOCUS_PREV, IPT_UI_FOCUS_NEXT, switch_ids[SWITCH_DPAD_LEFT], switch_ids[SWITCH_DPAD_RIGHT]))
+ {
+ // took D-pad left/right - use it for zoom as well
+ consume_button_pair(assignments, IPT_UI_ZOOM_OUT, IPT_UI_ZOOM_IN, switch_ids[SWITCH_DPAD_LEFT], switch_ids[SWITCH_DPAD_RIGHT]);
+ }
+ else if (add_button_pair_assignment(assignments, IPT_UI_FOCUS_PREV, IPT_UI_FOCUS_NEXT, switch_ids[SWITCH_DPAD_UP], switch_ids[SWITCH_DPAD_DOWN]))
+ {
+ // took D-pad left/right - use it for zoom as well
+ consume_button_pair(assignments, IPT_UI_ZOOM_OUT, IPT_UI_ZOOM_IN, switch_ids[SWITCH_DPAD_UP], switch_ids[SWITCH_DPAD_DOWN]);
+ }
- // Configure each gamepad to add buttons and Axes, etc.
- devinfo->configure();
+ // use D-pad for page up/down and home/end if it's still available
+ if (consume_button_pair(assignments, IPT_UI_PAGE_UP, IPT_UI_PAGE_DOWN, switch_ids[SWITCH_DPAD_UP], switch_ids[SWITCH_DPAD_DOWN]))
+ {
+ // took D-pad up/down
+ }
+ else if (consume_button_pair(assignments, IPT_UI_PAGE_UP, IPT_UI_PAGE_DOWN, switch_ids[SWITCH_DPAD_LEFT], switch_ids[SWITCH_DPAD_RIGHT]))
+ {
+ // took D-pad left/right
}
+ consume_button_pair(assignments, IPT_UI_HOME, IPT_UI_END, switch_ids[SWITCH_DPAD_LEFT], switch_ids[SWITCH_DPAD_RIGHT]);
}
}
+ // assign UI select/back/clear/help
+ assign_ui_actions(
+ assignments,
+ SWITCH_B,
+ SWITCH_X,
+ SWITCH_Y,
+ SWITCH_START,
+ SWITCH_BACK,
+ switch_ids,
+ numbered_buttons,
+ button_count);
+
+ // set default assignments
+ device.set_default_assignments(std::move(assignments));
+}
+
+
+
+//============================================================
+// XInput guitar handler
+//============================================================
+
+class xinput_guitar_device : public xinput_device_base
+{
+public:
+ xinput_guitar_device(
+ std::string &&name,
+ std::string &&id,
+ input_module &module,
+ u32 player,
+ XINPUT_CAPABILITIES const &caps,
+ xinput_api_helper const &helper);
+
+ virtual void poll(bool relative_reset) override;
+ virtual void reset() override;
+ virtual void configure(input_device &device) override;
+
private:
- std::shared_ptr<xinput_api_helper> m_xinput_helper;
+ static inline constexpr USHORT SWITCH_BITS[] =
+ {
+ XINPUT_GAMEPAD_A,
+ XINPUT_GAMEPAD_B,
+ XINPUT_GAMEPAD_Y,
+ XINPUT_GAMEPAD_X,
+ XINPUT_GAMEPAD_LEFT_SHOULDER,
+ XINPUT_GAMEPAD_LEFT_THUMB,
+ XINPUT_GAMEPAD_RIGHT_SHOULDER,
+ XINPUT_GAMEPAD_RIGHT_THUMB,
+ XINPUT_GAMEPAD_START,
+ XINPUT_GAMEPAD_BACK,
+
+ XINPUT_GAMEPAD_DPAD_UP,
+ XINPUT_GAMEPAD_DPAD_DOWN,
+ XINPUT_GAMEPAD_DPAD_LEFT,
+ XINPUT_GAMEPAD_DPAD_RIGHT
+ };
+
+ enum
+ {
+ SWITCH_FRET1,
+ SWITCH_FRET2,
+ SWITCH_FRET3,
+ SWITCH_FRET4,
+ SWITCH_FRET5,
+ SWITCH_FRET_MOD, // indicates a "solo fret" is pressed, not a separate button
+ SWITCH_RB, // often reported present but no physical button
+ SWITCH_RSB, // usually reported absent
+ SWITCH_START,
+ SWITCH_BACK, // also used for "Star Power" in some games
+
+ SWITCH_DPAD_UP, // D-pad bits
+ SWITCH_DPAD_DOWN,
+ SWITCH_DPAD_LEFT,
+ SWITCH_DPAD_RIGHT,
+
+ SWITCH_TOTAL
+ };
+
+ enum
+ {
+ AXIS_SLIDER, // LSX, positive toward bridge
+ AXIS_LSY, // not used on guitar controllers?
+ AXIS_WHAMMY, // RSX, single-ended, neutral at negative extreme
+
+ AXIS_ORIENT_NECK, // RSY
+ AXIS_ORIENT_BRIDGE, // LT, toward zero with frets up
+ AXIS_ORIENT_BODY, // RT, toward zero in right-handed orientation
+
+ AXIS_PICKUP, // LT, positive extreme at one end
+
+ AXIS_TOTAL
+ };
+
+ u8 m_switches[SWITCH_TOTAL];
+ s32 m_axes[AXIS_TOTAL];
};
-} // anonymous namespace
+
+xinput_guitar_device::xinput_guitar_device(
+ std::string &&name,
+ std::string &&id,
+ input_module &module,
+ u32 player,
+ XINPUT_CAPABILITIES const &caps,
+ xinput_api_helper const &helper) :
+ xinput_device_base(std::move(name), std::move(id), module, player, caps, helper)
+{
+ std::fill(std::begin(m_switches), std::end(m_switches), 0);
+ std::fill(std::begin(m_axes), std::end(m_axes), 0);
+}
-int xinput_api_helper::initialize()
+void xinput_guitar_device::poll(bool relative_reset)
{
- m_xinput_dll = osd::dynamic_module::open(XINPUT_LIBRARIES);
+ // poll the device first, and skip if nothing changed
+ if (!read_state())
+ return;
- XInputGetState = m_xinput_dll->bind<xinput_get_state_fn>("XInputGetState");
- XInputGetCapabilities = m_xinput_dll->bind<xinput_get_caps_fn>("XInputGetCapabilities");
+ // translate button bits
+ for (unsigned i = 0; std::size(SWITCH_BITS) > i; ++i)
+ m_switches[SWITCH_FRET1 + i] = (buttons() & SWITCH_BITS[i]) ? 0xff : 0x00;
- if (!XInputGetState || !XInputGetCapabilities)
+ // translate miscellaneous axes
+ m_axes[AXIS_SLIDER] = normalize_absolute_axis(thumb_left_x(), XINPUT_AXIS_MINVALUE, XINPUT_AXIS_MAXVALUE);
+ m_axes[AXIS_LSY] = normalize_absolute_axis(-thumb_left_y(), XINPUT_AXIS_MINVALUE, XINPUT_AXIS_MAXVALUE);
+ m_axes[AXIS_WHAMMY] = -normalize_absolute_axis(s32(thumb_right_x()) + 32'768, -65'535, 65'535);
+
+ // translate orientation sensors
+ m_axes[AXIS_ORIENT_NECK] = normalize_absolute_axis(-thumb_right_y(), XINPUT_AXIS_MINVALUE, XINPUT_AXIS_MAXVALUE);
+ m_axes[AXIS_ORIENT_BRIDGE] = normalize_absolute_axis(trigger_left(), 0, 255);
+ m_axes[AXIS_ORIENT_BODY] = normalize_absolute_axis(trigger_right(), 0, 255);
+
+ // translate pickup selector
+ m_axes[AXIS_PICKUP] = -normalize_absolute_axis(trigger_left(), -255, 255);
+}
+
+
+void xinput_guitar_device::reset()
+{
+ set_reset();
+ std::fill(std::begin(m_switches), std::end(m_switches), 0);
+ std::fill(std::begin(m_axes), std::end(m_axes), 0);
+}
+
+
+void xinput_guitar_device::configure(input_device &device)
+{
+ // TODO: does subtype 0x06 indicate digital neck orientation sensor or lack of three-axis accelerometer?
+
+ // track item IDs for setting up default assignments
+ input_device::assignment_vector assignments;
+ input_item_id switch_ids[SWITCH_TOTAL];
+ std::fill(std::begin(switch_ids), std::end(switch_ids), ITEM_ID_INVALID);
+
+ // add axes
+ std::tuple<input_item_id, char const *, bool> const axis_caps[]{
+ { ITEM_ID_RXAXIS, "Neck Slider", has_thumb_left_x() },
+ { ITEM_ID_RYAXIS, "LSY", has_thumb_left_y() },
+ { ITEM_ID_SLIDER1, "Whammy Bar", has_thumb_right_x() },
+ { ITEM_ID_YAXIS, "Neck Orientation", has_thumb_right_y() },
+ { ITEM_ID_XAXIS, "Bridge Orientation", has_trigger_left() && has_trigger_right() },
+ { ITEM_ID_ZAXIS, "Body Orientation", has_trigger_right() },
+ { ITEM_ID_SLIDER2, "Pickup Selector", has_trigger_left() && !has_trigger_right() } };
+ input_item_id axis_ids[AXIS_TOTAL];
+ for (unsigned i = 0; AXIS_TOTAL > i; ++i)
{
- osd_printf_verbose("Could not find XInput. Please try to reinstall DirectX runtime package.\n");
- return -1;
+ auto const [item, name, supported] = axis_caps[i];
+ if (supported)
+ {
+ axis_ids[i] = device.add_item(
+ name,
+ std::string_view(),
+ item,
+ generic_axis_get_state<s32>,
+ &m_axes[i]);
+ }
+ else
+ {
+ axis_ids[i] = ITEM_ID_INVALID;
+ }
}
- return 0;
+ // add hats
+ for (unsigned i = 0; (SWITCH_DPAD_RIGHT - SWITCH_DPAD_UP) >= i; ++i)
+ {
+ if (has_button(SWITCH_BITS[SWITCH_DPAD_UP + i]))
+ {
+ switch_ids[SWITCH_DPAD_UP + i] = device.add_item(
+ HAT_NAMES_GUITAR[i],
+ std::string_view(),
+ input_item_id(ITEM_ID_HAT1UP + i), // matches up/down/left/right order
+ generic_button_get_state<u8>,
+ &m_switches[SWITCH_DPAD_UP + i]);
+ }
+ }
+
+ // add buttons
+ input_item_id button_id = ITEM_ID_BUTTON1;
+ unsigned button_count = 0;
+ unsigned numbered_buttons[SWITCH_FRET5 - SWITCH_FRET1 + 1];
+ for (unsigned i = 0; (SWITCH_RSB - SWITCH_FRET1) >= i; ++i)
+ {
+ if (has_button(SWITCH_BITS[i]))
+ {
+ switch_ids[SWITCH_FRET1 + i] = device.add_item(
+ BUTTON_NAMES_GUITAR[i],
+ std::string_view(),
+ button_id++,
+ generic_button_get_state<u8>,
+ &m_switches[SWITCH_FRET1 + i]);
+
+ // use fret buttons for automatically numbered buttons and pedals
+ if ((SWITCH_FRET5 - SWITCH_FRET1) >= i)
+ {
+ numbered_buttons[button_count] = SWITCH_FRET1 + i;
+ input_seq const seq(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, switch_ids[SWITCH_FRET1 + i]));
+ assignments.emplace_back(ioport_type(IPT_BUTTON1 + button_count), SEQ_TYPE_STANDARD, seq);
+ if (((ITEM_ID_INVALID != axis_ids[AXIS_WHAMMY]) ? 2 : 3) > button_count)
+ {
+ ioport_type const first_pedal = (ITEM_ID_INVALID != axis_ids[AXIS_WHAMMY])
+ ? IPT_PEDAL2
+ : IPT_PEDAL;
+ assignments.emplace_back(
+ ioport_type(first_pedal + button_count),
+ SEQ_TYPE_INCREMENT,
+ seq);
+ }
+ ++button_count;
+ }
+ }
+ }
+
+ // add start/back
+ if (has_button(XINPUT_GAMEPAD_START))
+ {
+ switch_ids[SWITCH_START] = device.add_item(
+ "Start",
+ std::string_view(),
+ ITEM_ID_START,
+ generic_button_get_state<u8>,
+ &m_switches[SWITCH_START]);
+ add_button_assignment(assignments, IPT_START, { switch_ids[SWITCH_START] });
+ }
+ if (has_button(XINPUT_GAMEPAD_BACK))
+ {
+ switch_ids[SWITCH_BACK] = device.add_item(
+ "Back",
+ std::string_view(),
+ ITEM_ID_SELECT,
+ generic_button_get_state<u8>,
+ &m_switches[SWITCH_BACK]);
+ add_button_assignment(assignments, IPT_SELECT, { switch_ids[SWITCH_BACK] });
+ }
+
+ // use the D-pad for directional controls - accelerometers are an annoyance
+ add_directional_assignments(
+ assignments,
+ ITEM_ID_INVALID,
+ ITEM_ID_INVALID,
+ switch_ids[SWITCH_DPAD_LEFT],
+ switch_ids[SWITCH_DPAD_RIGHT],
+ switch_ids[SWITCH_DPAD_UP],
+ switch_ids[SWITCH_DPAD_DOWN]);
+
+ // use the whammy bar for the first pedal and focus next if present
+ if (ITEM_ID_INVALID != axis_ids[AXIS_WHAMMY])
+ {
+ assignments.emplace_back(
+ IPT_PEDAL,
+ SEQ_TYPE_STANDARD,
+ input_seq(make_code(ITEM_CLASS_ABSOLUTE, ITEM_MODIFIER_NEG, axis_ids[AXIS_WHAMMY])));
+ assignments.emplace_back(
+ IPT_UI_FOCUS_NEXT,
+ SEQ_TYPE_STANDARD,
+ input_seq(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NEG, axis_ids[AXIS_WHAMMY])));
+ }
+
+ // use the neck slider for a couple of things if it's present
+ if (ITEM_ID_INVALID != axis_ids[AXIS_SLIDER])
+ {
+ input_seq const seq(make_code(ITEM_CLASS_ABSOLUTE, ITEM_MODIFIER_NONE, axis_ids[AXIS_SLIDER]));
+ assignments.emplace_back(IPT_PADDLE, SEQ_TYPE_STANDARD, seq);
+ assignments.emplace_back(IPT_AD_STICK_X, SEQ_TYPE_STANDARD, seq);
+ }
+
+ // assign UI select/back/clear/help
+ assign_ui_actions(
+ assignments,
+ SWITCH_FRET2,
+ SWITCH_FRET3,
+ SWITCH_FRET4,
+ SWITCH_START,
+ SWITCH_BACK,
+ switch_ids,
+ numbered_buttons,
+ button_count);
+
+ // set default assignments
+ device.set_default_assignments(std::move(assignments));
}
+
+
//============================================================
-// create_xinput_device
+// XInput drum kit handler
//============================================================
-xinput_joystick_device * xinput_api_helper::create_xinput_device(running_machine &machine, UINT index, wininput_module &module)
+class xinput_drumkit_device : public xinput_device_base
{
- XINPUT_CAPABILITIES caps = { 0 };
- if (FAILED(xinput_get_capabilities(index, 0, &caps)))
+public:
+ xinput_drumkit_device(
+ std::string &&name,
+ std::string &&id,
+ input_module &module,
+ u32 player,
+ XINPUT_CAPABILITIES const &caps,
+ xinput_api_helper const &helper);
+
+ virtual void poll(bool relative_reset) override;
+ virtual void reset() override;
+ virtual void configure(input_device &device) override;
+
+private:
+ static inline constexpr USHORT SWITCH_BITS[] =
{
- // If we can't get the capabilities skip this device
- return nullptr;
+ XINPUT_GAMEPAD_A,
+ XINPUT_GAMEPAD_B,
+ XINPUT_GAMEPAD_X,
+ XINPUT_GAMEPAD_Y,
+ XINPUT_GAMEPAD_RIGHT_SHOULDER,
+ XINPUT_GAMEPAD_LEFT_SHOULDER,
+ XINPUT_GAMEPAD_LEFT_THUMB,
+ XINPUT_GAMEPAD_RIGHT_THUMB,
+ XINPUT_GAMEPAD_START,
+ XINPUT_GAMEPAD_BACK,
+
+ XINPUT_GAMEPAD_DPAD_UP,
+ XINPUT_GAMEPAD_DPAD_DOWN,
+ XINPUT_GAMEPAD_DPAD_LEFT,
+ XINPUT_GAMEPAD_DPAD_RIGHT
+ };
+
+ enum
+ {
+ SWITCH_GREEN, // button bits
+ SWITCH_RED,
+ SWITCH_BLUE,
+ SWITCH_YELLOW,
+ SWITCH_ORANGE,
+ SWITCH_BASS_DRUM,
+ SWITCH_LSB,
+ SWITCH_RSB,
+ SWITCH_START,
+ SWITCH_BACK,
+
+ SWITCH_DPAD_UP, // D-pad bits
+ SWITCH_DPAD_DOWN,
+ SWITCH_DPAD_LEFT,
+ SWITCH_DPAD_RIGHT,
+
+ SWITCH_TOTAL
+ };
+
+ enum
+ {
+ AXIS_GREEN, // LSY low
+ AXIS_RED, // LSY high
+ AXIS_BLUE, // RSX high
+ AXIS_YELLOW, // RSX low
+ AXIS_ORANGE, // RSY low
+ AXIS_BASS_DRUM, // RSY high
+
+ AXIS_TOTAL
+ };
+
+ u8 m_switches[SWITCH_TOTAL];
+ s32 m_axes[AXIS_TOTAL];
+};
+
+
+xinput_drumkit_device::xinput_drumkit_device(
+ std::string &&name,
+ std::string &&id,
+ input_module &module,
+ u32 player,
+ XINPUT_CAPABILITIES const &caps,
+ xinput_api_helper const &helper) :
+ xinput_device_base(std::move(name), std::move(id), module, player, caps, helper)
+{
+ std::fill(std::begin(m_switches), std::end(m_switches), 0);
+ std::fill(std::begin(m_axes), std::end(m_axes), 0);
+}
+
+
+void xinput_drumkit_device::poll(bool relative_reset)
+{
+ // poll the device first, and skip if nothing changed
+ if (!read_state())
+ return;
+
+ // translate button bits
+ for (unsigned i = 0; std::size(SWITCH_BITS) > i; ++i)
+ m_switches[SWITCH_GREEN + i] = (buttons() & SWITCH_BITS[i]) ? 0xff : 0x00;
+
+ // translate axes
+ m_axes[AXIS_GREEN] = -normalize_absolute_axis(BIT(u16(thumb_left_y()), 0, 8), -255, 255);
+ m_axes[AXIS_RED] = -normalize_absolute_axis(BIT(u16(thumb_left_y()), 8, 8), -255, 255);
+ m_axes[AXIS_BLUE] = -normalize_absolute_axis(BIT(u16(thumb_right_x()), 8, 8), -255, 255);
+ m_axes[AXIS_YELLOW] = -normalize_absolute_axis(BIT(u16(thumb_right_x()), 0, 8), -255, 255);
+ m_axes[AXIS_ORANGE] = -normalize_absolute_axis(BIT(u16(thumb_right_y()), 0, 8), -255, 255);
+ m_axes[AXIS_BASS_DRUM] = -normalize_absolute_axis(BIT(u16(thumb_right_y()), 8, 8), -255, 255);
+}
+
+
+void xinput_drumkit_device::reset()
+{
+ set_reset();
+ std::fill(std::begin(m_switches), std::end(m_switches), 0);
+ std::fill(std::begin(m_axes), std::end(m_axes), 0);
+}
+
+
+void xinput_drumkit_device::configure(input_device &device)
+{
+ // track item IDs for setting up default assignments
+ input_device::assignment_vector assignments;
+ input_item_id switch_ids[SWITCH_TOTAL];
+ std::fill(std::begin(switch_ids), std::end(switch_ids), ITEM_ID_INVALID);
+
+ // add axes
+ std::tuple<input_item_id, char const *, bool> const axis_caps[]{
+ { ITEM_ID_XAXIS, "Green Velocity", has_thumb_left_y() },
+ { ITEM_ID_YAXIS, "Red Velocity", has_thumb_left_y() },
+ { ITEM_ID_ZAXIS, "Blue Velocity", has_thumb_right_x() },
+ { ITEM_ID_RXAXIS, "Yellow Velocity", has_thumb_right_x() },
+ { ITEM_ID_RYAXIS, "Orange Velocity", has_thumb_right_y() },
+ { ITEM_ID_RZAXIS, "Bass Drum Velocity", has_thumb_right_y() } };
+ for (unsigned i = 0; (AXIS_BASS_DRUM - AXIS_GREEN) >= i; ++i)
+ {
+ auto const [item, name, supported] = axis_caps[i];
+ if (supported)
+ {
+ device.add_item(
+ name,
+ std::string_view(),
+ item,
+ generic_axis_get_state<s32>,
+ &m_axes[AXIS_GREEN + i]);
+ }
}
- char device_name[16];
- snprintf(device_name, sizeof(device_name), "XInput Player %u", index + 1);
+ // add hats
+ for (unsigned i = 0; (SWITCH_DPAD_RIGHT - SWITCH_DPAD_UP) >= i; ++i)
+ {
+ if (has_button(SWITCH_BITS[SWITCH_DPAD_UP + i]))
+ {
+ switch_ids[SWITCH_DPAD_UP + i] = device.add_item(
+ HAT_NAMES_GAMEPAD[i],
+ std::string_view(),
+ input_item_id(ITEM_ID_HAT1UP + i), // matches up/down/left/right order
+ generic_button_get_state<u8>,
+ &m_switches[SWITCH_DPAD_UP + i]);
+ }
+ }
- // allocate the device object
- auto &devinfo = module.devicelist().create_device<xinput_joystick_device>(machine, device_name, device_name, module, shared_from_this());
+ // add buttons
+ unsigned button_count = 0;
+ unsigned numbered_buttons[SWITCH_RSB - SWITCH_GREEN + 1];
+ for (unsigned i = 0; (SWITCH_RSB - SWITCH_GREEN) >= i; ++i)
+ {
+ if (has_button(SWITCH_BITS[i]))
+ {
+ switch_ids[SWITCH_GREEN + i] = device.add_item(
+ BUTTON_NAMES_DRUMKIT[i],
+ std::string_view(),
+ input_item_id(ITEM_ID_BUTTON1 + button_count),
+ generic_button_get_state<u8>,
+ &m_switches[SWITCH_GREEN + i]);
+ numbered_buttons[button_count] = SWITCH_GREEN + i;
- // Set the player ID
- devinfo.xinput_state.player_index = index;
+ // use these for automatically numbered buttons and pedals
+ input_seq const seq(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, switch_ids[SWITCH_GREEN + i]));
+ assignments.emplace_back(ioport_type(IPT_BUTTON1 + button_count), SEQ_TYPE_STANDARD, seq);
+ if (3 > button_count)
+ assignments.emplace_back(ioport_type(IPT_PEDAL + button_count), SEQ_TYPE_INCREMENT, seq);
+ ++button_count;
+ }
+ }
- // Assign the caps we captured earlier
- devinfo.xinput_state.caps = caps;
+ // add start/back
+ if (has_button(XINPUT_GAMEPAD_START))
+ {
+ switch_ids[SWITCH_START] = device.add_item(
+ "Start",
+ std::string_view(),
+ ITEM_ID_START,
+ generic_button_get_state<u8>,
+ &m_switches[SWITCH_START]);
+ add_button_assignment(assignments, IPT_START, { switch_ids[SWITCH_START] });
+ }
+ if (has_button(XINPUT_GAMEPAD_BACK))
+ {
+ switch_ids[SWITCH_BACK] = device.add_item(
+ "Back",
+ std::string_view(),
+ ITEM_ID_SELECT,
+ generic_button_get_state<u8>,
+ &m_switches[SWITCH_BACK]);
+ add_button_assignment(assignments, IPT_SELECT, { switch_ids[SWITCH_BACK] });
+ }
+
+ // use the D-pad for directional controls
+ add_directional_assignments(
+ assignments,
+ ITEM_ID_INVALID,
+ ITEM_ID_INVALID,
+ switch_ids[SWITCH_DPAD_LEFT],
+ switch_ids[SWITCH_DPAD_RIGHT],
+ switch_ids[SWITCH_DPAD_UP],
+ switch_ids[SWITCH_DPAD_DOWN]);
+
+ // use the D-pad and A/B/X/Y diamond for twin sticks
+ add_twin_stick_assignments(
+ assignments,
+ ITEM_ID_INVALID,
+ ITEM_ID_INVALID,
+ ITEM_ID_INVALID,
+ ITEM_ID_INVALID,
+ switch_ids[SWITCH_DPAD_LEFT],
+ switch_ids[SWITCH_DPAD_RIGHT],
+ switch_ids[SWITCH_DPAD_UP],
+ switch_ids[SWITCH_DPAD_DOWN],
+ switch_ids[SWITCH_BLUE],
+ switch_ids[SWITCH_RED],
+ switch_ids[SWITCH_YELLOW],
+ switch_ids[SWITCH_GREEN]);
- return &devinfo;
+ // assign UI select/back/clear/help
+ assign_ui_actions(
+ assignments,
+ SWITCH_RED,
+ SWITCH_BLUE,
+ SWITCH_YELLOW,
+ SWITCH_START,
+ SWITCH_BACK,
+ switch_ids,
+ numbered_buttons,
+ button_count);
+
+ // use bass drum pedal for focus next if available to make the system selection menu usable
+ if (add_button_assignment(assignments, IPT_UI_FOCUS_NEXT, { switch_ids[SWITCH_BASS_DRUM] }))
+ switch_ids[SWITCH_BASS_DRUM] = ITEM_ID_INVALID;
+
+ // set default assignments
+ device.set_default_assignments(std::move(assignments));
}
+
+
//============================================================
-// xinput_joystick_device
+// XInput turntable handler
//============================================================
-xinput_joystick_device::xinput_joystick_device(running_machine &machine, std::string &&name, std::string &&id, input_module &module, std::shared_ptr<xinput_api_helper> helper) :
- device_info(machine, std::string(name), std::string(id), DEVICE_CLASS_JOYSTICK, module),
- gamepad({ { 0 } }),
- xinput_state({ 0 }),
- m_xinput_helper(helper),
- m_configured(false)
+class xinput_turntable_device : public xinput_device_base
{
-}
+public:
+ xinput_turntable_device(
+ std::string &&name,
+ std::string &&id,
+ input_module &module,
+ u32 player,
+ XINPUT_CAPABILITIES const &caps,
+ xinput_api_helper const &helper);
-void xinput_joystick_device::poll()
+ virtual void poll(bool relative_reset) override;
+ virtual void reset() override;
+ virtual void configure(input_device &device) override;
+
+private:
+ static inline constexpr USHORT SWITCH_BITS[] =
+ {
+ XINPUT_GAMEPAD_A,
+ XINPUT_GAMEPAD_B,
+ XINPUT_GAMEPAD_X,
+ XINPUT_GAMEPAD_Y,
+ XINPUT_GAMEPAD_LEFT_SHOULDER,
+ XINPUT_GAMEPAD_RIGHT_SHOULDER,
+ XINPUT_GAMEPAD_LEFT_THUMB,
+ XINPUT_GAMEPAD_RIGHT_THUMB,
+ XINPUT_GAMEPAD_START,
+ XINPUT_GAMEPAD_BACK,
+
+ XINPUT_GAMEPAD_DPAD_UP,
+ XINPUT_GAMEPAD_DPAD_DOWN,
+ XINPUT_GAMEPAD_DPAD_LEFT,
+ XINPUT_GAMEPAD_DPAD_RIGHT
+ };
+
+ enum
+ {
+ SWITCH_A, // button bits
+ SWITCH_B,
+ SWITCH_X,
+ SWITCH_Y,
+ SWITCH_LB,
+ SWITCH_RB,
+ SWITCH_LSB,
+ SWITCH_RSB,
+ SWITCH_START,
+ SWITCH_BACK,
+
+ SWITCH_DPAD_UP, // D-pad bits
+ SWITCH_DPAD_DOWN,
+ SWITCH_DPAD_LEFT,
+ SWITCH_DPAD_RIGHT,
+
+ SWITCH_GREEN, // RT bits
+ SWITCH_RED,
+ SWITCH_BLUE,
+
+ SWITCH_TOTAL
+ };
+
+ enum
+ {
+ AXIS_TURNTABLE, // LSY
+ AXIS_EFFECT, // RSX
+ AXIS_CROSSFADE, // RSY
+
+ AXIS_TOTAL
+ };
+
+ u8 m_switches[SWITCH_TOTAL];
+ s32 m_axes[AXIS_TOTAL];
+ u16 m_prev_effect;
+};
+
+
+xinput_turntable_device::xinput_turntable_device(
+ std::string &&name,
+ std::string &&id,
+ input_module &module,
+ u32 player,
+ XINPUT_CAPABILITIES const &caps,
+ xinput_api_helper const &helper) :
+ xinput_device_base(std::move(name), std::move(id), module, player, caps, helper),
+ m_prev_effect(0)
{
- if (!m_configured)
- return;
+ std::fill(std::begin(m_switches), std::end(m_switches), 0);
+ std::fill(std::begin(m_axes), std::end(m_axes), 0);
+}
+
+void xinput_turntable_device::poll(bool relative_reset)
+{
// poll the device first
- HRESULT result = m_xinput_helper->xinput_get_state(xinput_state.player_index, &xinput_state.xstate);
+ bool const was_reset = is_reset();
+ if (read_state())
+ {
+ // translate button bits
+ for (unsigned i = 0; std::size(SWITCH_BITS) > i; ++i)
+ m_switches[SWITCH_A + i] = (buttons() & SWITCH_BITS[i]) ? 0xff : 0x00;
- // If we can't poll the device, skip
- if (FAILED(result))
- return;
+ // translate RT bits
+ for (unsigned i = 0; (SWITCH_BLUE - SWITCH_GREEN) >= i; ++i)
+ m_switches[SWITCH_GREEN + i] = BIT(trigger_right(), i) ? 0xff : 0x00;
+
+ // translate axes
+ m_axes[AXIS_TURNTABLE] = s32(thumb_left_y()) * input_device::RELATIVE_PER_PIXEL * 2;
+ m_axes[AXIS_CROSSFADE] = normalize_absolute_axis(thumb_right_y(), XINPUT_AXIS_MINVALUE, XINPUT_AXIS_MAXVALUE);
+ }
- // Copy the XState into State
- // Start with the POV (DPAD)
- for (int povindex = 0; povindex < XINPUT_MAX_POV; povindex++)
+ // handle effect dial
+ if (was_reset)
+ {
+ // just grab the current count after regaining focus
+ m_prev_effect = u16(thumb_right_x());
+ }
+ else if (relative_reset)
{
- int currentPov = xinput_pov_dir[povindex];
- gamepad.povs[povindex] = (xinput_state.xstate.Gamepad.wButtons & currentPov) ? 0xFF : 0;
+ // convert value to relative displacement
+ s32 effect_delta = s32(u32(u16(thumb_right_x()))) - s32(u32(m_prev_effect));
+ m_prev_effect = u16(thumb_right_x());
+ if (0x8000 < effect_delta)
+ effect_delta -= 0x1'0000;
+ else if (-0x8000 > effect_delta)
+ effect_delta += 0x1'0000;
+ m_axes[AXIS_EFFECT] = effect_delta * input_device::RELATIVE_PER_PIXEL / 128;
}
+}
- // Now do the buttons
- for (int buttonindex = 0; buttonindex < XINPUT_MAX_BUTTONS; buttonindex++)
+
+void xinput_turntable_device::reset()
+{
+ set_reset();
+ std::fill(std::begin(m_switches), std::end(m_switches), 0);
+ std::fill(std::begin(m_axes), std::end(m_axes), 0);
+}
+
+
+void xinput_turntable_device::configure(input_device &device)
+{
+ // track item IDs for setting up default assignments
+ input_device::assignment_vector assignments;
+ input_item_id switch_ids[SWITCH_TOTAL];
+ std::fill(std::begin(switch_ids), std::end(switch_ids), ITEM_ID_INVALID);
+
+ // add axes
+ input_item_id const turntable_id = device.add_item(
+ "Turntable",
+ std::string_view(),
+ ITEM_ID_ADD_RELATIVE1,
+ generic_axis_get_state<s32>,
+ &m_axes[AXIS_TURNTABLE]);
+ input_item_id const effect_id = device.add_item(
+ "Effect",
+ std::string_view(),
+ ITEM_ID_ADD_RELATIVE2,
+ generic_axis_get_state<s32>,
+ &m_axes[AXIS_EFFECT]);
+ input_item_id const crossfade_id = device.add_item(
+ "Crossfade",
+ std::string_view(),
+ ITEM_ID_XAXIS,
+ generic_axis_get_state<s32>,
+ &m_axes[AXIS_CROSSFADE]);
+
+ // add hats
+ for (unsigned i = 0; (SWITCH_DPAD_RIGHT - SWITCH_DPAD_UP) >= i; ++i)
+ {
+ if (has_button(SWITCH_BITS[SWITCH_DPAD_UP + i]))
+ {
+ switch_ids[SWITCH_DPAD_UP + i] = device.add_item(
+ HAT_NAMES_GAMEPAD[i],
+ std::string_view(),
+ input_item_id(ITEM_ID_HAT1UP + i), // matches up/down/left/right order
+ generic_button_get_state<u8>,
+ &m_switches[SWITCH_DPAD_UP + i]);
+ }
+ }
+
+ // add buttons
+ input_item_id button_id = ITEM_ID_BUTTON1;
+ unsigned button_count = 0;
+ unsigned numbered_buttons[SWITCH_RSB - SWITCH_A + 1];
+ for (unsigned i = 0; (SWITCH_RSB - SWITCH_A) >= i; ++i)
+ {
+ if (has_button(SWITCH_BITS[i]))
+ {
+ switch_ids[SWITCH_A + i] = device.add_item(
+ BUTTON_NAMES_KEYBOARD[i],
+ std::string_view(),
+ button_id++,
+ generic_button_get_state<u8>,
+ &m_switches[SWITCH_A + i]);
+ numbered_buttons[button_count] = SWITCH_A + i;
+
+ // use these for automatically numbered buttons and pedals
+ input_seq const seq(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, switch_ids[SWITCH_A + i]));
+ assignments.emplace_back(ioport_type(IPT_BUTTON1 + button_count), SEQ_TYPE_STANDARD, seq);
+ if (3 > button_count)
+ assignments.emplace_back(ioport_type(IPT_PEDAL + button_count), SEQ_TYPE_INCREMENT, seq);
+ ++button_count;
+ }
+ }
+
+ // turntable buttons activate these as well as A/B/X
+ switch_ids[SWITCH_GREEN] = device.add_item(
+ "Green",
+ std::string_view(),
+ button_id++,
+ generic_button_get_state<u8>,
+ &m_switches[SWITCH_GREEN]);
+ switch_ids[SWITCH_RED] = device.add_item(
+ "Red",
+ std::string_view(),
+ button_id++,
+ generic_button_get_state<u8>,
+ &m_switches[SWITCH_RED]);
+ switch_ids[SWITCH_BLUE] = device.add_item(
+ "Blue",
+ std::string_view(),
+ button_id++,
+ generic_button_get_state<u8>,
+ &m_switches[SWITCH_BLUE]);
+
+ // add start/back
+ if (has_button(XINPUT_GAMEPAD_START))
+ {
+ switch_ids[SWITCH_START] = device.add_item(
+ "Start",
+ std::string_view(),
+ ITEM_ID_START,
+ generic_button_get_state<u8>,
+ &m_switches[SWITCH_START]);
+ add_button_assignment(assignments, IPT_START, { switch_ids[SWITCH_START] });
+ }
+ if (has_button(XINPUT_GAMEPAD_BACK))
+ {
+ switch_ids[SWITCH_BACK] = device.add_item(
+ "Back",
+ std::string_view(),
+ ITEM_ID_SELECT,
+ generic_button_get_state<u8>,
+ &m_switches[SWITCH_BACK]);
+ add_button_assignment(assignments, IPT_SELECT, { switch_ids[SWITCH_BACK] });
+ }
+
+ // use D-pad and A/B/X/Y diamond for twin sticks
+ add_twin_stick_assignments(
+ assignments,
+ ITEM_ID_INVALID,
+ ITEM_ID_INVALID,
+ ITEM_ID_INVALID,
+ ITEM_ID_INVALID,
+ switch_ids[SWITCH_DPAD_LEFT],
+ switch_ids[SWITCH_DPAD_RIGHT],
+ switch_ids[SWITCH_DPAD_UP],
+ switch_ids[SWITCH_DPAD_DOWN],
+ switch_ids[SWITCH_X],
+ switch_ids[SWITCH_B],
+ switch_ids[SWITCH_Y],
+ switch_ids[SWITCH_A]);
+
+ // for most analog player controls, use turntable for X and effect for Y
+ input_seq const turntable_seq(make_code(ITEM_CLASS_RELATIVE, ITEM_MODIFIER_NONE, turntable_id));
+ input_seq const effect_seq(make_code(ITEM_CLASS_RELATIVE, ITEM_MODIFIER_NONE, effect_id));
+ input_seq const crossfade_seq(make_code(ITEM_CLASS_ABSOLUTE, ITEM_MODIFIER_NONE, crossfade_id));
+ input_seq joystick_left_seq(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NEG, turntable_id));
+ input_seq joystick_right_seq(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_POS, turntable_id));
+ input_seq joystick_up_seq(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NEG, effect_id));
+ input_seq joystick_down_seq(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_POS, effect_id));
+ assignments.emplace_back(IPT_PADDLE, SEQ_TYPE_STANDARD, turntable_seq);
+ assignments.emplace_back(IPT_PADDLE_V, SEQ_TYPE_STANDARD, effect_seq);
+ assignments.emplace_back(IPT_POSITIONAL, SEQ_TYPE_STANDARD, crossfade_seq);
+ assignments.emplace_back(IPT_POSITIONAL_V, SEQ_TYPE_STANDARD, effect_seq);
+ assignments.emplace_back(IPT_DIAL, SEQ_TYPE_STANDARD, turntable_seq);
+ assignments.emplace_back(IPT_DIAL_V, SEQ_TYPE_STANDARD, effect_seq);
+ assignments.emplace_back(IPT_TRACKBALL_X, SEQ_TYPE_STANDARD, turntable_seq);
+ assignments.emplace_back(IPT_TRACKBALL_Y, SEQ_TYPE_STANDARD, effect_seq);
+ assignments.emplace_back(IPT_AD_STICK_X, SEQ_TYPE_STANDARD, turntable_seq);
+ assignments.emplace_back(IPT_AD_STICK_Y, SEQ_TYPE_STANDARD, effect_seq);
+ assignments.emplace_back(IPT_AD_STICK_Z, SEQ_TYPE_STANDARD, crossfade_seq);
+ assignments.emplace_back(IPT_LIGHTGUN_X, SEQ_TYPE_STANDARD, turntable_seq);
+ assignments.emplace_back(IPT_LIGHTGUN_Y, SEQ_TYPE_STANDARD, effect_seq);
+ assignments.emplace_back(IPT_MOUSE_X, SEQ_TYPE_STANDARD, turntable_seq);
+ assignments.emplace_back(IPT_MOUSE_Y, SEQ_TYPE_STANDARD, effect_seq);
+
+ // use D-pad for analog controls as well if present
+ bool const have_dpad_left = ITEM_ID_INVALID != switch_ids[SWITCH_DPAD_LEFT];
+ bool const have_dpad_right = ITEM_ID_INVALID != switch_ids[SWITCH_DPAD_RIGHT];
+ bool const have_dpad_up = ITEM_ID_INVALID != switch_ids[SWITCH_DPAD_UP];
+ bool const have_dpad_down = ITEM_ID_INVALID != switch_ids[SWITCH_DPAD_DOWN];
+ if (have_dpad_left)
+ {
+ input_code const code(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, switch_ids[SWITCH_DPAD_LEFT]));
+ input_seq const left_seq(code);
+ joystick_left_seq += input_seq::or_code;
+ joystick_left_seq += code;
+ assignments.emplace_back(IPT_PADDLE, SEQ_TYPE_DECREMENT, left_seq);
+ assignments.emplace_back(IPT_POSITIONAL, SEQ_TYPE_DECREMENT, left_seq);
+ assignments.emplace_back(IPT_DIAL, SEQ_TYPE_DECREMENT, left_seq);
+ assignments.emplace_back(IPT_TRACKBALL_X, SEQ_TYPE_DECREMENT, left_seq);
+ assignments.emplace_back(IPT_AD_STICK_X, SEQ_TYPE_DECREMENT, left_seq);
+ assignments.emplace_back(IPT_LIGHTGUN_X, SEQ_TYPE_DECREMENT, left_seq);
+ }
+ if (have_dpad_right)
+ {
+ input_code const code(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, switch_ids[SWITCH_DPAD_RIGHT]));
+ input_seq const right_seq(code);
+ joystick_right_seq += input_seq::or_code;
+ joystick_right_seq += code;
+ assignments.emplace_back(IPT_PADDLE, SEQ_TYPE_INCREMENT, right_seq);
+ assignments.emplace_back(IPT_POSITIONAL, SEQ_TYPE_INCREMENT, right_seq);
+ assignments.emplace_back(IPT_DIAL, SEQ_TYPE_INCREMENT, right_seq);
+ assignments.emplace_back(IPT_TRACKBALL_X, SEQ_TYPE_INCREMENT, right_seq);
+ assignments.emplace_back(IPT_AD_STICK_X, SEQ_TYPE_INCREMENT, right_seq);
+ assignments.emplace_back(IPT_LIGHTGUN_X, SEQ_TYPE_INCREMENT, right_seq);
+ }
+ if (have_dpad_up)
+ {
+ input_code const code(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, switch_ids[SWITCH_DPAD_UP]));
+ input_seq const up_seq(code);
+ joystick_up_seq += input_seq::or_code;
+ joystick_up_seq += code;
+ assignments.emplace_back(IPT_PADDLE_V, SEQ_TYPE_DECREMENT, up_seq);
+ assignments.emplace_back(IPT_POSITIONAL_V, SEQ_TYPE_DECREMENT, up_seq);
+ assignments.emplace_back(IPT_DIAL_V, SEQ_TYPE_DECREMENT, up_seq);
+ assignments.emplace_back(IPT_TRACKBALL_Y, SEQ_TYPE_DECREMENT, up_seq);
+ assignments.emplace_back(IPT_AD_STICK_Y, SEQ_TYPE_DECREMENT, up_seq);
+ assignments.emplace_back(IPT_LIGHTGUN_Y, SEQ_TYPE_DECREMENT, up_seq);
+ }
+ if (have_dpad_down)
+ {
+ input_code const code(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, switch_ids[SWITCH_DPAD_DOWN]));
+ input_seq const down_seq(code);
+ joystick_down_seq += input_seq::or_code;
+ joystick_down_seq += code;
+ assignments.emplace_back(IPT_PADDLE_V, SEQ_TYPE_INCREMENT, down_seq);
+ assignments.emplace_back(IPT_POSITIONAL_V, SEQ_TYPE_INCREMENT, down_seq);
+ assignments.emplace_back(IPT_DIAL_V, SEQ_TYPE_INCREMENT, down_seq);
+ assignments.emplace_back(IPT_TRACKBALL_Y, SEQ_TYPE_INCREMENT, down_seq);
+ assignments.emplace_back(IPT_AD_STICK_Y, SEQ_TYPE_INCREMENT, down_seq);
+ assignments.emplace_back(IPT_LIGHTGUN_Y, SEQ_TYPE_INCREMENT, down_seq);
+ }
+ assignments.emplace_back(IPT_JOYSTICK_LEFT, SEQ_TYPE_STANDARD, joystick_left_seq);
+ assignments.emplace_back(IPT_JOYSTICK_RIGHT, SEQ_TYPE_STANDARD, joystick_right_seq);
+ assignments.emplace_back(IPT_JOYSTICK_UP, SEQ_TYPE_STANDARD, joystick_up_seq);
+ assignments.emplace_back(IPT_JOYSTICK_DOWN, SEQ_TYPE_STANDARD, joystick_down_seq);
+
+ // choose navigation controls
+ input_seq ui_up_seq(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NEG, turntable_id));
+ input_seq ui_down_seq(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_POS, turntable_id));
+ input_seq ui_left_seq(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NEG, effect_id));
+ input_seq ui_right_seq(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_POS, effect_id));
+ if ((have_dpad_up && have_dpad_down) || !have_dpad_left || !have_dpad_right)
+ {
+ if (have_dpad_up)
+ {
+ ui_up_seq += input_seq::or_code;
+ ui_up_seq += make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, switch_ids[SWITCH_DPAD_UP]);
+ }
+ if (have_dpad_down)
+ {
+ ui_down_seq += input_seq::or_code;
+ ui_down_seq += make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, switch_ids[SWITCH_DPAD_DOWN]);
+ }
+ if (have_dpad_left)
+ {
+ ui_left_seq += input_seq::or_code;
+ ui_left_seq += make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, switch_ids[SWITCH_DPAD_LEFT]);
+ }
+ if (have_dpad_right)
+ {
+ ui_right_seq += input_seq::or_code;
+ ui_right_seq += make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, switch_ids[SWITCH_DPAD_RIGHT]);
+ }
+ }
+ else
{
- int currentButton = xinput_buttons[buttonindex];
- gamepad.buttons[buttonindex] = (xinput_state.xstate.Gamepad.wButtons & currentButton) ? 0xFF : 0;
+ if (have_dpad_left)
+ {
+ ui_up_seq += input_seq::or_code;
+ ui_up_seq += make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, switch_ids[SWITCH_DPAD_LEFT]);
+ }
+ if (have_dpad_right)
+ {
+ ui_down_seq += input_seq::or_code;
+ ui_down_seq += make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, switch_ids[SWITCH_DPAD_RIGHT]);
+ }
+ if (have_dpad_up)
+ {
+ ui_left_seq += input_seq::or_code;
+ ui_left_seq += make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, switch_ids[SWITCH_DPAD_UP]);
+ }
+ if (have_dpad_down)
+ {
+ ui_right_seq += input_seq::or_code;
+ ui_right_seq += make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, switch_ids[SWITCH_DPAD_DOWN]);
+ }
}
+ assignments.emplace_back(IPT_UI_UP, SEQ_TYPE_STANDARD, ui_up_seq);
+ assignments.emplace_back(IPT_UI_DOWN, SEQ_TYPE_STANDARD, ui_down_seq);
+ assignments.emplace_back(IPT_UI_LEFT, SEQ_TYPE_STANDARD, ui_left_seq);
+ assignments.emplace_back(IPT_UI_RIGHT, SEQ_TYPE_STANDARD, ui_right_seq);
- // Now grab the axis values
- // Each of the thumbstick axis members is a signed value between -32768 and 32767 describing the position of the thumbstick
- // However, the Y axis values are inverted from what MAME expects, so negate the value
- gamepad.left_thumb_x = normalize_absolute_axis(xinput_state.xstate.Gamepad.sThumbLX, XINPUT_AXIS_MINVALUE, XINPUT_AXIS_MAXVALUE);
- gamepad.left_thumb_y = normalize_absolute_axis(-xinput_state.xstate.Gamepad.sThumbLY, XINPUT_AXIS_MINVALUE, XINPUT_AXIS_MAXVALUE);
- gamepad.right_thumb_x = normalize_absolute_axis(xinput_state.xstate.Gamepad.sThumbRX, XINPUT_AXIS_MINVALUE, XINPUT_AXIS_MAXVALUE);
- gamepad.right_thumb_y = normalize_absolute_axis(-xinput_state.xstate.Gamepad.sThumbRY, XINPUT_AXIS_MINVALUE, XINPUT_AXIS_MAXVALUE);
+ // assign UI select/back/clear/help
+ assign_ui_actions(
+ assignments,
+ SWITCH_B,
+ SWITCH_X,
+ SWITCH_Y,
+ SWITCH_START,
+ SWITCH_BACK,
+ switch_ids,
+ numbered_buttons,
+ std::min<unsigned>(button_count, 4));
- // Now the triggers, place them on half-axes (negative side)
- gamepad.left_trigger = -normalize_absolute_axis(xinput_state.xstate.Gamepad.bLeftTrigger, -255, 255);
- gamepad.right_trigger = -normalize_absolute_axis(xinput_state.xstate.Gamepad.bRightTrigger, -255, 255);
+ // set default assignments
+ device.set_default_assignments(std::move(assignments));
}
-void xinput_joystick_device::reset()
+
+
+//============================================================
+// XInput keyboard handler
+//============================================================
+
+class xinput_keyboard_device : public xinput_device_base
{
- memset(&gamepad, 0, sizeof(gamepad));
+public:
+ xinput_keyboard_device(
+ std::string &&name,
+ std::string &&id,
+ input_module &module,
+ u32 player,
+ XINPUT_CAPABILITIES const &caps,
+ xinput_api_helper const &helper);
+
+ virtual void poll(bool relative_reset) override;
+ virtual void reset() override;
+ virtual void configure(input_device &device) override;
+
+private:
+ static inline constexpr USHORT SWITCH_BITS[] =
+ {
+ XINPUT_GAMEPAD_A,
+ XINPUT_GAMEPAD_B,
+ XINPUT_GAMEPAD_X,
+ XINPUT_GAMEPAD_Y,
+ XINPUT_GAMEPAD_LEFT_SHOULDER,
+ XINPUT_GAMEPAD_RIGHT_SHOULDER,
+ XINPUT_GAMEPAD_LEFT_THUMB,
+ XINPUT_GAMEPAD_RIGHT_THUMB,
+ XINPUT_GAMEPAD_START,
+ XINPUT_GAMEPAD_BACK,
+
+ XINPUT_GAMEPAD_DPAD_UP,
+ XINPUT_GAMEPAD_DPAD_DOWN,
+ XINPUT_GAMEPAD_DPAD_LEFT,
+ XINPUT_GAMEPAD_DPAD_RIGHT
+ };
+
+ enum
+ {
+ SWITCH_A, // button bits
+ SWITCH_B,
+ SWITCH_X,
+ SWITCH_Y,
+ SWITCH_LB,
+ SWITCH_RB,
+ SWITCH_LSB,
+ SWITCH_RSB,
+ SWITCH_START,
+ SWITCH_BACK,
+
+ SWITCH_DPAD_UP, // D-pad bits
+ SWITCH_DPAD_DOWN,
+ SWITCH_DPAD_LEFT,
+ SWITCH_DPAD_RIGHT,
+
+ SWITCH_C1,
+ SWITCH_C3 = SWITCH_C1 + 24,
+
+ SWITCH_TOTAL
+ };
+
+ enum
+ {
+ AXIS_VELOCITY, // field in LSX
+ AXIS_PEDAL, // RSY, most positive value neutral
+
+ AXIS_TOTAL
+ };
+
+ u8 m_switches[SWITCH_TOTAL];
+ s32 m_axes[AXIS_TOTAL];
+};
+
+
+xinput_keyboard_device::xinput_keyboard_device(
+ std::string &&name,
+ std::string &&id,
+ input_module &module,
+ u32 player,
+ XINPUT_CAPABILITIES const &caps,
+ xinput_api_helper const &helper) :
+ xinput_device_base(std::move(name), std::move(id), module, player, caps, helper)
+{
+ std::fill(std::begin(m_switches), std::end(m_switches), 0);
+ std::fill(std::begin(m_axes), std::end(m_axes), 0);
}
-void xinput_joystick_device::configure()
+
+void xinput_keyboard_device::poll(bool relative_reset)
{
- std::lock_guard<std::mutex> scope_lock(m_device_lock);
+ // TODO: how many bits are really velocity?
+ // TODO: how are touch strip and overdrive read?
- if (m_configured)
+ // poll the device first, and skip if nothing changed
+ if (!read_state())
return;
- // Add the axes
- for (int axisnum = 0; axisnum < XINPUT_MAX_AXIS; axisnum++)
+ // translate button bits
+ for (unsigned i = 0; std::size(SWITCH_BITS) > i; ++i)
+ m_switches[SWITCH_A + i] = (buttons() & SWITCH_BITS[i]) ? 0xff : 0x00;
+
+ // translate keys
+ for (unsigned i = 0; 8 > i; ++i)
+ {
+ m_switches[SWITCH_C1 + i] = BIT(trigger_left(), 7 - i) ? 0xff : 0x00;
+ m_switches[SWITCH_C1 + 8 + i] = BIT(trigger_right(), 7 - i) ? 0xff : 0x00;
+ m_switches[SWITCH_C1 + 16 + i] = BIT(thumb_left_x(), 7 - i) ? 0xff : 0x00;
+ }
+ m_switches[SWITCH_C3] = BIT(thumb_left_x(), 15) ? 0xff : 0x00;
+
+ // translate axes
+ m_axes[AXIS_VELOCITY] = -normalize_absolute_axis(BIT(thumb_left_x(), 8, 7), -127, 127);
+ m_axes[AXIS_PEDAL] = -normalize_absolute_axis(32'767 - thumb_right_y(), -32'767, 32'767);
+}
+
+
+void xinput_keyboard_device::reset()
+{
+ set_reset();
+ std::fill(std::begin(m_switches), std::end(m_switches), 0);
+ std::fill(std::begin(m_axes), std::end(m_axes), 0);
+}
+
+
+void xinput_keyboard_device::configure(input_device &device)
+{
+ // track item IDs for setting up default assignments
+ input_device::assignment_vector assignments;
+ input_item_id switch_ids[SWITCH_TOTAL];
+ std::fill(std::begin(switch_ids), std::end(switch_ids), ITEM_ID_INVALID);
+
+ // add axes
+ device.add_item(
+ "Velocity",
+ std::string_view(),
+ ITEM_ID_SLIDER1,
+ generic_axis_get_state<s32>,
+ &m_axes[AXIS_VELOCITY]);
+ input_item_id const pedal_id = device.add_item(
+ "Pedal",
+ std::string_view(),
+ ITEM_ID_SLIDER2,
+ generic_axis_get_state<s32>,
+ &m_axes[AXIS_PEDAL]);
+ assignments.emplace_back(
+ IPT_PEDAL,
+ SEQ_TYPE_STANDARD,
+ input_seq(make_code(ITEM_CLASS_ABSOLUTE, ITEM_MODIFIER_NEG, pedal_id)));
+
+ // add hats
+ for (unsigned i = 0; (SWITCH_DPAD_RIGHT - SWITCH_DPAD_UP) >= i; ++i)
{
- device()->add_item(
- xinput_axis_name[axisnum],
- xinput_axis_ids[axisnum],
- generic_axis_get_state<LONG>,
- &gamepad.left_thumb_x + axisnum);
+ if (has_button(SWITCH_BITS[SWITCH_DPAD_UP + i]))
+ {
+ switch_ids[SWITCH_DPAD_UP + i] = device.add_item(
+ HAT_NAMES_GAMEPAD[i],
+ std::string_view(),
+ input_item_id(ITEM_ID_HAT1UP + i), // matches up/down/left/right order
+ generic_button_get_state<u8>,
+ &m_switches[SWITCH_DPAD_UP + i]);
+ }
}
- // Populate the POVs
- // For XBOX, we treat the DPAD as a hat switch
- for (int povnum = 0; povnum < XINPUT_MAX_POV; povnum++)
+ // add buttons
+ input_item_id button_id = ITEM_ID_BUTTON1;
+ unsigned button_count = 0;
+ unsigned numbered_buttons[SWITCH_RSB - SWITCH_A + 1];
+ for (unsigned i = 0; (SWITCH_RSB - SWITCH_A) >= i; ++i)
{
- device()->add_item(
- xinput_pov_names[povnum],
- ITEM_ID_OTHER_SWITCH,
- generic_button_get_state<BYTE>,
- &gamepad.povs[povnum]);
+ if (has_button(SWITCH_BITS[i]))
+ {
+ switch_ids[SWITCH_A + i] = device.add_item(
+ BUTTON_NAMES_KEYBOARD[i],
+ std::string_view(),
+ button_id++,
+ generic_button_get_state<u8>,
+ &m_switches[SWITCH_A + i]);
+ numbered_buttons[button_count] = SWITCH_A + i;
+
+ // use these for automatically numbered buttons and pedals
+ input_seq const seq(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, switch_ids[SWITCH_A + i]));
+ assignments.emplace_back(ioport_type(IPT_BUTTON1 + button_count), SEQ_TYPE_STANDARD, seq);
+ if (3 > button_count)
+ assignments.emplace_back(ioport_type(IPT_PEDAL + button_count), SEQ_TYPE_INCREMENT, seq);
+ ++button_count;
+ }
}
- // populate the buttons
- for (int butnum = 0; butnum < XINPUT_MAX_BUTTONS; butnum++)
+ // add keys
+ char const *const key_formats[]{
+ "C %d", "C# %d", "D %d", "D# %d", "E %d", "F %d", "F# %d", "G %d", "G# %d", "A %d", "A# %d", "B %d" };
+ std::pair<ioport_type, ioport_type> const key_ids[]{
+ { IPT_MAHJONG_A, IPT_HANAFUDA_A }, // C
+ { IPT_MAHJONG_SCORE, IPT_INVALID }, // C#
+ { IPT_MAHJONG_B, IPT_HANAFUDA_B }, // D
+ { IPT_MAHJONG_DOUBLE_UP, IPT_INVALID }, // D#
+ { IPT_MAHJONG_C, IPT_HANAFUDA_C }, // E
+ { IPT_MAHJONG_D, IPT_HANAFUDA_D }, // F
+ { IPT_MAHJONG_BIG, IPT_INVALID }, // F#
+ { IPT_MAHJONG_E, IPT_HANAFUDA_E }, // G
+ { IPT_MAHJONG_SMALL, IPT_INVALID }, // G#
+ { IPT_MAHJONG_F, IPT_HANAFUDA_F }, // A
+ { IPT_MAHJONG_LAST_CHANCE, IPT_INVALID }, // A#
+ { IPT_MAHJONG_G, IPT_HANAFUDA_G }, // B
+ { IPT_MAHJONG_H, IPT_HANAFUDA_H }, // C
+ { IPT_MAHJONG_KAN, IPT_INVALID }, // C#
+ { IPT_MAHJONG_I, IPT_INVALID }, // D
+ { IPT_MAHJONG_PON, IPT_INVALID }, // D#
+ { IPT_MAHJONG_J, IPT_INVALID }, // E
+ { IPT_MAHJONG_K, IPT_INVALID }, // F
+ { IPT_MAHJONG_CHI, IPT_INVALID }, // F#
+ { IPT_MAHJONG_L, IPT_INVALID }, // G
+ { IPT_MAHJONG_REACH, IPT_INVALID }, // G#
+ { IPT_MAHJONG_M, IPT_HANAFUDA_YES }, // A
+ { IPT_MAHJONG_RON, IPT_INVALID }, // A#
+ { IPT_MAHJONG_N, IPT_HANAFUDA_NO }, // B
+ { IPT_MAHJONG_O, IPT_INVALID } }; // C
+ for (unsigned i = 0; (SWITCH_C3 - SWITCH_C1) >= i; ++i)
{
- device()->add_item(
- xinput_button_names[butnum],
- static_cast<input_item_id>(ITEM_ID_BUTTON1 + butnum),
- generic_button_get_state<BYTE>,
- &gamepad.buttons[butnum]);
+ switch_ids[SWITCH_C1 + i] = device.add_item(
+ util::string_format(key_formats[i % 12], (i / 12) + 1),
+ std::string_view(),
+ (ITEM_ID_BUTTON32 >= button_id) ? button_id++ : ITEM_ID_OTHER_SWITCH,
+ generic_button_get_state<u8>,
+ &m_switches[SWITCH_C1 + i]);
+
+ // add mahjong/hanafuda control assignments
+ input_seq const seq(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, switch_ids[SWITCH_C1 + i]));
+ if (IPT_INVALID != key_ids[i].first)
+ assignments.emplace_back(key_ids[i].first, SEQ_TYPE_STANDARD, seq);
+ if (IPT_INVALID != key_ids[i].second)
+ assignments.emplace_back(key_ids[i].second, SEQ_TYPE_STANDARD, seq);
}
- device()->add_item(
- "RT",
- ITEM_ID_ZAXIS,
- generic_axis_get_state<LONG>,
- &gamepad.right_trigger);
+ // add start/back
+ if (has_button(XINPUT_GAMEPAD_START))
+ {
+ switch_ids[SWITCH_START] = device.add_item(
+ "Start",
+ std::string_view(),
+ ITEM_ID_START,
+ generic_button_get_state<u8>,
+ &m_switches[SWITCH_START]);
+ add_button_assignment(assignments, IPT_START, { switch_ids[SWITCH_START] });
+ }
+ if (has_button(XINPUT_GAMEPAD_BACK))
+ {
+ switch_ids[SWITCH_BACK] = device.add_item(
+ "Back",
+ std::string_view(),
+ ITEM_ID_SELECT,
+ generic_button_get_state<u8>,
+ &m_switches[SWITCH_BACK]);
+ add_button_assignment(assignments, IPT_SELECT, { switch_ids[SWITCH_BACK] });
+ }
- device()->add_item(
- "LT",
- ITEM_ID_RZAXIS,
- generic_axis_get_state<LONG>,
- &gamepad.left_trigger);
+ // use the D-pad for directional controls
+ add_directional_assignments(
+ assignments,
+ ITEM_ID_INVALID,
+ ITEM_ID_INVALID,
+ switch_ids[SWITCH_DPAD_LEFT],
+ switch_ids[SWITCH_DPAD_RIGHT],
+ switch_ids[SWITCH_DPAD_UP],
+ switch_ids[SWITCH_DPAD_DOWN]);
+
+ // use the D-pad and A/B/X/Y diamond for twin sticks
+ add_twin_stick_assignments(
+ assignments,
+ ITEM_ID_INVALID,
+ ITEM_ID_INVALID,
+ ITEM_ID_INVALID,
+ ITEM_ID_INVALID,
+ switch_ids[SWITCH_DPAD_LEFT],
+ switch_ids[SWITCH_DPAD_RIGHT],
+ switch_ids[SWITCH_DPAD_UP],
+ switch_ids[SWITCH_DPAD_DOWN],
+ switch_ids[SWITCH_X],
+ switch_ids[SWITCH_B],
+ switch_ids[SWITCH_Y],
+ switch_ids[SWITCH_A]);
+
+ // assign UI select/back/clear/help
+ assign_ui_actions(
+ assignments,
+ SWITCH_B,
+ SWITCH_X,
+ SWITCH_Y,
+ SWITCH_START,
+ SWITCH_BACK,
+ switch_ids,
+ numbered_buttons,
+ button_count);
+
+ // set default assignments
+ device.set_default_assignments(std::move(assignments));
+}
+
+
+
+//============================================================
+// XInput joystick module
+//============================================================
+
+class xinput_joystick_module : public input_module_impl<device_info, osd_common_t>
+{
+public:
+ xinput_joystick_module() : input_module_impl<device_info, osd_common_t>(OSD_JOYSTICKINPUT_PROVIDER, "xinput")
+ {
+ }
+
+ virtual int init(osd_interface &osd, const osd_options &options) override
+ {
+ int status;
+
+ // Call the base
+ status = input_module_impl<device_info, osd_common_t>::init(osd, options);
+ if (status != 0)
+ return status;
+
+ // Create and initialize our helper
+ m_xinput_helper = std::make_unique<xinput_api_helper>();
+ status = m_xinput_helper->initialize();
+ if (status != 0)
+ {
+ osd_printf_error("xinput_joystick_module failed to get XInput interface! Error: %u\n", static_cast<unsigned int>(status));
+ return -1;
+ }
+
+ return 0;
+ }
+
+ virtual void input_init(running_machine &machine) override
+ {
+ input_module_impl<device_info, osd_common_t>::input_init(machine);
+
+ // Loop through each gamepad to determine if they are connected
+ for (UINT i = 0; i < XUSER_MAX_COUNT; i++)
+ {
+ // allocate and link in a new device
+ auto devinfo = m_xinput_helper->create_xinput_device(i, *this);
+ if (devinfo)
+ add_device(DEVICE_CLASS_JOYSTICK, std::move(devinfo));
+ }
+ }
+
+ virtual void exit() override
+ {
+ input_module_impl<device_info, osd_common_t>::exit();
- m_configured = true;
+ m_xinput_helper.reset();
+ }
+
+private:
+ std::unique_ptr<xinput_api_helper> m_xinput_helper;
+};
+
+} // anonymous namespace
+
+
+
+int xinput_api_helper::initialize()
+{
+ m_xinput_dll = dynamic_module::open(XINPUT_LIBRARIES);
+
+ XInputGetState = m_xinput_dll->bind<xinput_get_state_fn>("XInputGetState");
+ XInputGetCapabilities = m_xinput_dll->bind<xinput_get_caps_fn>("XInputGetCapabilities");
+
+ if (!XInputGetState || !XInputGetCapabilities)
+ {
+ osd_printf_error("XInput: Could not find API functions.\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+
+//============================================================
+// create_xinput_device
+//============================================================
+
+std::unique_ptr<device_info> xinput_api_helper::create_xinput_device(
+ UINT index,
+ input_module_base &module)
+{
+ // If we can't get the capabilities skip this device
+ XINPUT_STATE state{ 0 };
+ if (xinput_get_state(index, &state) != ERROR_SUCCESS)
+ return nullptr;
+ XINPUT_CAPABILITIES caps{ 0 };
+ if (FAILED(xinput_get_capabilities(index, 0, &caps)))
+ return nullptr;
+
+ char device_name[16];
+ snprintf(device_name, sizeof(device_name), "XInput Player %u", index + 1);
+
+ // allocate specialised device objects
+ switch (caps.Type)
+ {
+ case XINPUT_DEVTYPE_GAMEPAD:
+ switch (caps.SubType)
+ {
+ case 0x04: // XINPUT_DEVSUBTYPE_FLIGHT_STICK: work around MinGW header issues
+ return std::make_unique<xinput_flight_stick_device>(
+ device_name,
+ device_name,
+ module,
+ index,
+ caps,
+ *this);
+ case XINPUT_DEVSUBTYPE_GUITAR:
+ case XINPUT_DEVSUBTYPE_GUITAR_ALTERNATE:
+ case XINPUT_DEVSUBTYPE_GUITAR_BASS:
+ return std::make_unique<xinput_guitar_device>(
+ device_name,
+ device_name,
+ module,
+ index,
+ caps,
+ *this);
+ case XINPUT_DEVSUBTYPE_DRUM_KIT:
+ return std::make_unique<xinput_drumkit_device>(
+ device_name,
+ device_name,
+ module,
+ index,
+ caps,
+ *this);
+ case 0x0f:
+ return std::make_unique<xinput_keyboard_device>(
+ device_name,
+ device_name,
+ module,
+ index,
+ caps,
+ *this);
+ case 0x17:
+ return std::make_unique<xinput_turntable_device>(
+ device_name,
+ device_name,
+ module,
+ index,
+ caps,
+ *this);
+ }
+ }
+
+ // create default general-purpose device
+ return std::make_unique<xinput_joystick_device>(
+ device_name,
+ device_name,
+ module,
+ index,
+ caps,
+ *this);
}
-#else // defined(OSD_WINDOWS)
+} // namespace osd
+
+#else // defined(OSD_WINDOWS) || defined(SDLMAME_WIN32)
#include "input_module.h"
-MODULE_NOT_SUPPORTED(xinput_joystick_module, OSD_JOYSTICKINPUT_PROVIDER, "xinput")
+namespace osd { namespace { MODULE_NOT_SUPPORTED(xinput_joystick_module, OSD_JOYSTICKINPUT_PROVIDER, "xinput") } }
-#endif // defined(OSD_WINDOWS)
+#endif // defined(OSD_WINDOWS) || defined(SDLMAME_WIN32)
-MODULE_DEFINITION(JOYSTICKINPUT_XINPUT, xinput_joystick_module)
+MODULE_DEFINITION(JOYSTICKINPUT_XINPUT, osd::xinput_joystick_module)
diff --git a/src/osd/modules/input/input_xinput.h b/src/osd/modules/input/input_xinput.h
index bd918f9aacb..fa36b7a2622 100644
--- a/src/osd/modules/input/input_xinput.h
+++ b/src/osd/modules/input/input_xinput.h
@@ -1,30 +1,30 @@
+// license:BSD-3-Clause
+// copyright-holders:Brad Hughes, Vas Crabb
#ifndef MAME_OSD_INPUT_INPUT_XINPUT_H
#define MAME_OSD_INPUT_INPUT_XINPUT_H
#pragma once
-#include "input_windows.h"
+#include "input_common.h"
#include "modules/lib/osdlib.h"
-#include <cstdint>
#include <memory>
-#include <mutex>
-#include <string_view>
+#include <windows.h>
#include <xinput.h>
-class xinput_joystick_device;
+namespace osd {
-
-class xinput_api_helper : public std::enable_shared_from_this<xinput_api_helper>
+class xinput_api_helper
{
public:
xinput_api_helper() { }
int initialize();
- xinput_joystick_device *create_xinput_device(running_machine &machine, UINT index, wininput_module &module);
+
+ std::unique_ptr<device_info> create_xinput_device(UINT index, input_module_base &module);
DWORD xinput_get_state(DWORD dwUserindex, XINPUT_STATE *pState) const
{
@@ -41,53 +41,11 @@ private:
typedef DWORD (WINAPI *xinput_get_state_fn)(DWORD, XINPUT_STATE *);
typedef DWORD (WINAPI *xinput_get_caps_fn)(DWORD, DWORD, XINPUT_CAPABILITIES *);
- osd::dynamic_module::ptr m_xinput_dll = nullptr;
- xinput_get_state_fn XInputGetState = nullptr;
- xinput_get_caps_fn XInputGetCapabilities = nullptr;
+ dynamic_module::ptr m_xinput_dll = nullptr;
+ xinput_get_state_fn XInputGetState = nullptr;
+ xinput_get_caps_fn XInputGetCapabilities = nullptr;
};
-
-class xinput_joystick_device : public device_info
-{
-public:
- static inline constexpr int XINPUT_MAX_POV = 4;
- static inline constexpr int XINPUT_MAX_BUTTONS = 10;
- static inline constexpr int XINPUT_MAX_AXIS = 4;
-
- struct gamepad_state
- {
- BYTE buttons[XINPUT_MAX_BUTTONS];
- BYTE povs[XINPUT_MAX_POV];
- LONG left_trigger;
- LONG right_trigger;
- LONG left_thumb_x;
- LONG left_thumb_y;
- LONG right_thumb_x;
- LONG right_thumb_y;
- };
-
- // state information for a gamepad; state must be first element
- struct xinput_api_state
- {
- uint32_t player_index;
- XINPUT_STATE xstate;
- XINPUT_CAPABILITIES caps;
- };
-
- gamepad_state gamepad;
- xinput_api_state xinput_state;
-
-private:
- std::shared_ptr<xinput_api_helper> m_xinput_helper;
- std::mutex m_device_lock;
- bool m_configured;
-
-public:
- xinput_joystick_device(running_machine &machine, std::string &&name, std::string &&id, input_module &module, std::shared_ptr<xinput_api_helper> helper);
-
- void poll() override;
- void reset() override;
- void configure();
-};
+} // namespace osd
#endif // MAME_OSD_INPUT_INPUT_XINPUT_H
diff --git a/src/osd/modules/lib/osdlib.h b/src/osd/modules/lib/osdlib.h
index 8ca4762a111..967cb0d61ae 100644
--- a/src/osd/modules/lib/osdlib.h
+++ b/src/osd/modules/lib/osdlib.h
@@ -12,16 +12,21 @@
// - osd_ticks
// - osd_sleep
//============================================================
+#ifndef MAME_OSD_LIB_OSDLIB_H
+#define MAME_OSD_LIB_OSDLIB_H
-#ifndef __OSDLIB__
-#define __OSDLIB__
+#pragma once
+#include <cstdint>
#include <initializer_list>
#include <string>
+#include <string_view>
+#include <system_error>
#include <type_traits>
#include <vector>
#include <memory>
+
/*-----------------------------------------------------------------------------
osd_process_kill: kill the current process
@@ -54,15 +59,27 @@ void osd_process_kill();
int osd_setenv(const char *name, const char *value, int overwrite);
-/*-----------------------------------------------------------------------------
- osd_get_clipboard_text: retrieves text from the clipboard
------------------------------------------------------------------------------*/
-std::string osd_get_clipboard_text();
+/// \brief Get clipboard text
+///
+/// Gets current clipboard content as UTF-8 text. Returns an empty
+/// string if the clipboard contents cannot be converted to plain text.
+/// \return Clipboard contents or an empty string.
+std::string osd_get_clipboard_text() noexcept;
+
+
+/// \brief Set clipboard text
+///
+/// Sets the desktop environment's clipboard contents to the supplied
+/// UTF-8 text. The contents of the clipboard may be changed on error.
+/// \param [in] text The text to copy to the clipboard.
+/// \return An error condition if the operation failed or is
+/// unsupported.
+std::error_condition osd_set_clipboard_text(std::string_view text) noexcept;
namespace osd {
-bool invalidate_instruction_cache(void const *start, std::size_t size);
+bool invalidate_instruction_cache(void const *start, std::size_t size) noexcept;
class virtual_memory_allocation
@@ -82,12 +99,12 @@ public:
virtual_memory_allocation(virtual_memory_allocation const &) = delete;
virtual_memory_allocation &operator=(virtual_memory_allocation const &) = delete;
- virtual_memory_allocation() { }
- virtual_memory_allocation(std::initializer_list<std::size_t> blocks, unsigned intent)
+ virtual_memory_allocation() noexcept { }
+ virtual_memory_allocation(std::initializer_list<std::size_t> blocks, unsigned intent) noexcept
{
m_memory = do_alloc(blocks, intent, m_size, m_page_size);
}
- virtual_memory_allocation(virtual_memory_allocation &&that) : m_memory(that.m_memory), m_size(that.m_size), m_page_size(that.m_page_size)
+ virtual_memory_allocation(virtual_memory_allocation &&that) noexcept : m_memory(that.m_memory), m_size(that.m_size), m_page_size(that.m_page_size)
{
that.m_memory = nullptr;
that.m_size = that.m_page_size = 0U;
@@ -98,12 +115,12 @@ public:
do_free(m_memory, m_size);
}
- explicit operator bool() const { return bool(m_memory); }
- void *get() { return m_memory; }
- std::size_t size() const { return m_size; }
- std::size_t page_size() const { return m_page_size; }
+ explicit operator bool() const noexcept { return bool(m_memory); }
+ void *get() noexcept { return m_memory; }
+ std::size_t size() const noexcept { return m_size; }
+ std::size_t page_size() const noexcept { return m_page_size; }
- bool set_access(std::size_t start, std::size_t size, unsigned access)
+ bool set_access(std::size_t start, std::size_t size, unsigned access) noexcept
{
if ((start % m_page_size) || (size % m_page_size) || (start > m_size) || ((m_size - start) < size))
return false;
@@ -111,7 +128,7 @@ public:
return do_set_access(reinterpret_cast<std::uint8_t *>(m_memory) + start, size, access);
}
- virtual_memory_allocation &operator=(std::nullptr_t)
+ virtual_memory_allocation &operator=(std::nullptr_t) noexcept
{
if (m_memory)
do_free(m_memory, m_size);
@@ -120,7 +137,7 @@ public:
return *this;
}
- virtual_memory_allocation &operator=(virtual_memory_allocation &&that)
+ virtual_memory_allocation &operator=(virtual_memory_allocation &&that) noexcept
{
if (&that != this)
{
@@ -136,9 +153,9 @@ public:
}
private:
- static void *do_alloc(std::initializer_list<std::size_t> blocks, unsigned intent, std::size_t &size, std::size_t &page_size);
- static void do_free(void *start, std::size_t size);
- static bool do_set_access(void *start, std::size_t size, unsigned access);
+ static void *do_alloc(std::initializer_list<std::size_t> blocks, unsigned intent, std::size_t &size, std::size_t &page_size) noexcept;
+ static void do_free(void *start, std::size_t size) noexcept;
+ static bool do_set_access(void *start, std::size_t size, unsigned access) noexcept;
void *m_memory = nullptr;
std::size_t m_size = 0U, m_page_size = 0U;
@@ -193,4 +210,4 @@ protected:
#define OSD_DYNAMIC_CALL(fname, ...) (*m_##fname##_pfn) ( __VA_ARGS__ )
#define OSD_DYNAMIC_API_TEST(fname) (m_##fname##_pfn != nullptr)
-#endif /* __OSDLIB__ */
+#endif // MAME_OSD_LIB_OSDLIB_H
diff --git a/src/osd/modules/lib/osdlib_macosx.cpp b/src/osd/modules/lib/osdlib_macosx.cpp
index 19b228b6369..9d13f118ff2 100644
--- a/src/osd/modules/lib/osdlib_macosx.cpp
+++ b/src/osd/modules/lib/osdlib_macosx.cpp
@@ -85,7 +85,7 @@ void osd_break_into_debugger(const char *message)
// osd_get_clipboard_text
//============================================================
-std::string osd_get_clipboard_text()
+std::string osd_get_clipboard_text() noexcept
{
std::string result;
bool has_result = false;
@@ -121,31 +121,48 @@ std::string osd_get_clipboard_text()
CFStringEncoding encoding;
if (UTTypeConformsTo(flavor_type, kUTTypeUTF16PlainText))
encoding = kCFStringEncodingUTF16;
- else if (UTTypeConformsTo (flavor_type, kUTTypeUTF8PlainText))
+ else if (UTTypeConformsTo(flavor_type, kUTTypeUTF8PlainText))
encoding = kCFStringEncodingUTF8;
- else if (UTTypeConformsTo (flavor_type, kUTTypePlainText))
+ else if (UTTypeConformsTo(flavor_type, kUTTypePlainText))
encoding = kCFStringEncodingMacRoman;
else
continue;
CFDataRef flavor_data;
err = PasteboardCopyItemFlavorData(pasteboard_ref, item_id, flavor_type, &flavor_data);
+ if (err)
+ continue;
- if (!err)
+ CFDataRef utf8_data;
+ if (kCFStringEncodingUTF8 == encoding)
+ {
+ utf8_data = flavor_data;
+ }
+ else
{
CFStringRef string_ref = CFStringCreateFromExternalRepresentation(kCFAllocatorDefault, flavor_data, encoding);
- CFDataRef data_ref = CFStringCreateExternalRepresentation (kCFAllocatorDefault, string_ref, kCFStringEncodingUTF8, '?');
- CFRelease(string_ref);
CFRelease(flavor_data);
+ if (!string_ref)
+ continue;
- CFIndex const length = CFDataGetLength(data_ref);
- CFRange const range = CFRangeMake(0, length);
-
- result.resize(length);
- CFDataGetBytes(data_ref, range, reinterpret_cast<unsigned char *>(&result[0]));
- has_result = true;
+ utf8_data = CFStringCreateExternalRepresentation(kCFAllocatorDefault, string_ref, kCFStringEncodingUTF8, '?');
+ CFRelease(string_ref);
+ }
- CFRelease(data_ref);
+ if (utf8_data)
+ {
+ CFIndex const length = CFDataGetLength(utf8_data);
+ CFRange const range = CFRangeMake(0, length);
+ try
+ {
+ result.resize(length);
+ CFDataGetBytes(utf8_data, range, reinterpret_cast<UInt8 *>(result.data()));
+ has_result = true;
+ }
+ catch (std::bad_alloc const &)
+ {
+ }
+ CFRelease(utf8_data);
}
}
@@ -157,11 +174,51 @@ std::string osd_get_clipboard_text()
return result;
}
+
+//============================================================
+// osd_set_clipboard_text
+//============================================================
+
+std::error_condition osd_set_clipboard_text(std::string_view text) noexcept
+{
+ // FIXME: better conversion of OSStatus to std::error_condition
+ OSStatus err;
+
+ CFDataRef const data = CFDataCreate(kCFAllocatorDefault, reinterpret_cast<UInt8 const *>(text.data()), text.length());
+ if (!data)
+ return std::errc::not_enough_memory;
+
+ PasteboardRef pasteboard_ref;
+ err = PasteboardCreate(kPasteboardClipboard, &pasteboard_ref);
+ if (err)
+ {
+ CFRelease(data);
+ return std::errc::io_error;
+ }
+
+ err = PasteboardClear(pasteboard_ref);
+ if (err)
+ {
+ CFRelease(data);
+ CFRelease(pasteboard_ref);
+ return std::errc::io_error;
+ }
+
+ err = PasteboardPutItemFlavor(pasteboard_ref, PasteboardItemID(1), kUTTypeUTF8PlainText, data, kPasteboardFlavorNoFlags);
+ CFRelease(data);
+ CFRelease(pasteboard_ref);
+ if (err)
+ return std::errc::io_error;
+
+ return std::error_condition();
+}
+
+
//============================================================
// osd_getpid
//============================================================
-int osd_getpid()
+int osd_getpid() noexcept
{
return getpid();
}
@@ -225,7 +282,7 @@ private:
} // anonymous namespace
-bool invalidate_instruction_cache(void const *start, std::size_t size)
+bool invalidate_instruction_cache(void const *start, std::size_t size) noexcept
{
char const *const begin(reinterpret_cast<char const *>(start));
char const *const end(begin + size);
@@ -234,7 +291,7 @@ bool invalidate_instruction_cache(void const *start, std::size_t size)
}
-void *virtual_memory_allocation::do_alloc(std::initializer_list<std::size_t> blocks, unsigned intent, std::size_t &size, std::size_t &page_size)
+void *virtual_memory_allocation::do_alloc(std::initializer_list<std::size_t> blocks, unsigned intent, std::size_t &size, std::size_t &page_size) noexcept
{
long const p(sysconf(_SC_PAGE_SIZE));
if (0 >= p)
@@ -253,12 +310,12 @@ void *virtual_memory_allocation::do_alloc(std::initializer_list<std::size_t> blo
return result;
}
-void virtual_memory_allocation::do_free(void *start, std::size_t size)
+void virtual_memory_allocation::do_free(void *start, std::size_t size) noexcept
{
munmap(start, size);
}
-bool virtual_memory_allocation::do_set_access(void *start, std::size_t size, unsigned access)
+bool virtual_memory_allocation::do_set_access(void *start, std::size_t size, unsigned access) noexcept
{
int prot((NONE == access) ? PROT_NONE : 0);
if (access & READ)
diff --git a/src/osd/modules/lib/osdlib_unix.cpp b/src/osd/modules/lib/osdlib_unix.cpp
index 4b091450116..20f6a9ab40c 100644
--- a/src/osd/modules/lib/osdlib_unix.cpp
+++ b/src/osd/modules/lib/osdlib_unix.cpp
@@ -69,35 +69,73 @@ void osd_break_into_debugger(const char *message)
}
#ifdef SDLMAME_ANDROID
-std::string osd_get_clipboard_text()
+std::string osd_get_clipboard_text() noexcept
{
return std::string();
}
+
+std::error_condition osd_set_clipboard_text(std::string_view text) noexcept
+{
+ return std::errc::io_error; // TODO: better error code?
+}
#else
//============================================================
// osd_get_clipboard_text
//============================================================
-std::string osd_get_clipboard_text()
+std::string osd_get_clipboard_text() noexcept
{
+ // TODO: better error handling
std::string result;
if (SDL_HasClipboardText())
{
- char *temp = SDL_GetClipboardText();
- result.assign(temp);
- SDL_free(temp);
+ char *const temp = SDL_GetClipboardText();
+ if (temp)
+ {
+ try
+ {
+ result.assign(temp);
+ }
+ catch (std::bad_alloc const &)
+ {
+ }
+ SDL_free(temp);
+ }
}
return result;
}
+
+//============================================================
+// osd_set_clipboard_text
+//============================================================
+
+std::error_condition osd_set_clipboard_text(std::string_view text) noexcept
+{
+ try
+ {
+ std::string const clip(text); // need to do this to ensure there's a terminating NUL for SDL
+ if (0 > SDL_SetClipboardText(clip.c_str()))
+ {
+ // SDL_GetError returns a message, can't really convert it to an error condition
+ return std::errc::io_error; // TODO: better error code?
+ }
+
+ return std::error_condition();
+ }
+ catch (std::bad_alloc const &)
+ {
+ return std::errc::not_enough_memory;
+ }
+}
#endif
//============================================================
// osd_getpid
//============================================================
-int osd_getpid()
+int osd_getpid() noexcept
{
return getpid();
}
@@ -161,7 +199,7 @@ private:
} // anonymous namespace
-bool invalidate_instruction_cache(void const *start, std::size_t size)
+bool invalidate_instruction_cache(void const *start, std::size_t size) noexcept
{
#if !defined(SDLMAME_EMSCRIPTEN)
char const *const begin(reinterpret_cast<char const *>(start));
@@ -172,7 +210,7 @@ bool invalidate_instruction_cache(void const *start, std::size_t size)
}
-void *virtual_memory_allocation::do_alloc(std::initializer_list<std::size_t> blocks, unsigned intent, std::size_t &size, std::size_t &page_size)
+void *virtual_memory_allocation::do_alloc(std::initializer_list<std::size_t> blocks, unsigned intent, std::size_t &size, std::size_t &page_size) noexcept
{
long const p(sysconf(_SC_PAGE_SIZE));
if (0 >= p)
@@ -209,12 +247,12 @@ void *virtual_memory_allocation::do_alloc(std::initializer_list<std::size_t> blo
return result;
}
-void virtual_memory_allocation::do_free(void *start, std::size_t size)
+void virtual_memory_allocation::do_free(void *start, std::size_t size) noexcept
{
munmap(reinterpret_cast<char *>(start), size);
}
-bool virtual_memory_allocation::do_set_access(void *start, std::size_t size, unsigned access)
+bool virtual_memory_allocation::do_set_access(void *start, std::size_t size, unsigned access) noexcept
{
int prot((NONE == access) ? PROT_NONE : 0);
if (access & READ)
diff --git a/src/osd/modules/lib/osdlib_win32.cpp b/src/osd/modules/lib/osdlib_win32.cpp
index 174dc769760..d42ad14d3df 100644
--- a/src/osd/modules/lib/osdlib_win32.cpp
+++ b/src/osd/modules/lib/osdlib_win32.cpp
@@ -14,10 +14,10 @@
#include "osdcore.h"
#include "strconv.h"
-#ifdef OSD_WINDOWS
#include "winutf8.h"
-#endif
+#include "winutil.h"
+#include <algorithm>
#include <cstdio>
#include <cstdlib>
@@ -168,25 +168,92 @@ static std::string convert_ansi(LPCVOID data)
// osd_get_clipboard_text
//============================================================
-std::string osd_get_clipboard_text()
+std::string osd_get_clipboard_text() noexcept
{
std::string result;
- // try to access unicode text
- if (!get_clipboard_text_by_format(result, CF_UNICODETEXT, convert_wide))
+ // TODO: better error handling
+ try
+ {
+ // try to access unicode text
+ if (!get_clipboard_text_by_format(result, CF_UNICODETEXT, convert_wide))
+ {
+ // try to access ANSI text
+ get_clipboard_text_by_format(result, CF_TEXT, convert_ansi);
+ }
+ }
+ catch (...)
{
- // try to access ANSI text
- get_clipboard_text_by_format(result, CF_TEXT, convert_ansi);
}
return result;
}
//============================================================
+// osd_set_clipboard_text
+//============================================================
+
+std::error_condition osd_set_clipboard_text(std::string_view text) noexcept
+{
+ try
+ {
+ // convert the text to a wide char string and create a moveable global block
+ std::wstring const wtext = osd::text::to_wstring(text);
+ HGLOBAL const clip = GlobalAlloc(GMEM_MOVEABLE, (text.length() + 1) * sizeof(wchar_t));
+ if (!clip)
+ return win_error_to_error_condition(GetLastError());
+ LPWSTR const lock = reinterpret_cast<LPWSTR>(GlobalLock(clip));
+ if (!lock)
+ {
+ DWORD const err(GetLastError());
+ GlobalFree(clip);
+ return win_error_to_error_condition(err);
+ }
+
+ // clear current clipboard contents
+ if (!OpenClipboard(nullptr))
+ {
+ DWORD const err(GetLastError());
+ GlobalUnlock(clip);
+ GlobalFree(clip);
+ return win_error_to_error_condition(err);
+ }
+ if (!EmptyClipboard())
+ {
+ DWORD const err(GetLastError());
+ CloseClipboard();
+ GlobalUnlock(clip);
+ GlobalFree(clip);
+ return win_error_to_error_condition(err);
+ }
+
+ // copy the text (plus NUL terminator) to the moveable block and put it on the clipboard
+ std::copy_n(wtext.c_str(), wtext.length() + 1, lock);
+ GlobalUnlock(clip);
+ if (!SetClipboardData(CF_UNICODETEXT, clip))
+ {
+ DWORD const err(GetLastError());
+ CloseClipboard();
+ GlobalFree(clip);
+ return win_error_to_error_condition(err);
+ }
+
+ // clean up
+ if (!CloseClipboard())
+ return win_error_to_error_condition(GetLastError());
+ return std::error_condition();
+ }
+ catch (std::bad_alloc const &)
+ {
+ return std::errc::not_enough_memory;
+ }
+}
+
+//============================================================
// osd_getpid
//============================================================
-int osd_getpid()
+int osd_getpid() noexcept
{
return GetCurrentProcessId();
}
@@ -257,13 +324,13 @@ private:
} // anonymous namespace
-bool invalidate_instruction_cache(void const *start, std::size_t size)
+bool invalidate_instruction_cache(void const *start, std::size_t size) noexcept
{
return FlushInstructionCache(GetCurrentProcess(), start, size) != 0;
}
-void *virtual_memory_allocation::do_alloc(std::initializer_list<std::size_t> blocks, unsigned intent, std::size_t &size, std::size_t &page_size)
+void *virtual_memory_allocation::do_alloc(std::initializer_list<std::size_t> blocks, unsigned intent, std::size_t &size, std::size_t &page_size) noexcept
{
SYSTEM_INFO info;
GetSystemInfo(&info);
@@ -282,19 +349,19 @@ void *virtual_memory_allocation::do_alloc(std::initializer_list<std::size_t> blo
return result;
}
-void virtual_memory_allocation::do_free(void *start, std::size_t size)
+void virtual_memory_allocation::do_free(void *start, std::size_t size) noexcept
{
VirtualFree(start, 0, MEM_RELEASE);
}
-bool virtual_memory_allocation::do_set_access(void *start, std::size_t size, unsigned access)
+bool virtual_memory_allocation::do_set_access(void *start, std::size_t size, unsigned access) noexcept
{
- DWORD p, o;
+ DWORD p;
if (access & EXECUTE)
p = (access & WRITE) ? PAGE_EXECUTE_READWRITE : (access & READ) ? PAGE_EXECUTE_READ : PAGE_EXECUTE;
else
p = (access & WRITE) ? PAGE_READWRITE : (access & READ) ? PAGE_READONLY : PAGE_NOACCESS;
- return VirtualProtect(start, size, p, &o) != 0;
+ return VirtualAlloc(start, size, MEM_COMMIT, p) != nullptr;
}
diff --git a/src/osd/modules/lib/osdobj_common.cpp b/src/osd/modules/lib/osdobj_common.cpp
index 9adf9f2e604..430f6ceeac9 100644
--- a/src/osd/modules/lib/osdobj_common.cpp
+++ b/src/osd/modules/lib/osdobj_common.cpp
@@ -2,21 +2,25 @@
// copyright-holders:Aaron Giles
/***************************************************************************
- osdepend.c
+ osdobj_common.h
OS-dependent code interface.
***************************************************************************/
-#include "modules/lib/osdobj_common.h"
+#include "osdobj_common.h"
+#include "modules/osdwindow.h"
+#include "modules/debugger/debug_module.h"
#include "modules/font/font_module.h"
#include "modules/input/input_module.h"
-#include "modules/sound/sound_module.h"
-#include "modules/debugger/debug_module.h"
-#include "modules/netdev/netdev_module.h"
#include "modules/midi/midi_module.h"
#include "modules/monitor/monitor_module.h"
+#include "modules/netdev/netdev_module.h"
+#include "modules/render/render_module.h"
+#include "modules/sound/sound_module.h"
+
+#include "osdnet.h"
#include "watchdog.h"
#include "emu.h"
@@ -27,151 +31,158 @@
const options_entry osd_options::s_option_entries[] =
{
- { nullptr, nullptr, core_options::option_type::HEADER, "OSD KEYBOARD MAPPING OPTIONS" },
+ { nullptr, nullptr, core_options::option_type::HEADER, "OSD INPUT MAPPING OPTIONS" },
#if defined(SDLMAME_MACOSX) || defined(OSD_MAC)
- { OSDOPTION_UIMODEKEY, "DEL", core_options::option_type::STRING, "key to enable/disable MAME controls when emulated system has keyboard inputs" },
+ { OSDOPTION_UIMODEKEY, "DEL", core_options::option_type::STRING, "key to enable/disable MAME controls when emulated system has keyboard inputs" },
#else
- { OSDOPTION_UIMODEKEY, "SCRLOCK", core_options::option_type::STRING, "key to enable/disable MAME controls when emulated system has keyboard inputs" },
+ { OSDOPTION_UIMODEKEY, "auto", core_options::option_type::STRING, "key to enable/disable MAME controls when emulated system has keyboard inputs" },
#endif // SDLMAME_MACOSX
-
- { nullptr, nullptr, core_options::option_type::HEADER, "OSD FONT OPTIONS" },
- { OSD_FONT_PROVIDER, OSDOPTVAL_AUTO, core_options::option_type::STRING, "provider for UI font: " },
-
- { nullptr, nullptr, core_options::option_type::HEADER, "OSD OUTPUT OPTIONS" },
- { OSD_OUTPUT_PROVIDER, OSDOPTVAL_AUTO, core_options::option_type::STRING, "provider for output notifications: " },
-
- { nullptr, nullptr, core_options::option_type::HEADER, "OSD INPUT OPTIONS" },
- { OSD_KEYBOARDINPUT_PROVIDER, OSDOPTVAL_AUTO, core_options::option_type::STRING, "provider for keyboard input: " },
- { OSD_MOUSEINPUT_PROVIDER, OSDOPTVAL_AUTO, core_options::option_type::STRING, "provider for mouse input: " },
- { OSD_LIGHTGUNINPUT_PROVIDER, OSDOPTVAL_AUTO, core_options::option_type::STRING, "provider for lightgun input: " },
- { OSD_JOYSTICKINPUT_PROVIDER, OSDOPTVAL_AUTO, core_options::option_type::STRING, "provider for joystick input: " },
-
- { nullptr, nullptr, core_options::option_type::HEADER, "OSD CLI OPTIONS" },
- { OSDCOMMAND_LIST_MIDI_DEVICES ";mlist", "0", core_options::option_type::COMMAND, "list available MIDI I/O devices" },
- { OSDCOMMAND_LIST_NETWORK_ADAPTERS ";nlist", "0", core_options::option_type::COMMAND, "list available network adapters" },
-
- { nullptr, nullptr, core_options::option_type::HEADER, "OSD DEBUGGING OPTIONS" },
- { OSDOPTION_DEBUGGER, OSDOPTVAL_AUTO, core_options::option_type::STRING, "debugger used: " },
- { OSDOPTION_DEBUGGER_PORT, "23946", core_options::option_type::INTEGER, "port to use for gdbstub debugger" },
- { OSDOPTION_DEBUGGER_FONT ";dfont", OSDOPTVAL_AUTO, core_options::option_type::STRING, "font to use for debugger views" },
- { OSDOPTION_DEBUGGER_FONT_SIZE ";dfontsize", "0", core_options::option_type::FLOAT, "font size to use for debugger views" },
- { OSDOPTION_WATCHDOG ";wdog", "0", core_options::option_type::INTEGER, "force the program to terminate if no updates within specified number of seconds" },
-
- { nullptr, nullptr, core_options::option_type::HEADER, "OSD PERFORMANCE OPTIONS" },
- { OSDOPTION_NUMPROCESSORS ";np", OSDOPTVAL_AUTO, core_options::option_type::STRING, "number of processors; this overrides the number the system reports" },
- { OSDOPTION_BENCH, "0", core_options::option_type::INTEGER, "benchmark for the given number of emulated seconds; implies -video none -sound none -nothrottle" },
-
- { nullptr, nullptr, core_options::option_type::HEADER, "OSD VIDEO OPTIONS" },
-// OS X can be trusted to have working hardware OpenGL, so default to it on for the best user experience
- { OSDOPTION_VIDEO, OSDOPTVAL_AUTO, core_options::option_type::STRING, "video output method: " },
- { OSDOPTION_NUMSCREENS "(1-4)", "1", core_options::option_type::INTEGER, "number of output screens/windows to create; usually, you want just one" },
- { OSDOPTION_WINDOW ";w", "0", core_options::option_type::BOOLEAN, "enable window mode; otherwise, full screen mode is assumed" },
- { OSDOPTION_MAXIMIZE ";max", "1", core_options::option_type::BOOLEAN, "default to maximized windows" },
- { OSDOPTION_WAITVSYNC ";vs", "0", core_options::option_type::BOOLEAN, "enable waiting for the start of VBLANK before flipping screens (reduces tearing effects)" },
- { OSDOPTION_SYNCREFRESH ";srf", "0", core_options::option_type::BOOLEAN, "enable using the start of VBLANK for throttling instead of the game time" },
- { OSD_MONITOR_PROVIDER, OSDOPTVAL_AUTO, core_options::option_type::STRING, "monitor discovery method: " },
+ { OSDOPTION_CONTROLLER_MAP_FILE ";ctrlmap", OSDOPTVAL_NONE, core_options::option_type::PATH, "game controller mapping file" },
+ { OSDOPTION_BACKGROUND_INPUT, "0", core_options::option_type::BOOLEAN, "don't ignore input when losing UI focus" },
+
+ { nullptr, nullptr, core_options::option_type::HEADER, "OSD FONT OPTIONS" },
+ { OSD_FONT_PROVIDER, OSDOPTVAL_AUTO, core_options::option_type::STRING, "provider for UI font: " },
+
+ { nullptr, nullptr, core_options::option_type::HEADER, "OSD OUTPUT OPTIONS" },
+ { OSD_OUTPUT_PROVIDER, OSDOPTVAL_AUTO, core_options::option_type::STRING, "provider for output notifications: " },
+
+ { nullptr, nullptr, core_options::option_type::HEADER, "OSD INPUT OPTIONS" },
+ { OSD_KEYBOARDINPUT_PROVIDER, OSDOPTVAL_AUTO, core_options::option_type::STRING, "provider for keyboard input: " },
+ { OSD_MOUSEINPUT_PROVIDER, OSDOPTVAL_AUTO, core_options::option_type::STRING, "provider for mouse input: " },
+ { OSD_LIGHTGUNINPUT_PROVIDER, OSDOPTVAL_AUTO, core_options::option_type::STRING, "provider for lightgun input: " },
+ { OSD_JOYSTICKINPUT_PROVIDER, OSDOPTVAL_AUTO, core_options::option_type::STRING, "provider for joystick input: " },
+
+ { nullptr, nullptr, core_options::option_type::HEADER, "OSD CLI OPTIONS" },
+ { OSDCOMMAND_LIST_MIDI_DEVICES ";mlist", "0", core_options::option_type::COMMAND, "list available MIDI I/O devices" },
+ { OSDCOMMAND_LIST_NETWORK_ADAPTERS ";nlist", "0", core_options::option_type::COMMAND, "list available network adapters" },
+
+ { nullptr, nullptr, core_options::option_type::HEADER, "OSD DEBUGGING OPTIONS" },
+ { OSDOPTION_DEBUGGER, OSDOPTVAL_AUTO, core_options::option_type::STRING, "debugger used: " },
+ { OSDOPTION_DEBUGGER_PORT, "23946", core_options::option_type::INTEGER, "port to use for gdbstub debugger" },
+ { OSDOPTION_DEBUGGER_FONT ";dfont", OSDOPTVAL_AUTO, core_options::option_type::STRING, "font to use for debugger views" },
+ { OSDOPTION_DEBUGGER_FONT_SIZE ";dfontsize", "0", core_options::option_type::FLOAT, "font size to use for debugger views" },
+ { OSDOPTION_WATCHDOG ";wdog", "0", core_options::option_type::INTEGER, "force the program to terminate if no updates within specified number of seconds" },
+
+ { nullptr, nullptr, core_options::option_type::HEADER, "OSD PERFORMANCE OPTIONS" },
+ { OSDOPTION_NUMPROCESSORS ";np", OSDOPTVAL_AUTO, core_options::option_type::STRING, "number of processors; this overrides the number the system reports" },
+ { OSDOPTION_BENCH, "0", core_options::option_type::INTEGER, "benchmark for the given number of emulated seconds; implies -video none -sound none -nothrottle" },
+
+ { nullptr, nullptr, core_options::option_type::HEADER, "OSD VIDEO OPTIONS" },
+ { OSDOPTION_VIDEO, OSDOPTVAL_AUTO, core_options::option_type::STRING, "video output method: " },
+ { OSDOPTION_NUMSCREENS "(1-4)", "1", core_options::option_type::INTEGER, "number of output screens/windows to create; usually, you want just one" },
+ { OSDOPTION_WINDOW ";w", "0", core_options::option_type::BOOLEAN, "enable window mode; otherwise, full screen mode is assumed" },
+ { OSDOPTION_MAXIMIZE ";max", "1", core_options::option_type::BOOLEAN, "default to maximized windows" },
+ { OSDOPTION_WAITVSYNC ";vs", "0", core_options::option_type::BOOLEAN, "enable waiting for the start of VBLANK before flipping screens (reduces tearing effects)" },
+ { OSDOPTION_SYNCREFRESH ";srf", "0", core_options::option_type::BOOLEAN, "enable using the start of VBLANK for throttling instead of the game time" },
+ { OSD_MONITOR_PROVIDER, OSDOPTVAL_AUTO, core_options::option_type::STRING, "monitor discovery method: " },
// per-window options
- { nullptr, nullptr, core_options::option_type::HEADER, "OSD PER-WINDOW VIDEO OPTIONS" },
- { OSDOPTION_SCREEN, OSDOPTVAL_AUTO, core_options::option_type::STRING, "explicit name of the first screen; 'auto' here will try to make a best guess" },
- { OSDOPTION_ASPECT ";screen_aspect", OSDOPTVAL_AUTO, core_options::option_type::STRING, "aspect ratio for all screens; 'auto' here will try to make a best guess" },
- { OSDOPTION_RESOLUTION ";r", OSDOPTVAL_AUTO, core_options::option_type::STRING, "preferred resolution for all screens; format is <width>x<height>[@<refreshrate>] or 'auto'" },
- { OSDOPTION_VIEW, OSDOPTVAL_AUTO, core_options::option_type::STRING, "preferred view for all screens" },
-
- { OSDOPTION_SCREEN "0", OSDOPTVAL_AUTO, core_options::option_type::STRING, "explicit name of the first screen; 'auto' here will try to make a best guess" },
- { OSDOPTION_ASPECT "0", OSDOPTVAL_AUTO, core_options::option_type::STRING, "aspect ratio of the first screen; 'auto' here will try to make a best guess" },
- { OSDOPTION_RESOLUTION "0;r0", OSDOPTVAL_AUTO, core_options::option_type::STRING, "preferred resolution of the first screen; format is <width>x<height>[@<refreshrate>] or 'auto'" },
- { OSDOPTION_VIEW "0", OSDOPTVAL_AUTO, core_options::option_type::STRING, "preferred view for the first screen" },
-
- { OSDOPTION_SCREEN "1", OSDOPTVAL_AUTO, core_options::option_type::STRING, "explicit name of the second screen; 'auto' here will try to make a best guess" },
- { OSDOPTION_ASPECT "1", OSDOPTVAL_AUTO, core_options::option_type::STRING, "aspect ratio of the second screen; 'auto' here will try to make a best guess" },
- { OSDOPTION_RESOLUTION "1;r1", OSDOPTVAL_AUTO, core_options::option_type::STRING, "preferred resolution of the second screen; format is <width>x<height>[@<refreshrate>] or 'auto'" },
- { OSDOPTION_VIEW "1", OSDOPTVAL_AUTO, core_options::option_type::STRING, "preferred view for the second screen" },
-
- { OSDOPTION_SCREEN "2", OSDOPTVAL_AUTO, core_options::option_type::STRING, "explicit name of the third screen; 'auto' here will try to make a best guess" },
- { OSDOPTION_ASPECT "2", OSDOPTVAL_AUTO, core_options::option_type::STRING, "aspect ratio of the third screen; 'auto' here will try to make a best guess" },
- { OSDOPTION_RESOLUTION "2;r2", OSDOPTVAL_AUTO, core_options::option_type::STRING, "preferred resolution of the third screen; format is <width>x<height>[@<refreshrate>] or 'auto'" },
- { OSDOPTION_VIEW "2", OSDOPTVAL_AUTO, core_options::option_type::STRING, "preferred view for the third screen" },
-
- { OSDOPTION_SCREEN "3", OSDOPTVAL_AUTO, core_options::option_type::STRING, "explicit name of the fourth screen; 'auto' here will try to make a best guess" },
- { OSDOPTION_ASPECT "3", OSDOPTVAL_AUTO, core_options::option_type::STRING, "aspect ratio of the fourth screen; 'auto' here will try to make a best guess" },
- { OSDOPTION_RESOLUTION "3;r3", OSDOPTVAL_AUTO, core_options::option_type::STRING, "preferred resolution of the fourth screen; format is <width>x<height>[@<refreshrate>] or 'auto'" },
- { OSDOPTION_VIEW "3", OSDOPTVAL_AUTO, core_options::option_type::STRING, "preferred view for the fourth screen" },
+ { nullptr, nullptr, core_options::option_type::HEADER, "OSD PER-WINDOW VIDEO OPTIONS" },
+ { OSDOPTION_SCREEN, OSDOPTVAL_AUTO, core_options::option_type::STRING, "explicit name of the first screen; 'auto' here will try to make a best guess" },
+ { OSDOPTION_ASPECT ";screen_aspect", OSDOPTVAL_AUTO, core_options::option_type::STRING, "aspect ratio for all screens; 'auto' here will try to make a best guess" },
+ { OSDOPTION_RESOLUTION ";r", OSDOPTVAL_AUTO, core_options::option_type::STRING, "preferred resolution for all screens; format is <width>x<height>[@<refreshrate>] or 'auto'" },
+ { OSDOPTION_VIEW, OSDOPTVAL_AUTO, core_options::option_type::STRING, "preferred view for all screens" },
+
+ { OSDOPTION_SCREEN "0", OSDOPTVAL_AUTO, core_options::option_type::STRING, "explicit name of the first screen; 'auto' here will try to make a best guess" },
+ { OSDOPTION_ASPECT "0", OSDOPTVAL_AUTO, core_options::option_type::STRING, "aspect ratio of the first screen; 'auto' here will try to make a best guess" },
+ { OSDOPTION_RESOLUTION "0;r0", OSDOPTVAL_AUTO, core_options::option_type::STRING, "preferred resolution of the first screen; format is <width>x<height>[@<refreshrate>] or 'auto'" },
+ { OSDOPTION_VIEW "0", OSDOPTVAL_AUTO, core_options::option_type::STRING, "preferred view for the first screen" },
+
+ { OSDOPTION_SCREEN "1", OSDOPTVAL_AUTO, core_options::option_type::STRING, "explicit name of the second screen; 'auto' here will try to make a best guess" },
+ { OSDOPTION_ASPECT "1", OSDOPTVAL_AUTO, core_options::option_type::STRING, "aspect ratio of the second screen; 'auto' here will try to make a best guess" },
+ { OSDOPTION_RESOLUTION "1;r1", OSDOPTVAL_AUTO, core_options::option_type::STRING, "preferred resolution of the second screen; format is <width>x<height>[@<refreshrate>] or 'auto'" },
+ { OSDOPTION_VIEW "1", OSDOPTVAL_AUTO, core_options::option_type::STRING, "preferred view for the second screen" },
+
+ { OSDOPTION_SCREEN "2", OSDOPTVAL_AUTO, core_options::option_type::STRING, "explicit name of the third screen; 'auto' here will try to make a best guess" },
+ { OSDOPTION_ASPECT "2", OSDOPTVAL_AUTO, core_options::option_type::STRING, "aspect ratio of the third screen; 'auto' here will try to make a best guess" },
+ { OSDOPTION_RESOLUTION "2;r2", OSDOPTVAL_AUTO, core_options::option_type::STRING, "preferred resolution of the third screen; format is <width>x<height>[@<refreshrate>] or 'auto'" },
+ { OSDOPTION_VIEW "2", OSDOPTVAL_AUTO, core_options::option_type::STRING, "preferred view for the third screen" },
+
+ { OSDOPTION_SCREEN "3", OSDOPTVAL_AUTO, core_options::option_type::STRING, "explicit name of the fourth screen; 'auto' here will try to make a best guess" },
+ { OSDOPTION_ASPECT "3", OSDOPTVAL_AUTO, core_options::option_type::STRING, "aspect ratio of the fourth screen; 'auto' here will try to make a best guess" },
+ { OSDOPTION_RESOLUTION "3;r3", OSDOPTVAL_AUTO, core_options::option_type::STRING, "preferred resolution of the fourth screen; format is <width>x<height>[@<refreshrate>] or 'auto'" },
+ { OSDOPTION_VIEW "3", OSDOPTVAL_AUTO, core_options::option_type::STRING, "preferred view for the fourth screen" },
// full screen options
- { nullptr, nullptr, core_options::option_type::HEADER, "OSD FULL SCREEN OPTIONS" },
- { OSDOPTION_SWITCHRES, "0", core_options::option_type::BOOLEAN, "enable resolution switching" },
+ { nullptr, nullptr, core_options::option_type::HEADER, "OSD FULL SCREEN OPTIONS" },
+ { OSDOPTION_SWITCHRES, "0", core_options::option_type::BOOLEAN, "enable resolution switching" },
- { nullptr, nullptr, core_options::option_type::HEADER, "OSD ACCELERATED VIDEO OPTIONS" },
- { OSDOPTION_FILTER ";glfilter;flt", "1", core_options::option_type::BOOLEAN, "use bilinear filtering when scaling emulated video" },
- { OSDOPTION_PRESCALE "(1-8)", "1", core_options::option_type::INTEGER, "scale emulated video by this factor before applying filters/shaders" },
+ { nullptr, nullptr, core_options::option_type::HEADER, "OSD ACCELERATED VIDEO OPTIONS" },
+ { OSDOPTION_FILTER ";glfilter;flt", "1", core_options::option_type::BOOLEAN, "use bilinear filtering when scaling emulated video" },
+ { OSDOPTION_PRESCALE "(1-20)", "1", core_options::option_type::INTEGER, "scale emulated video by this factor before applying filters/shaders" },
#if USE_OPENGL
- { nullptr, nullptr, core_options::option_type::HEADER, "OpenGL-SPECIFIC OPTIONS" },
- { OSDOPTION_GL_FORCEPOW2TEXTURE, "0", core_options::option_type::BOOLEAN, "force power-of-two texture sizes (default no)" },
- { OSDOPTION_GL_NOTEXTURERECT, "0", core_options::option_type::BOOLEAN, "don't use OpenGL GL_ARB_texture_rectangle (default on)" },
- { OSDOPTION_GL_VBO, "1", core_options::option_type::BOOLEAN, "enable OpenGL VBO if available (default on)" },
- { OSDOPTION_GL_PBO, "1", core_options::option_type::BOOLEAN, "enable OpenGL PBO if available (default on)" },
- { OSDOPTION_GL_GLSL, "0", core_options::option_type::BOOLEAN, "enable OpenGL GLSL if available (default off)" },
- { OSDOPTION_GLSL_FILTER, "1", core_options::option_type::STRING, "enable OpenGL GLSL filtering instead of FF filtering 0-plain, 1-bilinear (default), 2-bicubic" },
- { OSDOPTION_SHADER_MAME "0", OSDOPTVAL_NONE, core_options::option_type::STRING, "custom OpenGL GLSL shader set mame bitmap 0" },
- { OSDOPTION_SHADER_MAME "1", OSDOPTVAL_NONE, core_options::option_type::STRING, "custom OpenGL GLSL shader set mame bitmap 1" },
- { OSDOPTION_SHADER_MAME "2", OSDOPTVAL_NONE, core_options::option_type::STRING, "custom OpenGL GLSL shader set mame bitmap 2" },
- { OSDOPTION_SHADER_MAME "3", OSDOPTVAL_NONE, core_options::option_type::STRING, "custom OpenGL GLSL shader set mame bitmap 3" },
- { OSDOPTION_SHADER_MAME "4", OSDOPTVAL_NONE, core_options::option_type::STRING, "custom OpenGL GLSL shader set mame bitmap 4" },
- { OSDOPTION_SHADER_MAME "5", OSDOPTVAL_NONE, core_options::option_type::STRING, "custom OpenGL GLSL shader set mame bitmap 5" },
- { OSDOPTION_SHADER_MAME "6", OSDOPTVAL_NONE, core_options::option_type::STRING, "custom OpenGL GLSL shader set mame bitmap 6" },
- { OSDOPTION_SHADER_MAME "7", OSDOPTVAL_NONE, core_options::option_type::STRING, "custom OpenGL GLSL shader set mame bitmap 7" },
- { OSDOPTION_SHADER_MAME "8", OSDOPTVAL_NONE, core_options::option_type::STRING, "custom OpenGL GLSL shader set mame bitmap 8" },
- { OSDOPTION_SHADER_MAME "9", OSDOPTVAL_NONE, core_options::option_type::STRING, "custom OpenGL GLSL shader set mame bitmap 9" },
- { OSDOPTION_SHADER_SCREEN "0", OSDOPTVAL_NONE, core_options::option_type::STRING, "custom OpenGL GLSL shader screen bitmap 0" },
- { OSDOPTION_SHADER_SCREEN "1", OSDOPTVAL_NONE, core_options::option_type::STRING, "custom OpenGL GLSL shader screen bitmap 1" },
- { OSDOPTION_SHADER_SCREEN "2", OSDOPTVAL_NONE, core_options::option_type::STRING, "custom OpenGL GLSL shader screen bitmap 2" },
- { OSDOPTION_SHADER_SCREEN "3", OSDOPTVAL_NONE, core_options::option_type::STRING, "custom OpenGL GLSL shader screen bitmap 3" },
- { OSDOPTION_SHADER_SCREEN "4", OSDOPTVAL_NONE, core_options::option_type::STRING, "custom OpenGL GLSL shader screen bitmap 4" },
- { OSDOPTION_SHADER_SCREEN "5", OSDOPTVAL_NONE, core_options::option_type::STRING, "custom OpenGL GLSL shader screen bitmap 5" },
- { OSDOPTION_SHADER_SCREEN "6", OSDOPTVAL_NONE, core_options::option_type::STRING, "custom OpenGL GLSL shader screen bitmap 6" },
- { OSDOPTION_SHADER_SCREEN "7", OSDOPTVAL_NONE, core_options::option_type::STRING, "custom OpenGL GLSL shader screen bitmap 7" },
- { OSDOPTION_SHADER_SCREEN "8", OSDOPTVAL_NONE, core_options::option_type::STRING, "custom OpenGL GLSL shader screen bitmap 8" },
- { OSDOPTION_SHADER_SCREEN "9", OSDOPTVAL_NONE, core_options::option_type::STRING, "custom OpenGL GLSL shader screen bitmap 9" },
+ { nullptr, nullptr, core_options::option_type::HEADER, "OpenGL-SPECIFIC OPTIONS" },
+ { OSDOPTION_GL_FORCEPOW2TEXTURE, "0", core_options::option_type::BOOLEAN, "force power-of-two texture sizes (default no)" },
+ { OSDOPTION_GL_NOTEXTURERECT, "0", core_options::option_type::BOOLEAN, "don't use OpenGL GL_ARB_texture_rectangle (default on)" },
+ { OSDOPTION_GL_VBO, "1", core_options::option_type::BOOLEAN, "enable OpenGL VBO if available (default on)" },
+ { OSDOPTION_GL_PBO, "1", core_options::option_type::BOOLEAN, "enable OpenGL PBO if available (default on)" },
+ { OSDOPTION_GL_GLSL, "0", core_options::option_type::BOOLEAN, "enable OpenGL GLSL if available (default off)" },
+ { OSDOPTION_GLSL_FILTER, "1", core_options::option_type::STRING, "enable OpenGL GLSL filtering instead of FF filtering 0-plain, 1-bilinear (default), 2-bicubic" },
+ { OSDOPTION_SHADER_MAME "0", OSDOPTVAL_NONE, core_options::option_type::STRING, "custom OpenGL GLSL shader set mame bitmap 0" },
+ { OSDOPTION_SHADER_MAME "1", OSDOPTVAL_NONE, core_options::option_type::STRING, "custom OpenGL GLSL shader set mame bitmap 1" },
+ { OSDOPTION_SHADER_MAME "2", OSDOPTVAL_NONE, core_options::option_type::STRING, "custom OpenGL GLSL shader set mame bitmap 2" },
+ { OSDOPTION_SHADER_MAME "3", OSDOPTVAL_NONE, core_options::option_type::STRING, "custom OpenGL GLSL shader set mame bitmap 3" },
+ { OSDOPTION_SHADER_MAME "4", OSDOPTVAL_NONE, core_options::option_type::STRING, "custom OpenGL GLSL shader set mame bitmap 4" },
+ { OSDOPTION_SHADER_MAME "5", OSDOPTVAL_NONE, core_options::option_type::STRING, "custom OpenGL GLSL shader set mame bitmap 5" },
+ { OSDOPTION_SHADER_MAME "6", OSDOPTVAL_NONE, core_options::option_type::STRING, "custom OpenGL GLSL shader set mame bitmap 6" },
+ { OSDOPTION_SHADER_MAME "7", OSDOPTVAL_NONE, core_options::option_type::STRING, "custom OpenGL GLSL shader set mame bitmap 7" },
+ { OSDOPTION_SHADER_MAME "8", OSDOPTVAL_NONE, core_options::option_type::STRING, "custom OpenGL GLSL shader set mame bitmap 8" },
+ { OSDOPTION_SHADER_MAME "9", OSDOPTVAL_NONE, core_options::option_type::STRING, "custom OpenGL GLSL shader set mame bitmap 9" },
+ { OSDOPTION_SHADER_SCREEN "0", OSDOPTVAL_NONE, core_options::option_type::STRING, "custom OpenGL GLSL shader screen bitmap 0" },
+ { OSDOPTION_SHADER_SCREEN "1", OSDOPTVAL_NONE, core_options::option_type::STRING, "custom OpenGL GLSL shader screen bitmap 1" },
+ { OSDOPTION_SHADER_SCREEN "2", OSDOPTVAL_NONE, core_options::option_type::STRING, "custom OpenGL GLSL shader screen bitmap 2" },
+ { OSDOPTION_SHADER_SCREEN "3", OSDOPTVAL_NONE, core_options::option_type::STRING, "custom OpenGL GLSL shader screen bitmap 3" },
+ { OSDOPTION_SHADER_SCREEN "4", OSDOPTVAL_NONE, core_options::option_type::STRING, "custom OpenGL GLSL shader screen bitmap 4" },
+ { OSDOPTION_SHADER_SCREEN "5", OSDOPTVAL_NONE, core_options::option_type::STRING, "custom OpenGL GLSL shader screen bitmap 5" },
+ { OSDOPTION_SHADER_SCREEN "6", OSDOPTVAL_NONE, core_options::option_type::STRING, "custom OpenGL GLSL shader screen bitmap 6" },
+ { OSDOPTION_SHADER_SCREEN "7", OSDOPTVAL_NONE, core_options::option_type::STRING, "custom OpenGL GLSL shader screen bitmap 7" },
+ { OSDOPTION_SHADER_SCREEN "8", OSDOPTVAL_NONE, core_options::option_type::STRING, "custom OpenGL GLSL shader screen bitmap 8" },
+ { OSDOPTION_SHADER_SCREEN "9", OSDOPTVAL_NONE, core_options::option_type::STRING, "custom OpenGL GLSL shader screen bitmap 9" },
#endif
- { nullptr, nullptr, core_options::option_type::HEADER, "OSD SOUND OPTIONS" },
- { OSDOPTION_SOUND, OSDOPTVAL_AUTO, core_options::option_type::STRING, "sound output method: " },
- { OSDOPTION_AUDIO_LATENCY "(0-5)", "2", core_options::option_type::INTEGER, "set audio latency (increase to reduce glitches, decrease for responsiveness)" },
+ { nullptr, nullptr, core_options::option_type::HEADER, "OSD SOUND OPTIONS" },
+ { OSDOPTION_SOUND, OSDOPTVAL_AUTO, core_options::option_type::STRING, "sound output method: " },
+ { OSDOPTION_AUDIO_LATENCY "(0-5)", "2", core_options::option_type::INTEGER, "set audio latency (increase to reduce glitches, decrease for responsiveness)" },
#ifndef NO_USE_PORTAUDIO
- { nullptr, nullptr, core_options::option_type::HEADER, "PORTAUDIO OPTIONS" },
- { OSDOPTION_PA_API, OSDOPTVAL_NONE, core_options::option_type::STRING, "PortAudio API" },
- { OSDOPTION_PA_DEVICE, OSDOPTVAL_NONE, core_options::option_type::STRING, "PortAudio device" },
- { OSDOPTION_PA_LATENCY "(0-0.25)", "0", core_options::option_type::FLOAT, "suggested latency in seconds, 0 for default" },
+ { nullptr, nullptr, core_options::option_type::HEADER, "PORTAUDIO OPTIONS" },
+ { OSDOPTION_PA_API, OSDOPTVAL_NONE, core_options::option_type::STRING, "PortAudio API" },
+ { OSDOPTION_PA_DEVICE, OSDOPTVAL_NONE, core_options::option_type::STRING, "PortAudio device" },
+ { OSDOPTION_PA_LATENCY "(0-0.25)", "0", core_options::option_type::FLOAT, "suggested latency in seconds, 0 for default" },
#endif
#ifdef SDLMAME_MACOSX
- { nullptr, nullptr, core_options::option_type::HEADER, "CoreAudio-SPECIFIC OPTIONS" },
- { OSDOPTION_AUDIO_OUTPUT, OSDOPTVAL_AUTO, core_options::option_type::STRING, "audio output device" },
- { OSDOPTION_AUDIO_EFFECT "0", OSDOPTVAL_NONE, core_options::option_type::STRING, "AudioUnit effect 0" },
- { OSDOPTION_AUDIO_EFFECT "1", OSDOPTVAL_NONE, core_options::option_type::STRING, "AudioUnit effect 1" },
- { OSDOPTION_AUDIO_EFFECT "2", OSDOPTVAL_NONE, core_options::option_type::STRING, "AudioUnit effect 2" },
- { OSDOPTION_AUDIO_EFFECT "3", OSDOPTVAL_NONE, core_options::option_type::STRING, "AudioUnit effect 3" },
- { OSDOPTION_AUDIO_EFFECT "4", OSDOPTVAL_NONE, core_options::option_type::STRING, "AudioUnit effect 4" },
- { OSDOPTION_AUDIO_EFFECT "5", OSDOPTVAL_NONE, core_options::option_type::STRING, "AudioUnit effect 5" },
- { OSDOPTION_AUDIO_EFFECT "6", OSDOPTVAL_NONE, core_options::option_type::STRING, "AudioUnit effect 6" },
- { OSDOPTION_AUDIO_EFFECT "7", OSDOPTVAL_NONE, core_options::option_type::STRING, "AudioUnit effect 7" },
- { OSDOPTION_AUDIO_EFFECT "8", OSDOPTVAL_NONE, core_options::option_type::STRING, "AudioUnit effect 8" },
- { OSDOPTION_AUDIO_EFFECT "9", OSDOPTVAL_NONE, core_options::option_type::STRING, "AudioUnit effect 9" },
+ { nullptr, nullptr, core_options::option_type::HEADER, "CoreAudio-SPECIFIC OPTIONS" },
+ { OSDOPTION_AUDIO_OUTPUT, OSDOPTVAL_AUTO, core_options::option_type::STRING, "audio output device" },
+ { OSDOPTION_AUDIO_EFFECT "0", OSDOPTVAL_NONE, core_options::option_type::STRING, "AudioUnit effect 0" },
+ { OSDOPTION_AUDIO_EFFECT "1", OSDOPTVAL_NONE, core_options::option_type::STRING, "AudioUnit effect 1" },
+ { OSDOPTION_AUDIO_EFFECT "2", OSDOPTVAL_NONE, core_options::option_type::STRING, "AudioUnit effect 2" },
+ { OSDOPTION_AUDIO_EFFECT "3", OSDOPTVAL_NONE, core_options::option_type::STRING, "AudioUnit effect 3" },
+ { OSDOPTION_AUDIO_EFFECT "4", OSDOPTVAL_NONE, core_options::option_type::STRING, "AudioUnit effect 4" },
+ { OSDOPTION_AUDIO_EFFECT "5", OSDOPTVAL_NONE, core_options::option_type::STRING, "AudioUnit effect 5" },
+ { OSDOPTION_AUDIO_EFFECT "6", OSDOPTVAL_NONE, core_options::option_type::STRING, "AudioUnit effect 6" },
+ { OSDOPTION_AUDIO_EFFECT "7", OSDOPTVAL_NONE, core_options::option_type::STRING, "AudioUnit effect 7" },
+ { OSDOPTION_AUDIO_EFFECT "8", OSDOPTVAL_NONE, core_options::option_type::STRING, "AudioUnit effect 8" },
+ { OSDOPTION_AUDIO_EFFECT "9", OSDOPTVAL_NONE, core_options::option_type::STRING, "AudioUnit effect 9" },
#endif
- { nullptr, nullptr, core_options::option_type::HEADER, "BGFX POST-PROCESSING OPTIONS" },
- { OSDOPTION_BGFX_PATH, "bgfx", core_options::option_type::STRING, "path to BGFX-related files" },
- { OSDOPTION_BGFX_BACKEND, "auto", core_options::option_type::STRING, "BGFX backend to use (d3d9, d3d11, d3d12, metal, opengl, gles, vulkan)" },
- { OSDOPTION_BGFX_DEBUG, "0", core_options::option_type::BOOLEAN, "enable BGFX debugging statistics" },
- { OSDOPTION_BGFX_SCREEN_CHAINS, "default", core_options::option_type::STRING, "comma-delimited list of screen chain JSON names, colon-delimited per-window" },
- { OSDOPTION_BGFX_SHADOW_MASK, "slot-mask.png", core_options::option_type::STRING, "shadow mask texture name" },
- { OSDOPTION_BGFX_LUT, "lut-default.png", core_options::option_type::STRING, "LUT texture name" },
- { OSDOPTION_BGFX_AVI_NAME, OSDOPTVAL_AUTO, core_options::option_type::STRING, "filename for BGFX output logging" },
+ { nullptr, nullptr, core_options::option_type::HEADER, "OSD MIDI OPTIONS" },
+ { OSDOPTION_MIDI_PROVIDER, OSDOPTVAL_AUTO, core_options::option_type::STRING, "MIDI I/O method: " },
+
+ { nullptr, nullptr, core_options::option_type::HEADER, "OSD EMULATED NETWORKING OPTIONS" },
+ { OSDOPTION_NETWORK_PROVIDER, OSDOPTVAL_AUTO, core_options::option_type::STRING, "Emulated networking provider: " },
- // End of list
+ { nullptr, nullptr, core_options::option_type::HEADER, "BGFX POST-PROCESSING OPTIONS" },
+ { OSDOPTION_BGFX_PATH, "bgfx", core_options::option_type::PATH, "path to BGFX-related files" },
+ { OSDOPTION_BGFX_BACKEND, "auto", core_options::option_type::STRING, "BGFX backend to use (d3d9, d3d11, d3d12, metal, opengl, gles, vulkan)" },
+ { OSDOPTION_BGFX_DEBUG, "0", core_options::option_type::BOOLEAN, "enable BGFX debugging statistics" },
+ { OSDOPTION_BGFX_SCREEN_CHAINS, "", core_options::option_type::STRING, "comma-delimited list of screen chain JSON names, colon-delimited per-window" },
+ { OSDOPTION_BGFX_SHADOW_MASK, "slot-mask.png", core_options::option_type::STRING, "shadow mask texture name" },
+ { OSDOPTION_BGFX_LUT, "lut-default.png", core_options::option_type::STRING, "LUT texture name" },
+ { OSDOPTION_BGFX_AVI_NAME, OSDOPTVAL_AUTO, core_options::option_type::PATH, "filename for BGFX output logging" },
+
+ // End of list
{ nullptr }
};
@@ -182,7 +193,7 @@ osd_options::osd_options()
}
// Window list
-std::list<std::shared_ptr<osd_window>> osd_common_t::s_window_list;
+std::list<std::unique_ptr<osd_window> > osd_common_t::s_window_list;
//-------------------------------------------------
// osd_interface - constructor
@@ -217,7 +228,7 @@ osd_common_t::~osd_common_t()
osd_output::pop(this);
}
-#define REGISTER_MODULE(_O, _X ) { extern const module_type _X; _O . register_module( _X ); }
+#define REGISTER_MODULE(O, X) { extern const module_type X; O.register_module(X); }
void osd_common_t::register_options()
{
@@ -227,6 +238,26 @@ void osd_common_t::register_options()
REGISTER_MODULE(m_mod_man, FONT_SDL);
REGISTER_MODULE(m_mod_man, FONT_NONE);
+#if defined(SDLMAME_EMSCRIPTEN)
+ REGISTER_MODULE(m_mod_man, RENDERER_SDL1); // don't bother trying to use video acceleration in browsers
+#endif
+#if defined(OSD_WINDOWS)
+ REGISTER_MODULE(m_mod_man, RENDERER_D3D); // this is only built for OSD=windows, there's no dummy stub
+#endif
+#if defined(OSD_WINDOWS) || defined(SDLMAME_WIN32)
+ REGISTER_MODULE(m_mod_man, RENDERER_BGFX); // try BGFX before GDI on windows to get DirectX 10/11 acceleration
+#endif
+ REGISTER_MODULE(m_mod_man, RENDERER_GDI); // GDI ahead of OpenGL as there's a chance Windows has no OpenGL
+ REGISTER_MODULE(m_mod_man, RENDERER_OPENGL);
+#if !defined(OSD_WINDOWS) && !defined(SDLMAME_WIN32)
+ REGISTER_MODULE(m_mod_man, RENDERER_BGFX); // try BGFX after OpenGL on other operating systems for now
+#endif
+ REGISTER_MODULE(m_mod_man, RENDERER_SDL2);
+#if !defined(SDLMAME_EMSCRIPTEN)
+ REGISTER_MODULE(m_mod_man, RENDERER_SDL1);
+#endif
+ REGISTER_MODULE(m_mod_man, RENDERER_NONE);
+
REGISTER_MODULE(m_mod_man, SOUND_DSOUND);
REGISTER_MODULE(m_mod_man, SOUND_XAUDIO2);
REGISTER_MODULE(m_mod_man, SOUND_COREAUDIO);
@@ -282,7 +313,8 @@ void osd_common_t::register_options()
REGISTER_MODULE(m_mod_man, LIGHTGUNINPUT_WIN32);
REGISTER_MODULE(m_mod_man, LIGHTGUN_NONE);
- REGISTER_MODULE(m_mod_man, JOYSTICKINPUT_SDL);
+ REGISTER_MODULE(m_mod_man, JOYSTICKINPUT_SDLGAME);
+ REGISTER_MODULE(m_mod_man, JOYSTICKINPUT_SDLJOY);
REGISTER_MODULE(m_mod_man, JOYSTICKINPUT_WINHYBRID);
REGISTER_MODULE(m_mod_man, JOYSTICKINPUT_DINPUT);
REGISTER_MODULE(m_mod_man, JOYSTICKINPUT_XINPUT);
@@ -295,95 +327,34 @@ void osd_common_t::register_options()
// after initialization we know which modules are supported
-
- const char *names[20];
- int num;
- std::vector<const char *> dnames;
-
- m_mod_man.get_module_names(OSD_MONITOR_PROVIDER, 20, num, names);
- for (int i = 0; i < num; i++)
- dnames.push_back(names[i]);
- update_option(OSD_MONITOR_PROVIDER, dnames);
-
- m_mod_man.get_module_names(OSD_FONT_PROVIDER, 20, num, names);
- dnames.clear();
- for (int i = 0; i < num; i++)
- dnames.push_back(names[i]);
- update_option(OSD_FONT_PROVIDER, dnames);
-
- m_mod_man.get_module_names(OSD_KEYBOARDINPUT_PROVIDER, 20, num, names);
- dnames.clear();
- for (int i = 0; i < num; i++)
- dnames.push_back(names[i]);
- update_option(OSD_KEYBOARDINPUT_PROVIDER, dnames);
-
- m_mod_man.get_module_names(OSD_MOUSEINPUT_PROVIDER, 20, num, names);
- dnames.clear();
- for (int i = 0; i < num; i++)
- dnames.push_back(names[i]);
- update_option(OSD_MOUSEINPUT_PROVIDER, dnames);
-
- m_mod_man.get_module_names(OSD_LIGHTGUNINPUT_PROVIDER, 20, num, names);
- dnames.clear();
- for (int i = 0; i < num; i++)
- dnames.push_back(names[i]);
- update_option(OSD_LIGHTGUNINPUT_PROVIDER, dnames);
-
- m_mod_man.get_module_names(OSD_JOYSTICKINPUT_PROVIDER, 20, num, names);
- dnames.clear();
- for (int i = 0; i < num; i++)
- dnames.push_back(names[i]);
- update_option(OSD_JOYSTICKINPUT_PROVIDER, dnames);
-
- m_mod_man.get_module_names(OSD_SOUND_PROVIDER, 20, num, names);
- dnames.clear();
- for (int i = 0; i < num; i++)
- dnames.push_back(names[i]);
- update_option(OSD_SOUND_PROVIDER, dnames);
-
-#if 0
- // Register midi options and update options
- m_mod_man.get_module_names(OSD_MIDI_PROVIDER, 20, num, names);
- dnames.clear();
- for (int i = 0; i < num; i++)
- dnames.push_back(names[i]);
- update_option(OSD_MIDI_PROVIDER, dnames);
-#endif
-
- // Register debugger options and update options
- m_mod_man.get_module_names(OSD_DEBUG_PROVIDER, 20, num, names);
- dnames.clear();
- for (int i = 0; i < num; i++)
- dnames.push_back(names[i]);
- update_option(OSD_DEBUG_PROVIDER, dnames);
-
- m_mod_man.get_module_names(OSD_OUTPUT_PROVIDER, 20, num, names);
- dnames.clear();
- for (int i = 0; i < num; i++)
- dnames.push_back(names[i]);
- update_option(OSD_OUTPUT_PROVIDER, dnames);
-
- // Register video options and update options
- video_options_add("none", nullptr);
- video_register();
- update_option(OSDOPTION_VIDEO, m_video_names);
-}
-
-void osd_common_t::update_option(const std::string &key, std::vector<const char *> &values)
+ update_option(OSD_FONT_PROVIDER, m_mod_man.get_module_names(OSD_FONT_PROVIDER));
+ update_option(OSD_RENDERER_PROVIDER, m_mod_man.get_module_names(OSD_RENDERER_PROVIDER));
+ update_option(OSD_SOUND_PROVIDER, m_mod_man.get_module_names(OSD_SOUND_PROVIDER));
+ update_option(OSD_MONITOR_PROVIDER, m_mod_man.get_module_names(OSD_MONITOR_PROVIDER));
+ update_option(OSD_KEYBOARDINPUT_PROVIDER, m_mod_man.get_module_names(OSD_KEYBOARDINPUT_PROVIDER));
+ update_option(OSD_MOUSEINPUT_PROVIDER, m_mod_man.get_module_names(OSD_MOUSEINPUT_PROVIDER));
+ update_option(OSD_LIGHTGUNINPUT_PROVIDER, m_mod_man.get_module_names(OSD_LIGHTGUNINPUT_PROVIDER));
+ update_option(OSD_JOYSTICKINPUT_PROVIDER, m_mod_man.get_module_names(OSD_JOYSTICKINPUT_PROVIDER));
+ update_option(OSD_MIDI_PROVIDER, m_mod_man.get_module_names(OSD_MIDI_PROVIDER));
+ update_option(OSD_NETDEV_PROVIDER, m_mod_man.get_module_names(OSD_NETDEV_PROVIDER));
+ update_option(OSD_DEBUG_PROVIDER, m_mod_man.get_module_names(OSD_DEBUG_PROVIDER));
+ update_option(OSD_OUTPUT_PROVIDER, m_mod_man.get_module_names(OSD_OUTPUT_PROVIDER));
+}
+
+void osd_common_t::update_option(const std::string &key, std::vector<std::string_view> const &values)
{
std::string current_value(m_options.description(key.c_str()));
std::string new_option_value("");
for (unsigned int index = 0; index < values.size(); index++)
{
- std::string t(values[index]);
if (new_option_value.length() > 0)
{
- if( index != (values.size()-1))
+ if (index != (values.size() - 1))
new_option_value.append(", ");
else
new_option_value.append(" or ");
}
- new_option_value.append(t);
+ new_option_value.append(values[index]);
}
m_option_descs[key] = current_value + new_option_value;
@@ -394,7 +365,7 @@ void osd_common_t::update_option(const std::string &key, std::vector<const char
//-------------------------------------------------
// output_callback - callback for osd_printf_...
//-------------------------------------------------
-void osd_common_t::output_callback(osd_output_channel channel, const util::format_argument_pack<std::ostream> &args)
+void osd_common_t::output_callback(osd_output_channel channel, const util::format_argument_pack<char> &args)
{
switch (channel)
{
@@ -620,28 +591,50 @@ bool osd_common_t::execute_command(const char *command)
{
if (strcmp(command, OSDCOMMAND_LIST_NETWORK_ADAPTERS) == 0)
{
- osd_module *om = select_module_options(options(), OSD_NETDEV_PROVIDER);
-
- if (om->probe())
+ osd_module &om = select_module_options<osd_module>(OSD_NETDEV_PROVIDER);
+ auto const &interfaces = get_netdev_list();
+ if (interfaces.empty())
+ {
+ printf("No supported network interfaces were found\n");
+ }
+ else
{
- om->init(options());
- osd_list_network_adapters();
- om->exit();
+ printf("Available network interfaces:\n");
+ for (auto &entry : interfaces)
+ {
+ printf(" %s\n", entry->description);
+ }
}
+ om.exit();
return true;
}
else if (strcmp(command, OSDCOMMAND_LIST_MIDI_DEVICES) == 0)
{
- osd_module *om = select_module_options(options(), OSD_MIDI_PROVIDER);
- auto *pm = select_module_options<midi_module *>(options(), OSD_MIDI_PROVIDER);
-
- if (om->probe())
+ osd_module &om = select_module_options<osd_module>(OSD_MIDI_PROVIDER);
+ auto const ports = dynamic_cast<midi_module &>(om).list_midi_ports();
+ if (ports.empty())
{
- om->init(options());
- pm->list_midi_devices();
- om->exit();
+ printf("No MIDI ports were found\n");
}
+ else
+ {
+ printf("MIDI input ports:\n");
+ for (auto const &port : ports)
+ {
+ if (port.input)
+ printf(port.default_input ? "%s (default)\n" : "%s\n", port.name.c_str());
+ }
+
+ printf("\nMIDI output ports:\n");
+ for (auto const &port : ports)
+ {
+ if (port.output)
+ printf(port.default_output ? "%s (default)\n" : "%s\n", port.name.c_str());
+ }
+ }
+ om.exit();
+
return true;
}
@@ -657,10 +650,10 @@ static void output_notifier_callback(const char *outname, int32_t value, void *p
void osd_common_t::init_subsystems()
{
// monitors have to be initialized before video init
- m_monitor_module = select_module_options<monitor_module *>(options(), OSD_MONITOR_PROVIDER);
- assert(m_monitor_module != nullptr);
- m_monitor_module->init(options());
+ m_monitor_module = &select_module_options<monitor_module>(OSD_MONITOR_PROVIDER);
+ // various modules depend on having a window handle
+ m_render = &select_module_options<render_module>(OSD_RENDERER_PROVIDER);
if (!video_init())
{
video_exit();
@@ -670,32 +663,24 @@ void osd_common_t::init_subsystems()
exit(-1);
}
- m_keyboard_input = select_module_options<input_module *>(options(), OSD_KEYBOARDINPUT_PROVIDER);
- m_mouse_input = select_module_options<input_module *>(options(), OSD_MOUSEINPUT_PROVIDER);
- m_lightgun_input = select_module_options<input_module *>(options(), OSD_LIGHTGUNINPUT_PROVIDER);
- m_joystick_input = select_module_options<input_module *>(options(), OSD_JOYSTICKINPUT_PROVIDER);
+ m_keyboard_input = &select_module_options<input_module>(OSD_KEYBOARDINPUT_PROVIDER);
+ m_mouse_input = &select_module_options<input_module>(OSD_MOUSEINPUT_PROVIDER);
+ m_lightgun_input = &select_module_options<input_module>(OSD_LIGHTGUNINPUT_PROVIDER);
+ m_joystick_input = &select_module_options<input_module>(OSD_JOYSTICKINPUT_PROVIDER);
- m_font_module = select_module_options<font_module *>(options(), OSD_FONT_PROVIDER);
- m_sound = select_module_options<sound_module *>(options(), OSD_SOUND_PROVIDER);
- m_sound->m_sample_rate = options().sample_rate();
- m_sound->m_audio_latency = options().audio_latency();
+ m_font_module = &select_module_options<font_module>(OSD_FONT_PROVIDER);
+ m_sound = &select_module_options<sound_module>(OSD_SOUND_PROVIDER);
- m_debugger = select_module_options<debug_module *>(options(), OSD_DEBUG_PROVIDER);
+ m_debugger = &select_module_options<debug_module>(OSD_DEBUG_PROVIDER);
- select_module_options<netdev_module *>(options(), OSD_NETDEV_PROVIDER);
+ select_module_options<netdev_module>(OSD_NETDEV_PROVIDER);
- m_midi = select_module_options<midi_module *>(options(), OSD_MIDI_PROVIDER);
+ m_midi = &select_module_options<midi_module>(OSD_MIDI_PROVIDER);
- m_output = select_module_options<output_module *>(options(), OSD_OUTPUT_PROVIDER);
- m_output->set_machine(&machine());
+ m_output = &select_module_options<output_module>(OSD_OUTPUT_PROVIDER);
machine().output().set_global_notifier(output_notifier_callback, this);
- m_mod_man.init(options());
-
input_init();
- // we need pause callbacks
- machine().add_notifier(MACHINE_NOTIFY_PAUSE, machine_notify_delegate(&osd_common_t::input_pause, this));
- machine().add_notifier(MACHINE_NOTIFY_RESUME, machine_notify_delegate(&osd_common_t::input_resume, this));
}
bool osd_common_t::video_init()
@@ -713,10 +698,6 @@ bool osd_common_t::no_sound()
return (strcmp(options().sound(),"none")==0) ? true : false;
}
-void osd_common_t::video_register()
-{
-}
-
bool osd_common_t::input_init()
{
m_keyboard_input->input_init(machine());
@@ -726,20 +707,12 @@ bool osd_common_t::input_init()
return true;
}
-void osd_common_t::input_pause()
-{
- m_keyboard_input->pause();
- m_mouse_input->pause();
- m_lightgun_input->pause();
- m_joystick_input->pause();
-}
-
-void osd_common_t::input_resume()
+void osd_common_t::poll_input_modules(bool relative_reset)
{
- m_keyboard_input->resume();
- m_mouse_input->resume();
- m_lightgun_input->resume();
- m_joystick_input->resume();
+ m_keyboard_input->poll_if_necessary(relative_reset);
+ m_mouse_input->poll_if_necessary(relative_reset);
+ m_lightgun_input->poll_if_necessary(relative_reset);
+ m_joystick_input->poll_if_necessary(relative_reset);
}
void osd_common_t::exit_subsystems()
@@ -757,17 +730,15 @@ void osd_common_t::window_exit()
void osd_common_t::osd_exit()
{
+ // destroy the renderers before shutting down their parent module
+ for (auto it = window_list().rbegin(); window_list().rend() != it; ++it)
+ (*it)->renderer_reset();
+
m_mod_man.exit();
exit_subsystems();
}
-void osd_common_t::video_options_add(const char *name, void *type)
-{
- //m_video_options.add(name, type, false);
- m_video_names.push_back(name);
-}
-
osd_font::ptr osd_common_t::font_alloc()
{
return m_font_module->font_alloc();
@@ -778,7 +749,12 @@ bool osd_common_t::get_font_families(std::string const &font_path, std::vector<s
return m_font_module->get_font_families(font_path, result);
}
-std::unique_ptr<osd_midi_device> osd_common_t::create_midi_device()
+std::unique_ptr<osd::midi_input_port> osd_common_t::create_midi_input(std::string_view name)
+{
+ return m_midi->create_input(name);
+}
+
+std::unique_ptr<osd::midi_output_port> osd_common_t::create_midi_output(std::string_view name)
{
- return m_midi->create_midi_device();
+ return m_midi->create_output(name);
}
diff --git a/src/osd/modules/lib/osdobj_common.h b/src/osd/modules/lib/osdobj_common.h
index 55ed36e5060..919bbc4f717 100644
--- a/src/osd/modules/lib/osdobj_common.h
+++ b/src/osd/modules/lib/osdobj_common.h
@@ -2,30 +2,42 @@
// copyright-holders:Aaron Giles
/***************************************************************************
- osdepend.h
+ osdobj_common.h
OS-dependent code interface.
*******************************************************************c********/
-
-#pragma once
-
#ifndef MAME_OSD_LIB_OSDOBJ_COMMON_H
#define MAME_OSD_LIB_OSDOBJ_COMMON_H
+#pragma once
+
#include "osdcore.h"
#include "osdepend.h"
+
#include "modules/osdmodule.h"
#include "modules/output/output_module.h"
+
#include "emuopts.h"
+
#include "strformat.h"
+
+#include <iosfwd>
#include <list>
+#include <memory>
+#include <string>
+#include <string_view>
+#include <unordered_map>
+#include <vector>
+
//============================================================
// Defines
//============================================================
#define OSDOPTION_UIMODEKEY "uimodekey"
+#define OSDOPTION_CONTROLLER_MAP_FILE "controller_map"
+#define OSDOPTION_BACKGROUND_INPUT "background_input"
#define OSDCOMMAND_LIST_MIDI_DEVICES "listmidi"
#define OSDCOMMAND_LIST_NETWORK_ADAPTERS "listnetwork"
@@ -75,8 +87,9 @@
#define OSDOPTION_AUDIO_OUTPUT "audio_output"
#define OSDOPTION_AUDIO_EFFECT "audio_effect"
-#define OSDOPTVAL_AUTO "auto"
-#define OSDOPTVAL_NONE "none"
+#define OSDOPTION_MIDI_PROVIDER "midiprovider"
+
+#define OSDOPTION_NETWORK_PROVIDER "networkprovider"
#define OSDOPTION_BGFX_PATH "bgfx_path"
#define OSDOPTION_BGFX_BACKEND "bgfx_backend"
@@ -86,6 +99,9 @@
#define OSDOPTION_BGFX_LUT "bgfx_lut"
#define OSDOPTION_BGFX_AVI_NAME "bgfx_avi_name"
+#define OSDOPTVAL_AUTO "auto"
+#define OSDOPTVAL_NONE "none"
+
//============================================================
// TYPE DEFINITIONS
//============================================================
@@ -98,6 +114,8 @@ public:
// keyboard mapping
const char *ui_mode_key() const { return value(OSDOPTION_UIMODEKEY); }
+ const char *controller_mapping_file() const { return value(OSDOPTION_CONTROLLER_MAP_FILE); }
+ bool background_input() const { return bool_value(OSDOPTION_BACKGROUND_INPUT); }
// debugging options
const char *debugger() const { return value(OSDOPTION_DEBUGGER); }
@@ -165,22 +183,23 @@ public:
// PortAudio options
const char *pa_api() const { return value(OSDOPTION_PA_API); }
const char *pa_device() const { return value(OSDOPTION_PA_DEVICE); }
- const float pa_latency() const { return float_value(OSDOPTION_PA_LATENCY); }
+ float pa_latency() const { return float_value(OSDOPTION_PA_LATENCY); }
static const options_entry s_option_entries[];
};
// ======================> osd_interface
-class font_module;
-class sound_module;
class debug_module;
-class midi_module;
+class font_module;
class input_module;
-class output_module;
+class midi_module;
class monitor_module;
class osd_watchdog;
class osd_window;
+class output_module;
+class render_module;
+class sound_module;
// description of the currently-running machine
class osd_common_t : public osd_interface, osd_output
@@ -219,7 +238,8 @@ public:
virtual osd_font::ptr font_alloc() override;
virtual bool get_font_families(std::string const &font_path, std::vector<std::pair<std::string, std::string> > &result) override;
- virtual std::unique_ptr<osd_midi_device> create_midi_device() override;
+ virtual std::unique_ptr<osd::midi_input_port> create_midi_input(std::string_view name) override;
+ virtual std::unique_ptr<osd::midi_output_port> create_midi_output(std::string_view name) override;
// FIXME: everything below seems to be osd specific and not part of
// this INTERFACE but part of the osd IMPLEMENTATION
@@ -232,37 +252,38 @@ public:
virtual void init_subsystems();
virtual bool video_init();
- virtual void video_register();
virtual bool window_init();
- virtual void input_resume();
-
virtual void exit_subsystems();
virtual void video_exit();
virtual void window_exit();
virtual void osd_exit();
- virtual void video_options_add(const char *name, void *type);
-
virtual osd_options &options() { return m_options; }
// osd_output interface ...
- virtual void output_callback(osd_output_channel channel, const util::format_argument_pack<std::ostream> &args) override;
+ virtual void output_callback(osd_output_channel channel, const util::format_argument_pack<char> &args) override;
bool verbose() const { return m_print_verbose; }
virtual void set_verbose(bool print_verbose) override { m_print_verbose = print_verbose; }
void notify(const char *outname, int32_t value) const { m_output->notify(outname, value); }
- static std::list<std::shared_ptr<osd_window>> s_window_list;
+ virtual void process_events() = 0;
+ virtual bool has_focus() const = 0;
+
+ static const std::list<std::unique_ptr<osd_window> > &window_list() { return s_window_list; }
protected:
virtual bool input_init();
- virtual void input_pause();
virtual void build_slider_list() { }
virtual void update_slider_list() { }
+ void poll_input_modules(bool relative_reset);
+
+ static std::list<std::unique_ptr<osd_window> > s_window_list;
+
private:
// internal state
running_machine * m_machine;
@@ -273,28 +294,26 @@ private:
osd_module_manager m_mod_man;
font_module *m_font_module;
- void update_option(const std::string &key, std::vector<const char *> &values);
+ void update_option(const std::string &key, std::vector<std::string_view> const &values);
// FIXME: should be elsewhere
- osd_module *select_module_options(const core_options &opts, const std::string &opt_name)
+ template<class C>
+ C &select_module_options(const std::string &opt_name)
{
- std::string opt_val = opts.exists(opt_name) ? opts.value(opt_name) : "";
- if (opt_val.compare("auto")==0)
+ std::string opt_val = options().exists(opt_name) ? options().value(opt_name) : "";
+ if (opt_val == "auto")
+ {
opt_val = "";
+ }
else if (!m_mod_man.type_has_name(opt_name.c_str(), opt_val.c_str()))
{
osd_printf_warning("Value %s not supported for option %s - falling back to auto\n", opt_val, opt_name);
opt_val = "";
}
- return m_mod_man.select_module(opt_name.c_str(), opt_val.c_str());
- }
-
- template<class C>
- C select_module_options(const core_options &opts, const std::string &opt_name)
- {
- return dynamic_cast<C>(select_module_options(opts, opt_name));
+ return m_mod_man.select_module<C>(*this, options(), opt_name.c_str(), opt_val.c_str());
}
protected:
+ render_module* m_render;
sound_module* m_sound;
debug_module* m_debugger;
midi_module* m_midi;
@@ -308,7 +327,6 @@ protected:
std::vector<ui::menu_item> m_sliders;
private:
- std::vector<const char *> m_video_names;
std::unordered_map<std::string, std::string> m_option_descs;
};
diff --git a/src/osd/modules/midi/midi_module.h b/src/osd/modules/midi/midi_module.h
index 8e64800622e..6ea7290805b 100644
--- a/src/osd/modules/midi/midi_module.h
+++ b/src/osd/modules/midi/midi_module.h
@@ -9,10 +9,12 @@
#pragma once
-#include "osdepend.h"
-#include "modules/osdmodule.h"
+#include "interface/midiport.h"
#include <memory>
+#include <string>
+#include <string_view>
+#include <vector>
//============================================================
@@ -24,12 +26,23 @@
class midi_module
{
public:
- virtual ~midi_module() { }
+ struct port_info
+ {
+ std::string name;
+ bool input;
+ bool output;
+ bool default_input;
+ bool default_output;
+ };
+ using port_info_vector = std::vector<port_info>;
+
+ virtual ~midi_module() = default;
+
// specific routines
- virtual std::unique_ptr<osd_midi_device> create_midi_device() = 0;
- // FIXME: should return a list of strings ...
- virtual void list_midi_devices() = 0;
+ virtual std::unique_ptr<osd::midi_input_port> create_input(std::string_view name) = 0;
+ virtual std::unique_ptr<osd::midi_output_port> create_output(std::string_view name) = 0;
+ virtual port_info_vector list_midi_ports() = 0;
};
#endif // MAME_OSD_MODULES_MIDI_MIDI_MODULE_H
diff --git a/src/osd/modules/midi/none.cpp b/src/osd/modules/midi/none.cpp
index 21837d1be3c..c3dd0aaadc5 100644
--- a/src/osd/modules/midi/none.cpp
+++ b/src/osd/modules/midi/none.cpp
@@ -6,87 +6,36 @@
Empty shim for systems not supporting midi / portmidi
-*******************************************************************c********/
+***************************************************************************/
-#include "osdcore.h"
-#include "modules/osdmodule.h"
#include "midi_module.h"
-class none_module : public osd_module, public midi_module
-{
-public:
+#include "modules/osdmodule.h"
+#include "osdcore.h"
- none_module() : osd_module(OSD_MIDI_PROVIDER, "pm"), midi_module()
- {
- }
- virtual ~none_module() { }
+#include <memory>
- virtual int init(const osd_options &options) override;
- virtual void exit() override;
- virtual std::unique_ptr<osd_midi_device> create_midi_device() override;
- virtual void list_midi_devices() override;
-};
+namespace osd {
+namespace {
-class osd_midi_device_none : public osd_midi_device
+class none_module : public osd_module, public midi_module
{
public:
- virtual ~osd_midi_device_none() { }
- virtual bool open_input(const char *devname) override;
- virtual bool open_output(const char *devname) override;
- virtual void close() override;
- virtual bool poll() override;
- virtual int read(uint8_t *pOut) override;
- virtual void write(uint8_t data) override;
-};
+ none_module() : osd_module(OSD_MIDI_PROVIDER, "none"), midi_module() { }
-std::unique_ptr<osd_midi_device> none_module::create_midi_device()
-{
- return std::make_unique<osd_midi_device_none>();
-}
-
-
-int none_module::init(const osd_options &options)
-{
- return 0;
-}
+ virtual int init(osd_interface &osd, const osd_options &options) override { return 0; }
+ virtual void exit() override { }
-void none_module::exit()
-{
-}
-
-void none_module::list_midi_devices()
-{
- osd_printf_warning("\nMIDI is not supported in this build\n");
-}
-
-bool osd_midi_device_none::open_input(const char *devname)
-{
- return false;
-}
-
-bool osd_midi_device_none::open_output(const char *devname)
-{
- return false;
-}
-
-void osd_midi_device_none::close()
-{
-}
+ virtual std::unique_ptr<midi_input_port> create_input(std::string_view name) override { return nullptr; }
+ virtual std::unique_ptr<midi_output_port> create_output(std::string_view name) override { return nullptr; }
+ virtual port_info_vector list_midi_ports() override { return port_info_vector(); }
+};
-bool osd_midi_device_none::poll()
-{
- return false;
-}
+} // anonymous namespace
-int osd_midi_device_none::read(uint8_t *pOut)
-{
- return 0;
-}
+} // namespace osd
-void osd_midi_device_none::write(uint8_t data)
-{
-}
-MODULE_DEFINITION(MIDI_NONE, none_module)
+MODULE_DEFINITION(MIDI_NONE, osd::none_module)
diff --git a/src/osd/modules/midi/portmidi.cpp b/src/osd/modules/midi/portmidi.cpp
index 9cb5ddac39b..3a1dbf6739d 100644
--- a/src/osd/modules/midi/portmidi.cpp
+++ b/src/osd/modules/midi/portmidi.cpp
@@ -2,18 +2,30 @@
// copyright-holders:R. Belmont
/***************************************************************************
- portmap.c
+ portmidi.cpp
Midi implementation based on portmidi library
*******************************************************************c********/
+#include "midi_module.h"
+
+#include "modules/osdmodule.h"
+
#ifndef NO_USE_MIDI
+#include "interface/midiport.h"
+#include "osdcore.h" // osd_printf_*
+
#include <portmidi.h>
-#include "osdcore.h"
-#include "modules/osdmodule.h"
-#include "midi_module.h"
+
+#include <cstdio>
+#include <cstring>
+
+
+namespace osd {
+
+namespace {
class pm_module : public osd_module, public midi_module
{
@@ -24,48 +36,54 @@ public:
}
virtual ~pm_module() { }
- virtual int init(const osd_options &options)override;
- virtual void exit()override;
+ virtual int init(osd_interface &osd, const osd_options &options) override;
+ virtual void exit() override;
- virtual std::unique_ptr<osd_midi_device> create_midi_device() override;
- virtual void list_midi_devices() override;
+ virtual std::unique_ptr<midi_input_port> create_input(std::string_view name) override;
+ virtual std::unique_ptr<midi_output_port> create_output(std::string_view name) override;
+ virtual port_info_vector list_midi_ports() override;
};
-static const int RX_EVENT_BUF_SIZE = 512;
+static constexpr unsigned RX_EVENT_BUF_SIZE = 512;
-#define MIDI_SYSEX 0xf0
-#define MIDI_EOX 0xf7
+static constexpr uint8_t MIDI_SYSEX = 0xf0;
+static constexpr uint8_t MIDI_EOX = 0xf7;
-class osd_midi_device_pm : public osd_midi_device
+class midi_input_pm : public midi_input_port
{
public:
- osd_midi_device_pm(): pmStream(nullptr), xmit_cnt(0), last_status(0), rx_sysex(false) { }
- virtual ~osd_midi_device_pm() { }
- virtual bool open_input(const char *devname) override;
- virtual bool open_output(const char *devname) override;
- virtual void close() override;
+ midi_input_pm(PortMidiStream *stream) : m_stream(stream), m_rx_sysex(false) { }
+ virtual ~midi_input_pm();
+
virtual bool poll() override;
virtual int read(uint8_t *pOut) override;
- virtual void write(uint8_t data) override;
private:
- PortMidiStream *pmStream;
- PmEvent rx_evBuf[RX_EVENT_BUF_SIZE];
- uint8_t xmit_in[4]; // Pm_Messages mean we can at most have 3 residue bytes
- int xmit_cnt;
- uint8_t last_status;
- bool rx_sysex;
+ PortMidiStream *const m_stream;
+ PmEvent m_evbuf[RX_EVENT_BUF_SIZE];
+ bool m_rx_sysex;
};
-std::unique_ptr<osd_midi_device> pm_module::create_midi_device()
+class midi_output_pm : public midi_output_port
{
- return std::make_unique<osd_midi_device_pm>();
-}
+public:
+ midi_output_pm(PortMidiStream *stream) : m_stream(stream), m_xmit_cnt(0), m_last_status(0) { }
+ virtual ~midi_output_pm();
+
+ virtual void write(uint8_t data) override;
+private:
+ PortMidiStream *const m_stream;
+ uint8_t m_xmit_in[4]; // Pm_Messages mean we can at most have 3 residue bytes
+ int m_xmit_cnt;
+ uint8_t m_last_status;
+};
-int pm_module::init(const osd_options &options)
+
+int pm_module::init(osd_interface &osd, const osd_options &options)
{
+ // FIXME: check error return code
Pm_Initialize();
return 0;
}
@@ -75,151 +93,126 @@ void pm_module::exit()
Pm_Terminate();
}
-void pm_module::list_midi_devices()
+std::unique_ptr<midi_input_port> pm_module::create_input(std::string_view name)
{
- int num_devs = Pm_CountDevices();
- const PmDeviceInfo *pmInfo;
-
- printf("\n");
-
- if (num_devs == 0)
+ int found_dev = -1;
+ if (name == "default")
{
- printf("No MIDI ports were found\n");
- return;
+ found_dev = Pm_GetDefaultInputDeviceID();
}
-
- printf("MIDI input ports:\n");
- for (int i = 0; i < num_devs; i++)
+ else
{
- pmInfo = Pm_GetDeviceInfo(i);
-
- if (pmInfo->input)
+ int const num_devs = Pm_CountDevices();
+ for (found_dev = 0; num_devs > found_dev; ++found_dev)
{
- printf("%s %s\n", pmInfo->name, (i == Pm_GetDefaultInputDeviceID()) ? "(default)" : "");
+ auto const info = Pm_GetDeviceInfo(found_dev);
+ if (info->input && (name == info->name))
+ break;
}
+ if (num_devs <= found_dev)
+ found_dev = -1;
}
- printf("\nMIDI output ports:\n");
- for (int i = 0; i < num_devs; i++)
+ if (0 > found_dev)
{
- pmInfo = Pm_GetDeviceInfo(i);
-
- if (pmInfo->output)
- {
- printf("%s %s\n", pmInfo->name, (i == Pm_GetDefaultOutputDeviceID()) ? "(default)" : "");
- }
+ osd_printf_warning("No MIDI input device named '%s' was found.\n", name);
+ return nullptr;
}
-}
-bool osd_midi_device_pm::open_input(const char *devname)
-{
- int num_devs = Pm_CountDevices();
- int found_dev = -1;
- const PmDeviceInfo *pmInfo;
- PortMidiStream *stm;
-
- if (!strcmp("default", devname))
- {
- found_dev = Pm_GetDefaultInputDeviceID();
- }
- else
+ PortMidiStream *stream = nullptr;
+ PmError const err = Pm_OpenInput(&stream, found_dev, nullptr, RX_EVENT_BUF_SIZE, nullptr, nullptr);
+ if (pmNoError != err)
{
- for (int i = 0; i < num_devs; i++)
- {
- pmInfo = Pm_GetDeviceInfo(i);
-
- if (pmInfo->input)
- {
- if (!strcmp(devname, pmInfo->name))
- {
- found_dev = i;
- break;
- }
- }
- }
+ osd_printf_error("Error opening PortMidi device '%s' for input.\n", name);
+ return nullptr;
}
- if (found_dev >= 0)
+ try
{
- if (Pm_OpenInput(&stm, found_dev, nullptr, RX_EVENT_BUF_SIZE, nullptr, nullptr) == pmNoError)
- {
- pmStream = stm;
- return true;
- }
- else
- {
- printf("Couldn't open PM device\n");
- return false;
- }
+ return std::make_unique<midi_input_pm>(stream);
}
- else
+ catch (...)
{
- return false;
+ Pm_Close(stream);
+ return nullptr;
}
}
-bool osd_midi_device_pm::open_output(const char *devname)
+std::unique_ptr<midi_output_port> pm_module::create_output(std::string_view name)
{
- int num_devs = Pm_CountDevices();
int found_dev = -1;
- const PmDeviceInfo *pmInfo;
- PortMidiStream *stm;
-
- if (!strcmp("default", devname))
+ if (name == "default")
{
found_dev = Pm_GetDefaultOutputDeviceID();
}
else
{
- for (int i = 0; i < num_devs; i++)
+ int const num_devs = Pm_CountDevices();
+ for (found_dev = 0; num_devs > found_dev; ++found_dev)
{
- pmInfo = Pm_GetDeviceInfo(i);
-
- if (pmInfo->output)
- {
- if (!strcmp(devname, pmInfo->name))
- {
- found_dev = i;
- break;
- }
- }
+ auto const info = Pm_GetDeviceInfo(found_dev);
+ if (info->output && (name == info->name))
+ break;
}
+ if (num_devs <= found_dev)
+ found_dev = -1;
}
- if (found_dev >= 0)
+ PortMidiStream *stream = nullptr;
+ PmError const err = Pm_OpenOutput(&stream, found_dev, nullptr, 100, nullptr, nullptr, 0);
+ if (pmNoError != err)
{
- if (Pm_OpenOutput(&stm, found_dev, nullptr, 100, nullptr, nullptr, 0) == pmNoError)
- {
- pmStream = stm;
- return true;
- }
- else
- {
- printf("Couldn't open PM device\n");
- return false;
- }
+ osd_printf_error("Error opening PortMidi device '%s' for output.\n", name);
+ return nullptr;
}
- else
+
+ try
{
- return false;
+ return std::make_unique<midi_output_pm>(stream);
+ }
+ catch (...)
+ {
+ Pm_Close(stream);
+ return nullptr;
}
}
-void osd_midi_device_pm::close()
+midi_module::port_info_vector pm_module::list_midi_ports()
{
- Pm_Close(pmStream);
+ int const num_devs = Pm_CountDevices();
+ int const def_input = Pm_GetDefaultInputDeviceID();
+ int const def_output = Pm_GetDefaultOutputDeviceID();
+ port_info_vector result;
+ result.reserve(num_devs);
+ for (int i = 0; num_devs > i; ++i)
+ {
+ auto const pm_info = Pm_GetDeviceInfo(i);
+ result.emplace_back(port_info{
+ pm_info->name,
+ 0 != pm_info->input,
+ 0 != pm_info->output,
+ def_input == i,
+ def_output == i });
+ }
+ return result;
}
-bool osd_midi_device_pm::poll()
+
+midi_input_pm::~midi_input_pm()
{
- PmError chk = Pm_Poll(pmStream);
+ if (m_stream)
+ Pm_Close(m_stream);
+}
+bool midi_input_pm::poll()
+{
+ PmError const chk = Pm_Poll(m_stream);
return (chk == pmGotData) ? true : false;
}
-int osd_midi_device_pm::read(uint8_t *pOut)
+int midi_input_pm::read(uint8_t *pOut)
{
- int msgsRead = Pm_Read(pmStream, rx_evBuf, RX_EVENT_BUF_SIZE);
+ int msgsRead = Pm_Read(m_stream, m_evbuf, RX_EVENT_BUF_SIZE);
int bytesOut = 0;
if (msgsRead <= 0)
@@ -229,23 +222,23 @@ int osd_midi_device_pm::read(uint8_t *pOut)
for (int msg = 0; msg < msgsRead; msg++)
{
- uint8_t status = Pm_MessageStatus(rx_evBuf[msg].message);
+ uint8_t status = Pm_MessageStatus(m_evbuf[msg].message);
- if (rx_sysex)
+ if (m_rx_sysex)
{
if (status & 0x80) // sys real-time imposing on us?
{
if (status == 0xf2)
{
*pOut++ = status;
- *pOut++ = Pm_MessageData1(rx_evBuf[msg].message);
- *pOut++ = Pm_MessageData2(rx_evBuf[msg].message);
+ *pOut++ = Pm_MessageData1(m_evbuf[msg].message);
+ *pOut++ = Pm_MessageData2(m_evbuf[msg].message);
bytesOut += 3;
}
else if (status == 0xf3)
{
*pOut++ = status;
- *pOut++ = Pm_MessageData1(rx_evBuf[msg].message);
+ *pOut++ = Pm_MessageData1(m_evbuf[msg].message);
bytesOut += 2;
}
else
@@ -254,7 +247,7 @@ int osd_midi_device_pm::read(uint8_t *pOut)
bytesOut++;
if (status == MIDI_EOX)
{
- rx_sysex = false;
+ m_rx_sysex = false;
}
}
}
@@ -262,15 +255,15 @@ int osd_midi_device_pm::read(uint8_t *pOut)
{
for (int i = 0; i < 4; i++)
{
- uint8_t byte = rx_evBuf[msg].message & 0xff;
+ uint8_t byte = m_evbuf[msg].message & 0xff;
*pOut++ = byte;
bytesOut++;
if (byte == MIDI_EOX)
{
- rx_sysex = false;
+ m_rx_sysex = false;
break;
}
- rx_evBuf[msg].message >>= 8;
+ m_evbuf[msg].message >>= 8;
}
}
}
@@ -281,7 +274,7 @@ int osd_midi_device_pm::read(uint8_t *pOut)
case 0xc: // 2-byte messages
case 0xd:
*pOut++ = status;
- *pOut++ = Pm_MessageData1(rx_evBuf[msg].message);
+ *pOut++ = Pm_MessageData1(m_evbuf[msg].message);
bytesOut += 2;
break;
@@ -291,30 +284,30 @@ int osd_midi_device_pm::read(uint8_t *pOut)
case 0: // System Exclusive
{
*pOut++ = status; // this should be OK: the shortest legal sysex is F0 tt dd F7, I believe
- *pOut++ = (rx_evBuf[msg].message>>8) & 0xff;
- *pOut++ = (rx_evBuf[msg].message>>16) & 0xff;
- uint8_t last = *pOut++ = (rx_evBuf[msg].message>>24) & 0xff;
+ *pOut++ = (m_evbuf[msg].message>>8) & 0xff;
+ *pOut++ = (m_evbuf[msg].message>>16) & 0xff;
+ uint8_t last = *pOut++ = (m_evbuf[msg].message>>24) & 0xff;
bytesOut += 4;
- rx_sysex = (last != MIDI_EOX);
+ m_rx_sysex = (last != MIDI_EOX);
break;
}
case 7: // End of System Exclusive
*pOut++ = status;
bytesOut += 1;
- rx_sysex = false;
+ m_rx_sysex = false;
break;
case 2: // song pos
*pOut++ = status;
- *pOut++ = Pm_MessageData1(rx_evBuf[msg].message);
- *pOut++ = Pm_MessageData2(rx_evBuf[msg].message);
+ *pOut++ = Pm_MessageData1(m_evbuf[msg].message);
+ *pOut++ = Pm_MessageData2(m_evbuf[msg].message);
bytesOut += 3;
break;
case 3: // song select
*pOut++ = status;
- *pOut++ = Pm_MessageData1(rx_evBuf[msg].message);
+ *pOut++ = Pm_MessageData1(m_evbuf[msg].message);
bytesOut += 2;
break;
@@ -327,8 +320,8 @@ int osd_midi_device_pm::read(uint8_t *pOut)
default:
*pOut++ = status;
- *pOut++ = Pm_MessageData1(rx_evBuf[msg].message);
- *pOut++ = Pm_MessageData2(rx_evBuf[msg].message);
+ *pOut++ = Pm_MessageData1(m_evbuf[msg].message);
+ *pOut++ = Pm_MessageData2(m_evbuf[msg].message);
bytesOut += 3;
break;
}
@@ -338,57 +331,64 @@ int osd_midi_device_pm::read(uint8_t *pOut)
return bytesOut;
}
-void osd_midi_device_pm::write(uint8_t data)
+
+midi_output_pm::~midi_output_pm()
+{
+ if (m_stream)
+ Pm_Close(m_stream);
+}
+
+void midi_output_pm::write(uint8_t data)
{
int bytes_needed = 0;
PmEvent ev;
ev.timestamp = 0; // use the current time
-// printf("write: %02x (%d)\n", data, xmit_cnt);
+// printf("write: %02x (%d)\n", data, m_xmit_cnt);
// reject data bytes when no valid status exists
- if ((last_status == 0) && !(data & 0x80))
+ if ((m_last_status == 0) && !(data & 0x80))
{
- xmit_cnt = 0;
+ m_xmit_cnt = 0;
return;
}
- if (xmit_cnt >= 4)
+ if (m_xmit_cnt >= 4)
{
printf("MIDI out: packet assembly overflow, contact MAMEdev!\n");
return;
}
// handle sysex
- if (last_status == MIDI_SYSEX)
+ if (m_last_status == MIDI_SYSEX)
{
-// printf("sysex: %02x (%d)\n", data, xmit_cnt);
+// printf("sysex: %02x (%d)\n", data, m_xmit_cnt);
// if we get a status that isn't sysex, assume it's system common
if ((data & 0x80) && (data != MIDI_EOX))
{
// printf("common during sysex!\n");
ev.message = Pm_Message(data, 0, 0);
- Pm_Write(pmStream, &ev, 1);
+ Pm_Write(m_stream, &ev, 1);
return;
}
- xmit_in[xmit_cnt++] = data;
+ m_xmit_in[m_xmit_cnt++] = data;
// if EOX or 4 bytes filled, transmit 4 bytes
- if ((xmit_cnt == 4) || (data == MIDI_EOX))
+ if ((m_xmit_cnt == 4) || (data == MIDI_EOX))
{
- ev.message = xmit_in[0] | (xmit_in[1]<<8) | (xmit_in[2]<<16) | (xmit_in[3]<<24);
- Pm_Write(pmStream, &ev, 1);
- xmit_in[0] = xmit_in[1] = xmit_in[2] = xmit_in[3] = 0;
- xmit_cnt = 0;
+ ev.message = m_xmit_in[0] | (m_xmit_in[1]<<8) | (m_xmit_in[2]<<16) | (m_xmit_in[3]<<24);
+ Pm_Write(m_stream, &ev, 1);
+ m_xmit_in[0] = m_xmit_in[1] = m_xmit_in[2] = m_xmit_in[3] = 0;
+ m_xmit_cnt = 0;
// printf("SysEx packet: %08x\n", ev.message);
// if this is EOX, kill the running status
if (data == MIDI_EOX)
{
- last_status = 0;
+ m_last_status = 0;
}
}
@@ -396,33 +396,33 @@ void osd_midi_device_pm::write(uint8_t data)
}
// handle running status. don't allow system real-time messages to be considered as running status.
- if ((xmit_cnt == 0) && (data & 0x80) && (data < 0xf8))
+ if ((m_xmit_cnt == 0) && (data & 0x80) && (data < 0xf8))
{
- last_status = data;
+ m_last_status = data;
}
- if ((xmit_cnt == 0) && !(data & 0x80))
+ if ((m_xmit_cnt == 0) && !(data & 0x80))
{
- xmit_in[xmit_cnt++] = last_status;
- xmit_in[xmit_cnt++] = data;
-// printf("\trunning status: [%d] = %02x, [%d] = %02x, last_status = %02x\n", xmit_cnt-2, last_status, xmit_cnt-1, data, last_status);
+ m_xmit_in[m_xmit_cnt++] = m_last_status;
+ m_xmit_in[m_xmit_cnt++] = data;
+// printf("\trunning status: [%d] = %02x, [%d] = %02x, m_last_status = %02x\n", m_xmit_cnt-2, m_last_status, m_xmit_cnt-1, data, m_last_status);
}
else
{
- xmit_in[xmit_cnt++] = data;
-// printf("\tNRS: [%d] = %02x\n", xmit_cnt-1, data);
+ m_xmit_in[m_xmit_cnt++] = data;
+// printf("\tNRS: [%d] = %02x\n", m_xmit_cnt-1, data);
}
- if ((xmit_cnt == 1) && (xmit_in[0] == MIDI_SYSEX))
+ if ((m_xmit_cnt == 1) && (m_xmit_in[0] == MIDI_SYSEX))
{
// printf("Start SysEx!\n");
- last_status = MIDI_SYSEX;
+ m_last_status = MIDI_SYSEX;
return;
}
// are we there yet?
-// printf("status check: %02x\n", xmit_in[0]);
- switch ((xmit_in[0]>>4) & 0xf)
+// printf("status check: %02x\n", m_xmit_in[0]);
+ switch ((m_xmit_in[0]>>4) & 0xf)
{
case 0xc: // 2-byte messages
case 0xd:
@@ -430,7 +430,7 @@ void osd_midi_device_pm::write(uint8_t data)
break;
case 0xf: // system common
- switch (xmit_in[0] & 0xf)
+ switch (m_xmit_in[0] & 0xf)
{
case 0: // System Exclusive is handled above
break;
@@ -455,20 +455,24 @@ void osd_midi_device_pm::write(uint8_t data)
break;
}
- if (xmit_cnt == bytes_needed)
+ if (m_xmit_cnt == bytes_needed)
{
- ev.message = Pm_Message(xmit_in[0], xmit_in[1], xmit_in[2]);
- Pm_Write(pmStream, &ev, 1);
- xmit_cnt = 0;
+ ev.message = Pm_Message(m_xmit_in[0], m_xmit_in[1], m_xmit_in[2]);
+ Pm_Write(m_stream, &ev, 1);
+ m_xmit_cnt = 0;
}
}
+
+} // anonymous namespace
+
+} // namespace osd
+
#else
- #include "modules/osdmodule.h"
- #include "midi_module.h"
- MODULE_NOT_SUPPORTED(pm_module, OSD_MIDI_PROVIDER, "pm")
+namespace osd { namespace { MODULE_NOT_SUPPORTED(pm_module, OSD_MIDI_PROVIDER, "pm") } }
+
#endif
-MODULE_DEFINITION(MIDI_PM, pm_module)
+MODULE_DEFINITION(MIDI_PM, osd::pm_module)
diff --git a/src/osd/modules/monitor/monitor_common.cpp b/src/osd/modules/monitor/monitor_common.cpp
index baa80ed7f66..f6a338d327c 100644
--- a/src/osd/modules/monitor/monitor_common.cpp
+++ b/src/osd/modules/monitor/monitor_common.cpp
@@ -96,7 +96,7 @@ float monitor_module_base::get_aspect(const char* defdata, const char* data, int
return float(num) / float(den);
}
-int monitor_module_base::init(const osd_options& options)
+int monitor_module_base::init(osd_interface &osd, const osd_options &options)
{
if (!m_initialized)
{
diff --git a/src/osd/modules/monitor/monitor_common.h b/src/osd/modules/monitor/monitor_common.h
index c8257c36e74..4b1d17d2f1f 100644
--- a/src/osd/modules/monitor/monitor_common.h
+++ b/src/osd/modules/monitor/monitor_common.h
@@ -4,11 +4,17 @@
* monitor_common.h
*
*/
-#ifndef __MONITOR_COMMON_H__
-#define __MONITOR_COMMON_H__
+#ifndef MAME_OSD_MONITOR_MONITOR_COMMON_H
+#define MAME_OSD_MONITOR_MONITOR_COMMON_H
+
+#pragma once
#include "monitor_module.h"
+
+#include <cstdint>
#include <map>
+#include <memory>
+
//============================================================
// monitor_module_base
@@ -16,32 +22,30 @@
class monitor_module_base : public monitor_module
{
-private:
- std::map<std::uint64_t, std::shared_ptr<osd_monitor_info>> m_monitor_index;
-
-protected:
- bool m_initialized;
-
public:
- monitor_module_base(const char* type, const char* name)
- : monitor_module(type, name),
- m_initialized(false)
+ monitor_module_base(const char* type, const char* name) :
+ monitor_module(type, name),
+ m_initialized(false)
{
}
std::shared_ptr<osd_monitor_info> pick_monitor(osd_options& options, int index) override;
std::shared_ptr<osd_monitor_info> monitor_from_handle(std::uint64_t handle) override;
- int init(const osd_options& options) override;
+ int init(osd_interface &osd, const osd_options& options) override;
void exit() override;
protected:
- virtual int init_internal(const osd_options& options) = 0;
+ virtual int init_internal(const osd_options &options) = 0;
void add_monitor(std::shared_ptr<osd_monitor_info> monitor);
+ bool m_initialized;
+
private:
- std::shared_ptr<osd_monitor_info> pick_monitor_internal(osd_options& options, int index);
static float get_aspect(const char *defdata, const char *data, int report_error);
+
+ std::map<std::uint64_t, std::shared_ptr<osd_monitor_info> > m_monitor_index;
+ std::shared_ptr<osd_monitor_info> pick_monitor_internal(osd_options& options, int index);
};
-#endif
+#endif // MAME_OSD_MONITOR_MONITOR_COMMON_H
diff --git a/src/osd/modules/monitor/monitor_module.h b/src/osd/modules/monitor/monitor_module.h
index 3244e7fd42b..38e7e02fec2 100644
--- a/src/osd/modules/monitor/monitor_module.h
+++ b/src/osd/modules/monitor/monitor_module.h
@@ -8,6 +8,7 @@
#ifndef MAME_OSD_MODULES_MONITOR_MONITORMODULE_H
#define MAME_OSD_MODULES_MONITOR_MONITORMODULE_H
+#include <cstdint>
#include <vector>
#include "modules/osdmodule.h"
@@ -53,7 +54,7 @@ public:
float aspect() const { return m_aspect; }
float pixel_aspect() const { return m_aspect / (float(m_pos_size.width()) / float(m_pos_size.height())); }
- void update_resolution(const int new_width, const int new_height) const { m_pos_size.resize(new_width, new_height); }
+ void update_resolution(const int new_width, const int new_height) { m_pos_size = m_pos_size.resize(new_width, new_height); }
void set_aspect(const float a) { m_aspect = a; }
bool is_primary() const { return m_is_primary; }
diff --git a/src/osd/modules/monitor/monitor_sdl.cpp b/src/osd/modules/monitor/monitor_sdl.cpp
index 13f1b847693..679c7a4f97d 100644
--- a/src/osd/modules/monitor/monitor_sdl.cpp
+++ b/src/osd/modules/monitor/monitor_sdl.cpp
@@ -10,14 +10,19 @@
#if defined(OSD_SDL)
-#include <algorithm>
-#include <SDL2/SDL.h>
+#include "monitor_common.h"
+#include "modules/lib/osdobj_common.h"
#include "modules/osdwindow.h"
-#include "monitor_common.h"
+
#include "osdcore.h"
#include "window.h"
+#include <SDL2/SDL.h>
+
+#include <algorithm>
+
+
inline osd_rect SDL_Rect_to_osd_rect(const SDL_Rect &r)
{
return osd_rect(r.x, r.y, r.w, r.h);
diff --git a/src/osd/modules/netdev/netdev_module.h b/src/osd/modules/netdev/netdev_module.h
index b1d537cacf5..b102e56fbb8 100644
--- a/src/osd/modules/netdev/netdev_module.h
+++ b/src/osd/modules/netdev/netdev_module.h
@@ -4,25 +4,23 @@
* netdev_module.h
*
*/
+#ifndef MAME_OSD_NETDEV_NETDEV_MODULE_H
+#define MAME_OSD_NETDEV_NETDEV_MODULE_H
-#ifndef NETDEV_MODULE_H_
-#define NETDEV_MODULE_H_
+#pragma once
-#include "osdepend.h"
-#include "modules/osdmodule.h"
//============================================================
// CONSTANTS
//============================================================
-#define OSD_NETDEV_PROVIDER "netdevprovider"
+#define OSD_NETDEV_PROVIDER "networkprovider"
class netdev_module
{
public:
- virtual ~netdev_module() { }
+ virtual ~netdev_module() = default;
// no specific routines below ... may change
};
-
-#endif /* NETDEV_MODULE_H_ */
+#endif // MAME_OSD_NETDEV_NETDEV_MODULE_H
diff --git a/src/osd/modules/netdev/none.cpp b/src/osd/modules/netdev/none.cpp
index a5b520f26a5..8441c002802 100644
--- a/src/osd/modules/netdev/none.cpp
+++ b/src/osd/modules/netdev/none.cpp
@@ -4,20 +4,28 @@
* none.c
*
*/
-
#include "netdev_module.h"
+
#include "modules/osdmodule.h"
+
+namespace osd {
+
+namespace {
+
class netdev_none : public osd_module, public netdev_module
{
public:
- netdev_none()
- : osd_module(OSD_NETDEV_PROVIDER, "none"), netdev_module()
+ netdev_none() : osd_module(OSD_NETDEV_PROVIDER, "none"), netdev_module()
{
}
virtual ~netdev_none() { }
- virtual int init(const osd_options &options) override { return 0; }
+ virtual int init(osd_interface &osd, const osd_options &options) override { return 0; }
};
-MODULE_DEFINITION(NETDEV_NONE, netdev_none)
+} // anonymous namespace
+
+} // namespace osd
+
+MODULE_DEFINITION(NETDEV_NONE, osd::netdev_none)
diff --git a/src/osd/modules/netdev/pcap.cpp b/src/osd/modules/netdev/pcap.cpp
index 2ae32df0f3b..77ca557f1de 100644
--- a/src/osd/modules/netdev/pcap.cpp
+++ b/src/osd/modules/netdev/pcap.cpp
@@ -1,13 +1,17 @@
// license:BSD-3-Clause
// copyright-holders:Carl
-#if defined(OSD_NET_USE_PCAP)
-
-#include "emu.h"
-#include "osdnet.h"
#include "netdev_module.h"
+
#include "modules/osdmodule.h"
+
+#if defined(OSD_NET_USE_PCAP)
+
#include "modules/lib/osdlib.h"
+#include "osdnet.h"
+#include "osdcore.h" // osd_printf_*
+
+#include "util/strformat.h" // string_format
#if defined(SDLMAME_WIN32) || defined(OSD_WINDOWS)
#include <windows.h>
@@ -25,6 +29,10 @@
#include <pcap.h>
+namespace osd {
+
+namespace {
+
// Typedefs for dynamically loaded functions
typedef int (*pcap_findalldevs_fn)(pcap_if_t **, char *);
typedef pcap_t *(*pcap_open_live_fn)(const char *, int, int, int, char *);
@@ -48,7 +56,7 @@ public:
virtual ~pcap_module() { }
- virtual int init(const osd_options &options) override;
+ virtual int init(osd_interface &osd, const osd_options &options) override;
virtual void exit() override;
virtual bool probe() override
@@ -93,7 +101,8 @@ public:
static pcap_module *module = nullptr;
#ifdef SDLMAME_MACOSX
-struct netdev_pcap_context {
+struct netdev_pcap_context
+{
uint8_t *pkt;
int len;
pcap_t *p;
@@ -105,16 +114,18 @@ struct netdev_pcap_context {
};
#endif
-class netdev_pcap : public osd_netdev
+class netdev_pcap : public osd_network_device
{
public:
- netdev_pcap(const char *name, class device_network_interface *ifdev, int rate);
+ netdev_pcap(const char *name, network_handler &ifdev);
~netdev_pcap();
virtual int send(uint8_t *buf, int len) override;
- virtual void set_mac(const char *mac) override;
+ virtual void set_mac(const uint8_t *mac) override;
+
protected:
virtual int recv_dev(uint8_t **buf) override;
+
private:
pcap_t *m_p;
#ifdef SDLMAME_MACOSX
@@ -124,7 +135,8 @@ private:
};
#ifdef SDLMAME_MACOSX
-static void netdev_pcap_handler(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes) {
+static void netdev_pcap_handler(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes)
+{
struct netdev_pcap_context *ctx = (struct netdev_pcap_context*)user;
if(!ctx->p) return;
@@ -149,8 +161,8 @@ static void *netdev_pcap_blocker(void *arg) {
}
#endif
-netdev_pcap::netdev_pcap(const char *name, class device_network_interface *ifdev, int rate)
- : osd_netdev(ifdev, rate)
+netdev_pcap::netdev_pcap(const char *name, network_handler &ifdev)
+ : osd_network_device(ifdev)
{
char errbuf[PCAP_ERRBUF_SIZE];
#if defined(SDLMAME_WIN32) || defined(OSD_WINDOWS)
@@ -170,7 +182,7 @@ netdev_pcap::netdev_pcap(const char *name, class device_network_interface *ifdev
m_p = nullptr;
return;
}
- netdev_pcap::set_mac(get_mac());
+ netdev_pcap::set_mac(&get_mac()[0]);
#ifdef SDLMAME_MACOSX
m_ctx.head = 0;
@@ -180,17 +192,16 @@ netdev_pcap::netdev_pcap(const char *name, class device_network_interface *ifdev
#endif
}
-void netdev_pcap::set_mac(const char *mac)
+void netdev_pcap::set_mac(const uint8_t *mac)
{
- char filter[256];
struct bpf_program fp;
if(!m_p) return;
#ifdef SDLMAME_MACOSX
- sprintf(filter, "not ether src %.2X:%.2X:%.2X:%.2X:%.2X:%.2X and (ether dst %.2X:%.2X:%.2X:%.2X:%.2X:%.2X or ether multicast or ether broadcast or ether dst 09:00:07:ff:ff:ff)", (unsigned char)mac[0], (unsigned char)mac[1], (unsigned char)mac[2],(unsigned char)mac[3], (unsigned char)mac[4], (unsigned char)mac[5], (unsigned char)mac[0], (unsigned char)mac[1], (unsigned char)mac[2],(unsigned char)mac[3], (unsigned char)mac[4], (unsigned char)mac[5]);
+ auto filter = util::string_format("not ether src %02X:%02X:%02X:%02X:%02X:%02X and (ether dst %02X:%02X:%02X:%02X:%02X:%02X or ether multicast or ether broadcast or ether dst 09:00:07:ff:ff:ff)", (unsigned char)mac[0], (unsigned char)mac[1], (unsigned char)mac[2],(unsigned char)mac[3], (unsigned char)mac[4], (unsigned char)mac[5], (unsigned char)mac[0], (unsigned char)mac[1], (unsigned char)mac[2],(unsigned char)mac[3], (unsigned char)mac[4], (unsigned char)mac[5]);
#else
- sprintf(filter, "ether dst %.2X:%.2X:%.2X:%.2X:%.2X:%.2X or ether multicast or ether broadcast", (unsigned char)mac[0], (unsigned char)mac[1], (unsigned char)mac[2],(unsigned char)mac[3], (unsigned char)mac[4], (unsigned char)mac[5]);
+ auto filter = util::string_format("ether dst %02X:%02X:%02X:%02X:%02X:%02X or ether multicast or ether broadcast", (unsigned char)mac[0], (unsigned char)mac[1], (unsigned char)mac[2],(unsigned char)mac[3], (unsigned char)mac[4], (unsigned char)mac[5]);
#endif
- if ((*module->pcap_compile_dl)(m_p, &fp, filter, 1, 0) == -1) {
+ if ((*module->pcap_compile_dl)(m_p, &fp, filter.c_str(), 1, 0) == -1) {
osd_printf_error("Error with pcap_compile\n");
}
if ((*module->pcap_setfilter_dl)(m_p, &fp) == -1) {
@@ -250,11 +261,11 @@ netdev_pcap::~netdev_pcap()
static CREATE_NETDEV(create_pcap)
{
- auto *dev = new netdev_pcap(ifname, ifdev, rate);
- return dynamic_cast<osd_netdev *>(dev);
+ auto *dev = new netdev_pcap(ifname, ifdev);
+ return dynamic_cast<osd_network_device *>(dev);
}
-int pcap_module::init(const osd_options &options)
+int pcap_module::init(osd_interface &osd, const osd_options &options)
{
pcap_if_t *devs;
char errbuf[PCAP_ERRBUF_SIZE];
@@ -285,12 +296,15 @@ void pcap_module::exit()
clear_netdev();
}
+} // anonymous namespace
+
+} // namespace osd
+
#else
- #include "modules/osdmodule.h"
- #include "netdev_module.h"
- MODULE_NOT_SUPPORTED(pcap_module, OSD_NETDEV_PROVIDER, "pcap")
+namespace osd { namespace { MODULE_NOT_SUPPORTED(pcap_module, OSD_NETDEV_PROVIDER, "pcap") } }
+
#endif
-MODULE_DEFINITION(NETDEV_PCAP, pcap_module)
+MODULE_DEFINITION(NETDEV_PCAP, osd::pcap_module)
diff --git a/src/osd/modules/netdev/taptun.cpp b/src/osd/modules/netdev/taptun.cpp
index c0d99ec750c..a2953f33efc 100644
--- a/src/osd/modules/netdev/taptun.cpp
+++ b/src/osd/modules/netdev/taptun.cpp
@@ -1,5 +1,9 @@
// license:BSD-3-Clause
// copyright-holders:Carl
+#include "netdev_module.h"
+
+#include "modules/osdmodule.h"
+
#if defined(OSD_NET_USE_TAPTUN)
#if defined(_WIN32)
@@ -13,12 +17,13 @@
#include <cerrno>
#endif
-#include "emu.h"
+#include "osdcore.h" // osd_printf_verbose
+#include "osdfile.h" // PATH_SEPARATOR
#include "osdnet.h"
-#include "modules/osdmodule.h"
-#include "netdev_module.h"
#include "unicode.h"
+#include "util/hashing.h" // crc32_creator
+
#ifdef __linux__
#define IFF_TAP 0x0002
#define IFF_NO_PI 0x1000
@@ -31,6 +36,10 @@
#define PRODUCT_TAP_WIN_COMPONENT_ID "tap0901"
#endif
+namespace osd {
+
+namespace {
+
// Ethernet minimum frame length
static constexpr int ETHERNET_MIN_FRAME = 64;
@@ -43,7 +52,7 @@ public:
}
virtual ~taptun_module() { }
- virtual int init(const osd_options &options);
+ virtual int init(osd_interface &osd, const osd_options &options);
virtual void exit();
virtual bool probe() { return true; }
@@ -51,16 +60,18 @@ public:
-class netdev_tap : public osd_netdev
+class netdev_tap : public osd_network_device
{
public:
- netdev_tap(const char *name, class device_network_interface *ifdev, int rate);
+ netdev_tap(const char *name, network_handler &ifdev);
~netdev_tap();
int send(uint8_t *buf, int len) override;
- void set_mac(const char *mac) override;
+ void set_mac(const uint8_t *mac) override;
+
protected:
int recv_dev(uint8_t **buf) override;
+
private:
#if defined(_WIN32)
HANDLE m_handle = INVALID_HANDLE_VALUE;
@@ -74,8 +85,8 @@ private:
uint8_t m_buf[2048];
};
-netdev_tap::netdev_tap(const char *name, class device_network_interface *ifdev, int rate)
- : osd_netdev(ifdev, rate)
+netdev_tap::netdev_tap(const char *name, network_handler &ifdev)
+ : osd_network_device(ifdev)
{
#ifdef __linux__
struct ifreq ifr;
@@ -134,7 +145,7 @@ netdev_tap::~netdev_tap()
#endif
}
-void netdev_tap::set_mac(const char *mac)
+void netdev_tap::set_mac(const uint8_t *mac)
{
memcpy(m_mac, mac, 6);
}
@@ -286,16 +297,21 @@ static std::vector<std::wstring> get_tap_adapters()
// check if the ComponentId value indicates a TAP-Windows adapter
if (RegQueryValueExW(unit_key, L"ComponentId", NULL, &data_type, LPBYTE(component_id), &component_id_len) == ERROR_SUCCESS
- && data_type == REG_SZ
- && safe_string(component_id, component_id_len) == L"" PRODUCT_TAP_WIN_COMPONENT_ID)
+ && data_type == REG_SZ)
{
- WCHAR net_cfg_instance_id[MAX_PATH];
- DWORD net_cfg_instance_id_len = sizeof(net_cfg_instance_id);
-
- // add the adapter to the result
- if (RegQueryValueExW(unit_key, L"NetCfgInstanceId", NULL, &data_type, LPBYTE(net_cfg_instance_id), &net_cfg_instance_id_len) == ERROR_SUCCESS
- && data_type == REG_SZ)
- result.push_back(safe_string(net_cfg_instance_id, net_cfg_instance_id_len));
+ std::wstring const value(safe_string(component_id, component_id_len));
+
+ // some older versions may not set the "root\" prefix
+ if (value == L"root\\" PRODUCT_TAP_WIN_COMPONENT_ID || value == L"" PRODUCT_TAP_WIN_COMPONENT_ID)
+ {
+ WCHAR net_cfg_instance_id[MAX_PATH];
+ DWORD net_cfg_instance_id_len = sizeof(net_cfg_instance_id);
+
+ // add the adapter to the result
+ if (RegQueryValueExW(unit_key, L"NetCfgInstanceId", NULL, &data_type, LPBYTE(net_cfg_instance_id), &net_cfg_instance_id_len) == ERROR_SUCCESS
+ && data_type == REG_SZ)
+ result.push_back(safe_string(net_cfg_instance_id, net_cfg_instance_id_len));
+ }
}
RegCloseKey(unit_key);
@@ -326,7 +342,7 @@ int netdev_tap::recv_dev(uint8_t **buf)
// are in promiscuous mode or got a packet with our mac.
do {
len = read(m_fd, m_buf, sizeof(m_buf));
- } while((len > 0) && memcmp(get_mac(), m_buf, 6) && !get_promisc() && !(m_buf[0] & 1));
+ } while((len > 0) && memcmp(&get_mac()[0], m_buf, 6) && !get_promisc() && !(m_buf[0] & 1));
if (len > 0)
len = finalise_frame(m_buf, len);
@@ -338,11 +354,11 @@ int netdev_tap::recv_dev(uint8_t **buf)
static CREATE_NETDEV(create_tap)
{
- auto *dev = new netdev_tap(ifname, ifdev, rate);
- return dynamic_cast<osd_netdev *>(dev);
+ auto *dev = new netdev_tap(ifname, ifdev);
+ return dynamic_cast<osd_network_device *>(dev);
}
-int taptun_module::init(const osd_options &options)
+int taptun_module::init(osd_interface &osd, const osd_options &options)
{
#if defined(_WIN32)
for (std::wstring &id : get_tap_adapters())
@@ -358,13 +374,16 @@ void taptun_module::exit()
clear_netdev();
}
+} // anonymous namespace
+
+} // namespace osd
+
#else
- #include "modules/osdmodule.h"
- #include "netdev_module.h"
- MODULE_NOT_SUPPORTED(taptun_module, OSD_NETDEV_PROVIDER, "taptun")
+namespace osd { namespace { MODULE_NOT_SUPPORTED(taptun_module, OSD_NETDEV_PROVIDER, "taptun") } }
+
#endif
-MODULE_DEFINITION(NETDEV_TAPTUN, taptun_module)
+MODULE_DEFINITION(NETDEV_TAPTUN, osd::taptun_module)
diff --git a/src/osd/modules/opengl/gl_shader_mgr.cpp b/src/osd/modules/opengl/gl_shader_mgr.cpp
index ea09a7fa6a3..4567a8e8085 100644
--- a/src/osd/modules/opengl/gl_shader_mgr.cpp
+++ b/src/osd/modules/opengl/gl_shader_mgr.cpp
@@ -1,13 +1,17 @@
// license:BSD-3-Clause
// copyright-holders:Sven Gothel
-#include <cstdio> /* snprintf */
-#include <cstdlib> /* malloc */
+
+#include "gl_shader_mgr.h"
#include "osdcomm.h"
-#include "osd_opengl.h"
-#include "gl_shader_mgr.h"
-#include "gl_shader_tool.h"
+#include "util/strformat.h"
+
+#include <algorithm>
+#include <iterator>
+
+
+namespace {
#define GLSL_VERTEX_SHADER_INT_NUMBER 1 // general
#define GLSL_VERTEX_SHADER_MAX_NUMBER 2 // general + custom
@@ -15,16 +19,16 @@
#ifdef GLSL_SOURCE_ON_DISK
-static char const *const glsl_mamebm_vsh_files [GLSL_VERTEX_SHADER_INT_NUMBER] =
+static char const *const glsl_mamebm_vsh_files[GLSL_VERTEX_SHADER_INT_NUMBER] =
{
- "/tmp/glsl_general.vsh" // general
+ "/tmp/glsl_general.vsh" // general
};
-static char const *const glsl_mamebm_fsh_files [GLSL_SHADER_FEAT_INT_NUMBER] =
+static char const *const glsl_mamebm_fsh_files[glsl_shader_info::FEAT_INT_NUMBER] =
{
- "/tmp/glsl_plain_rgb32_dir.fsh", // rgb32 dir plain
- "/tmp/glsl_bilinear_rgb32_dir.fsh", // rgb32 dir bilinear
- "/tmp/glsl_bicubic_rgb32_dir.fsh", // rgb32 dir bicubic
+ "/tmp/glsl_plain_rgb32_dir.fsh", // rgb32 dir plain
+ "/tmp/glsl_bilinear_rgb32_dir.fsh", // rgb32 dir bilinear
+ "/tmp/glsl_bicubic_rgb32_dir.fsh", // rgb32 dir bicubic
};
#else // GLSL_SOURCE_ON_DISK
@@ -35,207 +39,239 @@ static char const *const glsl_mamebm_fsh_files [GLSL_SHADER_FEAT_INT_NUMBER] =
#include "shader/glsl_bilinear_rgb32_dir.fsh.c"
#include "shader/glsl_bicubic_rgb32_dir.fsh.c"
-static char const *const glsl_mamebm_vsh_sources [GLSL_VERTEX_SHADER_INT_NUMBER] =
+static char const *const glsl_mamebm_vsh_sources[GLSL_VERTEX_SHADER_INT_NUMBER] =
{
- glsl_general_vsh_src // general
+ glsl_general_vsh_src // general
};
-static char const *const glsl_mamebm_fsh_sources [GLSL_SHADER_FEAT_INT_NUMBER] =
+static char const *const glsl_mamebm_fsh_sources[glsl_shader_info::FEAT_INT_NUMBER] =
{
- glsl_plain_rgb32_dir_fsh_src, // rgb32 dir plain
- glsl_bilinear_rgb32_dir_fsh_src, // rgb32 dir bilinear
- glsl_bicubic_rgb32_dir_fsh_src, // rgb32 dir bicubic
+ glsl_plain_rgb32_dir_fsh_src, // rgb32 dir plain
+ glsl_bilinear_rgb32_dir_fsh_src, // rgb32 dir bilinear
+ glsl_bicubic_rgb32_dir_fsh_src, // rgb32 dir bicubic
};
#endif // GLSL_SOURCE_ON_DISK
-static char const *const glsl_mamebm_filter_names [GLSL_SHADER_FEAT_MAX_NUMBER] =
-{
- "plain",
- "bilinear",
- "bicubic",
- "custom"
-};
-
-static GLhandleARB glsl_mamebm_programs [GLSL_SHADER_FEAT_MAX_NUMBER+9] =
-{
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* rgb32 dir: plain, bilinear, bicubic, custom0-9, .. */
-};
+static char const *const glsl_mamebm_filter_names[glsl_shader_info::FEAT_MAX_NUMBER]{
+ "plain",
+ "bilinear",
+ "bicubic",
+ "custom" };
/**
* fragment shader -> vertex shader mapping
*/
-static int glsl_mamebm_fsh2vsh[GLSL_SHADER_FEAT_MAX_NUMBER] =
+static const int glsl_mamebm_fsh2vsh[glsl_shader_info::FEAT_MAX_NUMBER] =
{
0, // plain -> general
0, // bilinear -> general
0, // bicubic -> general
- 1, // custom -> custom
-};
-
-static GLhandleARB glsl_mamebm_vsh_shader[GLSL_VERTEX_SHADER_MAX_NUMBER+9] =
-{
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-}; /* general, custom0-9 */
-
-static GLhandleARB glsl_mamebm_fsh_shader [GLSL_SHADER_FEAT_MAX_NUMBER+9] =
-{
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* rgb32 dir: plain, bilinear, bicubic, custom0-9 */
+ 1, // custom -> custom
};
-static GLhandleARB glsl_scrn_programs [10] =
-{
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* rgb32: custom0-9, .. */
-};
-
-static GLhandleARB glsl_scrn_vsh_shader[10] =
-{
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-}; /* custom0-9 */
-
-static GLhandleARB glsl_scrn_fsh_shader [10] =
-{
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-}; /* rgb32: custom0-9 */
-
-const char * glsl_shader_get_filter_name_mamebm(int glslShaderFeature)
-{
- if ( !(0 <= glslShaderFeature && glslShaderFeature < GLSL_SHADER_FEAT_MAX_NUMBER) )
- return "illegal shader feature";
-
- return glsl_mamebm_filter_names[glslShaderFeature];
-}
-
-GLhandleARB glsl_shader_get_program_mamebm(int glslShaderFeature, int idx)
-{
- if ( !(0 <= glslShaderFeature && glslShaderFeature < GLSL_SHADER_FEAT_MAX_NUMBER) )
- return 0;
-
- return glsl_mamebm_programs[glslShaderFeature+idx];
-}
-
-GLhandleARB glsl_shader_get_program_scrn(int idx)
+class glsl_shader_impl : public glsl_shader_info
{
- if ( !(0 <= idx && idx < 10) )
- return 0;
+public:
+ glsl_shader_impl(
+#if defined(USE_DISPATCH_GL)
+ osd_gl_dispatch *gld
+#endif
+ )
+#if defined(USE_DISPATCH_GL)
+ : glsl_shader_info(gld)
+#endif
+ {
+ std::fill(std::begin(mamebm_programs), std::end(mamebm_programs), GLhandleARB(0));
+ std::fill(std::begin(mamebm_vsh_shader), std::end(mamebm_vsh_shader), GLhandleARB(0));
+ std::fill(std::begin(mamebm_fsh_shader), std::end(mamebm_fsh_shader), GLhandleARB(0));
+ std::fill(std::begin(scrn_programs), std::end(scrn_programs), GLhandleARB(0));
+ std::fill(std::begin(scrn_vsh_shader), std::end(scrn_vsh_shader), GLhandleARB(0));
+ std::fill(std::begin(scrn_fsh_shader), std::end(scrn_fsh_shader), GLhandleARB(0));
+ }
- return glsl_scrn_programs[idx];
-}
+ bool initalize(osd_gl_context &gl_ctx)
+ {
+ if (!load_extension(gl_ctx))
+ return false;
-glsl_shader_info *glsl_shader_init(osd_gl_context *gl_ctx)
-{
- int i,j, err;
+ int err = 0;
- err = gl_shader_loadExtention(gl_ctx);
- if(err) return nullptr;
+ for (int i = 0; !err && (i < GLSL_VERTEX_SHADER_INT_NUMBER); i++)
+ {
+#ifdef GLSL_SOURCE_ON_DISK
+ if (glsl_mamebm_vsh_files[i])
+ err = compile_file(
+ &mamebm_vsh_shader[i],
+ GL_VERTEX_SHADER_ARB,
+ glsl_mamebm_vsh_files[i],
+ false);
+#else
+ if (glsl_mamebm_vsh_sources[i])
+ err = compile_source(
+ &mamebm_vsh_shader[i],
+ GL_VERTEX_SHADER_ARB,
+ glsl_mamebm_vsh_sources[i],
+ false);
+#endif
+ }
+ if (err)
+ return false;
+
+ for (int j = 0; !err && (j < FEAT_INT_NUMBER); j++)
+ {
+#ifdef GLSL_SOURCE_ON_DISK
+ if (glsl_mamebm_fsh_files[j])
+ err = compile_files(
+ &mamebm_programs[j],
+ &mamebm_vsh_shader[glsl_mamebm_fsh2vsh[j]],
+ &mamebm_fsh_shader[j],
+ nullptr, // precompiled
+ glsl_mamebm_fsh_files[j],
+ false);
+#else
+ if (glsl_mamebm_fsh_sources[j])
+ err = compile_sources(
+ &mamebm_programs[j],
+ &mamebm_vsh_shader[glsl_mamebm_fsh2vsh[j]],
+ &mamebm_fsh_shader[j],
+ nullptr, // precompiled
+ glsl_mamebm_fsh_sources[j]);
+#endif
+ }
+ if (err)
+ return false;
+
+ return true;
+ }
- for (i=0; !err && i<GLSL_VERTEX_SHADER_INT_NUMBER; i++)
+ virtual ~glsl_shader_impl()
{
- #ifdef GLSL_SOURCE_ON_DISK
- if(glsl_mamebm_vsh_files[i])
- err = gl_compile_shader_file ( &glsl_mamebm_vsh_shader[i], GL_VERTEX_SHADER_ARB,
- glsl_mamebm_vsh_files[i], 0);
- #else
- if(glsl_mamebm_vsh_sources[i])
- err = gl_compile_shader_source( &glsl_mamebm_vsh_shader[i], GL_VERTEX_SHADER_ARB,
- glsl_mamebm_vsh_sources[i], 0);
- #endif
- }
+ pfn_glUseProgramObjectARB(0);
+ glFinish();
- if(err) return nullptr;
+ for (int i = 0; i < GLSL_VERTEX_SHADER_MAX_NUMBER + 9; i++)
+ {
+ if (mamebm_vsh_shader[i])
+ delete_shader(nullptr, &mamebm_vsh_shader[i], nullptr);
+ }
+
+ for (int j = 0; j < FEAT_MAX_NUMBER + 9; j++)
+ {
+ if (mamebm_fsh_shader[j])
+ delete_shader(nullptr, nullptr, &mamebm_fsh_shader[j]);
+ }
+
+ for (int j = 0; j < FEAT_MAX_NUMBER + 9; j++)
+ {
+ if (mamebm_programs[j])
+ delete_shader(&mamebm_programs[j], nullptr, nullptr);
+ }
+
+ for (int i = 0; i < 10; i++)
+ {
+ if (scrn_vsh_shader[i])
+ delete_shader(nullptr, &scrn_vsh_shader[i], nullptr);
+ if (scrn_fsh_shader[i])
+ delete_shader(nullptr, nullptr, &scrn_fsh_shader[i]);
+ if (scrn_programs[i])
+ delete_shader(&scrn_programs[i], nullptr, nullptr);
+ }
+ }
- for (j=0; !err && j<GLSL_SHADER_FEAT_INT_NUMBER; j++)
+ virtual const char *get_filter_name_mamebm(int glslShaderFeature) override
{
- #ifdef GLSL_SOURCE_ON_DISK
- if(glsl_mamebm_fsh_files[j])
- err = gl_compile_shader_files (&glsl_mamebm_programs[j],
- &glsl_mamebm_vsh_shader[glsl_mamebm_fsh2vsh[j]],
- &glsl_mamebm_fsh_shader[j],
- nullptr /*precompiled*/, glsl_mamebm_fsh_files[j], 0);
- #else
- if(glsl_mamebm_fsh_sources[j])
- err = gl_compile_shader_sources(&glsl_mamebm_programs[j],
- &glsl_mamebm_vsh_shader[glsl_mamebm_fsh2vsh[j]],
- &glsl_mamebm_fsh_shader[j],
- nullptr /*precompiled*/, glsl_mamebm_fsh_sources[j]);
- #endif
- }
- if (err) return nullptr;
- return new glsl_shader_info{ 0 };
-}
+ if ((0 > glslShaderFeature) || (glslShaderFeature >= FEAT_MAX_NUMBER))
+ return "illegal shader feature";
-int glsl_shader_free(glsl_shader_info *shinfo)
-{
- pfn_glUseProgramObjectARB(0); // back to fixed function pipeline
- glFinish();
+ return glsl_mamebm_filter_names[glslShaderFeature];
+ }
- for (int i=0; i<GLSL_VERTEX_SHADER_MAX_NUMBER+9; i++)
+ virtual GLhandleARB get_program_mamebm(int glslShaderFeature, int idx) override
{
- if ( glsl_mamebm_vsh_shader[i] )
- (void) gl_delete_shader(nullptr, &glsl_mamebm_vsh_shader[i], nullptr);
+ if ((0 > glslShaderFeature) || (glslShaderFeature >= FEAT_MAX_NUMBER))
+ return 0;
+
+ return mamebm_programs[glslShaderFeature + idx];
}
- for (int j=0; j<GLSL_SHADER_FEAT_MAX_NUMBER+9; j++)
+ virtual GLhandleARB get_program_scrn(int idx) override
{
- if ( glsl_mamebm_fsh_shader[j] )
- (void) gl_delete_shader(nullptr, nullptr, &glsl_mamebm_fsh_shader[j]);
+ if ((0 > idx) || (idx >= 10))
+ return 0;
+
+ return scrn_programs[idx];
}
- for (int j=0; j<GLSL_SHADER_FEAT_MAX_NUMBER+9; j++)
+ virtual int add_mamebm(const char *custShaderPrefix, int idx) override
{
- if ( glsl_mamebm_programs[j] )
- (void) gl_delete_shader( &glsl_mamebm_programs[j], nullptr, nullptr);
+ int err;
+
+ err = compile_file(
+ &mamebm_vsh_shader[GLSL_VERTEX_SHADER_CUSTOM + idx],
+ GL_VERTEX_SHADER_ARB,
+ util::string_format("%s.vsh", custShaderPrefix).c_str(),
+ false);
+ if (err)
+ return err;
+
+ err = compile_files(
+ &mamebm_programs[FEAT_CUSTOM + idx],
+ &mamebm_vsh_shader[GLSL_VERTEX_SHADER_CUSTOM + idx],
+ &mamebm_fsh_shader[FEAT_CUSTOM + idx],
+ nullptr, // precompiled
+ util::string_format("%s_rgb32_dir.fsh", custShaderPrefix).c_str(),
+ false);
+ return err;
}
- for (int i=0; i<10; i++)
+ virtual int add_scrn(const char *custShaderPrefix, int idx) override
{
- if ( glsl_scrn_vsh_shader[i] )
- (void) gl_delete_shader(nullptr, &glsl_scrn_vsh_shader[i], nullptr);
- if ( glsl_scrn_fsh_shader[i] )
- (void) gl_delete_shader(nullptr, nullptr, &glsl_scrn_fsh_shader[i]);
- if ( glsl_scrn_programs[i] )
- (void) gl_delete_shader( &glsl_scrn_programs[i], nullptr, nullptr);
+ int err;
+
+ err = compile_file(
+ &scrn_vsh_shader[idx],
+ GL_VERTEX_SHADER_ARB,
+ util::string_format("%s.vsh", custShaderPrefix).c_str(),
+ false);
+ if (err)
+ return err;
+
+ err = compile_files(
+ &scrn_programs[idx],
+ &scrn_vsh_shader[idx],
+ &scrn_fsh_shader[idx],
+ nullptr, // precompiled
+ util::string_format("%s.fsh", custShaderPrefix).c_str(),
+ false);
+ return err;
}
- delete shinfo;
- return 0;
-}
-
-int glsl_shader_add_mamebm(glsl_shader_info *shinfo, const char * custShaderPrefix, int idx)
-{
- int err;
- static char fname[8192];
-
- snprintf(fname, 8192, "%s.vsh", custShaderPrefix); fname[8191]=0;
-
- err = gl_compile_shader_file ( &glsl_mamebm_vsh_shader[GLSL_VERTEX_SHADER_CUSTOM+idx], GL_VERTEX_SHADER_ARB, fname, 0);
- if(err) return err;
-
- snprintf(fname, 8192, "%s_rgb32_dir.fsh", custShaderPrefix); fname[8191]=0;
+private:
+ GLhandleARB mamebm_programs[FEAT_MAX_NUMBER + 9]; // rgb32 dir: plain, bilinear, bicubic, custom0-9, ..
+ GLhandleARB mamebm_vsh_shader[GLSL_VERTEX_SHADER_MAX_NUMBER + 9]; // general, custom0-9
+ GLhandleARB mamebm_fsh_shader[FEAT_MAX_NUMBER+9]; // rgb32 dir: plain, bilinear, bicubic, custom0-9
+ GLhandleARB scrn_programs[10]; // rgb32: custom0-9, ..
+ GLhandleARB scrn_vsh_shader[10]; // custom0-9
+ GLhandleARB scrn_fsh_shader[10]; // rgb32: custom0-9
+};
- err = gl_compile_shader_files (&glsl_mamebm_programs[GLSL_SHADER_FEAT_CUSTOM+idx],
- &glsl_mamebm_vsh_shader[GLSL_VERTEX_SHADER_CUSTOM+idx],
- &glsl_mamebm_fsh_shader[GLSL_SHADER_FEAT_CUSTOM+idx],
- nullptr /*precompiled*/, fname, 0);
+} // anonymous namespace
- return err;
-}
-int glsl_shader_add_scrn(glsl_shader_info *shinfo, const char * custShaderPrefix, int idx)
+std::unique_ptr<glsl_shader_info> glsl_shader_info::init(
+ osd_gl_context &gl_ctx
+#if defined(USE_DISPATCH_GL)
+ , osd_gl_dispatch *gld
+#endif
+ )
{
- int err;
- static char fname[8192];
-
- snprintf(fname, 8192, "%s.vsh", custShaderPrefix); fname[8191]=0;
-
- err = gl_compile_shader_file ( &glsl_scrn_vsh_shader[idx], GL_VERTEX_SHADER_ARB, fname, 0);
- if(err) return err;
-
- snprintf(fname, 8192, "%s.fsh", custShaderPrefix); fname[8191]=0;
-
- err = gl_compile_shader_files (&glsl_scrn_programs[idx],
- &glsl_scrn_vsh_shader[idx],
- &glsl_scrn_fsh_shader[idx],
- nullptr /*precompiled*/, fname, 0);
- return err;
+ auto result = std::make_unique<glsl_shader_impl>(
+#if defined(USE_DISPATCH_GL)
+ gld
+#endif
+ );
+ if (!result->initalize(gl_ctx))
+ result.reset();
+ return result;
}
diff --git a/src/osd/modules/opengl/gl_shader_mgr.h b/src/osd/modules/opengl/gl_shader_mgr.h
index f95ec8c2244..ad9e248ac5f 100644
--- a/src/osd/modules/opengl/gl_shader_mgr.h
+++ b/src/osd/modules/opengl/gl_shader_mgr.h
@@ -1,51 +1,57 @@
// license:BSD-3-Clause
// copyright-holders:Sven Gothel
+#ifndef MAME_OSD_OPENGL_GL_SHADER_MGR_H
+#define MAME_OSD_OPENGL_GL_SHADER_MGR_H
-#ifndef GL_SHADER_MGR_H
-#define GL_SHADER_MGR_H
+#pragma once
+#include "gl_shader_tool.h"
#include "osd_opengl.h"
+#include <memory>
+
+
// #define GLSL_SOURCE_ON_DISK 1
-enum GLSL_SHADER_FEATURE {
- GLSL_SHADER_FEAT_PLAIN,
- GLSL_SHADER_FEAT_BILINEAR,
- GLSL_SHADER_FEAT_BICUBIC,
- GLSL_SHADER_FEAT_INT_NUMBER,
- GLSL_SHADER_FEAT_CUSTOM = GLSL_SHADER_FEAT_INT_NUMBER,
- GLSL_SHADER_FEAT_MAX_NUMBER
-};
-// old code passed sdl_info * to functions here
-// however the parameter was not used
-// changed interface to more generic one.
-struct glsl_shader_info
+class glsl_shader_info : public gl_shader_tool
{
- int dummy; // avoid compiler breakage
+public:
+ enum FEATURE
+ {
+ FEAT_PLAIN,
+ FEAT_BILINEAR,
+ FEAT_BICUBIC,
+ FEAT_INT_NUMBER,
+ FEAT_CUSTOM = FEAT_INT_NUMBER,
+ FEAT_MAX_NUMBER
+ };
+
+ using gl_shader_tool::gl_shader_tool;
+
+ virtual ~glsl_shader_info() = default;
+
+ /**
+ * returns the GLSL program if ok/available, otherwise 0
+ */
+ virtual GLhandleARB get_program_mamebm(int glslShaderFeature, int idx) = 0;
+
+ virtual const char *get_filter_name_mamebm(int glslShaderFeature) = 0;
+
+ virtual int add_mamebm(const char *custShaderPrefix, int idx) = 0;
+
+ virtual GLhandleARB get_program_scrn(int idx) = 0;
+ virtual int add_scrn(const char *custShaderPrefix, int idx) = 0;
+
+ /**
+ * returns pointer if OK, otherwise nullptr
+ */
+ static std::unique_ptr<glsl_shader_info> init(
+ osd_gl_context &gl_ctx
+#if defined(USE_DISPATCH_GL)
+ , osd_gl_dispatch *gld
+#endif
+ );
};
-
-/**
- * returns pointer if ok, otherwise nullptr
- */
-glsl_shader_info *glsl_shader_init(osd_gl_context *gl_ctx);
-
-/**
- * returns 0 if ok, otherwise an error value
- */
-int glsl_shader_free(glsl_shader_info *shinfo);
-
-/**
- * returns the GLSL program if ok/available, otherwise 0
- */
-GLhandleARB glsl_shader_get_program_mamebm(int glslShaderFeature, int idx);
-
-const char * glsl_shader_get_filter_name_mamebm(int glslShaderFeature);
-
-int glsl_shader_add_mamebm(glsl_shader_info *shinfo, const char * custShaderPrefix, int idx);
-
-GLhandleARB glsl_shader_get_program_scrn(int idx);
-int glsl_shader_add_scrn(glsl_shader_info *shinfo, const char * custShaderPrefix, int idx);
-
-#endif // GL_SHADER_MGR_H
+#endif // MAME_OSD_OPENGL_GL_SHADER_MGR_H
diff --git a/src/osd/modules/opengl/gl_shader_tool.cpp b/src/osd/modules/opengl/gl_shader_tool.cpp
index 5696d14f834..fb880178b98 100644
--- a/src/osd/modules/opengl/gl_shader_tool.cpp
+++ b/src/osd/modules/opengl/gl_shader_tool.cpp
@@ -15,59 +15,90 @@
*
*/
-#include "emu.h"
#include "gl_shader_tool.h"
-PFNGLGETOBJECTPARAMETERIVARBPROC pfn_glGetObjectParameterivARB= nullptr;
-PFNGLGETINFOLOGARBPROC pfn_glGetInfoLogARB= nullptr;
-PFNGLDELETEOBJECTARBPROC pfn_glDeleteObjectARB= nullptr;
-PFNGLCREATESHADEROBJECTARBPROC pfn_glCreateShaderObjectARB= nullptr;
-PFNGLSHADERSOURCEARBPROC pfn_glShaderSourceARB= nullptr;
-PFNGLCOMPILESHADERARBPROC pfn_glCompileShaderARB= nullptr;
-PFNGLCREATEPROGRAMOBJECTARBPROC pfn_glCreateProgramObjectARB= nullptr;
-PFNGLATTACHOBJECTARBPROC pfn_glAttachObjectARB= nullptr;
-PFNGLLINKPROGRAMARBPROC pfn_glLinkProgramARB= nullptr;
-PFNGLVALIDATEPROGRAMARBPROC pfn_glValidateProgramARB= nullptr;
-PFNGLUSEPROGRAMOBJECTARBPROC pfn_glUseProgramObjectARB= nullptr;
-PFNGLGETUNIFORMLOCATIONARBPROC pfn_glGetUniformLocationARB= nullptr;
-PFNGLUNIFORM1FARBPROC pfn_glUniform1fARB= nullptr;
-PFNGLUNIFORM1IARBPROC pfn_glUniform1iARB= nullptr;
-PFNGLUNIFORM1FVARBPROC pfn_glUniform1fvARB= nullptr;
-PFNGLUNIFORM2FVARBPROC pfn_glUniform2fvARB= nullptr;
-PFNGLUNIFORM3FVARBPROC pfn_glUniform3fvARB= nullptr;
-PFNGLUNIFORM4FVARBPROC pfn_glUniform4fvARB= nullptr;
-PFNGLUNIFORM1IVARBPROC pfn_glUniform1ivARB= nullptr;
-PFNGLUNIFORM2IVARBPROC pfn_glUniform2ivARB= nullptr;
-PFNGLUNIFORM3IVARBPROC pfn_glUniform3ivARB= nullptr;
-PFNGLUNIFORM4IVARBPROC pfn_glUniform4ivARB= nullptr;
-
-
-int gl_shader_loadExtention(osd_gl_context *gl_ctx)
+#include "osdcore.h"
+
+
+#define GL_CHECK_ERROR_VERBOSE() check_error(CHECK_ALWAYS_VERBOSE, __FILE__, __LINE__)
+#define GL_CHECK_ERROR_NORMAL() check_error(CHECK_VERBOSE, __FILE__, __LINE__)
+#define GL_CHECK_ERROR_QUIET() check_error(CHECK_QUIET, __FILE__, __LINE__)
+#define GL_CHECK_ERROR(m) check_error(m, __FILE__, __LINE__)
+
+#define GL_SHADER_CHECK_ERROR_VERBOSE(o,q) check_error(o, q, CHECK_ALWAYS_VERBOSE, __FILE__, __LINE__)
+#define GL_SHADER_CHECK_ERROR_NORMAL(o,q) check_error(o, q, CHECK_VERBOSE, __FILE__, __LINE__)
+#define GL_SHADER_CHECK_ERROR_QUIET(o,q) check_error(o, q, CHECK_QUIET, __FILE__, __LINE__)
+#define GL_SHADER_CHECK_ERROR(o,q,m) check_error(o, q, m, __FILE__, __LINE__)
+
+#ifdef GL_SHADER_TOOL_DEBUG
+ #define GL_SHADER_CHECK(o, q) GL_SHADER_CHECK_ERROR_VERBOSE(o, q)
+ #define GL_CHECK() GL_CHECK_ERROR_VERBOSE()
+#else
+ #define GL_SHADER_CHECK(o, q) GL_SHADER_CHECK_ERROR_NORMAL(o, q)
+ #define GL_CHECK() GL_CHECK_ERROR_NORMAL()
+#endif
+
+
+gl_shader_tool::gl_shader_tool(
+#if defined(USE_DISPATCH_GL)
+ osd_gl_dispatch *gld
+#endif
+ )
+ : pfn_glGetObjectParameterivARB(nullptr)
+ , pfn_glGetInfoLogARB(nullptr)
+ , pfn_glDeleteObjectARB(nullptr)
+ , pfn_glCreateShaderObjectARB(nullptr)
+ , pfn_glShaderSourceARB(nullptr)
+ , pfn_glCompileShaderARB(nullptr)
+ , pfn_glCreateProgramObjectARB(nullptr)
+ , pfn_glAttachObjectARB(nullptr)
+ , pfn_glLinkProgramARB(nullptr)
+ , pfn_glValidateProgramARB(nullptr)
+ , pfn_glUseProgramObjectARB(nullptr)
+ , pfn_glGetUniformLocationARB(nullptr)
+ , pfn_glUniform1fARB(nullptr)
+ , pfn_glUniform1iARB(nullptr)
+ , pfn_glUniform1fvARB(nullptr)
+ , pfn_glUniform2fvARB(nullptr)
+ , pfn_glUniform3fvARB(nullptr)
+ , pfn_glUniform4fvARB(nullptr)
+ , pfn_glUniform1ivARB(nullptr)
+ , pfn_glUniform2ivARB(nullptr)
+ , pfn_glUniform3ivARB(nullptr)
+ , pfn_glUniform4ivARB(nullptr)
+#if defined(USE_DISPATCH_GL)
+ , gl_dispatch(gld)
+#endif
+{
+}
+
+
+bool gl_shader_tool::load_extension(osd_gl_context &gl_ctx)
{
- pfn_glGetObjectParameterivARB = (PFNGLGETOBJECTPARAMETERIVARBPROC) gl_ctx->getProcAddress("glGetObjectParameterivARB");
- pfn_glGetInfoLogARB = (PFNGLGETINFOLOGARBPROC) gl_ctx->getProcAddress ("glGetInfoLogARB");
- pfn_glDeleteObjectARB = (PFNGLDELETEOBJECTARBPROC) gl_ctx->getProcAddress ("glDeleteObjectARB");
- pfn_glCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC) gl_ctx->getProcAddress ("glCreateShaderObjectARB");
- pfn_glShaderSourceARB = (PFNGLSHADERSOURCEARBPROC) gl_ctx->getProcAddress ("glShaderSourceARB");
- pfn_glCompileShaderARB = (PFNGLCOMPILESHADERARBPROC) gl_ctx->getProcAddress ("glCompileShaderARB");
- pfn_glCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC) gl_ctx->getProcAddress ("glCreateProgramObjectARB");
- pfn_glAttachObjectARB = (PFNGLATTACHOBJECTARBPROC) gl_ctx->getProcAddress ("glAttachObjectARB");
- pfn_glLinkProgramARB = (PFNGLLINKPROGRAMARBPROC) gl_ctx->getProcAddress ("glLinkProgramARB");
- pfn_glValidateProgramARB = (PFNGLVALIDATEPROGRAMARBPROC) gl_ctx->getProcAddress ("glValidateProgramARB");
- pfn_glUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC) gl_ctx->getProcAddress ("glUseProgramObjectARB");
- pfn_glGetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC) gl_ctx->getProcAddress ("glGetUniformLocationARB");
- pfn_glUniform1fARB = (PFNGLUNIFORM1FARBPROC) gl_ctx->getProcAddress ("glUniform1fARB");
- pfn_glUniform1iARB = (PFNGLUNIFORM1IARBPROC) gl_ctx->getProcAddress ("glUniform1iARB");
- pfn_glUniform1fvARB = (PFNGLUNIFORM1FVARBPROC) gl_ctx->getProcAddress ("glUniform1fvARB");
- pfn_glUniform2fvARB = (PFNGLUNIFORM2FVARBPROC) gl_ctx->getProcAddress ("glUniform2fvARB");
- pfn_glUniform3fvARB = (PFNGLUNIFORM3FVARBPROC) gl_ctx->getProcAddress ("glUniform3fvARB");
- pfn_glUniform4fvARB = (PFNGLUNIFORM4FVARBPROC) gl_ctx->getProcAddress ("glUniform4fvARB");
- pfn_glUniform1ivARB = (PFNGLUNIFORM1IVARBPROC) gl_ctx->getProcAddress ("glUniform1ivARB");
- pfn_glUniform2ivARB = (PFNGLUNIFORM2IVARBPROC) gl_ctx->getProcAddress ("glUniform2ivARB");
- pfn_glUniform3ivARB = (PFNGLUNIFORM3IVARBPROC) gl_ctx->getProcAddress ("glUniform3ivARB");
- pfn_glUniform4ivARB = (PFNGLUNIFORM4IVARBPROC) gl_ctx->getProcAddress ("glUniform4ivARB");
-
- if ( pfn_glGetObjectParameterivARB && pfn_glGetInfoLogARB && pfn_glDeleteObjectARB && pfn_glCreateShaderObjectARB &&
+ gl_ctx.get_proc_address(pfn_glGetObjectParameterivARB, "glGetObjectParameterivARB");
+ gl_ctx.get_proc_address(pfn_glGetInfoLogARB, "glGetInfoLogARB");
+ gl_ctx.get_proc_address(pfn_glDeleteObjectARB, "glDeleteObjectARB");
+ gl_ctx.get_proc_address(pfn_glCreateShaderObjectARB, "glCreateShaderObjectARB");
+ gl_ctx.get_proc_address(pfn_glShaderSourceARB, "glShaderSourceARB");
+ gl_ctx.get_proc_address(pfn_glCompileShaderARB, "glCompileShaderARB");
+ gl_ctx.get_proc_address(pfn_glCreateProgramObjectARB, "glCreateProgramObjectARB");
+ gl_ctx.get_proc_address(pfn_glAttachObjectARB, "glAttachObjectARB");
+ gl_ctx.get_proc_address(pfn_glLinkProgramARB, "glLinkProgramARB");
+ gl_ctx.get_proc_address(pfn_glValidateProgramARB, "glValidateProgramARB");
+ gl_ctx.get_proc_address(pfn_glUseProgramObjectARB, "glUseProgramObjectARB");
+ gl_ctx.get_proc_address(pfn_glGetUniformLocationARB, "glGetUniformLocationARB");
+ gl_ctx.get_proc_address(pfn_glUniform1fARB, "glUniform1fARB");
+ gl_ctx.get_proc_address(pfn_glUniform1iARB, "glUniform1iARB");
+ gl_ctx.get_proc_address(pfn_glUniform1fvARB, "glUniform1fvARB");
+ gl_ctx.get_proc_address(pfn_glUniform2fvARB, "glUniform2fvARB");
+ gl_ctx.get_proc_address(pfn_glUniform3fvARB, "glUniform3fvARB");
+ gl_ctx.get_proc_address(pfn_glUniform4fvARB, "glUniform4fvARB");
+ gl_ctx.get_proc_address(pfn_glUniform1ivARB, "glUniform1ivARB");
+ gl_ctx.get_proc_address(pfn_glUniform2ivARB, "glUniform2ivARB");
+ gl_ctx.get_proc_address(pfn_glUniform3ivARB, "glUniform3ivARB");
+ gl_ctx.get_proc_address(pfn_glUniform4ivARB, "glUniform4ivARB");
+
+ if (pfn_glGetObjectParameterivARB && pfn_glGetInfoLogARB && pfn_glDeleteObjectARB && pfn_glCreateShaderObjectARB &&
pfn_glShaderSourceARB && pfn_glCompileShaderARB && pfn_glCreateProgramObjectARB && pfn_glAttachObjectARB &&
pfn_glLinkProgramARB && pfn_glValidateProgramARB && pfn_glUseProgramObjectARB &&
pfn_glGetUniformLocationARB && pfn_glUniform1fARB && pfn_glUniform1iARB &&
@@ -75,62 +106,52 @@ int gl_shader_loadExtention(osd_gl_context *gl_ctx)
pfn_glUniform1ivARB && pfn_glUniform2ivARB && pfn_glUniform3ivARB && pfn_glUniform4ivARB
)
{
- return 0;
+ return true;
}
osd_printf_error("OpenGL: missing ARB shader function: ");
- if (!pfn_glGetObjectParameterivARB) osd_printf_error("glGetObjectParameterivARB, ");
- if (!pfn_glGetInfoLogARB) osd_printf_error("glGetInfoLogARB, ");
- if (!pfn_glDeleteObjectARB) osd_printf_error("glDeleteObjectARB, ");
- if (!pfn_glCreateShaderObjectARB) osd_printf_error("glCreateShaderObjectARB, ");
- if (!pfn_glShaderSourceARB) osd_printf_error("glShaderSourceARB, ");
- if (!pfn_glCompileShaderARB) osd_printf_error("glCompileShaderARB, ");
- if (!pfn_glCreateProgramObjectARB) osd_printf_error("glCreateProgramObjectARB, ");
- if (!pfn_glAttachObjectARB) osd_printf_error("glAttachObjectARB, ");
- if (!pfn_glLinkProgramARB) osd_printf_error("glLinkProgramARB, ");
- if (!pfn_glValidateProgramARB) osd_printf_error("glValidateProgramARB, ");
- if (!pfn_glUseProgramObjectARB) osd_printf_error("glUseProgramObjectARB, ");
- if (!pfn_glGetUniformLocationARB) osd_printf_error("glGetUniformLocationARB, ");
- if (!pfn_glUniform1fARB) osd_printf_error("glUniform1fARB, ");
- if (!pfn_glUniform1iARB) osd_printf_error("glUniform1iARB");
- if (!pfn_glUniform1fvARB) osd_printf_error("glUniform1fvARB, ");
- if (!pfn_glUniform2fvARB) osd_printf_error("glUniform2fvARB, ");
- if (!pfn_glUniform3fvARB) osd_printf_error("glUniform3fvARB, ");
- if (!pfn_glUniform4fvARB) osd_printf_error("glUniform4fvARB, ");
- if (!pfn_glUniform1ivARB) osd_printf_error("glUniform1ivARB");
- if (!pfn_glUniform2ivARB) osd_printf_error("glUniform2ivARB");
- if (!pfn_glUniform3ivARB) osd_printf_error("glUniform3ivARB");
- if (!pfn_glUniform4ivARB) osd_printf_error("glUniform4ivARB");
+ if (!pfn_glGetObjectParameterivARB) osd_printf_error(" glGetObjectParameterivARB");
+ if (!pfn_glGetInfoLogARB) osd_printf_error(" glGetInfoLogARB");
+ if (!pfn_glDeleteObjectARB) osd_printf_error(" glDeleteObjectARB");
+ if (!pfn_glCreateShaderObjectARB) osd_printf_error(" glCreateShaderObjectARB");
+ if (!pfn_glShaderSourceARB) osd_printf_error(" glShaderSourceARB");
+ if (!pfn_glCompileShaderARB) osd_printf_error(" glCompileShaderARB");
+ if (!pfn_glCreateProgramObjectARB) osd_printf_error(" glCreateProgramObjectARB");
+ if (!pfn_glAttachObjectARB) osd_printf_error(" glAttachObjectARB");
+ if (!pfn_glLinkProgramARB) osd_printf_error(" glLinkProgramARB");
+ if (!pfn_glValidateProgramARB) osd_printf_error(" glValidateProgramARB");
+ if (!pfn_glUseProgramObjectARB) osd_printf_error(" glUseProgramObjectARB");
+ if (!pfn_glGetUniformLocationARB) osd_printf_error(" glGetUniformLocationARB");
+ if (!pfn_glUniform1fARB) osd_printf_error(" glUniform1fARB");
+ if (!pfn_glUniform1iARB) osd_printf_error(" glUniform1iARB");
+ if (!pfn_glUniform1fvARB) osd_printf_error(" glUniform1fvARB");
+ if (!pfn_glUniform2fvARB) osd_printf_error(" glUniform2fvARB");
+ if (!pfn_glUniform3fvARB) osd_printf_error(" glUniform3fvARB");
+ if (!pfn_glUniform4fvARB) osd_printf_error(" glUniform4fvARB");
+ if (!pfn_glUniform1ivARB) osd_printf_error(" glUniform1ivARB");
+ if (!pfn_glUniform2ivARB) osd_printf_error(" glUniform2ivARB");
+ if (!pfn_glUniform3ivARB) osd_printf_error(" glUniform3ivARB");
+ if (!pfn_glUniform4ivARB) osd_printf_error(" glUniform4ivARB");
osd_printf_error("\n");
- return -1;
+ return false;
}
-int gl_check_error(GLSLCheckMode m, const char *file, const int line)
+int gl_shader_tool::check_error(GLSLCheckMode m, const char *file, const int line)
{
- GLenum glerr = glGetError();
-
- if (GL_NO_ERROR != glerr)
- {
- if ( CHECK_VERBOSE <= m )
- {
- osd_printf_warning( "%s:%d: GL Error: %d 0x%X\n", file, line, (int)glerr, (unsigned int)glerr);
- }
- }
- return (GL_NO_ERROR != glerr)? glerr : 0;
+ GLenum const glerr = glGetError();
+ if (GL_NO_ERROR != glerr)
+ {
+ if (CHECK_VERBOSE <= m)
+ osd_printf_warning("%s:%d: GL Error: %d 0x%X\n", file, line, int(glerr), unsigned(glerr));
+ }
+ return (GL_NO_ERROR != glerr) ? glerr : 0;
}
-int gl_shader_check_error(GLhandleARB obj, GLenum obj_query, GLSLCheckMode m, const char *file, const int line)
+int gl_shader_tool::check_error(GLhandleARB obj, GLenum obj_query, GLSLCheckMode m, const char *file, const int line)
{
- GLsizei length;
- GLcharARB buffer[255];
- GLenum glerr;
- GLint param;
- int res=0;
-
- glerr = gl_check_error(m, file, line);
-
- if(!obj)
+ GLenum const glerr = check_error(m, file, line);
+ if (!obj)
return glerr;
if(obj_query != GL_OBJECT_TYPE_ARB &&
@@ -144,79 +165,88 @@ int gl_shader_check_error(GLhandleARB obj, GLenum obj_query, GLSLCheckMode m, co
return -1;
}
+ GLint param;
pfn_glGetObjectParameterivARB(obj, obj_query, &param);
+ int res = 0;
switch(obj_query)
{
- case GL_OBJECT_TYPE_ARB:
- if( param!=GL_PROGRAM_OBJECT_ARB && param!=GL_SHADER_OBJECT_ARB )
+ case GL_OBJECT_TYPE_ARB:
+ if (param != GL_PROGRAM_OBJECT_ARB && param != GL_SHADER_OBJECT_ARB)
{
if ( CHECK_VERBOSE <= m )
osd_printf_warning("%s:%d: GL Error: object type 0x%X generation failed\n", file, line, (unsigned int)(uintptr_t)obj);
res=-1;
- } else if ( CHECK_ALWAYS_VERBOSE <= m )
+ }
+ else if (CHECK_ALWAYS_VERBOSE <= m)
{
- if(param==GL_PROGRAM_OBJECT_ARB)
+ if (param==GL_PROGRAM_OBJECT_ARB)
osd_printf_warning("%s:%d: GL Error: object type 0x%X is PROGRAM, successful\n", file, line, (unsigned int)(uintptr_t)obj);
else
osd_printf_warning("%s:%d: GL Info: object type 0x%X is SHADER, successful\n", file, line, (unsigned int)(uintptr_t)obj);
}
break;
- case GL_OBJECT_DELETE_STATUS_ARB:
- if(param!=1)
+ case GL_OBJECT_DELETE_STATUS_ARB:
+ if (param != 1)
{
- if ( CHECK_ALWAYS_VERBOSE <= m )
+ if (CHECK_ALWAYS_VERBOSE <= m)
osd_printf_warning("%s:%d: GL Info: object 0x%X not yet marked for deletion\n", file, line, (unsigned int)(uintptr_t)obj);
- } else if ( CHECK_ALWAYS_VERBOSE <= m )
+ }
+ else if (CHECK_ALWAYS_VERBOSE <= m)
{
osd_printf_warning("%s:%d: GL Info: object 0x%X deletion successful\n", file, line, (unsigned int)(uintptr_t)obj);
}
break;
- case GL_OBJECT_COMPILE_STATUS_ARB:
- if(param!=1)
+ case GL_OBJECT_COMPILE_STATUS_ARB:
+ if (param != 1)
{
- if ( CHECK_VERBOSE <= m )
+ if (CHECK_VERBOSE <= m)
osd_printf_warning("%s:%d: GL Error: object 0x%X compilation failed\n", file, line, (unsigned int)(uintptr_t)obj);
- res=-1;
- } else if ( CHECK_ALWAYS_VERBOSE <= m )
+ res = -1;
+ }
+ else if (CHECK_ALWAYS_VERBOSE <= m)
{
osd_printf_warning("%s:%d: GL Info: object 0x%X compiled successful\n", file, line, (unsigned int)(uintptr_t)obj);
}
break;
- case GL_OBJECT_LINK_STATUS_ARB:
- if(param!=1)
+ case GL_OBJECT_LINK_STATUS_ARB:
+ if (param != 1)
{
- if ( CHECK_VERBOSE <= m )
+ if (CHECK_VERBOSE <= m)
osd_printf_warning("%s:%d: GL Error: object 0x%X linking failed\n", file, line, (unsigned int)(uintptr_t)obj);
- res=-1;
- } else if ( CHECK_ALWAYS_VERBOSE <= m )
+ res = -1;
+ }
+ else if (CHECK_ALWAYS_VERBOSE <= m)
{
osd_printf_warning("%s:%d: GL Info: object 0x%X linked successful\n", file, line, (unsigned int)(uintptr_t)obj);
}
break;
- case GL_OBJECT_VALIDATE_STATUS_ARB:
- if(param!=1)
+ case GL_OBJECT_VALIDATE_STATUS_ARB:
+ if (param != 1)
{
- if ( CHECK_VERBOSE <= m )
+ if (CHECK_VERBOSE <= m)
osd_printf_warning("%s:%d: GL Error: object 0x%X validation failed\n", file, line, (unsigned int)(uintptr_t)obj);
- res=-1;
- } else if ( CHECK_ALWAYS_VERBOSE <= m )
+ res = -1;
+ }
+ else if (CHECK_ALWAYS_VERBOSE <= m
+ )
{
osd_printf_warning("%s:%d: GL Info: object 0x%X validation successful\n", file, line, (unsigned int)(uintptr_t)obj);
}
break;
- }
+ }
- if ( res<0 || CHECK_ALWAYS_VERBOSE <= m )
+ if (res < 0 || CHECK_ALWAYS_VERBOSE <= m)
{
+ GLsizei length;
+ GLcharARB buffer[255];
length=0;
pfn_glGetInfoLogARB(obj, sizeof(buffer), &length, buffer);
- if(length>0)
+ if (length>0)
osd_printf_warning("%s:%d glInfoLog: %s\n", file, line, buffer);
}
- (void) glGetError(); // ;-)
-
+ (void)glGetError(); // ;-)
return res;
}
@@ -234,157 +264,175 @@ int gl_round_to_pow2(int v)
return v;
}
-int gl_texture_check_size(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height,
- GLint border, GLenum format, GLenum type,
- GLint *avail_width, GLint *avail_height,
- int verbose)
+int gl_shader_tool::texture_check_size(
+ GLenum target,
+ GLint level,
+ GLint internalFormat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ GLint *avail_width,
+ GLint *avail_height,
+ bool verbose)
{
- int err=1;
- GLenum texTargetProxy = (target==GL_TEXTURE_RECTANGLE_ARB)?GL_PROXY_TEXTURE_RECTANGLE_ARB:GL_PROXY_TEXTURE_2D;
-
- if ( !avail_width || !avail_height)
- return -1;
+ if (!avail_width || !avail_height)
+ return -1;
*avail_width = 0;
*avail_height = 0;
GL_CHECK_ERROR_QUIET();
- /* Test the max texture size */
- while(err && width>=1 && height>=1 /* && width>=64 && height>=64 */)
- {
- glTexImage2D (texTargetProxy, level,
- internalFormat,
- width, height,
- border, format, type, nullptr);
- if ( 0!=(err=GL_CHECK_ERROR_NORMAL() )) return err;
-
- glGetTexLevelParameteriv( texTargetProxy, level, GL_TEXTURE_WIDTH, avail_width);
- glGetTexLevelParameteriv( texTargetProxy, level, GL_TEXTURE_HEIGHT, avail_height);
- if ( 0!=(err=GL_CHECK_ERROR_NORMAL() )) return err;
-
- if ( (*avail_width) != width || (*avail_height) != height )
+ // Test the max texture size
+ int err = 1;
+ GLenum const texTargetProxy = (target == GL_TEXTURE_RECTANGLE_ARB) ? GL_PROXY_TEXTURE_RECTANGLE_ARB : GL_PROXY_TEXTURE_2D;
+ while (err && width>=1 && height>=1 /* && width>=64 && height>=64 */)
{
- err=1;
-
- if(verbose)
+ glTexImage2D(texTargetProxy, level,
+ internalFormat,
+ width, height,
+ border, format, type, nullptr);
+ if (0 != (err=GL_CHECK_ERROR_NORMAL()))
+ return err;
+
+ glGetTexLevelParameteriv(texTargetProxy, level, GL_TEXTURE_WIDTH, avail_width);
+ glGetTexLevelParameteriv(texTargetProxy, level, GL_TEXTURE_HEIGHT, avail_height);
+ if (0 != (err=GL_CHECK_ERROR_NORMAL()))
+ return err;
+
+ if ((*avail_width != width) || (*avail_height != height))
{
- osd_printf_warning("gl_texture_size_check: "
- "TexImage2D(0x%X, %d, 0x%X, %d, %d, %d, 0x%X, 0x%X): returned size does not match: %dx%d\n",
- (unsigned int)target, (int)level, (int)internalFormat,
- (int)width, (int)height, (int)border, (unsigned int)format, (unsigned int)type,
- (int)*avail_width, (int)*avail_height);
- }
-
- if ( (*avail_width) == width )
- height /= 2;
- else if ( (*avail_height) == height )
- width /= 2;
- else if (width > height)
+ err = 1;
+
+ if (verbose)
+ {
+ osd_printf_warning("gl_texture_size_check: "
+ "TexImage2D(0x%X, %d, 0x%X, %d, %d, %d, 0x%X, 0x%X): returned size does not match: %dx%d\n",
+ (unsigned int)target, (int)level, (int)internalFormat,
+ width, height, border, (unsigned int)format, (unsigned int)type,
+ *avail_width, *avail_height);
+ }
+
+ if (*avail_width == width)
+ height /= 2;
+ else if (*avail_height == height)
width /= 2;
- else
+ else if (width > height)
+ width /= 2;
+ else
height /= 2;
- if(verbose)
+ if (verbose)
+ {
+ osd_printf_verbose("gl_texture_size_check: trying [%dx%d] !\n", height, width);
+ }
+ }
+ else
{
- fprintf (stderr, "gl_texture_size_check: trying [%dx%d] !\n", (int)height, (int)width);
+ err = 0;
}
- } else {
- err=0;
- }
}
- if(!err)
+ if (!err)
{
- *avail_width = width;
+ *avail_width = width;
*avail_height = height;
}
return err;
}
-static int delete_shader_tool( GLhandleARB *program, GLhandleARB *vertex_shader, GLhandleARB *fragment_shader, int externalcall)
+int gl_shader_tool::delete_shader_tool(
+ GLhandleARB *program,
+ GLhandleARB *vertex_shader,
+ GLhandleARB *fragment_shader,
+ bool externalcall)
{
- int res=0;
+ int res = 0;
GL_CHECK_ERROR_QUIET();
- if(program!= nullptr && *program!=0)
+ if (program && *program!=0)
{
pfn_glDeleteObjectARB(*program);
- if(externalcall)
- {
+ if (externalcall)
res |= GL_SHADER_CHECK(*program, GL_OBJECT_DELETE_STATUS_ARB);
- }
- *program=0;
+ *program = 0;
}
- if(vertex_shader!= nullptr && *vertex_shader!=0)
+ if (vertex_shader && *vertex_shader!=0)
{
pfn_glDeleteObjectARB(*vertex_shader);
- if(externalcall)
- {
+ if (externalcall)
res |= GL_SHADER_CHECK(*vertex_shader, GL_OBJECT_DELETE_STATUS_ARB);
- }
*vertex_shader=0;
}
- if(fragment_shader!= nullptr && *fragment_shader!=0)
+ if (fragment_shader && *fragment_shader!=0)
{
pfn_glDeleteObjectARB(*fragment_shader);
- if(externalcall)
- {
+ if (externalcall)
res |= GL_SHADER_CHECK(*fragment_shader, GL_OBJECT_DELETE_STATUS_ARB);
- }
*fragment_shader=0;
}
- return res;
+ return res;
}
-int gl_compile_shader_source( GLhandleARB *shader, GLenum type, const char * shader_source, int verbose )
+int gl_shader_tool::compile_source(
+ GLhandleARB *shader,
+ GLenum type,
+ const char *shader_source,
+ bool verbose)
{
- int err = 0;
+ int err = 0;
- if(shader== nullptr || shader_source== nullptr)
+ if (!shader || !shader_source)
{
- if(shader== nullptr)
+ if (!shader)
osd_printf_warning("error: gl_compile_shader_source: nullptr shader passed\n");
- if(shader_source== nullptr)
+ if (!shader_source)
osd_printf_warning("error: gl_compile_shader_source: nullptr shader source passed\n");
return -1;
}
- *shader = pfn_glCreateShaderObjectARB(type);
- err=GL_SHADER_CHECK(*shader, GL_OBJECT_TYPE_ARB);
- if(err) goto errout;
+ *shader = pfn_glCreateShaderObjectARB(type);
+ err = GL_SHADER_CHECK(*shader, GL_OBJECT_TYPE_ARB);
+ if (err)
+ goto errout;
- pfn_glShaderSourceARB(*shader, 1, (const GLcharARB **)&shader_source, nullptr);
+ pfn_glShaderSourceARB(*shader, 1, (const GLcharARB **)&shader_source, nullptr);
- pfn_glCompileShaderARB(*shader);
- err=GL_SHADER_CHECK(*shader, GL_OBJECT_COMPILE_STATUS_ARB);
- if(err) goto errout;
+ pfn_glCompileShaderARB(*shader);
+ err = GL_SHADER_CHECK(*shader, GL_OBJECT_COMPILE_STATUS_ARB);
+ if (err)
+ goto errout;
- if(verbose)
+ if (verbose)
osd_printf_warning( "<%s>\n", shader_source);
return 0;
errout:
- if(*shader!=0)
- {
+ if (*shader != 0)
pfn_glDeleteObjectARB(*shader);
- }
+
osd_printf_warning("failed to process shader: <%s>\n", shader_source);
- return err;
+ return err;
}
-int gl_compile_shader_file( GLhandleARB *shader, GLenum type, const char * shader_file, int verbose )
+int gl_shader_tool::compile_file(
+ GLhandleARB *shader,
+ GLenum type,
+ const char *shader_file,
+ bool verbose)
{
- if(shader== nullptr || shader_file== nullptr)
+ if (!shader || !shader_file)
{
- if(shader== nullptr)
+ if (!shader)
osd_printf_warning("error: gl_compile_shader_source: nullptr shader passed\n");
- if(shader_file== nullptr)
+ if (!shader_file)
osd_printf_warning("error: gl_compile_shader_source: nullptr shader file passed\n");
return -1;
}
FILE *const file = fopen(shader_file, "r");
- if(!file)
+ if (!file)
{
osd_printf_warning("cannot open shader_file: %s\n", shader_file);
return -1;
@@ -399,15 +447,16 @@ int gl_compile_shader_file( GLhandleARB *shader, GLenum type, const char * shade
memset(buffer, 0, buffer_len + 1);
/* Load Shader Sources */
- for( int i = 0, c = 0; i<buffer_len && EOF!=(c=fgetc(file)); i++ )
- buffer[i]=(char)c;
+ for (int i = 0, c = 0; i<buffer_len && EOF!=(c=fgetc(file)); i++)
+ buffer[i] = char(c);
fclose(file);
- int const err=gl_compile_shader_source(shader, type, buffer, verbose);
+ int const err = compile_source(shader, type, buffer, verbose);
free(buffer);
- if(err) goto errout;
+ if (err)
+ goto errout;
- if(verbose)
+ if (verbose)
osd_printf_warning("shader file: %s\n", shader_file);
return 0;
@@ -418,180 +467,204 @@ errout:
}
-int gl_compile_shader_files( GLhandleARB *program, GLhandleARB *vertex_shader, GLhandleARB *fragment_shader,
- const char * vertex_shader_file,
- const char * fragment_shader_file,
- int verbose
- )
+int gl_shader_tool::compile_files(
+ GLhandleARB *program,
+ GLhandleARB *vertex_shader,
+ GLhandleARB *fragment_shader,
+ const char * vertex_shader_file,
+ const char * fragment_shader_file,
+ bool verbose)
{
int err;
if (!program)
{
- err=-1;
+ err = -1;
osd_printf_warning("no program ptr passed\n");
goto errout;
}
if (!vertex_shader)
{
- err=-1;
+ err = -1;
osd_printf_warning("no vertex_shader ptr passed\n");
goto errout;
}
if (!fragment_shader)
{
- err=-1;
+ err = -1;
osd_printf_warning("no fragment_shader ptr passed\n");
goto errout;
}
- *program = pfn_glCreateProgramObjectARB();
- err=GL_SHADER_CHECK(*program, GL_OBJECT_TYPE_ARB);
- if(err) goto errout;
+ *program = pfn_glCreateProgramObjectARB();
+ err=GL_SHADER_CHECK(*program, GL_OBJECT_TYPE_ARB);
+ if (err)
+ goto errout;
- if(!vertex_shader_file)
+ if (!vertex_shader_file)
{
if (!(*vertex_shader))
{
- err=-1;
+ err = -1;
osd_printf_warning("no vertex_shader_file, nor vertex_shader id passed\n");
goto errout;
}
- err=GL_SHADER_CHECK(*vertex_shader, GL_OBJECT_TYPE_ARB);
- if(err) goto errout;
- } else {
- err = gl_compile_shader_file(vertex_shader, GL_VERTEX_SHADER_ARB, vertex_shader_file, verbose);
- if(err) return err;
+ err = GL_SHADER_CHECK(*vertex_shader, GL_OBJECT_TYPE_ARB);
+ if (err)
+ goto errout;
+ }
+ else
+ {
+ err = compile_file(vertex_shader, GL_VERTEX_SHADER_ARB, vertex_shader_file, verbose);
+ if (err)
+ return err;
}
- pfn_glAttachObjectARB(*program, *vertex_shader);
+ pfn_glAttachObjectARB(*program, *vertex_shader);
- if(!fragment_shader_file)
+ if (!fragment_shader_file)
{
if (!(*fragment_shader))
{
- err=-1;
+ err = -1;
osd_printf_warning("no fragment_shader_file, nor fragment_shader id passed\n");
goto errout;
}
- err=GL_SHADER_CHECK(*fragment_shader, GL_OBJECT_TYPE_ARB);
- if(err) goto errout;
- } else {
- err = gl_compile_shader_file(fragment_shader, GL_FRAGMENT_SHADER_ARB, fragment_shader_file, verbose);
- if(err) return err;
+ err = GL_SHADER_CHECK(*fragment_shader, GL_OBJECT_TYPE_ARB);
+ if (err)
+ goto errout;
+ }
+ else
+ {
+ err = compile_file(fragment_shader, GL_FRAGMENT_SHADER_ARB, fragment_shader_file, verbose);
+ if (err)
+ return err;
}
- pfn_glAttachObjectARB(*program, *fragment_shader);
+ pfn_glAttachObjectARB(*program, *fragment_shader);
- pfn_glLinkProgramARB(*program);
- err=GL_SHADER_CHECK(*program, GL_OBJECT_LINK_STATUS_ARB);
- if(err) goto errout;
+ pfn_glLinkProgramARB(*program);
+ err = GL_SHADER_CHECK(*program, GL_OBJECT_LINK_STATUS_ARB);
+ if (err)
+ goto errout;
- pfn_glValidateProgramARB(*program);
- err=GL_SHADER_CHECK(*program, GL_OBJECT_VALIDATE_STATUS_ARB);
- if(err) goto errout;
+ pfn_glValidateProgramARB(*program);
+ err = GL_SHADER_CHECK(*program, GL_OBJECT_VALIDATE_STATUS_ARB);
+ if (err)
+ goto errout;
- return 0;
+ return 0;
errout:
- delete_shader_tool(program, vertex_shader, fragment_shader, 0);
- return err;
+ delete_shader_tool(program, vertex_shader, fragment_shader, false);
+ return err;
}
-int gl_compile_shader_sources( GLhandleARB *program, GLhandleARB *vertex_shader, GLhandleARB *fragment_shader,
- const GLcharARB * vertex_shader_source,
- const GLcharARB * fragment_shader_source
- )
+int gl_shader_tool::compile_sources(
+ GLhandleARB *program,
+ GLhandleARB *vertex_shader,
+ GLhandleARB *fragment_shader,
+ const GLcharARB * vertex_shader_source,
+ const GLcharARB * fragment_shader_source)
{
- int err = 0;
+ int err = 0;
if (!program)
{
- err=-1;
+ err = -1;
osd_printf_warning("no program ptr passed\n");
goto errout;
}
if (!vertex_shader)
{
- err=-1;
+ err = -1;
osd_printf_warning("no vertex_shader ptr passed\n");
goto errout;
}
if (!fragment_shader)
{
- err=-1;
+ err = -1;
osd_printf_warning("no fragment_shader ptr passed\n");
goto errout;
}
- *program = pfn_glCreateProgramObjectARB();
- err=GL_SHADER_CHECK(*program, GL_OBJECT_TYPE_ARB);
- if(err) goto errout;
+ *program = pfn_glCreateProgramObjectARB();
+ err = GL_SHADER_CHECK(*program, GL_OBJECT_TYPE_ARB);
+ if (err)
+ goto errout;
- if(!vertex_shader_source)
+ if (!vertex_shader_source)
{
if (!(*vertex_shader))
{
- err=-1;
+ err = -1;
osd_printf_warning("no vertex_shader_source nor a vertex_shader id passed\n");
goto errout;
}
- err=GL_SHADER_CHECK(*vertex_shader, GL_OBJECT_TYPE_ARB);
- if(err) goto errout;
+ err = GL_SHADER_CHECK(*vertex_shader, GL_OBJECT_TYPE_ARB);
+ if (err)
+ goto errout;
}
- if(!fragment_shader_source)
+ if (!fragment_shader_source)
{
if (!(*fragment_shader))
{
- err=-1;
+ err = -1;
osd_printf_warning("no fragment_shader_source nor a fragment_shader id passed\n");
goto errout;
}
- err=GL_SHADER_CHECK(*fragment_shader, GL_OBJECT_TYPE_ARB);
- if(err) goto errout;
+ err = GL_SHADER_CHECK(*fragment_shader, GL_OBJECT_TYPE_ARB);
+ if (err)
+ goto errout;
}
- if(vertex_shader_source)
+ if (vertex_shader_source)
{
- err=gl_compile_shader_source(vertex_shader, GL_VERTEX_SHADER_ARB, vertex_shader_source, 0);
- if(err) goto errout;
+ err = compile_source(vertex_shader, GL_VERTEX_SHADER_ARB, vertex_shader_source, false);
+ if (err)
+ goto errout;
}
- pfn_glAttachObjectARB(*program, *vertex_shader);
+ pfn_glAttachObjectARB(*program, *vertex_shader);
- if(fragment_shader_source)
+ if (fragment_shader_source)
{
- err=gl_compile_shader_source(fragment_shader, GL_FRAGMENT_SHADER_ARB, fragment_shader_source, 0);
- if(err) goto errout;
+ err = compile_source(fragment_shader, GL_FRAGMENT_SHADER_ARB, fragment_shader_source, false);
+ if (err)
+ goto errout;
}
- pfn_glAttachObjectARB(*program, *fragment_shader);
+ pfn_glAttachObjectARB(*program, *fragment_shader);
- pfn_glLinkProgramARB(*program);
- err=GL_SHADER_CHECK(*program, GL_OBJECT_LINK_STATUS_ARB);
- if(err) {
+ pfn_glLinkProgramARB(*program);
+ err = GL_SHADER_CHECK(*program, GL_OBJECT_LINK_STATUS_ARB);
+ if (err)
+ {
osd_printf_warning("failed to link program\n");
osd_printf_warning("vertex shader: <%s>\n", vertex_shader_source);
osd_printf_warning("fragment shader: <%s>\n", fragment_shader_source);
goto errout;
}
- pfn_glValidateProgramARB(*program);
- err=GL_SHADER_CHECK(*program, GL_OBJECT_VALIDATE_STATUS_ARB);
- if(err) {
+ pfn_glValidateProgramARB(*program);
+ err = GL_SHADER_CHECK(*program, GL_OBJECT_VALIDATE_STATUS_ARB);
+ if (err)
+ {
osd_printf_warning("failed to validate program\n");
osd_printf_warning("vertex shader: <%s>\n", vertex_shader_source);
osd_printf_warning("fragment shader: <%s>\n", fragment_shader_source);
goto errout;
}
- return 0;
+ return 0;
errout:
- delete_shader_tool(program, vertex_shader, fragment_shader, 0);
- return err;
-
+ delete_shader_tool(program, vertex_shader, fragment_shader, false);
+ return err;
}
-int gl_delete_shader( GLhandleARB *program, GLhandleARB *vertex_shader, GLhandleARB *fragment_shader )
+int gl_shader_tool::delete_shader(
+ GLhandleARB *program,
+ GLhandleARB *vertex_shader,
+ GLhandleARB *fragment_shader)
{
- return delete_shader_tool(program, vertex_shader, fragment_shader, 1);
+ return delete_shader_tool(program, vertex_shader, fragment_shader, true);
}
diff --git a/src/osd/modules/opengl/gl_shader_tool.h b/src/osd/modules/opengl/gl_shader_tool.h
index 2e0160cf85d..28a84143b29 100644
--- a/src/osd/modules/opengl/gl_shader_tool.h
+++ b/src/osd/modules/opengl/gl_shader_tool.h
@@ -17,10 +17,14 @@
* GL_ARB_fragment_shader
*
*/
+#ifndef MAME_OSD_OPENGL_GL_SHADER_TOOL_H
+#define MAME_OSD_OPENGL_GL_SHADER_TOOL_H
+#pragma once
-#ifndef _GL_SHADER_TOOL_
-#define _GL_SHADER_TOOL_
+#include "osd_opengl.h"
+
+#include <stdint.h>
#ifdef __cplusplus
extern "C" {
@@ -36,14 +40,10 @@ extern "C" {
*
*/
-#include <stdint.h>
-
#ifndef GL_GLEXT_PROTOTYPES
#define GL_GLEXT_PROTOTYPES 1
#endif
-#include "osd_opengl.h"
-
#if defined(SDLMAME_MACOSX)
#ifndef APIENTRY
@@ -55,80 +55,6 @@ extern "C" {
#endif
-typedef void * (APIENTRYP PFNGLGETPROCADDRESSOS)(const char *procName);
-
-/**
- * YOU HAVE TO CALL THIS FUNCTION ONCE !
- * @return 0 - ok .. all shader ARB functions loaded
- * otherwise !=0
- */
-int gl_shader_loadExtention(osd_gl_context *gl_ctx);
-
-enum GLSLCheckMode {
- CHECK_QUIET, /* just return 0, if no error, otherwise the GL error code, no stderr output */
- CHECK_VERBOSE, /* same as CHECK_QUIET, but in the case of an error, use stderr to be verbose */
- CHECK_ALWAYS_VERBOSE /* always print out all information available */
-};
-
-#define GL_CHECK_ERROR_VERBOSE() gl_check_error(CHECK_ALWAYS_VERBOSE,__FILE__,__LINE__)
-#define GL_CHECK_ERROR_NORMAL() gl_check_error(CHECK_VERBOSE,__FILE__,__LINE__)
-#define GL_CHECK_ERROR_QUIET() gl_check_error(CHECK_QUIET,__FILE__,__LINE__)
-#define GL_CHECK_ERROR(m) gl_check_error(m,__FILE__,__LINE__)
-
-#define GL_SHADER_CHECK_ERROR_VERBOSE(o,q) gl_shader_check_error(o,q,CHECK_ALWAYS_VERBOSE,__FILE__,__LINE__)
-#define GL_SHADER_CHECK_ERROR_NORMAL(o,q) gl_shader_check_error(o,q,CHECK_VERBOSE,__FILE__,__LINE__)
-#define GL_SHADER_CHECK_ERROR_QUIET(o,q) gl_shader_check_error(o,q,CHECK_QUIET,__FILE__,__LINE__)
-#define GL_SHADER_CHECK_ERROR(o,q,m) gl_shader_check_error(o,q,m,__FILE__,__LINE__)
-
-#ifdef GL_SHADER_TOOL_DEBUG
- #define GL_SHADER_CHECK(o,q) GL_SHADER_CHECK_ERROR_VERBOSE(o,q)
- #define GL_CHECK() GL_CHECK_ERROR_VERBOSE()
-#else
- #define GL_SHADER_CHECK(o,q) GL_SHADER_CHECK_ERROR_NORMAL(o,q)
- #define GL_CHECK() GL_CHECK_ERROR_NORMAL()
-#endif
-
-int gl_check_error(GLSLCheckMode m, const char *file, const int line);
-
-int gl_texture_check_size(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height,
- GLint border, GLenum format, GLenum type,
- GLsizei *avail_width, GLsizei *avail_height,
- int verbose);
-
-int gl_round_to_pow2(int v);
-
-/**
- * @param obj_query Can be either GL_OBJECT_TYPE_ARB, GL_OBJECT_DELETE_STATUS_ARB, GL_OBJECT_COMPILE_STATUS_ARB,
- * GL_OBJECT_LINK_STATUS_ARB, GL_OBJECT_VALIDATE_STATUS_ARB
- * Should be used after the referring action, i.e. GL_OBJECT_DELETE_STATUS_ARB after a
- * glDeleteObjectARB call, etc.
- */
-int gl_shader_check_error(GLhandleARB obj, GLenum obj_query, GLSLCheckMode m, const char *file, const int line);
-
-int gl_compile_shader_file ( GLhandleARB *shader, GLenum type, const char * shader_file, int verbose );
-int gl_compile_shader_source( GLhandleARB *shader, GLenum type, const char * shader_source, int verbose );
-
-/**
- * you can pass either a valid shader_file, or a precompiled vertex_shader,
- * this is true for both, vertex and fragment shaders.
- */
-int gl_compile_shader_files( GLhandleARB *program, GLhandleARB *vertex_shader, GLhandleARB *fragment_shader,
- const char * vertex_shader_file,
- const char * fragment_shader_file,
- int verbose
- );
-
-/**
- * you can pass either a valid shader_file, or a precompiled vertex_shader,
- * this is true for both, vertex and fragment shaders.
- */
-int gl_compile_shader_sources( GLhandleARB *program, GLhandleARB *vertex_shader, GLhandleARB *fragment_shader,
- const GLcharARB * vertex_shader_source,
- const GLcharARB * fragment_shader_source
- );
-
-int gl_delete_shader( GLhandleARB *program, GLhandleARB *vertex_shader, GLhandleARB *fragment_shader );
-
#if defined(SDLMAME_MACOSX)
#ifndef GL_ARB_shader_objects
typedef char GLcharARB;
@@ -158,32 +84,118 @@ typedef void (APIENTRYP PFNGLUNIFORM3IVARBPROC) (GLint location, GLsizei count,
typedef void (APIENTRYP PFNGLUNIFORM4IVARBPROC) (GLint location, GLsizei count, const GLint *value);
#endif
-extern PFNGLGETOBJECTPARAMETERIVARBPROC pfn_glGetObjectParameterivARB;
-extern PFNGLGETINFOLOGARBPROC pfn_glGetInfoLogARB;
-extern PFNGLDELETEOBJECTARBPROC pfn_glDeleteObjectARB;
-extern PFNGLCREATESHADEROBJECTARBPROC pfn_glCreateShaderObjectARB;
-extern PFNGLSHADERSOURCEARBPROC pfn_glShaderSourceARB;
-extern PFNGLCOMPILESHADERARBPROC pfn_glCompileShaderARB;
-extern PFNGLCREATEPROGRAMOBJECTARBPROC pfn_glCreateProgramObjectARB;
-extern PFNGLATTACHOBJECTARBPROC pfn_glAttachObjectARB;
-extern PFNGLLINKPROGRAMARBPROC pfn_glLinkProgramARB;
-extern PFNGLVALIDATEPROGRAMARBPROC pfn_glValidateProgramARB;
-extern PFNGLUSEPROGRAMOBJECTARBPROC pfn_glUseProgramObjectARB;
-extern PFNGLGETUNIFORMLOCATIONARBPROC pfn_glGetUniformLocationARB;
-extern PFNGLUNIFORM1FARBPROC pfn_glUniform1fARB;
-extern PFNGLUNIFORM1IARBPROC pfn_glUniform1iARB;
-extern PFNGLUNIFORM1FVARBPROC pfn_glUniform1fvARB;
-extern PFNGLUNIFORM2FVARBPROC pfn_glUniform2fvARB;
-extern PFNGLUNIFORM3FVARBPROC pfn_glUniform3fvARB;
-extern PFNGLUNIFORM4FVARBPROC pfn_glUniform4fvARB;
-extern PFNGLUNIFORM1IVARBPROC pfn_glUniform1ivARB;
-extern PFNGLUNIFORM2IVARBPROC pfn_glUniform2ivARB;
-extern PFNGLUNIFORM3IVARBPROC pfn_glUniform3ivARB;
-extern PFNGLUNIFORM4IVARBPROC pfn_glUniform4ivARB;
-
+typedef void * (APIENTRYP PFNGLGETPROCADDRESSOS)(const char *procName);
#ifdef __cplusplus
}
#endif
+class gl_shader_tool
+{
+public:
+ gl_shader_tool(
+#if defined(USE_DISPATCH_GL)
+ osd_gl_dispatch *gld
#endif
+ );
+
+ PFNGLGETOBJECTPARAMETERIVARBPROC pfn_glGetObjectParameterivARB;
+ PFNGLGETINFOLOGARBPROC pfn_glGetInfoLogARB;
+ PFNGLDELETEOBJECTARBPROC pfn_glDeleteObjectARB;
+ PFNGLCREATESHADEROBJECTARBPROC pfn_glCreateShaderObjectARB;
+ PFNGLSHADERSOURCEARBPROC pfn_glShaderSourceARB;
+ PFNGLCOMPILESHADERARBPROC pfn_glCompileShaderARB;
+ PFNGLCREATEPROGRAMOBJECTARBPROC pfn_glCreateProgramObjectARB;
+ PFNGLATTACHOBJECTARBPROC pfn_glAttachObjectARB;
+ PFNGLLINKPROGRAMARBPROC pfn_glLinkProgramARB;
+ PFNGLVALIDATEPROGRAMARBPROC pfn_glValidateProgramARB;
+ PFNGLUSEPROGRAMOBJECTARBPROC pfn_glUseProgramObjectARB;
+ PFNGLGETUNIFORMLOCATIONARBPROC pfn_glGetUniformLocationARB;
+ PFNGLUNIFORM1FARBPROC pfn_glUniform1fARB;
+ PFNGLUNIFORM1IARBPROC pfn_glUniform1iARB;
+ PFNGLUNIFORM1FVARBPROC pfn_glUniform1fvARB;
+ PFNGLUNIFORM2FVARBPROC pfn_glUniform2fvARB;
+ PFNGLUNIFORM3FVARBPROC pfn_glUniform3fvARB;
+ PFNGLUNIFORM4FVARBPROC pfn_glUniform4fvARB;
+ PFNGLUNIFORM1IVARBPROC pfn_glUniform1ivARB;
+ PFNGLUNIFORM2IVARBPROC pfn_glUniform2ivARB;
+ PFNGLUNIFORM3IVARBPROC pfn_glUniform3ivARB;
+ PFNGLUNIFORM4IVARBPROC pfn_glUniform4ivARB;
+
+ /**
+ * YOU HAVE TO CALL THIS FUNCTION ONCE !
+ * @return true - ok .. all shader ARB functions loaded
+ * otherwise false
+ */
+ bool load_extension(osd_gl_context &gl_ctx);
+
+ int texture_check_size(
+ GLenum target,
+ GLint level,
+ GLint internalFormat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ GLsizei *avail_width,
+ GLsizei *avail_height,
+ bool verbose);
+
+protected:
+ int compile_file(GLhandleARB *shader, GLenum type, const char *shader_file, bool verbose);
+ int compile_source(GLhandleARB *shader, GLenum type, const char *shader_source, bool verbose);
+
+ /**
+ * you can pass either a valid shader_file, or a precompiled vertex_shader,
+ * this is true for both, vertex and fragment shaders.
+ */
+ int compile_files(
+ GLhandleARB *program,
+ GLhandleARB *vertex_shader,
+ GLhandleARB *fragment_shader,
+ const char *vertex_shader_file,
+ const char *fragment_shader_file,
+ bool verbose);
+
+ /**
+ * you can pass either a valid shader_file, or a precompiled vertex_shader,
+ * this is true for both, vertex and fragment shaders.
+ */
+ int compile_sources(
+ GLhandleARB *program,
+ GLhandleARB *vertex_shader,
+ GLhandleARB *fragment_shader,
+ const GLcharARB *vertex_shader_source,
+ const GLcharARB *fragment_shader_source);
+
+ int delete_shader(GLhandleARB *program, GLhandleARB *vertex_shader, GLhandleARB *fragment_shader);
+
+#if defined(USE_DISPATCH_GL)
+ osd_gl_dispatch *const gl_dispatch; // name is magic, can't be changed
+#endif
+
+private:
+ enum GLSLCheckMode
+ {
+ CHECK_QUIET, // just return 0, if no error, otherwise the GL error code, no stderr output
+ CHECK_VERBOSE, // same as CHECK_QUIET, but in the case of an error, use stderr to be verbose
+ CHECK_ALWAYS_VERBOSE // always print out all information available
+ };
+
+ int check_error(GLSLCheckMode m, const char *file, const int line);
+
+ /**
+ * @param obj_query Can be either GL_OBJECT_TYPE_ARB, GL_OBJECT_DELETE_STATUS_ARB, GL_OBJECT_COMPILE_STATUS_ARB,
+ * GL_OBJECT_LINK_STATUS_ARB, GL_OBJECT_VALIDATE_STATUS_ARB
+ * Should be used after the referring action, i.e. GL_OBJECT_DELETE_STATUS_ARB after a
+ * glDeleteObjectARB call, etc.
+ */
+ int check_error(GLhandleARB obj, GLenum obj_query, GLSLCheckMode m, const char *file, const int line);
+
+ int delete_shader_tool(GLhandleARB *program, GLhandleARB *vertex_shader, GLhandleARB *fragment_shader, bool externalcall);
+};
+
+int gl_round_to_pow2(int v);
+
+#endif // MAME_OSD_OPENGL_GL_SHADER_TOOL_H
diff --git a/src/osd/modules/opengl/osd_opengl.h b/src/osd/modules/opengl/osd_opengl.h
index d3e2a758d73..712b3b880b4 100644
--- a/src/osd/modules/opengl/osd_opengl.h
+++ b/src/osd/modules/opengl/osd_opengl.h
@@ -36,35 +36,38 @@
#include <OpenGL/gl.h>
#include <OpenGL/glext.h>
#else
- #include <SDL2/SDL_version.h>
-
- #if (SDL_VERSION_ATLEAST(1,2,10))
- #if defined(SDLMAME_WIN32)
- // Avoid that winnt.h (included via sdl_opengl.h, windows.h, windef.h includes intrin.h
- #define __INTRIN_H_
- #endif
- #include <SDL2/SDL_opengl.h>
- #endif
+ #include <SDL2/SDL_version.h>
+ #include <SDL2/SDL_opengl.h>
#endif
class osd_gl_context
{
public:
- osd_gl_context() { }
- virtual ~osd_gl_context() { }
- virtual void MakeCurrent() = 0;
- virtual const char *LastErrorMsg() = 0;
- virtual void *getProcAddress(const char *proc) = 0;
+ virtual ~osd_gl_context() = default;
+
+ virtual explicit operator bool() const = 0;
+
+ virtual void make_current() = 0;
+ virtual const char *last_error_message() = 0;
+ virtual void *get_proc_address(const char *proc) = 0;
+
/*
* 0 for immediate updates,
* 1 for updates synchronized with the vertical retrace,
* -1 for late swap tearing
*
- * returns -1 if swap interval is not supported
- *
+ * returns false if swap interval is not supported
*/
- virtual int SetSwapInterval(const int swap) = 0;
- virtual void SwapBuffer() = 0;
+ virtual bool set_swap_interval(const int swap) = 0;
+
+ virtual void swap_buffer() = 0;
+
+ template <typename T>
+ bool get_proc_address(T &ptr, const char *name)
+ {
+ ptr = T(uintptr_t(get_proc_address(name)));
+ return bool(ptr);
+ }
};
@@ -100,11 +103,6 @@
#undef OSD_GL
#undef OSD_GL_UNUSED
-#ifdef _MSC_VER
- extern "C" osd_gl_dispatch *gl_dispatch;
-#endif
- extern osd_gl_dispatch *gl_dispatch;
-
/*
* Use gl_mangle to map function names
*/
@@ -127,67 +125,67 @@
*
***************************************************************/
- #define glAccum MANGLE(Accum)
- #define glActiveStencilFaceEXT MANGLE(ActiveStencilFaceEXT)
- #define glActiveTextureARB MANGLE(ActiveTextureARB)
- #define glActiveTexture MANGLE(ActiveTexture)
- #define glAlphaFragmentOp1ATI MANGLE(AlphaFragmentOp1ATI)
- #define glAlphaFragmentOp2ATI MANGLE(AlphaFragmentOp2ATI)
- #define glAlphaFragmentOp3ATI MANGLE(AlphaFragmentOp3ATI)
- #define glAlphaFunc MANGLE(AlphaFunc)
- #define glApplyTextureEXT MANGLE(ApplyTextureEXT)
- #define glAreProgramsResidentNV MANGLE(AreProgramsResidentNV)
+ #define glAccum MANGLE(Accum)
+ #define glActiveStencilFaceEXT MANGLE(ActiveStencilFaceEXT)
+ #define glActiveTextureARB MANGLE(ActiveTextureARB)
+ #define glActiveTexture MANGLE(ActiveTexture)
+ #define glAlphaFragmentOp1ATI MANGLE(AlphaFragmentOp1ATI)
+ #define glAlphaFragmentOp2ATI MANGLE(AlphaFragmentOp2ATI)
+ #define glAlphaFragmentOp3ATI MANGLE(AlphaFragmentOp3ATI)
+ #define glAlphaFunc MANGLE(AlphaFunc)
+ #define glApplyTextureEXT MANGLE(ApplyTextureEXT)
+ #define glAreProgramsResidentNV MANGLE(AreProgramsResidentNV)
#define glAreTexturesResidentEXT MANGLE(AreTexturesResidentEXT)
- #define glAreTexturesResident MANGLE(AreTexturesResident)
- #define glArrayElementEXT MANGLE(ArrayElementEXT)
- #define glArrayElement MANGLE(ArrayElement)
- #define glArrayObjectATI MANGLE(ArrayObjectATI)
- #define glAsyncMarkerSGIX MANGLE(AsyncMarkerSGIX)
- #define glAttachObjectARB MANGLE(AttachObjectARB)
- #define glAttachShader MANGLE(AttachShader)
+ #define glAreTexturesResident MANGLE(AreTexturesResident)
+ #define glArrayElementEXT MANGLE(ArrayElementEXT)
+ #define glArrayElement MANGLE(ArrayElement)
+ #define glArrayObjectATI MANGLE(ArrayObjectATI)
+ #define glAsyncMarkerSGIX MANGLE(AsyncMarkerSGIX)
+ #define glAttachObjectARB MANGLE(AttachObjectARB)
+ #define glAttachShader MANGLE(AttachShader)
#define glBeginFragmentShaderATI MANGLE(BeginFragmentShaderATI)
- #define glBegin MANGLE(Begin)
- #define glBeginOcclusionQueryNV MANGLE(BeginOcclusionQueryNV)
- #define glBeginQueryARB MANGLE(BeginQueryARB)
- #define glBeginQuery MANGLE(BeginQuery)
- #define glBeginVertexShaderEXT MANGLE(BeginVertexShaderEXT)
- #define glBindAttribLocationARB MANGLE(BindAttribLocationARB)
- #define glBindAttribLocation MANGLE(BindAttribLocation)
- #define glBindBufferARB MANGLE(BindBufferARB)
- #define glBindBuffer MANGLE(BindBuffer)
- #define glBindFragmentShaderATI MANGLE(BindFragmentShaderATI)
- #define glBindFramebufferEXT MANGLE(BindFramebufferEXT)
- #define glBindLightParameterEXT MANGLE(BindLightParameterEXT)
+ #define glBegin MANGLE(Begin)
+ #define glBeginOcclusionQueryNV MANGLE(BeginOcclusionQueryNV)
+ #define glBeginQueryARB MANGLE(BeginQueryARB)
+ #define glBeginQuery MANGLE(BeginQuery)
+ #define glBeginVertexShaderEXT MANGLE(BeginVertexShaderEXT)
+ #define glBindAttribLocationARB MANGLE(BindAttribLocationARB)
+ #define glBindAttribLocation MANGLE(BindAttribLocation)
+ #define glBindBufferARB MANGLE(BindBufferARB)
+ #define glBindBuffer MANGLE(BindBuffer)
+ #define glBindFragmentShaderATI MANGLE(BindFragmentShaderATI)
+ #define glBindFramebufferEXT MANGLE(BindFramebufferEXT)
+ #define glBindLightParameterEXT MANGLE(BindLightParameterEXT)
#define glBindMaterialParameterEXT MANGLE(BindMaterialParameterEXT)
- #define glBindParameterEXT MANGLE(BindParameterEXT)
- #define glBindProgramARB MANGLE(BindProgramARB)
- #define glBindProgramNV MANGLE(BindProgramNV)
- #define glBindRenderbufferEXT MANGLE(BindRenderbufferEXT)
+ #define glBindParameterEXT MANGLE(BindParameterEXT)
+ #define glBindProgramARB MANGLE(BindProgramARB)
+ #define glBindProgramNV MANGLE(BindProgramNV)
+ #define glBindRenderbufferEXT MANGLE(BindRenderbufferEXT)
#define glBindTexGenParameterEXT MANGLE(BindTexGenParameterEXT)
- #define glBindTextureEXT MANGLE(BindTextureEXT)
- #define glBindTexture MANGLE(BindTexture)
- #define glBindTextureUnitParameterEXT MANGLE(BindTextureUnitParameterEXT)
- #define glBindVertexArrayAPPLE MANGLE(BindVertexArrayAPPLE)
- #define glBindVertexShaderEXT MANGLE(BindVertexShaderEXT)
- #define glBinormal3bEXT MANGLE(Binormal3bEXT)
- #define glBinormal3bvEXT MANGLE(Binormal3bvEXT)
- #define glBinormal3dEXT MANGLE(Binormal3dEXT)
- #define glBinormal3dvEXT MANGLE(Binormal3dvEXT)
- #define glBinormal3fEXT MANGLE(Binormal3fEXT)
- #define glBinormal3fvEXT MANGLE(Binormal3fvEXT)
- #define glBinormal3iEXT MANGLE(Binormal3iEXT)
- #define glBinormal3ivEXT MANGLE(Binormal3ivEXT)
- #define glBinormal3sEXT MANGLE(Binormal3sEXT)
- #define glBinormal3svEXT MANGLE(Binormal3svEXT)
- #define glBinormalPointerEXT MANGLE(BinormalPointerEXT)
- #define glBitmap MANGLE(Bitmap)
- #define glBlendColorEXT MANGLE(BlendColorEXT)
- #define glBlendColor MANGLE(BlendColor)
- #define glBlendEquationEXT MANGLE(BlendEquationEXT)
- #define glBlendEquation MANGLE(BlendEquation)
+ #define glBindTextureEXT MANGLE(BindTextureEXT)
+ #define glBindTexture MANGLE(BindTexture)
+ #define glBindTextureUnitParameterEXT MANGLE(BindTextureUnitParameterEXT)
+ #define glBindVertexArrayAPPLE MANGLE(BindVertexArrayAPPLE)
+ #define glBindVertexShaderEXT MANGLE(BindVertexShaderEXT)
+ #define glBinormal3bEXT MANGLE(Binormal3bEXT)
+ #define glBinormal3bvEXT MANGLE(Binormal3bvEXT)
+ #define glBinormal3dEXT MANGLE(Binormal3dEXT)
+ #define glBinormal3dvEXT MANGLE(Binormal3dvEXT)
+ #define glBinormal3fEXT MANGLE(Binormal3fEXT)
+ #define glBinormal3fvEXT MANGLE(Binormal3fvEXT)
+ #define glBinormal3iEXT MANGLE(Binormal3iEXT)
+ #define glBinormal3ivEXT MANGLE(Binormal3ivEXT)
+ #define glBinormal3sEXT MANGLE(Binormal3sEXT)
+ #define glBinormal3svEXT MANGLE(Binormal3svEXT)
+ #define glBinormalPointerEXT MANGLE(BinormalPointerEXT)
+ #define glBitmap MANGLE(Bitmap)
+ #define glBlendColorEXT MANGLE(BlendColorEXT)
+ #define glBlendColor MANGLE(BlendColor)
+ #define glBlendEquationEXT MANGLE(BlendEquationEXT)
+ #define glBlendEquation MANGLE(BlendEquation)
#define glBlendEquationSeparateATI MANGLE(BlendEquationSeparateATI)
#define glBlendEquationSeparateEXT MANGLE(BlendEquationSeparateEXT)
- #define glBlendEquationSeparate MANGLE(BlendEquationSeparate)
+ #define glBlendEquationSeparate MANGLE(BlendEquationSeparate)
#define glBlendFunc MANGLE(BlendFunc)
#define glBlendFuncSeparateEXT MANGLE(BlendFuncSeparateEXT)
#define glBlendFuncSeparateINGR MANGLE(BlendFuncSeparateINGR)
diff --git a/src/osd/modules/osdmodule.cpp b/src/osd/modules/osdmodule.cpp
index 4f2cf079e3b..0fb43d4331a 100644
--- a/src/osd/modules/osdmodule.cpp
+++ b/src/osd/modules/osdmodule.cpp
@@ -1,11 +1,14 @@
// license:BSD-3-Clause
// copyright-holders:Couriersud
/*
- * osdmodule.c
+ * osdmodule.cpp
*
*/
#include "modules/osdmodule.h"
+
+#include "emucore.h"
+
#include "osdcore.h"
#include <algorithm>
@@ -47,20 +50,62 @@ osd_module *osd_module_manager::get_module_generic(const char *type, const char
return nullptr;
}
-osd_module *osd_module_manager::select_module(const char *type, const char *name)
+osd_module &osd_module_manager::select_module(osd_interface &osd, const osd_options &options, const char *type, const char *name)
{
- osd_module *m = get_module_generic(type, name);
+ // see if a module of this type has already been already selected
+ for (osd_module &existing : m_selected)
+ {
+ if (existing.type() == type)
+ {
+ osd_printf_warning(
+ "Attempt to select %s module %s after selecting module %s\n",
+ type,
+ (name && *name) ? name : "<default>",
+ existing.name());
+ return existing;
+ }
+ }
- // FIXME: check if already exists!
+ // try to start the selected module
+ osd_module *const m = get_module_generic(type, name);
if (m)
- m_selected.emplace_back(*m);
- return m;
-}
+ {
+ //osd_printf_verbose("Attempting to initialize %s module %s\n", type, m->name());
+ if (!m->init(osd, options))
+ {
+ m_selected.emplace_back(*m);
+ return *m;
+ }
+ osd_printf_verbose("Initializing %s module %s failed\n", type, m->name());
+ }
+ else
+ {
+ osd_printf_verbose("Could not find %s module %s\n", type, name ? name : "<default>");
+ }
-void osd_module_manager::init(const osd_options &options)
-{
- for (osd_module &m : m_selected)
- m.init(options);
+ // walk down the list until something works
+ for (auto const &fallback : m_modules)
+ {
+ if ((fallback->type() == type) && (fallback.get() != m))
+ {
+ osd_printf_verbose("Attempting to initialize %s module %s\n", type, fallback->name());
+ if (!fallback->init(osd, options))
+ {
+ osd_printf_warning(
+ m
+ ? "Initializing %s module %s failed, falling back to %s\n"
+ : "Could not find %s module %s, falling back to %s\n",
+ type,
+ m ? m->name() : (name && *name) ? name : "<default>",
+ fallback->name());
+ m_selected.emplace_back(*fallback);
+ return *fallback;
+ }
+ }
+ }
+
+ // can't deal with absence of a module, and at least the "none" module should have worked
+ throw emu_fatalerror("All %s modules failed to initialize", type);
}
void osd_module_manager::exit()
@@ -83,12 +128,13 @@ int osd_module_manager::get_module_index(const char *type, const char *name) con
return -1;
}
-void osd_module_manager::get_module_names(const char *type, const int max, int &num, const char *names[]) const
+std::vector<std::string_view> osd_module_manager::get_module_names(const char *type) const
{
- num = 0;
- for (int i = 0; (m_modules.size() > i) && (max > num); i++)
+ std::vector<std::string_view> result;
+ for (auto &m : m_modules)
{
- if (m_modules[i]->type() == type)
- names[num++] = m_modules[i]->name().c_str();
+ if (m->type() == type)
+ result.emplace_back(m->name());
}
+ return result;
}
diff --git a/src/osd/modules/osdmodule.h b/src/osd/modules/osdmodule.h
index 1c662417601..b690f874706 100644
--- a/src/osd/modules/osdmodule.h
+++ b/src/osd/modules/osdmodule.h
@@ -15,6 +15,7 @@
#include <functional>
#include <memory>
#include <string>
+#include <string_view>
#include <vector>
@@ -22,9 +23,13 @@
// TYPE DEFINITIONS
//============================================================
+class osd_interface;
class osd_options;
-// ======================> osd_module
+
+//============================================================
+// TYPE DEFINITIONS
+//============================================================
class osd_module
{
@@ -36,7 +41,7 @@ public:
virtual bool probe() { return true; }
- virtual int init(const osd_options &options) = 0;
+ virtual int init(osd_interface &osd, const osd_options &options) = 0;
virtual void exit() { }
protected:
@@ -48,9 +53,11 @@ private:
std::string const m_type;
};
+
// a module_type is simply a pointer to its alloc function
typedef std::unique_ptr<osd_module> (*module_type)();
+
// this template function creates a stub which constructs a module
template <class ModuleClass>
std::unique_ptr<osd_module> module_creator()
@@ -58,6 +65,7 @@ std::unique_ptr<osd_module> module_creator()
return std::unique_ptr<osd_module>(new ModuleClass);
}
+
class osd_module_manager
{
public:
@@ -70,16 +78,14 @@ public:
osd_module *get_module_generic(const char *type, const char *name);
template<class C>
- C select_module(const char *type, const char *name = "")
+ C &select_module(osd_interface &osd, const osd_options &options, const char *type, const char *name = "")
{
- return dynamic_cast<C>(select_module(type, name));
+ return dynamic_cast<C &>(select_module(osd, options, type, name));
}
- osd_module *select_module(const char *type, const char *name = "");
+ osd_module &select_module(osd_interface &osd, const osd_options &options, const char *type, const char *name = "");
- void get_module_names(const char *type, const int max, int &num, const char *names[]) const;
-
- void init(const osd_options &options);
+ std::vector<std::string_view> get_module_names(const char *type) const;
void exit();
@@ -90,18 +96,20 @@ private:
std::vector<std::reference_wrapper<osd_module> > m_selected;
};
+
#define MODULE_DEFINITION(mod_id, mod_class) \
- extern const module_type mod_id ; \
- const module_type mod_id = &module_creator< mod_class >;
+ extern const module_type mod_id ; \
+ const module_type mod_id = &module_creator<mod_class>;
#define MODULE_NOT_SUPPORTED(mod_class, mod_type, mod_name) \
- class mod_class : public osd_module { \
- public: \
- mod_class () : osd_module(mod_type, mod_name) { } \
- virtual ~mod_class() { } \
- virtual int init(const osd_options &options) override { return -1; } \
- virtual bool probe() override { return false; } \
- };
+ class mod_class : public osd_module \
+ { \
+ public: \
+ mod_class () : osd_module(mod_type, mod_name) { } \
+ virtual ~mod_class() { } \
+ virtual int init(osd_interface &osd, const osd_options &options) override { return -1; } \
+ virtual bool probe() override { return false; } \
+ };
#endif /* MAME_OSD_MODULES_OSDMODULE_H */
diff --git a/src/osd/modules/osdwindow.cpp b/src/osd/modules/osdwindow.cpp
index bc20676cbad..38b86e652e0 100644
--- a/src/osd/modules/osdwindow.cpp
+++ b/src/osd/modules/osdwindow.cpp
@@ -8,26 +8,23 @@
#include "emu.h"
#include "osdwindow.h"
-#include "modules/lib/osdobj_common.h"
-#include "modules/monitor/monitor_module.h"
-
-#include "render/drawnone.h"
-#include "render/drawbgfx.h"
-#if (USE_OPENGL)
-#include "render/drawogl.h"
-#endif
-#if defined(OSD_WINDOWS)
-#include "render/drawgdi.h"
-#include "render/drawd3d.h"
-#elif defined(OSD_SDL)
-#include "render/draw13.h"
-#include "render/drawsdl.h"
-#endif
-
-osd_window::osd_window(running_machine &machine, int index, std::shared_ptr<osd_monitor_info> monitor, const osd_window_config &config) :
-#ifdef OSD_WINDOWS
- m_dc(nullptr), m_resize_state(0),
-#endif
+
+// osd/modules
+#include "lib/osdobj_common.h"
+#include "monitor/monitor_module.h"
+#include "render/render_module.h"
+
+// emu
+#include "main.h"
+#include "render.h"
+
+
+osd_window::osd_window(
+ running_machine &machine,
+ render_module &renderprovider,
+ int index,
+ const std::shared_ptr<osd_monitor_info> &monitor,
+ const osd_window_config &config) :
m_target(nullptr),
m_primlist(nullptr),
m_win_config(config),
@@ -35,22 +32,26 @@ osd_window::osd_window(running_machine &machine, int index, std::shared_ptr<osd_
m_fullscreen(false),
m_prescale(1),
m_machine(machine),
+ m_renderprovider(renderprovider),
m_monitor(std::move(monitor)),
m_renderer(nullptr),
- m_main(nullptr),
m_title(
util::string_format(
(video_config.numscreens > 1)
? "%3$s [%4$s] screen %5$d - %1$s %2$s (%6$s%7$sP%8$d)"
: "%3$s [%4$s] - %1$s %2$s (%6$s%7$sP%8$d)",
- emulator_info::get_appname(),
- emulator_info::get_bare_build_version(),
- machine.system().type.fullname(),
- machine.system().name,
- index,
- (sizeof(int) == sizeof(void *)) ? "I" : "",
- (sizeof(long) == sizeof(void *)) ? "L" : (sizeof(long long) == sizeof(void *)) ? "LL" : "",
- sizeof(void *) * 8))
+ emulator_info::get_appname(),
+ emulator_info::get_bare_build_version(),
+ machine.system().type.fullname(),
+ machine.system().name,
+ index,
+ (sizeof(int) == sizeof(void *)) ? "I" : "",
+ (sizeof(long) == sizeof(void *)) ? "L" : (sizeof(long long) == sizeof(void *)) ? "LL" : "",
+ sizeof(void *) * 8))
+{
+}
+
+osd_window::~osd_window()
{
}
@@ -76,36 +77,6 @@ bool osd_window::keepaspect() const
return false;
}
-std::unique_ptr<osd_renderer> osd_renderer::make_for_type(int mode, std::shared_ptr<osd_window> window, int extra_flags)
-{
- switch(mode)
- {
-#if defined(OSD_WINDOWS)
- case VIDEO_MODE_NONE:
- return std::make_unique<renderer_none>(window);
-#endif
- case VIDEO_MODE_BGFX:
- return std::make_unique<renderer_bgfx>(window);
-#if (USE_OPENGL)
- case VIDEO_MODE_OPENGL:
- return std::make_unique<renderer_ogl>(window);
-#endif
-#if defined(OSD_WINDOWS)
- case VIDEO_MODE_GDI:
- return std::make_unique<renderer_gdi>(window);
- case VIDEO_MODE_D3D:
- return std::make_unique<renderer_d3d9>(window);
-#elif defined(OSD_SDL)
- case VIDEO_MODE_SDL2ACCEL:
- return std::make_unique<renderer_sdl2>(window, extra_flags);
- case VIDEO_MODE_SOFT:
- return std::make_unique<renderer_sdl1>(window, extra_flags);
-#endif
- default:
- return nullptr;
- }
-}
-
std::shared_ptr<osd_monitor_info> osd_window::monitor_from_rect(const osd_rect *proposed) const
{
std::shared_ptr<osd_monitor_info> monitor;
@@ -122,9 +93,6 @@ std::shared_ptr<osd_monitor_info> osd_window::monitor_from_rect(const osd_rect *
void osd_window::create_target()
{
- // add us to the list
- osd_common_t::s_window_list.push_back(shared_from_this());
-
// load the layout
m_target = m_machine.render().target_alloc();
@@ -133,6 +101,21 @@ void osd_window::create_target()
set_starting_view(m_index, options.view(), options.view(m_index));
}
+bool osd_window::renderer_interactive() const
+{
+ return m_renderprovider.is_interactive();
+}
+
+bool osd_window::renderer_sdl_needs_opengl() const
+{
+ return m_renderprovider.sdl_needs_opengl();
+}
+
+void osd_window::renderer_create()
+{
+ m_renderer = m_renderprovider.create(*this);
+}
+
void osd_window::set_starting_view(int index, const char *defview, const char *view)
{
// choose non-auto over auto
@@ -148,9 +131,6 @@ void osd_window::set_starting_view(int index, const char *defview, const char *v
void osd_window::destroy()
{
- // remove us from the list
- osd_common_t::s_window_list.remove(shared_from_this());
-
// free the textures etc
complete_destroy();
diff --git a/src/osd/modules/osdwindow.h b/src/osd/modules/osdwindow.h
index f0f3813e407..f3d39878b5e 100644
--- a/src/osd/modules/osdwindow.h
+++ b/src/osd/modules/osdwindow.h
@@ -6,13 +6,19 @@
//
//============================================================
-#ifndef __OSDWINDOW__
-#define __OSDWINDOW__
+#ifndef MAME_OSD_MODULES_OSDWINDOW_H
+#define MAME_OSD_MODULES_OSDWINDOW_H
+
+#pragma once
#include "emucore.h"
#include "osdhelper.h"
#include "../frontend/mame/ui/menuitem.h"
+#include <memory>
+#include <string>
+#include <vector>
+
// standard windows headers
#ifdef OSD_WINDOWS
#include <windows.h>
@@ -20,32 +26,16 @@
#include <mmsystem.h>
#endif
-#ifdef OSD_SDL
-// forward declaration
-struct SDL_Window;
-#endif
-
//============================================================
// TYPE DEFINITIONS
//============================================================
-class osd_options;
+class osd_monitor_info;
+class render_module;
class render_primitive_list;
-enum
-{
- VIDEO_MODE_NONE = 0,
- VIDEO_MODE_GDI,
- VIDEO_MODE_BGFX,
-#if defined(USE_OPENGL) && USE_OPENGL
- VIDEO_MODE_OPENGL,
-#endif
- VIDEO_MODE_SDL2ACCEL,
- VIDEO_MODE_D3D,
- VIDEO_MODE_SOFT,
+class osd_renderer;
- VIDEO_MODE_COUNT
-};
class osd_window_config
{
@@ -59,15 +49,11 @@ public:
int refresh; // decoded refresh
};
-class osd_renderer;
-class osd_monitor_info;
-class osd_window : public std::enable_shared_from_this<osd_window>
+class osd_window
{
public:
- osd_window(running_machine &machine, int index, std::shared_ptr<osd_monitor_info> monitor, const osd_window_config &config);
-
- virtual ~osd_window() { }
+ virtual ~osd_window();
render_target *target() const { return m_target; }
int fullscreen() const { return m_fullscreen; }
@@ -76,11 +62,7 @@ public:
bool has_renderer() const { return m_renderer != nullptr; }
osd_renderer &renderer() const { return *m_renderer; }
- void set_renderer(std::unique_ptr<osd_renderer> renderer)
- {
- m_renderer = std::move(renderer);
- }
- void renderer_reset() { m_renderer.reset(); }
+ void renderer_reset() { m_renderer.reset(); } // public because OSD object calls it directly during teardown
int index() const { return m_index; }
int prescale() const { return m_prescale; }
@@ -96,9 +78,6 @@ public:
osd_monitor_info *monitor() const { return m_monitor.get(); }
std::shared_ptr<osd_monitor_info> monitor_from_rect(const osd_rect *proposed) const;
- std::shared_ptr<osd_window> main_window() const { return m_main; }
- void set_main_window(std::shared_ptr<osd_window> main) { m_main = main; }
-
void create_target();
void destroy();
@@ -114,18 +93,21 @@ public:
virtual void update() = 0;
virtual void complete_destroy() = 0;
-#if defined(OSD_WINDOWS)
- virtual bool win_has_menu() = 0;
-#endif
+protected:
+ osd_window(
+ running_machine &machine,
+ render_module &renderprovider,
+ int index,
+ const std::shared_ptr<osd_monitor_info> &monitor,
+ const osd_window_config &config);
+
+ bool renderer_interactive() const;
+ bool renderer_sdl_needs_opengl() const;
+ void renderer_create();
private:
void set_starting_view(int index, const char *defview, const char *view);
-public: // TODO: make these private
-#ifdef OSD_WINDOWS
- HDC m_dc; // only used by GDI renderer!
- int m_resize_state;
-#endif
private:
render_target *m_target;
public:
@@ -136,33 +118,32 @@ private:
protected:
bool m_fullscreen;
int m_prescale;
+
private:
- running_machine &m_machine;
- std::shared_ptr<osd_monitor_info> m_monitor;
- std::unique_ptr<osd_renderer> m_renderer;
- std::shared_ptr<osd_window> m_main;
- const std::string m_title;
+ running_machine &m_machine;
+ render_module &m_renderprovider;
+ std::shared_ptr<osd_monitor_info> m_monitor;
+ std::unique_ptr<osd_renderer> m_renderer;
+ const std::string m_title;
};
template <class TWindowHandle>
class osd_window_t : public osd_window
{
-private:
- TWindowHandle m_platform_window;
public:
- osd_window_t(running_machine &machine, int index, std::shared_ptr<osd_monitor_info> monitor, const osd_window_config &config)
- : osd_window(machine, index, std::move(monitor), config),
- m_platform_window(nullptr)
- {
- }
-
TWindowHandle platform_window() const { return m_platform_window; }
+protected:
+ using osd_window::osd_window;
+
void set_platform_window(TWindowHandle window)
{
assert(window == nullptr || m_platform_window == nullptr);
m_platform_window = window;
}
+
+private:
+ TWindowHandle m_platform_window = nullptr;
};
@@ -172,31 +153,13 @@ public:
/* Generic flags */
static const int FLAG_NONE = 0x0000;
- static const int FLAG_NEEDS_OPENGL = 0x0001;
- static const int FLAG_HAS_VECTOR_SCREEN = 0x0002;
+ static const int FLAG_HAS_VECTOR_SCREEN = 0x0001;
- /* SDL 1.2 flags */
- static const int FLAG_NEEDS_DOUBLEBUF = 0x0100;
- static const int FLAG_NEEDS_ASYNCBLIT = 0x0200;
-
- osd_renderer(std::shared_ptr<osd_window> window, const int flags)
- : m_sliders_dirty(false), m_window(window), m_flags(flags)
- { }
+ osd_renderer(osd_window &window) : m_sliders_dirty(false), m_window(window), m_flags(0) { }
virtual ~osd_renderer() { }
- std::shared_ptr<osd_window> assert_window() const
- {
- auto win = m_window.lock();
- if (!win)
- throw emu_fatalerror("osd_renderer::assert_window: Window weak_ptr is not available!");
- return win;
- }
-
- std::shared_ptr<osd_window> try_getwindow() const
- {
- return m_window.lock();
- }
+ osd_window &window() const { return m_window; }
bool has_flags(const int flag) const { return ((m_flags & flag)) == flag; }
void set_flags(int aflag) { m_flags |= aflag; }
@@ -218,8 +181,6 @@ public:
virtual void toggle_fsfx() { }
virtual bool sliders_dirty() { return m_sliders_dirty; }
- static std::unique_ptr<osd_renderer> make_for_type(int mode, std::shared_ptr<osd_window> window, int extra_flags = FLAG_NONE);
-
protected:
virtual void build_slider_list() { }
@@ -229,7 +190,7 @@ protected:
std::vector<ui::menu_item> m_sliders;
private:
- std::weak_ptr<osd_window> m_window;
+ osd_window &m_window;
int m_flags;
};
@@ -241,10 +202,6 @@ private:
#define MAX_VIDEO_WINDOWS (4)
-#define VIDEO_SCALE_MODE_NONE (0)
-
-#define GLSL_SHADER_MAX 10
-
//============================================================
// TYPE DEFINITIONS
@@ -258,35 +215,19 @@ struct osd_video_config
int numscreens; // number of screens
// hardware options
- int mode; // output mode
int waitvsync; // spin until vsync
int syncrefresh; // sync only to refresh rate
int switchres; // switch resolutions
// d3d, accel, opengl
int filter; // enable filtering
- //int filter; // enable filtering, disabled if glsl_filter>0
-
- // OpenGL options
- int glsl;
- int glsl_filter; // glsl filtering, >0 disables filter
- char * glsl_shader_mamebm[GLSL_SHADER_MAX]; // custom glsl shader set, mame bitmap
- int glsl_shader_mamebm_num; // custom glsl shader set number, mame bitmap
- char * glsl_shader_scrn[GLSL_SHADER_MAX]; // custom glsl shader set, screen bitmap
- int glsl_shader_scrn_num; // custom glsl shader number, screen bitmap
- int pbo;
- int vbo;
- int allowtexturerect; // allow GL_ARB_texture_rectangle, default: no
- int forcepow2texture; // force power of two textures, default: no
-
- // dd, d3d
+
+ // d3d
int triplebuf; // triple buffer
//============================================================
// SDL - options
//============================================================
- int novideo; // don't draw, for pure CPU benchmarking
-
int centerh;
int centerv;
@@ -298,9 +239,6 @@ struct osd_video_config
// X11 options
int restrictonemonitor; // in fullscreen, confine to Xinerama monitor 0
-
- // YUV options
- int scale_mode;
};
//============================================================
@@ -309,4 +247,4 @@ struct osd_video_config
extern osd_video_config video_config;
-#endif /* __OSDWINDOW__ */
+#endif // MAME_OSD_MODULES_OSDWINDOW_H
diff --git a/src/osd/modules/output/console.cpp b/src/osd/modules/output/console.cpp
index 993f9429e41..14e0f0fdebf 100644
--- a/src/osd/modules/output/console.cpp
+++ b/src/osd/modules/output/console.cpp
@@ -9,20 +9,23 @@
*******************************************************************c********/
#include "output_module.h"
-#include "modules/osdmodule.h"
+#include "modules/osdmodule.h"
#include "osdcore.h"
+namespace osd {
+
+namespace {
+
class output_console : public osd_module, public output_module
{
public:
- output_console()
- : osd_module(OSD_OUTPUT_PROVIDER, "console"), output_module()
+ output_console() : osd_module(OSD_OUTPUT_PROVIDER, "console")
{
}
virtual ~output_console() { }
- virtual int init(const osd_options &options) override { return 0; }
+ virtual int init(osd_interface &osd, const osd_options &options) override { return 0; }
virtual void exit() override { }
// output_module
@@ -31,4 +34,9 @@ public:
};
-MODULE_DEFINITION(OUTPUT_CONSOLE, output_console)
+} // anonymous namespace
+
+} // namespace osd
+
+
+MODULE_DEFINITION(OUTPUT_CONSOLE, osd::output_console)
diff --git a/src/osd/modules/output/network.cpp b/src/osd/modules/output/network.cpp
index 4fc4b382da6..26ce3619a4c 100644
--- a/src/osd/modules/output/network.cpp
+++ b/src/osd/modules/output/network.cpp
@@ -9,8 +9,9 @@
***************************************************************************/
#include "output_module.h"
-#include "modules/osdmodule.h"
+
#include "modules/lib/osdobj_common.h"
+#include "modules/osdmodule.h"
#include "emu.h"
@@ -19,181 +20,182 @@
#define ASIO_HAS_EPOLL
#endif
-#include <thread>
-#include <set>
#include "asio.h"
+#include <memory>
+#include <set>
+#include <thread>
+
+
+namespace osd {
+
+namespace {
+
class output_client
{
public:
- virtual ~output_client() {}
- virtual void deliver(std::string &msg) = 0;
+ virtual ~output_client() { }
+ virtual void deliver(std::string &msg) = 0;
};
using output_client_ptr = std::shared_ptr<output_client>;
using client_set = std::set<output_client_ptr>;
-class output_session : public output_client,
- public std::enable_shared_from_this<output_session>
+class output_session : public output_client, public std::enable_shared_from_this<output_session>
{
public:
- output_session(asio::ip::tcp::socket socket, client_set *clients) :
- m_socket(std::move(socket)),
- m_clients(clients)
- {
- }
-
- void start(running_machine &machine)
- {
- m_machine = &machine;
- m_clients->insert(shared_from_this());
- // now send "mame_start = rom" to the newly connected client
- std::snprintf(m_data, max_length, "mame_start = %s\r", machine.system().name);
- do_write(std::strlen(m_data));
- do_read();
- }
-
-private:
- void deliver(std::string &msg)
- {
- std::strncpy(m_data, msg.c_str(), max_length);
- do_write(msg.size());
- }
+ output_session(asio::ip::tcp::socket socket, client_set *clients) :
+ m_socket(std::move(socket)),
+ m_clients(clients)
+ {
+ }
- void handle_message(char *msg)
- {
- const char *equals_delimiter = " = ";
- char *msg_name = strtok(msg, equals_delimiter);
- char *msg_value = strtok(NULL, equals_delimiter);
+ void start(running_machine &machine)
+ {
+ m_machine = &machine;
+ m_clients->insert(shared_from_this());
+ // now send "mame_start = rom" to the newly connected client
+ std::snprintf(m_data, max_length, "mame_start = %s\r", machine.system().name);
+ do_write(std::strlen(m_data));
+ do_read();
+ }
- //printf("handle_message: msg_name [%s] msg_value [%s]\n", msg_name, msg_value);
+private:
+ void deliver(std::string &msg)
+ {
+ std::strncpy(m_data, msg.c_str(), max_length);
+ do_write(msg.size());
+ }
- if (std::strcmp(msg_name, "mame_message") == 0)
+ void handle_message(char *msg)
{
- const char *comma_delimiter = ",";
- msg_name = strtok(msg_value, comma_delimiter);
- msg_value = strtok(NULL, comma_delimiter);
- int id = atoi(msg_name);
- int value = atoi(msg_value);
+ const char *equals_delimiter = " = ";
+ char *msg_name = strtok(msg, equals_delimiter);
+ char *msg_value = strtok(NULL, equals_delimiter);
- switch(id)
+ //printf("handle_message: msg_name [%s] msg_value [%s]\n", msg_name, msg_value);
+
+ if (std::strcmp(msg_name, "mame_message") == 0)
{
- case IM_MAME_PAUSE:
- if (value == 1 && !machine().paused())
- {
- machine().pause();
- }
- else if (value == 0 && machine().paused())
- {
- machine().resume();
- }
- break;
- case IM_MAME_SAVESTATE:
- if (value == 0)
- {
- machine().schedule_load("auto");
- }
- else if (value == 1)
+ const char *comma_delimiter = ",";
+ msg_name = strtok(msg_value, comma_delimiter);
+ msg_value = strtok(NULL, comma_delimiter);
+ int id = atoi(msg_name);
+ int value = atoi(msg_value);
+
+ switch(id)
{
- machine().schedule_save("auto");
+ case output_module::IM_MAME_PAUSE:
+ if (value == 1 && !machine().paused())
+ machine().pause();
+ else if (value == 0 && machine().paused())
+ machine().resume();
+ break;
+ case output_module::IM_MAME_SAVESTATE:
+ if (value == 0)
+ machine().schedule_load("auto");
+ else if (value == 1)
+ machine().schedule_save("auto");
+ break;
}
- break;
}
- }
-}
-
- void do_read()
- {
- auto self(shared_from_this());
- m_socket.async_read_some(asio::buffer(m_input_m_data, max_length),
- [this, self](std::error_code ec, std::size_t length)
- {
- if (!ec)
- {
- if (length > 0)
+ }
+
+ void do_read()
+ {
+ auto self(shared_from_this());
+ m_socket.async_read_some(
+ asio::buffer(m_input_m_data, max_length),
+ [this, self] (std::error_code ec, std::size_t length)
{
- m_input_m_data[length] = '\0';
- handle_message(m_input_m_data);
- }
- do_read();
- }
- else
- {
- m_clients->erase(shared_from_this());
- }
- });
- }
-
- void do_write(std::size_t length)
- {
- auto self(shared_from_this());
- asio::async_write(m_socket, asio::buffer(m_data, length),
- [this, self](std::error_code ec, std::size_t /*length*/)
- {
- if (ec)
- {
- m_clients->erase(shared_from_this());
- }
- });
- }
-
- running_machine &machine() const { return *m_machine; }
-
- asio::ip::tcp::socket m_socket;
- enum { max_length = 1024 };
- char m_data[max_length];
- char m_input_m_data[max_length];
- client_set *m_clients;
- running_machine *m_machine;
+ if (!ec)
+ {
+ if (length > 0)
+ {
+ m_input_m_data[length] = '\0';
+ handle_message(m_input_m_data);
+ }
+ do_read();
+ }
+ else
+ {
+ m_clients->erase(shared_from_this());
+ }
+ });
+ }
+
+ void do_write(std::size_t length)
+ {
+ auto self(shared_from_this());
+ asio::async_write(
+ m_socket,
+ asio::buffer(m_data, length),
+ [this, self] (std::error_code ec, std::size_t /*length*/)
+ {
+ if (ec)
+ {
+ m_clients->erase(shared_from_this());
+ }
+ });
+ }
+
+ running_machine &machine() const { return *m_machine; }
+
+ asio::ip::tcp::socket m_socket;
+ enum { max_length = 1024 };
+ char m_data[max_length];
+ char m_input_m_data[max_length];
+ client_set *m_clients;
+ running_machine *m_machine;
};
class output_network_server
{
public:
- output_network_server(asio::io_context& io_context, short port, running_machine &machine) :
- m_acceptor(io_context, asio::ip::tcp::endpoint(asio::ip::tcp::v4(), port))
- {
- m_machine = &machine;
- do_accept();
- }
-
- void deliver_to_all(std::string msg)
- {
- for (const auto &client: m_clients)
- client->deliver(msg);
- }
+ output_network_server(asio::io_context& io_context, short port, running_machine &machine) :
+ m_acceptor(io_context, asio::ip::tcp::endpoint(asio::ip::tcp::v4(), port))
+ {
+ m_machine = &machine;
+ do_accept();
+ }
+
+ void deliver_to_all(std::string msg)
+ {
+ for (const auto &client: m_clients)
+ client->deliver(msg);
+ }
private:
- void do_accept()
- {
- m_acceptor.async_accept(
- [this](std::error_code ec, asio::ip::tcp::socket socket)
- {
- if (!ec)
- {
- std::make_shared<output_session>(std::move(socket),&m_clients)->start(machine());
- }
+ void do_accept()
+ {
+ m_acceptor.async_accept(
+ [this] (std::error_code ec, asio::ip::tcp::socket socket)
+ {
+ if (!ec)
+ {
+ std::make_shared<output_session>(std::move(socket),&m_clients)->start(machine());
+ }
- do_accept();
- });
- }
+ do_accept();
+ });
+ }
- running_machine &machine() const { return *m_machine; }
+ running_machine &machine() const { return *m_machine; }
- asio::ip::tcp::acceptor m_acceptor;
- client_set m_clients;
- running_machine *m_machine;
+ asio::ip::tcp::acceptor m_acceptor;
+ client_set m_clients;
+ running_machine *m_machine;
};
class output_network : public osd_module, public output_module
{
public:
- output_network()
- : osd_module(OSD_OUTPUT_PROVIDER, "network"),
- output_module(),
- m_io_context(nullptr), m_server(nullptr)
+ output_network() :
+ osd_module(OSD_OUTPUT_PROVIDER, "network"),
+ output_module(),
+ m_machine(nullptr)
{
}
@@ -201,9 +203,10 @@ public:
{
}
- virtual int init(const osd_options &options) override
+ virtual int init(osd_interface &osd, const osd_options &options) override
{
- m_working_thread = std::thread([](output_network* self) { self->process_output(); }, this);
+ m_machine = &downcast<osd_common_t &>(osd).machine();
+ m_working_thread = std::thread([] (output_network* self) { self->process_output(); }, this);
return 0;
}
@@ -213,31 +216,38 @@ public:
notify("mame_stop", 1);
m_io_context->stop();
m_working_thread.join();
- delete m_server;
- delete m_io_context;
+ m_server.reset();
+ m_io_context.reset();
+ m_machine = nullptr;
}
// output_module
virtual void notify(const char *outname, int32_t value) override
{
- static char buf[256];
- sprintf(buf, "%s = %d\r", ((outname==nullptr) ? "none" : outname), value);
- m_server->deliver_to_all(buf);
+ auto msg = util::string_format("%s = %d\r", ((outname==nullptr) ? "none" : outname), value);
+ m_server->deliver_to_all(msg);
}
// implementation
void process_output()
{
- m_io_context = new asio::io_context();
- m_server = new output_network_server(*m_io_context, 8000, machine());
+ m_io_context.reset(new asio::io_context);
+ m_server.reset(new output_network_server(*m_io_context, 8000, machine()));
m_io_context->run();
}
private:
+ running_machine &machine() { return *m_machine; }
+
std::thread m_working_thread;
- asio::io_context *m_io_context;
- output_network_server *m_server;
+ std::unique_ptr<asio::io_context> m_io_context;
+ std::unique_ptr<output_network_server> m_server;
+ running_machine *m_machine;
};
-MODULE_DEFINITION(OUTPUT_NETWORK, output_network)
+} // anonymous namespace
+
+} // namespace osd
+
+MODULE_DEFINITION(OUTPUT_NETWORK, osd::output_network)
diff --git a/src/osd/modules/output/none.cpp b/src/osd/modules/output/none.cpp
index a4a613ef29f..3e06921827d 100644
--- a/src/osd/modules/output/none.cpp
+++ b/src/osd/modules/output/none.cpp
@@ -9,18 +9,22 @@
*******************************************************************c********/
#include "output_module.h"
+
#include "modules/osdmodule.h"
+namespace osd {
+
+namespace {
+
class output_none : public osd_module, public output_module
{
public:
- output_none()
- : osd_module(OSD_OUTPUT_PROVIDER, "none"), output_module()
+ output_none() : osd_module(OSD_OUTPUT_PROVIDER, "none")
{
}
virtual ~output_none() { }
- virtual int init(const osd_options &options) override { return 0; }
+ virtual int init(osd_interface &osd, const osd_options &options) override { return 0; }
virtual void exit() override { }
// output_module
@@ -29,4 +33,8 @@ public:
};
-MODULE_DEFINITION(OUTPUT_NONE, output_none)
+} // anonymous namespace
+
+} // namespace osd
+
+MODULE_DEFINITION(OUTPUT_NONE, osd::output_none)
diff --git a/src/osd/modules/output/output_module.h b/src/osd/modules/output/output_module.h
index 36194e356ea..ae86cfe9084 100644
--- a/src/osd/modules/output/output_module.h
+++ b/src/osd/modules/output/output_module.h
@@ -4,12 +4,15 @@
* outpout_module.h
*
*/
+#ifndef MAME_OSD_OUTPUT_OUTPUT_MODULE_H
+#define MAME_OSD_OUTPUT_OUTPUT_MODULE_H
-#ifndef OUTPUT_MODULE_H_
-#define OUTPUT_MODULE_H_
+#pragma once
#include "osdepend.h"
-#include "modules/osdmodule.h"
+
+#include <cstdint>
+
//============================================================
// CONSTANTS
@@ -17,22 +20,15 @@
#define OSD_OUTPUT_PROVIDER "output"
-#define IM_MAME_PAUSE 0
-#define IM_MAME_SAVESTATE 1
-
class output_module
{
public:
- output_module(): m_machine(nullptr) { }
+ static inline constexpr unsigned IM_MAME_PAUSE = 0;
+ static inline constexpr unsigned IM_MAME_SAVESTATE = 1;
- virtual ~output_module() { }
+ virtual ~output_module() = default;
virtual void notify(const char *outname, int32_t value) = 0;
-
- void set_machine(running_machine *machine) { m_machine = machine; }
- running_machine &machine() const { return *m_machine; }
-private:
- running_machine *m_machine;
};
-#endif /* OUTPUT_MODULE_H_ */
+#endif // MAME_OSD_OUTPUT_OUTPUT_MODULE_H
diff --git a/src/osd/modules/output/win32_output.cpp b/src/osd/modules/output/win32_output.cpp
index a7a36861989..0d2d355b577 100644
--- a/src/osd/modules/output/win32_output.cpp
+++ b/src/osd/modules/output/win32_output.cpp
@@ -7,21 +7,26 @@
//============================================================
#include "output_module.h"
+
#include "modules/osdmodule.h"
-#include "modules/lib/osdobj_common.h"
#if defined(OSD_WINDOWS)
-// standard windows headers
-#include <windows.h>
+#include "win32_output.h"
+
+#include "winmain.h"
+#include "winutil.h"
// MAME headers
#include "emu.h"
-#include "winmain.h"
-#include "winutil.h"
-#include "win32_output.h"
+// standard windows headers
+#include <windows.h>
+
+
+namespace osd {
+namespace {
//============================================================
// CONSTANTS
@@ -66,30 +71,36 @@ class output_win32 : public osd_module, public output_module
{
public:
output_win32()
- : osd_module(OSD_OUTPUT_PROVIDER, "windows"), output_module(), m_output_hwnd(nullptr), m_clientlist(nullptr)
+ : osd_module(OSD_OUTPUT_PROVIDER, "windows")
+ , output_module()
+ , m_output_hwnd(nullptr)
+ , m_clientlist(nullptr)
+ , m_machine(nullptr)
{
}
virtual ~output_win32() { }
- virtual int init(const osd_options &options) override;
+ virtual int init(osd_interface &osd, const osd_options &options) override;
virtual void exit() override;
// output_module
-
virtual void notify(const char *outname, int32_t value) override;
- int create_window_class();
+ running_machine &machine() { return *m_machine; }
+
LRESULT register_client(HWND hwnd, LPARAM id);
LRESULT unregister_client(HWND hwnd, LPARAM id);
LRESULT send_id_string(HWND hwnd, LPARAM id);
private:
+ int create_window_class();
// our HWND
HWND m_output_hwnd;
// client list
registered_client * m_clientlist;
+ running_machine * m_machine;
};
@@ -97,8 +108,10 @@ private:
// output_init
//============================================================
-int output_win32::init(const osd_options &options)
+int output_win32::init(osd_interface &osd, const osd_options &options)
{
+ m_machine = &downcast<osd_common_t &>(osd).machine();
+
int result;
// reset globals
@@ -226,13 +239,13 @@ static LRESULT CALLBACK output_window_proc(HWND wnd, UINT message, WPARAM wparam
{
switch(wparam)
{
- case IM_MAME_PAUSE:
+ case output_module::IM_MAME_PAUSE:
if (lparam == 1 && !output.machine().paused())
output.machine().pause();
else if (lparam == 0 && output.machine().paused())
output.machine().resume();
break;
- case IM_MAME_SAVESTATE:
+ case output_module::IM_MAME_SAVESTATE:
if (lparam == 0)
output.machine().schedule_load("auto");
else if (lparam == 1)
@@ -352,10 +365,15 @@ void output_win32::notify(const char *outname, int32_t value)
PostMessage(client->hwnd, om_mame_update_state, client->machine->output().name_to_id(outname), value);
}
+} // anonymous namespace
+
+} // namespace osd
#else
- MODULE_NOT_SUPPORTED(output_win32, OSD_OUTPUT_PROVIDER, "windows")
+
+namespace osd { namespace { MODULE_NOT_SUPPORTED(output_win32, OSD_OUTPUT_PROVIDER, "windows") } }
+
#endif
-MODULE_DEFINITION(OUTPUT_WIN32, output_win32)
+MODULE_DEFINITION(OUTPUT_WIN32, osd::output_win32)
diff --git a/src/osd/modules/output/win32_output.h b/src/osd/modules/output/win32_output.h
index f0996b52082..bff3219b21f 100644
--- a/src/osd/modules/output/win32_output.h
+++ b/src/osd/modules/output/win32_output.h
@@ -2,12 +2,14 @@
// copyright-holders:Aaron Giles
//============================================================
//
-// output.h - Win32 implementation of MAME output routines
+// win32_output.h - Win32 implementation of MAME output routines
//
//============================================================
-#ifndef __WINDOWS_OUTPUT_H__
-#define __WINDOWS_OUTPUT_H__
+#ifndef MAME_OSD_OUTPUT_WIN32_OUTPUT_H
+#define MAME_OSD_OUTPUT_WIN32_OUTPUT_H
+
+#pragma once
//============================================================
@@ -83,8 +85,8 @@
struct copydata_id_string
{
- uint32_t id; // ID that was requested
+ uint32_t id; // ID that was requested
char string[1]; // string array containing the data
};
-#endif /* __WINDOWS_OUTPUT_H__ */
+#endif // MAME_OSD_OUTPUT_WIN32_OUTPUT_H
diff --git a/src/osd/modules/render/aviwrite.cpp b/src/osd/modules/render/aviwrite.cpp
index 9148244111b..e86d8f99ba6 100644
--- a/src/osd/modules/render/aviwrite.cpp
+++ b/src/osd/modules/render/aviwrite.cpp
@@ -32,7 +32,7 @@ avi_write::~avi_write()
}
}
-void avi_write::record(const char *name)
+void avi_write::record(std::string_view name)
{
if (m_recording)
{
@@ -48,7 +48,7 @@ void avi_write::stop()
end_avi_recording();
}
-void avi_write::begin_avi_recording(const char *name)
+void avi_write::begin_avi_recording(std::string_view name)
{
// stop any existing recording
end_avi_recording();
@@ -81,7 +81,7 @@ void avi_write::begin_avi_recording(const char *name)
// create a new temporary movie file
emu_file tempfile(m_machine.options().snapshot_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
- const std::error_condition filerr = (!name || !name[0] || !std::strcmp(name, OSDOPTVAL_AUTO))
+ const std::error_condition filerr = (name.empty() || name == OSDOPTVAL_AUTO)
? m_machine.video().open_next(tempfile, "avi")
: tempfile.open(name);
diff --git a/src/osd/modules/render/aviwrite.h b/src/osd/modules/render/aviwrite.h
index e59ce275168..a933dc2a3e6 100644
--- a/src/osd/modules/render/aviwrite.h
+++ b/src/osd/modules/render/aviwrite.h
@@ -6,13 +6,20 @@
//
//============================================================
+#ifndef MAME_RENDER_AVIWRITE_H
+#define MAME_RENDER_AVIWRITE_H
+
#pragma once
-#ifndef __RENDER_AVIWRITE__
-#define __RENDER_AVIWRITE__
+// emu
+#include "attotime.h"
+// lib/util
#include "aviio.h"
+#include <string_view>
+
+
class running_machine;
class avi_write
@@ -21,7 +28,7 @@ public:
avi_write(running_machine& machine, uint32_t width, uint32_t height);
~avi_write();
- void record(const char *name);
+ void record(std::string_view name);
void stop();
void audio_frame(const int16_t *buffer, int samples_this_frame);
void video_frame(bitmap_rgb32& snap);
@@ -30,7 +37,7 @@ public:
bool recording() const { return m_recording; }
private:
- void begin_avi_recording(const char *name);
+ void begin_avi_recording(std::string_view name);
void end_avi_recording();
running_machine& m_machine;
@@ -47,4 +54,4 @@ private:
attotime m_next_frame_time;
};
-#endif // __RENDER_AVIWRITE__
+#endif // MAME_RENDER_AVIWRITE_H
diff --git a/src/osd/modules/render/bgfx/blendreader.cpp b/src/osd/modules/render/bgfx/blendreader.cpp
index 9e7ddb17ce3..53cd57a9f4a 100644
--- a/src/osd/modules/render/bgfx/blendreader.cpp
+++ b/src/osd/modules/render/bgfx/blendreader.cpp
@@ -44,8 +44,11 @@ uint64_t blend_reader::read_from_value(const Value& value)
uint64_t equation = get_enum_from_value(value, "equation", BGFX_STATE_BLEND_EQUATION_ADD, EQUATION_NAMES, EQUATION_COUNT);
uint64_t srccolor = get_enum_from_value(value, "srcColor", BGFX_STATE_BLEND_ONE, FUNCTION_NAMES, FUNCTION_COUNT);
uint64_t dstcolor = get_enum_from_value(value, "dstColor", BGFX_STATE_BLEND_ZERO, FUNCTION_NAMES, FUNCTION_COUNT);
- uint64_t srcalpha = get_enum_from_value(value, "srcAlpha", BGFX_STATE_BLEND_ONE, FUNCTION_NAMES, FUNCTION_COUNT);
- uint64_t dstalpha = get_enum_from_value(value, "dstAlpha", BGFX_STATE_BLEND_ZERO, FUNCTION_NAMES, FUNCTION_COUNT);
-
- return BGFX_STATE_BLEND_EQUATION(equation) | BGFX_STATE_BLEND_FUNC_SEPARATE(srccolor, dstcolor, srcalpha, dstalpha);
+ if (value.HasMember("srcAlpha") && value.HasMember("dstAlpha"))
+ {
+ uint64_t srcalpha = get_enum_from_value(value, "srcAlpha", BGFX_STATE_BLEND_ONE, FUNCTION_NAMES, FUNCTION_COUNT);
+ uint64_t dstalpha = get_enum_from_value(value, "dstAlpha", BGFX_STATE_BLEND_ZERO, FUNCTION_NAMES, FUNCTION_COUNT);
+ return BGFX_STATE_BLEND_EQUATION(equation) | BGFX_STATE_BLEND_FUNC_SEPARATE(srccolor, dstcolor, srcalpha, dstalpha);
+ }
+ return BGFX_STATE_BLEND_EQUATION(equation) | BGFX_STATE_BLEND_FUNC(srccolor, dstcolor);
}
diff --git a/src/osd/modules/render/bgfx/chain.cpp b/src/osd/modules/render/bgfx/chain.cpp
index b677569a67f..8d5adb0ec25 100644
--- a/src/osd/modules/render/bgfx/chain.cpp
+++ b/src/osd/modules/render/bgfx/chain.cpp
@@ -27,15 +27,24 @@
#include "clear.h"
#include "modules/osdwindow.h"
-bgfx_chain::bgfx_chain(std::string name, std::string author, bool transform, target_manager& targets, std::vector<bgfx_slider*> sliders, std::vector<bgfx_parameter*> params, std::vector<bgfx_chain_entry*> entries, std::vector<bgfx_target*> target_list, std::uint32_t screen_index)
- : m_name(name)
- , m_author(author)
+bgfx_chain::bgfx_chain(
+ std::string &&name,
+ std::string &&author,
+ bool transform,
+ target_manager& targets,
+ std::vector<bgfx_slider*> &&sliders,
+ std::vector<bgfx_parameter*> &&params,
+ std::vector<bgfx_chain_entry*> &&entries,
+ std::vector<bgfx_target*> &&target_list,
+ std::uint32_t screen_index)
+ : m_name(std::move(name))
+ , m_author(std::move(author))
, m_transform(transform)
, m_targets(targets)
- , m_sliders(sliders)
- , m_params(params)
- , m_entries(entries)
- , m_target_list(target_list)
+ , m_sliders(std::move(sliders))
+ , m_params(std::move(params))
+ , m_entries(std::move(entries))
+ , m_target_list(std::move(target_list))
, m_current_time(0)
, m_screen_index(screen_index)
, m_has_converter(false)
@@ -78,7 +87,7 @@ void bgfx_chain::repopulate_targets()
}
}
-void bgfx_chain::process(chain_manager::screen_prim &prim, int view, int screen, texture_manager& textures, osd_window& window, uint64_t blend)
+void bgfx_chain::process(chain_manager::screen_prim &prim, int view, int screen, texture_manager& textures, osd_window& window)
{
screen_device_enumerator screen_iterator(window.machine().root_device());
screen_device* screen_device = screen_iterator.byindex(screen);
@@ -108,11 +117,12 @@ void bgfx_chain::process(chain_manager::screen_prim &prim, int view, int screen,
}
int current_view = view;
- for (bgfx_chain_entry* entry : m_entries)
+ for (size_t i = 0; i < m_entries.size(); i++)
{
- if (!entry->skip())
+ if (!m_entries[i]->skip())
{
- entry->submit(current_view, prim, textures, screen_count, screen_width, screen_height, screen_scale_x, screen_scale_y, screen_offset_x, screen_offset_y, rotation_type, swap_xy, blend, screen);
+ m_entries[i]->submit(current_view, prim, textures, screen_count, screen_width, screen_height, screen_scale_x, screen_scale_y, screen_offset_x, screen_offset_y,
+ rotation_type, swap_xy, screen);
current_view++;
}
}
@@ -145,7 +155,7 @@ uint32_t bgfx_chain::applicable_passes()
return applicable_passes;
}
-void bgfx_chain::insert_effect(uint32_t index, bgfx_effect *effect, std::string name, std::string source, chain_manager &chains)
+void bgfx_chain::insert_effect(uint32_t index, bgfx_effect *effect, const bool apply_tint, std::string name, std::string source, chain_manager &chains)
{
auto *clear = new clear_state(BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH | BGFX_CLEAR_STENCIL, 0, 1.0f, 0);
std::vector<bgfx_suppressor*> suppressors;
@@ -164,11 +174,15 @@ void bgfx_chain::insert_effect(uint32_t index, bgfx_effect *effect, std::string
uniforms.push_back(new bgfx_value_uniform(new bgfx_uniform("u_tex_size1", bgfx::UniformType::Vec4), values, 4));
uniforms.push_back(new bgfx_value_uniform(new bgfx_uniform("u_inv_tex_size0", bgfx::UniformType::Vec4), values, 4));
uniforms.push_back(new bgfx_value_uniform(new bgfx_uniform("u_inv_tex_size1", bgfx::UniformType::Vec4), values, 4));
+ uniforms.push_back(new bgfx_value_uniform(new bgfx_uniform("u_tex_bounds0", bgfx::UniformType::Vec4), values, 4));
+ uniforms.push_back(new bgfx_value_uniform(new bgfx_uniform("u_tex_bounds1", bgfx::UniformType::Vec4), values, 4));
+ uniforms.push_back(new bgfx_value_uniform(new bgfx_uniform("u_inv_tex_bounds0", bgfx::UniformType::Vec4), values, 4));
+ uniforms.push_back(new bgfx_value_uniform(new bgfx_uniform("u_inv_tex_bounds1", bgfx::UniformType::Vec4), values, 4));
- m_entries.insert(m_entries.begin() + index, new bgfx_chain_entry(name, effect, clear, suppressors, inputs, uniforms, m_targets, "screen", false));
+ m_entries.insert(m_entries.begin() + index, new bgfx_chain_entry(name, effect, clear, suppressors, inputs, uniforms, m_targets, "screen", apply_tint));
const uint32_t screen_width = chains.targets().width(TARGET_STYLE_GUEST, m_screen_index);
const uint32_t screen_height = chains.targets().height(TARGET_STYLE_GUEST, m_screen_index);
m_targets.destroy_target("screen", m_screen_index);
- m_targets.create_target("screen", bgfx::TextureFormat::BGRA8, screen_width, screen_height, TARGET_STYLE_GUEST, true, false, 1, m_screen_index);
+ m_targets.create_target("screen", bgfx::TextureFormat::BGRA8, screen_width, screen_height, 1, 1, TARGET_STYLE_GUEST, true, false, 1, m_screen_index);
}
diff --git a/src/osd/modules/render/bgfx/chain.h b/src/osd/modules/render/bgfx/chain.h
index 5080532210c..5d84bb1ed0c 100644
--- a/src/osd/modules/render/bgfx/chain.h
+++ b/src/osd/modules/render/bgfx/chain.h
@@ -6,17 +6,17 @@
//
//============================================================
+#ifndef MAME_RENDER_BGFX_CHAIN_H
+#define MAME_RENDER_BGFX_CHAIN_H
+
#pragma once
-#ifndef __DRAWBGFX_CHAIN__
-#define __DRAWBGFX_CHAIN__
+#include "chainentry.h"
#include <string>
#include <vector>
#include <map>
-#include "chainentry.h"
-
class bgfx_slider;
class bgfx_parameter;
class texture_manager;
@@ -27,13 +27,14 @@ class osd_window;
class bgfx_chain
{
public:
- bgfx_chain(std::string name, std::string author, bool transform, target_manager& targets, std::vector<bgfx_slider*> sliders, std::vector<bgfx_parameter*> params, std::vector<bgfx_chain_entry*> entries, std::vector<bgfx_target*> target_list, uint32_t screen_index);
+ bgfx_chain(std::string &&name, std::string &&author, bool transform, target_manager& targets, std::vector<bgfx_slider*> &&sliders, std::vector<bgfx_parameter*> &&params, std::vector<bgfx_chain_entry*> &&entries, std::vector<bgfx_target*> &&target_list, uint32_t screen_index);
~bgfx_chain();
- void process(chain_manager::screen_prim &prim, int view, int screen, texture_manager& textures, osd_window &window, uint64_t blend = 0L);
+ void process(chain_manager::screen_prim &prim, int view, int screen, texture_manager& textures, osd_window &window);
void repopulate_targets();
// Getters
+ const std::string &name() const { return m_name; }
std::vector<bgfx_slider*>& sliders() { return m_sliders; }
std::vector<bgfx_chain_entry*>& entries() { return m_entries; }
uint32_t applicable_passes();
@@ -44,7 +45,7 @@ public:
// Setters
void set_has_converter(bool has_converter) { m_has_converter = has_converter; }
void set_has_adjuster(bool has_adjuster) { m_has_adjuster = has_adjuster; }
- void insert_effect(uint32_t index, bgfx_effect *effect, std::string name, std::string source, chain_manager &chains);
+ void insert_effect(uint32_t index, bgfx_effect *effect, const bool apply_tint, std::string name, std::string source, chain_manager &chains);
private:
std::string m_name;
@@ -63,4 +64,4 @@ private:
bool m_has_adjuster;
};
-#endif // __DRAWBGFX_CHAIN__
+#endif // MAME_RENDER_BGFX_CHAIN_H
diff --git a/src/osd/modules/render/bgfx/chainentry.cpp b/src/osd/modules/render/bgfx/chainentry.cpp
index 45c0b805882..c3f3ee3a8e3 100644
--- a/src/osd/modules/render/bgfx/chainentry.cpp
+++ b/src/osd/modules/render/bgfx/chainentry.cpp
@@ -30,7 +30,8 @@
#include "render.h"
-bgfx_chain_entry::bgfx_chain_entry(std::string name, bgfx_effect* effect, clear_state* clear, std::vector<bgfx_suppressor*> suppressors, std::vector<bgfx_input_pair*> inputs, std::vector<bgfx_entry_uniform*> uniforms, target_manager& targets, std::string output, bool apply_tint)
+bgfx_chain_entry::bgfx_chain_entry(std::string name, bgfx_effect* effect, clear_state* clear, std::vector<bgfx_suppressor*> suppressors, std::vector<bgfx_input_pair*> inputs,
+ std::vector<bgfx_entry_uniform*> uniforms, target_manager& targets, std::string output, bool apply_tint)
: m_name(name)
, m_effect(effect)
, m_clear(clear)
@@ -55,12 +56,18 @@ bgfx_chain_entry::~bgfx_chain_entry()
delete uniform;
}
m_uniforms.clear();
- delete m_clear;
+ if (m_clear)
+ {
+ delete m_clear;
+ }
}
-void bgfx_chain_entry::submit(int view, chain_manager::screen_prim &prim, texture_manager& textures, uint16_t screen_count, uint16_t screen_width, uint16_t screen_height, float screen_scale_x, float screen_scale_y, float screen_offset_x, float screen_offset_y, uint32_t rotation_type, bool swap_xy, uint64_t blend, int32_t screen)
+void bgfx_chain_entry::submit(int view, chain_manager::screen_prim &prim, texture_manager& textures, uint16_t screen_count, uint16_t screen_width, uint16_t screen_height,
+ float screen_scale_x, float screen_scale_y, float screen_offset_x, float screen_offset_y, uint32_t rotation_type, bool swap_xy, int32_t screen)
{
- if (!setup_view(textures, view, screen_width, screen_height, screen))
+ uint16_t view_width = screen_width;
+ uint16_t view_height = screen_height;
+ if (!setup_view(textures, view, screen_width, screen_height, screen, view_width, view_height))
{
return;
}
@@ -73,18 +80,19 @@ void bgfx_chain_entry::submit(int view, chain_manager::screen_prim &prim, textur
uint32_t tint = 0xffffffff;
if (m_apply_tint)
{
- const auto a = (uint8_t)std::round(prim.m_prim->color.a * 255);
- const auto r = (uint8_t)std::round(prim.m_prim->color.r * 255);
- const auto g = (uint8_t)std::round(prim.m_prim->color.g * 255);
- const auto b = (uint8_t)std::round(prim.m_prim->color.b * 255);
+ const uint8_t a = (uint8_t)std::round(prim.m_prim->color.a * 255);
+ const uint8_t r = (uint8_t)std::round(prim.m_prim->color.r * 255);
+ const uint8_t g = (uint8_t)std::round(prim.m_prim->color.g * 255);
+ const uint8_t b = (uint8_t)std::round(prim.m_prim->color.b * 255);
tint = (a << 24) | (b << 16) | (g << 8) | r;
}
bgfx::TransientVertexBuffer buffer;
- put_screen_buffer(prim.m_screen_width, prim.m_screen_height, tint, &buffer);
+ put_screen_buffer(view_width, view_height, tint, &buffer);
bgfx::setVertexBuffer(0, &buffer);
- setup_auto_uniforms(prim, textures, screen_count, screen_width, screen_height, screen_scale_x, screen_scale_y, screen_offset_x, screen_offset_y, rotation_type, swap_xy, screen);
+ setup_auto_uniforms(prim, textures, screen_count, view_width, view_height, screen_width, screen_height, screen_scale_x, screen_scale_y, screen_offset_x, screen_offset_y,
+ rotation_type, swap_xy, screen);
for (bgfx_entry_uniform* uniform : m_uniforms)
{
@@ -94,7 +102,7 @@ void bgfx_chain_entry::submit(int view, chain_manager::screen_prim &prim, textur
}
}
- m_effect->submit(view, blend);
+ m_effect->submit(view);
if (m_targets.target(screen, m_output) != nullptr)
{
@@ -102,6 +110,43 @@ void bgfx_chain_entry::submit(int view, chain_manager::screen_prim &prim, textur
}
}
+void bgfx_chain_entry::setup_auto_uniforms(chain_manager::screen_prim &prim, texture_manager& textures, uint16_t screen_count, uint16_t view_width, uint16_t view_height,
+ uint16_t screen_width, uint16_t screen_height, float screen_scale_x, float screen_scale_y, float screen_offset_x, float screen_offset_y,
+ uint32_t rotation_type, bool swap_xy, int32_t screen)
+{
+ setup_viewsize_uniforms(view_width, view_height);
+ setup_screensize_uniforms(textures, screen_width, screen_height, screen);
+ setup_screenscale_uniforms(screen_scale_x, screen_scale_y);
+ setup_screenoffset_uniforms(screen_offset_x, screen_offset_y);
+ setup_screencount_uniforms(screen_count);
+ setup_sourcesize_uniform(prim);
+ setup_targetsize_uniform(screen);
+ setup_targetscale_uniform(screen);
+ setup_rotationtype_uniform(rotation_type);
+ setup_swapxy_uniform(swap_xy);
+ setup_quaddims_uniform(prim);
+ setup_screenindex_uniform(screen);
+}
+
+void bgfx_chain_entry::setup_viewsize_uniforms(uint16_t view_width, uint16_t view_height)
+{
+ float width(view_width);
+ float height(view_height);
+ bgfx_uniform* view_dims = m_effect->uniform("u_view_dims");
+ if (view_dims != nullptr)
+ {
+ float values[2] = { width, height };
+ view_dims->set(values, sizeof(float) * 2);
+ }
+
+ bgfx_uniform* inv_view_dims = m_effect->uniform("u_inv_view_dims");
+ if (inv_view_dims != nullptr)
+ {
+ float values[2] = { -1.0f / width, 1.0f / height };
+ inv_view_dims->set(values, sizeof(float) * 2);
+ }
+}
+
void bgfx_chain_entry::setup_screensize_uniforms(texture_manager& textures, uint16_t screen_width, uint16_t screen_height, int32_t screen)
{
float width = screen_width;
@@ -235,22 +280,8 @@ void bgfx_chain_entry::setup_screenindex_uniform(int32_t screen) const
}
}
-void bgfx_chain_entry::setup_auto_uniforms(chain_manager::screen_prim &prim, texture_manager& textures, uint16_t screen_count, uint16_t screen_width, uint16_t screen_height, float screen_scale_x, float screen_scale_y, float screen_offset_x, float screen_offset_y, uint32_t rotation_type, bool swap_xy, int32_t screen)
-{
- setup_screensize_uniforms(textures, screen_width, screen_height, screen);
- setup_screenscale_uniforms(screen_scale_x, screen_scale_y);
- setup_screenoffset_uniforms(screen_offset_x, screen_offset_y);
- setup_screencount_uniforms(screen_count);
- setup_sourcesize_uniform(prim);
- setup_targetsize_uniform(screen);
- setup_targetscale_uniform(screen);
- setup_rotationtype_uniform(rotation_type);
- setup_swapxy_uniform(swap_xy);
- setup_quaddims_uniform(prim);
- setup_screenindex_uniform(screen);
-}
-
-bool bgfx_chain_entry::setup_view(texture_manager &textures, int view, uint16_t screen_width, uint16_t screen_height, int32_t screen) const
+bool bgfx_chain_entry::setup_view(texture_manager &textures, int view, uint16_t screen_width, uint16_t screen_height, int32_t screen,
+ uint16_t &out_view_width, uint16_t &out_view_height) const
{
bgfx::FrameBufferHandle handle = BGFX_INVALID_HANDLE;
uint16_t width = screen_width;
@@ -269,11 +300,13 @@ bool bgfx_chain_entry::setup_view(texture_manager &textures, int view, uint16_t
bgfx::setViewFrameBuffer(view, handle);
bgfx::setViewRect(view, 0, 0, width, height);
+ out_view_width = width;
+ out_view_height = height;
const bgfx::Caps* caps = bgfx::getCaps();
std::string name = m_inputs[0]->texture() + std::to_string(screen);
- const float right_ratio = (float)textures.provider(name)->width() / textures.provider(name)->rowpixels();
+ const float right_ratio = float(textures.provider(name)->width()) / textures.provider(name)->rowpixels();
float projMat[16];
bx::mtxOrtho(projMat, 0.0f, right_ratio, 1.0f, 0.0f, 0.0f, 100.0f, 0.0f, caps->homogeneousDepth);
@@ -307,14 +340,6 @@ void bgfx_chain_entry::put_screen_buffer(uint16_t screen_width, uint16_t screen_
v[0] = v[1] = 1;
v[2] = v[3] = 0;
}
- else if (renderer_type == bgfx::RendererType::Direct3D9)
- {
- for (int i = 0; i < 4; i++)
- {
- u[i] += 0.5f / screen_width;
- v[i] += 0.5f / screen_height;
- }
- }
vertex[0].m_x = x[0];
vertex[0].m_y = y[0];
diff --git a/src/osd/modules/render/bgfx/chainentry.h b/src/osd/modules/render/bgfx/chainentry.h
index 3fb1dd54ca6..a7504187879 100644
--- a/src/osd/modules/render/bgfx/chainentry.h
+++ b/src/osd/modules/render/bgfx/chainentry.h
@@ -34,10 +34,12 @@ class target_manager;
class bgfx_chain_entry
{
public:
- bgfx_chain_entry(std::string name, bgfx_effect* effect, clear_state* clear, std::vector<bgfx_suppressor*> suppressors, std::vector<bgfx_input_pair*> inputs, std::vector<bgfx_entry_uniform*> uniforms, target_manager& targets, std::string output, bool apply_tint);
+ bgfx_chain_entry(std::string name, bgfx_effect* effect, clear_state* clear, std::vector<bgfx_suppressor*> suppressors, std::vector<bgfx_input_pair*> inputs,
+ std::vector<bgfx_entry_uniform*> uniforms, target_manager& targets, std::string output, bool apply_tint);
~bgfx_chain_entry();
- void submit(int view, chain_manager::screen_prim &prim, texture_manager& textures, uint16_t screen_count, uint16_t screen_width, uint16_t screen_height, float screen_scale_x, float screen_scale_y, float screen_offset_x, float screen_offset_y, uint32_t rotation_type, bool swap_xy, uint64_t blend, int32_t screen);
+ void submit(int view, chain_manager::screen_prim &prim, texture_manager& textures, uint16_t screen_count, uint16_t screen_width, uint16_t screen_height,
+ float screen_scale_x, float screen_scale_y, float screen_offset_x, float screen_offset_y, uint32_t rotation_type, bool swap_xy, int32_t screen);
// Getters
std::string name() const { return m_name; }
@@ -45,7 +47,10 @@ public:
bool skip();
private:
- void setup_auto_uniforms(chain_manager::screen_prim &prim, texture_manager& textures, uint16_t screen_count, uint16_t screen_width, uint16_t screen_height, float screen_scale_x, float screen_scale_y, float screen_offset_x, float screen_offset_y, uint32_t rotation_type, bool swap_xy, int32_t screen);
+ void setup_auto_uniforms(chain_manager::screen_prim &prim, texture_manager& textures, uint16_t screen_count, uint16_t view_width, uint16_t view_height,
+ uint16_t screen_width, uint16_t screen_height, float screen_scale_x, float screen_scale_y, float screen_offset_x, float screen_offset_y,
+ uint32_t rotation_type, bool swap_xy, int32_t screen);
+ void setup_viewsize_uniforms(uint16_t view_width, uint16_t view_height);
void setup_screensize_uniforms(texture_manager& textures, uint16_t screen_width, uint16_t screen_height, int32_t screen);
void setup_screenscale_uniforms(float screen_scale_x, float screen_scale_y);
void setup_screenoffset_uniforms(float screen_offset_x, float screen_offset_y);
@@ -58,7 +63,8 @@ private:
void setup_quaddims_uniform(chain_manager::screen_prim &prim) const;
void setup_screenindex_uniform(int32_t screen) const;
- bool setup_view(texture_manager& textures, int view, uint16_t screen_width, uint16_t screen_height, int32_t screen) const;
+ bool setup_view(texture_manager& textures, int view, uint16_t screen_width, uint16_t screen_height, int32_t screen,
+ uint16_t &out_view_width, uint16_t &out_view_height) const;
void put_screen_buffer(uint16_t screen_width, uint16_t screen_height, uint32_t screen_tint, bgfx::TransientVertexBuffer* buffer) const;
std::string m_name;
diff --git a/src/osd/modules/render/bgfx/chainentryreader.cpp b/src/osd/modules/render/bgfx/chainentryreader.cpp
index c6b9953603f..ce58816e827 100644
--- a/src/osd/modules/render/bgfx/chainentryreader.cpp
+++ b/src/osd/modules/render/bgfx/chainentryreader.cpp
@@ -29,7 +29,13 @@
#include "clear.h"
#include "clearreader.h"
-bgfx_chain_entry* chain_entry_reader::read_from_value(const Value& value, std::string prefix, chain_manager& chains, std::map<std::string, bgfx_slider*>& sliders, std::map<std::string, bgfx_parameter*>& params, uint32_t screen_index)
+bgfx_chain_entry* chain_entry_reader::read_from_value(
+ const Value &value,
+ const std::string &prefix,
+ chain_manager &chains,
+ std::map<std::string, bgfx_slider*> &sliders,
+ std::map<std::string, bgfx_parameter*> &params,
+ uint32_t screen_index)
{
if (!validate_parameters(value, prefix))
{
@@ -52,18 +58,18 @@ bgfx_chain_entry* chain_entry_reader::read_from_value(const Value& value, std::s
for (uint32_t i = 0; i < input_array.Size(); i++)
{
const Value& input = input_array[i];
- if (!READER_CHECK(input.HasMember("sampler"), (prefix + "input[" + std::to_string(i) + ": Must have string value 'sampler' (what sampler are we binding to?)\n").c_str())) return nullptr;
- if (!READER_CHECK(input["sampler"].IsString(), (prefix + "input[" + std::to_string(i) + ": Value 'sampler' must be a string\n").c_str())) return nullptr;
+ if (!READER_CHECK(input.HasMember("sampler"), "%sinput[%u]: Must have string value 'sampler' (what sampler are we binding to?)\n", prefix, i)) return nullptr;
+ if (!READER_CHECK(input["sampler"].IsString(), "%sinput[%u]: Value 'sampler' must be a string\n", prefix, i)) return nullptr;
bool has_texture = input.HasMember("texture");
bool has_target = input.HasMember("target");
bool has_option = input.HasMember("option");
- if (!READER_CHECK(has_texture || has_target || has_option, (prefix + "input[" + std::to_string(i) + ": Must have string value 'target', 'texture' or 'option' (what source are we using?)\n").c_str())) return nullptr;
- if (!READER_CHECK(!has_texture || input["texture"].IsString(), (prefix + "input[" + std::to_string(i) + ": Value 'texture' must be a string\n").c_str())) return nullptr;
- if (!READER_CHECK(!has_target || input["target"].IsString(), (prefix + "input[" + std::to_string(i) + ": Value 'target' must be a string\n").c_str())) return nullptr;
- if (!READER_CHECK(!has_option || input["option"].IsString(), (prefix + "input[" + std::to_string(i) + ": Value 'option' must be a string\n").c_str())) return nullptr;
- if (!READER_CHECK(has_target || !input.HasMember("bilinear") || input["bilinear"].IsBool(), (prefix + "input[" + std::to_string(i) + ": Value 'bilinear' must be a boolean\n").c_str())) return nullptr;
- if (!READER_CHECK(has_target || !input.HasMember("clamp") || input["clamp"].IsBool(), (prefix + "input[" + std::to_string(i) + ": Value 'clamp' must be a boolean\n").c_str())) return nullptr;
- if (!READER_CHECK(has_texture || has_option || !input.HasMember("selection") || input["selection"].IsString(), (prefix + "input[" + std::to_string(i) + ": Value 'selection' must be a string\n").c_str())) return nullptr;
+ if (!READER_CHECK(has_texture || has_target || has_option, "%sinput[%u]: Must have string value 'target', 'texture' or 'option' (what source are we using?)\n", prefix, i)) return nullptr;
+ if (!READER_CHECK(!has_texture || input["texture"].IsString(), "%sinput[%u]: Value 'texture' must be a string\n", prefix, i)) return nullptr;
+ if (!READER_CHECK(!has_target || input["target"].IsString(), "%sinput[%u]: Value 'target' must be a string\n", prefix, i)) return nullptr;
+ if (!READER_CHECK(!has_option || input["option"].IsString(), "%sinput[%u]: Value 'option' must be a string\n", prefix, i)) return nullptr;
+ if (!READER_CHECK(has_target || !input.HasMember("bilinear") || input["bilinear"].IsBool(), "%sinput[%u]: Value 'bilinear' must be a boolean\n", prefix, i)) return nullptr;
+ if (!READER_CHECK(has_target || !input.HasMember("clamp") || input["clamp"].IsBool(), "%sinput[%u]: Value 'clamp' must be a boolean\n", prefix, i)) return nullptr;
+ if (!READER_CHECK(has_texture || has_option || !input.HasMember("selection") || input["selection"].IsString(), "%sinput[%u]: Value 'selection' must be a string\n", prefix, i)) return nullptr;
bool bilinear = get_bool(input, "bilinear", true);
bool clamp = get_bool(input, "clamp", false);
std::string selection = get_string(input, "selection", "");
@@ -223,17 +229,17 @@ bgfx_chain_entry* chain_entry_reader::read_from_value(const Value& value, std::s
return new bgfx_chain_entry(name, effect, clear, suppressors, inputs, uniforms, chains.targets(), output, applytint);
}
-bool chain_entry_reader::validate_parameters(const Value& value, std::string prefix)
+bool chain_entry_reader::validate_parameters(const Value& value, const std::string &prefix)
{
- if (!READER_CHECK(value.HasMember("effect"), (prefix + "Must have string value 'effect' (what effect does this entry use?)\n").c_str())) return false;
- if (!READER_CHECK(value["effect"].IsString(), (prefix + "Value 'effect' must be a string\n").c_str())) return false;
- if (!READER_CHECK(value.HasMember("name"), (prefix + "Must have string value 'effect' (what effect does this entry use?)\n").c_str())) return false;
- if (!READER_CHECK(value["name"].IsString(), (prefix + "Value 'name' must be a string\n").c_str())) return false;
- if (!READER_CHECK(value.HasMember("output"), (prefix + "Must have string value 'offset' (what target are we rendering to?)\n").c_str())) return false;
- if (!READER_CHECK(value["output"].IsString(), (prefix + "Value 'output' must be a string\n").c_str())) return false;
- if (!READER_CHECK(!value.HasMember("input") || value["input"].IsArray(), (prefix + "Value 'input' must be an array\n").c_str())) return false;
- if (!READER_CHECK(!value.HasMember("uniforms") || value["uniforms"].IsArray(), (prefix + "Value 'uniforms' must be an array\n").c_str())) return false;
- if (!READER_CHECK(!value.HasMember("disablewhen") || value["disablewhen"].IsArray(), (prefix + "Value 'disablewhen' must be an array\n").c_str())) return false;
- if (!READER_CHECK(!value.HasMember("applytint") || value["applytint"].IsBool(), (prefix + "Value 'applytint' must be a bool\n").c_str())) return false;
+ if (!READER_CHECK(value.HasMember("effect"), "%sMust have string value 'effect' (what effect does this entry use?)\n", prefix)) return false;
+ if (!READER_CHECK(value["effect"].IsString(), "%sValue 'effect' must be a string\n", prefix)) return false;
+ if (!READER_CHECK(value.HasMember("name"), "%sMust have string value 'effect' (what effect does this entry use?)\n", prefix)) return false;
+ if (!READER_CHECK(value["name"].IsString(), "%sValue 'name' must be a string\n", prefix)) return false;
+ if (!READER_CHECK(value.HasMember("output"), "%sMust have string value 'offset' (what target are we rendering to?)\n", prefix)) return false;
+ if (!READER_CHECK(value["output"].IsString(), "%sValue 'output' must be a string\n", prefix)) return false;
+ if (!READER_CHECK(!value.HasMember("input") || value["input"].IsArray(), "%sValue 'input' must be an array\n", prefix)) return false;
+ if (!READER_CHECK(!value.HasMember("uniforms") || value["uniforms"].IsArray(), "%sValue 'uniforms' must be an array\n", prefix)) return false;
+ if (!READER_CHECK(!value.HasMember("disablewhen") || value["disablewhen"].IsArray(), "%sValue 'disablewhen' must be an array\n", prefix)) return false;
+ if (!READER_CHECK(!value.HasMember("applytint") || value["applytint"].IsBool(), "%sValue 'applytint' must be a bool\n", prefix)) return false;
return true;
}
diff --git a/src/osd/modules/render/bgfx/chainentryreader.h b/src/osd/modules/render/bgfx/chainentryreader.h
index 0f604e9a71f..583e972732c 100644
--- a/src/osd/modules/render/bgfx/chainentryreader.h
+++ b/src/osd/modules/render/bgfx/chainentryreader.h
@@ -5,15 +5,15 @@
// chainentryreader.h - BGFX chain entry JSON reader
//
//============================================================
+#ifndef MAME_RENDER_BGFX_CHAINENTRYREADER_H
+#define MAME_RENDER_BGFX_CHAINENTRYREADER_H
#pragma once
-#ifndef __DRAWBGFX_CHAIN_ENTRY_READER__
-#define __DRAWBGFX_CHAIN_ENTRY_READER__
+#include "statereader.h"
#include <map>
-#include "statereader.h"
class bgfx_chain_entry;
class bgfx_slider;
@@ -23,10 +23,10 @@ class chain_manager;
class chain_entry_reader : public state_reader
{
public:
- static bgfx_chain_entry* read_from_value(const Value& value, std::string prefix, chain_manager& chains, std::map<std::string, bgfx_slider*>& sliders, std::map<std::string, bgfx_parameter*>& params, uint32_t screen_index);
+ static bgfx_chain_entry* read_from_value(const Value& value, const std::string &prefix, chain_manager& chains, std::map<std::string, bgfx_slider*>& sliders, std::map<std::string, bgfx_parameter*>& params, uint32_t screen_index);
private:
- static bool validate_parameters(const Value& value, std::string prefix);
+ static bool validate_parameters(const Value& value, const std::string &prefix);
};
-#endif // __DRAWBGFX_CHAIN_ENTRY_READER__
+#endif // MAME_RENDER_BGFX_CHAINENTRYREADER_H
diff --git a/src/osd/modules/render/bgfx/chainmanager.cpp b/src/osd/modules/render/bgfx/chainmanager.cpp
index c3b80e88d14..a15f2f1e584 100644
--- a/src/osd/modules/render/bgfx/chainmanager.cpp
+++ b/src/osd/modules/render/bgfx/chainmanager.cpp
@@ -26,45 +26,62 @@
#include "bgfxutil.h"
-#include "chainreader.h"
#include "chain.h"
-
-#include "texture.h"
-#include "target.h"
+#include "chainreader.h"
#include "slider.h"
+#include "target.h"
+#include "texture.h"
#include "sliderdirtynotifier.h"
+#include "util/path.h"
+#include "util/unicode.h"
+#include "util/xmlfile.h"
+
#include "osdcore.h"
#include "osdfile.h"
-using namespace rapidjson;
+#include <algorithm>
+#include <locale>
+
-const uint32_t chain_manager::CHAIN_NONE = 0;
+using namespace rapidjson;
chain_manager::screen_prim::screen_prim(render_primitive *prim)
{
m_prim = prim;
- m_screen_width = (uint16_t)floorf(prim->get_full_quad_width() + 0.5f);
- m_screen_height = (uint16_t)floorf(prim->get_full_quad_height() + 0.5f);
- m_quad_width = (uint16_t)floorf(prim->get_quad_width() + 0.5f);
- m_quad_height = (uint16_t)floorf(prim->get_quad_height() + 0.5f);
- m_tex_width = (float)prim->texture.width;
- m_tex_height = (float)prim->texture.height;
+ m_screen_width = uint16_t(floorf(prim->get_full_quad_width() + 0.5f));
+ m_screen_height = uint16_t(floorf(prim->get_full_quad_height() + 0.5f));
+ m_quad_width = uint16_t(floorf(prim->get_quad_width() + 0.5f));
+ m_quad_height = uint16_t(floorf(prim->get_quad_height() + 0.5f));
+ m_tex_width = prim->texture.width;
+ m_tex_height = prim->texture.height;
m_rowpixels = prim->texture.rowpixels;
m_palette_length = prim->texture.palette_length;
m_flags = prim->flags;
}
-chain_manager::chain_manager(running_machine& machine, osd_options& options, texture_manager& textures, target_manager& targets, effect_manager& effects, uint32_t window_index, slider_dirty_notifier& slider_notifier)
+chain_manager::chain_manager(
+ running_machine& machine,
+ const osd_options& options,
+ texture_manager& textures,
+ target_manager& targets,
+ effect_manager& effects,
+ uint32_t window_index,
+ slider_dirty_notifier& slider_notifier,
+ uint16_t user_prescale,
+ uint16_t max_prescale_size)
: m_machine(machine)
, m_options(options)
, m_textures(textures)
, m_targets(targets)
, m_effects(effects)
, m_window_index(window_index)
+ , m_user_prescale(user_prescale)
+ , m_max_prescale_size(max_prescale_size)
, m_slider_notifier(slider_notifier)
, m_screen_count(0)
+ , m_default_chain_index(-1)
{
m_converters.clear();
refresh_available_chains();
@@ -87,13 +104,55 @@ void chain_manager::init_texture_converters()
m_adjuster = m_effects.get_or_load_effect(m_options, "misc/bcg_adjust");
}
+void chain_manager::get_default_chain_info(std::string &out_chain_name, int32_t &out_chain_index)
+{
+ if (m_default_chain_index == -1)
+ {
+ out_chain_index = CHAIN_NONE;
+ out_chain_name = "";
+ return;
+ }
+
+ out_chain_index = m_default_chain_index;
+ out_chain_name = "default";
+ return;
+}
+
void chain_manager::refresh_available_chains()
{
m_available_chains.clear();
- m_available_chains.push_back(chain_desc("none", ""));
-
- const std::string chains_path = osd_subst_env(util::string_format("%s" PATH_SEPARATOR "chains", m_options.bgfx_path()));
- find_available_chains(chains_path, "");
+ m_available_chains.emplace_back("none", "");
+
+ find_available_chains(util::path_concat(m_options.bgfx_path(), "chains"), "");
+ std::collate<wchar_t> const &coll = std::use_facet<std::collate<wchar_t> >(std::locale());
+ std::sort(
+ m_available_chains.begin(),
+ m_available_chains.end(),
+ [&coll] (chain_desc const &x, chain_desc const &y) -> bool
+ {
+ if (x.m_name == "none")
+ return y.m_name != "none";
+ else if (y.m_name == "none")
+ return false;
+ else if (x.m_name == "default")
+ return y.m_name != "default";
+ else if (y.m_name == "default")
+ return false;
+ std::wstring const xstr = wstring_from_utf8(x.m_name);
+ std::wstring const ystr = wstring_from_utf8(y.m_name);
+ return coll.compare(xstr.data(), xstr.data() + xstr.size(), ystr.data(), ystr.data() + ystr.size()) < 0;
+ });
+
+ if (m_default_chain_index == -1)
+ {
+ for (size_t i = 0; i < m_available_chains.size(); i++)
+ {
+ if (m_available_chains[i].m_name == "default")
+ {
+ m_default_chain_index = int32_t(i);
+ }
+ }
+ }
destroy_unloaded_chains();
}
@@ -103,7 +162,7 @@ void chain_manager::destroy_unloaded_chains()
// O(shaders*available_chains), but we don't care because asset reloading happens rarely
for (int i = 0; i < m_chain_names.size(); i++)
{
- std::string name = m_chain_names[i];
+ const std::string &name = m_chain_names[i];
if (name.length() > 0)
{
for (chain_desc desc : m_available_chains)
@@ -112,8 +171,7 @@ void chain_manager::destroy_unloaded_chains()
{
delete m_screen_chains[i];
m_screen_chains[i] = nullptr;
- m_chain_names[i] = "";
- m_current_chain[i] = CHAIN_NONE;
+ get_default_chain_info(m_chain_names[i], m_current_chain[i]);
break;
}
}
@@ -121,56 +179,53 @@ void chain_manager::destroy_unloaded_chains()
}
}
-void chain_manager::find_available_chains(std::string root, std::string path)
+void chain_manager::find_available_chains(std::string_view root, std::string_view path)
{
- osd::directory::ptr directory = osd::directory::open(root + path);
- if (directory != nullptr)
+ osd::directory::ptr directory = osd::directory::open(path.empty() ? std::string(root) : util::path_concat(root, path));
+ if (directory)
{
- for (const osd::directory::entry *entry = directory->read(); entry != nullptr; entry = directory->read())
+ for (const osd::directory::entry *entry = directory->read(); entry; entry = directory->read())
{
if (entry->type == osd::directory::entry::entry_type::FILE)
{
- std::string name(entry->name);
- std::string extension(".json");
+ const std::string_view name(entry->name);
+ const std::string_view extension(".json");
// Does the name has at least one character in addition to ".json"?
if (name.length() > extension.length())
{
size_t start = name.length() - extension.length();
- std::string test_segment = name.substr(start, extension.length());
+ const std::string_view test_segment = name.substr(start, extension.length());
// Does it end in .json?
if (test_segment == extension)
{
- m_available_chains.push_back(chain_desc(name.substr(0, start), path));
+ m_available_chains.emplace_back(std::string(name.substr(0, start)), std::string(path));
}
}
}
else if (entry->type == osd::directory::entry::entry_type::DIR)
{
- std::string name = entry->name;
- if (!(name == "." || name == ".."))
+ const std::string_view name = entry->name;
+ if ((name != ".") && (name != ".."))
{
- std::string appended_path = path + "/" + name;
- if (path.length() == 0)
- {
- appended_path = name;
- }
- find_available_chains(root, path + "/" + name);
+ if (path.empty())
+ find_available_chains(root, name);
+ else
+ find_available_chains(root, util::path_concat(path, name));
}
}
}
}
}
-bgfx_chain* chain_manager::load_chain(std::string name, uint32_t screen_index)
+std::unique_ptr<bgfx_chain> chain_manager::load_chain(std::string name, uint32_t screen_index)
{
if (name.length() < 5 || (name.compare(name.length() - 5, 5, ".json") != 0))
{
- name = name + ".json";
+ name += ".json";
}
- std::string path = osd_subst_env(util::string_format("%s" PATH_SEPARATOR "chains" PATH_SEPARATOR, m_options.bgfx_path()));
- path += name;
+ const std::string path = util::path_concat(m_options.bgfx_path(), "chains", name);
bx::FileReader reader;
if (!bx::open(&reader, path.c_str()))
@@ -179,29 +234,35 @@ bgfx_chain* chain_manager::load_chain(std::string name, uint32_t screen_index)
return nullptr;
}
- int32_t size(bx::getSize(&reader));
+ const int32_t size(bx::getSize(&reader));
- char* data = new char[size + 1];
- bx::read(&reader, reinterpret_cast<void*>(data), size);
+ bx::ErrorAssert err;
+ std::unique_ptr<char []> data(new (std::nothrow) char [size + 1]);
+ if (!data)
+ {
+ osd_printf_error("Out of memory reading chain file %s\n", path);
+ bx::close(&reader);
+ return nullptr;
+ }
+
+ bx::read(&reader, reinterpret_cast<void*>(data.get()), size, &err);
bx::close(&reader);
data[size] = 0;
Document document;
- document.Parse<kParseCommentsFlag>(data);
-
- delete [] data;
+ document.Parse<kParseCommentsFlag>(data.get());
+ data.reset();
if (document.HasParseError())
{
std::string error(GetParseError_En(document.GetParseError()));
- osd_printf_warning("Unable to parse chain %s. Errors returned:\n", path);
- osd_printf_warning("%s\n", error);
+ osd_printf_warning("Unable to parse chain %s. Errors returned:\n%s\n", path, error);
return nullptr;
}
- bgfx_chain* chain = chain_reader::read_from_value(document, name + ": ", *this, screen_index);
+ std::unique_ptr<bgfx_chain> chain = chain_reader::read_from_value(document, name + ": ", *this, screen_index, m_user_prescale, m_max_prescale_size);
- if (chain == nullptr)
+ if (!chain)
{
osd_printf_warning("Unable to load chain %s, falling back to no post processing\n", path);
return nullptr;
@@ -210,17 +271,17 @@ bgfx_chain* chain_manager::load_chain(std::string name, uint32_t screen_index)
return chain;
}
-void chain_manager::parse_chain_selections(std::string chain_str)
+void chain_manager::parse_chain_selections(std::string_view chain_str)
{
- std::vector<std::string> chain_names = split_option_string(chain_str);
+ std::vector<std::string_view> chain_names = split_option_string(chain_str);
if (chain_names.empty())
chain_names.push_back("default");
- while (m_current_chain.size() != chain_names.size())
+ while (m_current_chain.size() < chain_names.size())
{
- m_screen_chains.push_back(nullptr);
- m_chain_names.push_back("");
+ m_screen_chains.emplace_back(nullptr);
+ m_chain_names.emplace_back();
m_current_chain.push_back(CHAIN_NONE);
}
@@ -230,9 +291,7 @@ void chain_manager::parse_chain_selections(std::string chain_str)
for (chain_index = 0; chain_index < m_available_chains.size(); chain_index++)
{
if (m_available_chains[chain_index].m_name == chain_names[index])
- {
break;
- }
}
if (chain_index < m_available_chains.size())
@@ -248,24 +307,35 @@ void chain_manager::parse_chain_selections(std::string chain_str)
}
}
-std::vector<std::string> chain_manager::split_option_string(std::string chain_str) const
+std::vector<std::string_view> chain_manager::split_option_string(std::string_view chain_str) const
{
- std::vector<std::string> chain_names;
+ std::vector<std::string_view> chain_names;
- uint32_t length = chain_str.length();
+ const uint32_t length = chain_str.length();
uint32_t win = 0;
uint32_t last_start = 0;
- for (uint32_t i = 0; i < length + 1; i++)
+ for (uint32_t i = 0; i <= length; i++)
{
- if (i == length || chain_str[i] == ',' || chain_str[i] == ':')
+ if (i == length || (chain_str[i] == ',') || (chain_str[i] == ':'))
{
- if (win == m_window_index)
+ if ((win == 0) || (win == m_window_index))
{
- chain_names.push_back(chain_str.substr(last_start, i - last_start));
+ // treat an empty string as equivalent to "default"
+ if (i > last_start)
+ chain_names.push_back(chain_str.substr(last_start, i - last_start));
+ else
+ chain_names.push_back("default");
}
+
last_start = i + 1;
- if (chain_str[i] == ':')
+ if ((i < length) && (chain_str[i] == ':'))
{
+ // no point walking the rest of the string if this was our window
+ if (win == m_window_index)
+ break;
+
+ // don't use first for all if more than one window is specified
+ chain_names.clear();
win++;
}
}
@@ -282,7 +352,7 @@ void chain_manager::load_chains()
{
chain_desc& desc = m_available_chains[m_current_chain[chain]];
m_chain_names[chain] = desc.m_name;
- m_screen_chains[chain] = load_chain(desc.m_path + "/" + desc.m_name, uint32_t(chain));
+ m_screen_chains[chain] = load_chain(util::path_concat(desc.m_path, desc.m_name), uint32_t(chain)).release();
}
}
}
@@ -319,7 +389,7 @@ bgfx_chain* chain_manager::screen_chain(uint32_t screen)
void chain_manager::process_screen_quad(uint32_t view, uint32_t screen, screen_prim &prim, osd_window& window)
{
- const bool any_targets_rebuilt = m_targets.update_target_sizes(screen, prim.m_tex_width, prim.m_tex_height, TARGET_STYLE_GUEST);
+ const bool any_targets_rebuilt = m_targets.update_target_sizes(screen, prim.m_tex_width, prim.m_tex_height, TARGET_STYLE_GUEST, m_user_prescale, m_max_prescale_size);
if (any_targets_rebuilt)
{
for (bgfx_chain* chain : m_screen_chains)
@@ -332,7 +402,7 @@ void chain_manager::process_screen_quad(uint32_t view, uint32_t screen, screen_p
}
bgfx_chain* chain = screen_chain(screen);
- chain->process(prim, view, screen, m_textures, window, bgfx_util::get_blend_state(PRIMFLAG_GET_BLENDMODE(prim.m_flags)));
+ chain->process(prim, view, screen, m_textures, window);
view += chain->applicable_passes();
}
@@ -359,7 +429,7 @@ uint32_t chain_manager::count_screens(render_primitive* prim)
if (screen_count > 0)
{
update_screen_count(screen_count);
- m_targets.update_screen_count(screen_count);
+ m_targets.update_screen_count(screen_count, m_user_prescale, m_max_prescale_size);
}
if (screen_count < m_screen_prims.size())
@@ -381,8 +451,12 @@ void chain_manager::update_screen_count(uint32_t screen_count)
while (m_screen_chains.size() < m_screen_count)
{
m_screen_chains.push_back(nullptr);
- m_chain_names.push_back("");
- m_current_chain.push_back(CHAIN_NONE);
+
+ int32_t chain_index = CHAIN_NONE;
+ std::string chain_name;
+ get_default_chain_info(chain_name, chain_index);
+ m_chain_names.emplace_back(std::move(chain_name));
+ m_current_chain.push_back(chain_index);
}
// Ensure we have a screen chain selection slider per screen
@@ -395,11 +469,20 @@ void chain_manager::update_screen_count(uint32_t screen_count)
}
}
+void chain_manager::set_current_chain(uint32_t screen, int32_t chain_index)
+{
+ if (chain_index < m_available_chains.size() && screen < m_current_chain.size() && screen < m_chain_names.size())
+ {
+ m_current_chain[screen] = chain_index;
+ m_chain_names[screen] = m_available_chains[chain_index].m_name;
+ }
+}
+
int32_t chain_manager::slider_changed(int id, std::string *str, int32_t newval)
{
if (newval != SLIDER_NOCHANGE)
{
- m_current_chain[id] = newval;
+ set_current_chain(id, newval);
std::vector<std::vector<float>> settings = slider_settings();
reload_chains();
@@ -428,11 +511,11 @@ void chain_manager::create_selection_slider(uint32_t screen_index)
int32_t maxval = m_available_chains.size() - 1;
int32_t incval = 1;
- std::string description = "Window " + std::to_string(m_window_index) + ", Screen " + std::to_string(screen_index) + " Effect:";
-
using namespace std::placeholders;
- auto state = std::make_unique<slider_state>(std::move(description), minval, defval, maxval, incval,
- std::bind(&chain_manager::slider_changed, this, screen_index, _1, _2));
+ auto state = std::make_unique<slider_state>(
+ util::string_format("Window %1$u, Screen %2$u Effect", m_window_index, screen_index),
+ minval, defval, maxval, incval,
+ std::bind(&chain_manager::slider_changed, this, screen_index, _1, _2));
ui::menu_item item(ui::menu_item_type::SLIDER, state.get());
item.set_text(state->description);
@@ -457,23 +540,17 @@ uint32_t chain_manager::update_screen_textures(uint32_t view, render_primitive *
const uint32_t src_format = (prim.m_flags & PRIMFLAG_TEXFORMAT_MASK) >> PRIMFLAG_TEXFORMAT_SHIFT;
const bool needs_conversion = m_converters[src_format] != nullptr;
const bool needs_adjust = prim.m_prim->texture.palette != nullptr && src_format != TEXFORMAT_PALETTE16;
- std::string screen_index = std::to_string(screen);
- std::string source_name = "source" + screen_index;
- std::string screen_name = "screen" + screen_index;
- std::string palette_name = "palette" + screen_index;
- std::string full_name = (needs_conversion || needs_adjust) ? source_name : screen_name;
+ const std::string screen_index = std::to_string(screen);
+ const std::string source_name = "source" + screen_index;
+ const std::string screen_name = "screen" + screen_index;
+ const std::string palette_name = "palette" + screen_index;
+ const std::string &full_name = (needs_conversion || needs_adjust) ? source_name : screen_name;
if (texture && (texture->width() != tex_width || texture->height() != tex_height))
{
- m_textures.add_provider(full_name, nullptr);
- delete texture;
+ m_textures.remove_provider(full_name);
+ m_textures.remove_provider(palette_name);
texture = nullptr;
-
- if (palette)
- {
- m_textures.add_provider(palette_name, nullptr);
- delete palette;
- palette = nullptr;
- }
+ palette = nullptr;
}
bgfx::TextureFormat::Enum dst_format = bgfx::TextureFormat::BGRA8;
@@ -481,36 +558,38 @@ uint32_t chain_manager::update_screen_textures(uint32_t view, render_primitive *
int width_div_factor = 1;
int width_mul_factor = 1;
const bgfx::Memory* mem = bgfx_util::mame_texture_data_to_bgfx_texture_data(dst_format, prim.m_flags & PRIMFLAG_TEXFORMAT_MASK,
- prim.m_rowpixels, tex_height, prim.m_prim->texture.palette, prim.m_prim->texture.base, pitch, width_div_factor, width_mul_factor);
+ prim.m_rowpixels, prim.m_prim->texture.width_margin, tex_height, prim.m_prim->texture.palette, prim.m_prim->texture.base, pitch, width_div_factor, width_mul_factor);
- if (texture == nullptr)
+ if (!texture)
{
uint32_t flags = BGFX_SAMPLER_MIN_POINT | BGFX_SAMPLER_MAG_POINT | BGFX_SAMPLER_MIP_POINT;
if (!PRIMFLAG_GET_TEXWRAP(prim.m_flags))
flags |= BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP;
- bgfx_texture *texture = new bgfx_texture(full_name, dst_format, tex_width, tex_height, mem, flags, pitch, prim.m_rowpixels, width_div_factor, width_mul_factor);
- m_textures.add_provider(full_name, texture);
+ auto newtex = std::make_unique<bgfx_texture>(full_name, dst_format, tex_width, prim.m_prim->texture.width_margin, tex_height, mem, flags, pitch, prim.m_rowpixels, width_div_factor, width_mul_factor);
+ texture = newtex.get();
+ m_textures.add_provider(full_name, std::move(newtex));
if (prim.m_prim->texture.palette)
{
- uint16_t palette_width = (uint16_t)std::min(prim.m_palette_length, 256U);
- uint16_t palette_height = (uint16_t)std::max((prim.m_palette_length + 255) / 256, 1U);
+ uint16_t palette_width = uint16_t(std::min(prim.m_palette_length, 256U));
+ uint16_t palette_height = uint16_t(std::max((prim.m_palette_length + 255) / 256, 1U));
m_palette_temp.resize(palette_width * palette_height * 4);
memcpy(&m_palette_temp[0], prim.m_prim->texture.palette, prim.m_palette_length * 4);
const bgfx::Memory *palmem = bgfx::copy(&m_palette_temp[0], palette_width * palette_height * 4);
- palette = new bgfx_texture(palette_name, bgfx::TextureFormat::BGRA8, palette_width, palette_height, palmem, BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP | BGFX_SAMPLER_MIN_POINT | BGFX_SAMPLER_MAG_POINT | BGFX_SAMPLER_MIP_POINT, palette_width * 4);
- m_textures.add_provider(palette_name, palette);
+ auto newpal = std::make_unique<bgfx_texture>(palette_name, bgfx::TextureFormat::BGRA8, palette_width, 0, palette_height, palmem, BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP | BGFX_SAMPLER_MIN_POINT | BGFX_SAMPLER_MAG_POINT | BGFX_SAMPLER_MIP_POINT, palette_width * 4);
+ palette = newpal.get();
+ m_textures.add_provider(palette_name, std::move(newpal));
}
while (screen >= m_screen_textures.size())
{
- m_screen_textures.push_back(nullptr);
+ m_screen_textures.emplace_back(nullptr);
}
m_screen_textures[screen] = texture;
while (screen >= m_screen_palettes.size())
{
- m_screen_palettes.push_back(nullptr);
+ m_screen_palettes.emplace_back(nullptr);
}
if (palette)
{
@@ -519,12 +598,12 @@ uint32_t chain_manager::update_screen_textures(uint32_t view, render_primitive *
}
else
{
- texture->update(mem, pitch);
+ texture->update(mem, pitch, prim.m_prim->texture.width_margin);
if (prim.m_prim->texture.palette)
{
- uint16_t palette_width = (uint16_t)std::min(prim.m_palette_length, 256U);
- uint16_t palette_height = (uint16_t)std::max((prim.m_palette_length + 255) / 256, 1U);
+ uint16_t palette_width = uint16_t(std::min(prim.m_palette_length, 256U));
+ uint16_t palette_height = uint16_t(std::max((prim.m_palette_length + 255) / 256, 1U));
const uint32_t palette_size = palette_width * palette_height * 4;
m_palette_temp.resize(palette_size);
memcpy(&m_palette_temp[0], prim.m_prim->texture.palette, prim.m_palette_length * 4);
@@ -536,26 +615,29 @@ uint32_t chain_manager::update_screen_textures(uint32_t view, render_primitive *
}
else
{
- palette = new bgfx_texture(palette_name, bgfx::TextureFormat::BGRA8, palette_width, palette_height, palmem, BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP | BGFX_SAMPLER_MIN_POINT | BGFX_SAMPLER_MAG_POINT | BGFX_SAMPLER_MIP_POINT, palette_width * 4);
- m_textures.add_provider(palette_name, palette);
+ auto newpal = std::make_unique<bgfx_texture>(palette_name, bgfx::TextureFormat::BGRA8, palette_width, 0, palette_height, palmem, BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP | BGFX_SAMPLER_MIN_POINT | BGFX_SAMPLER_MAG_POINT | BGFX_SAMPLER_MIP_POINT, palette_width * 4);
+ palette = newpal.get();
+ m_textures.add_provider(palette_name, std::move(newpal));
while (screen >= m_screen_palettes.size())
{
- m_screen_palettes.push_back(nullptr);
+ m_screen_palettes.emplace_back(nullptr);
}
m_screen_palettes[screen] = palette;
}
}
}
+ const bool has_tint = (prim.m_prim->color.a != 1.0f) || (prim.m_prim->color.r != 1.0f) || (prim.m_prim->color.g != 1.0f) || (prim.m_prim->color.b != 1.0f);
bgfx_chain* chain = screen_chain(screen);
if (chain && needs_adjust && !chain->has_adjuster())
{
- chain->insert_effect(chain->has_converter() ? 1 : 0, m_adjuster, "XXadjust", needs_conversion ? "screen" : "source", *this);
+ const bool apply_tint = !needs_conversion && has_tint;
+ chain->insert_effect(chain->has_converter() ? 1 : 0, m_adjuster, apply_tint, "XXadjust", needs_conversion ? "screen" : "source", *this);
chain->set_has_adjuster(true);
}
if (chain && needs_conversion && !chain->has_converter())
{
- chain->insert_effect(0, m_converters[src_format], "XXconvert", "source", *this);
+ chain->insert_effect(0, m_converters[src_format], has_tint, "XXconvert", "source", *this);
chain->set_has_converter(true);
}
}
@@ -583,7 +665,7 @@ uint32_t chain_manager::process_screen_chains(uint32_t view, osd_window& window)
std::swap(screen_width, screen_height);
}
- const bool any_targets_rebuilt = m_targets.update_target_sizes(screen_index, screen_width, screen_height, TARGET_STYLE_NATIVE);
+ const bool any_targets_rebuilt = m_targets.update_target_sizes(screen_index, screen_width, screen_height, TARGET_STYLE_NATIVE, m_user_prescale, m_max_prescale_size);
if (any_targets_rebuilt)
{
for (bgfx_chain* chain : m_screen_chains)
@@ -608,12 +690,12 @@ uint32_t chain_manager::process_screen_chains(uint32_t view, osd_window& window)
bool chain_manager::has_applicable_chain(uint32_t screen)
{
- return screen < m_screen_count && m_current_chain[screen] != CHAIN_NONE && m_screen_chains[screen] != nullptr;
+ return (screen < m_screen_count) && (m_current_chain[screen] != CHAIN_NONE) && m_screen_chains[screen];
}
bool chain_manager::needs_sliders()
{
- return m_screen_count > 0 && m_available_chains.size() > 1;
+ return (m_screen_count > 0) && (m_available_chains.size() > 1);
}
void chain_manager::restore_slider_settings(int32_t id, std::vector<std::vector<float>>& settings)
@@ -636,7 +718,7 @@ void chain_manager::restore_slider_settings(int32_t id, std::vector<std::vector<
continue;
}
- std::vector<bgfx_slider*> chain_sliders = chain->sliders();
+ const std::vector<bgfx_slider*> &chain_sliders = chain->sliders();
for (size_t slider = 0; slider < chain_sliders.size(); slider++)
{
chain_sliders[slider]->import(settings[index][slider]);
@@ -644,6 +726,151 @@ void chain_manager::restore_slider_settings(int32_t id, std::vector<std::vector<
}
}
+void chain_manager::load_config(util::xml::data_node const &windownode)
+{
+ // treat source INI files or more specific as higher priority than CFG
+ // FIXME: leaky abstraction - this depends on a front-end implementation detail
+ bool const persist = windownode.get_attribute_int("persist", 1) != 0;
+ bool const default_chains = (OPTION_PRIORITY_NORMAL + 5) > m_options.get_entry(OSDOPTION_BGFX_SCREEN_CHAINS)->priority();
+ bool const explicit_chains = !persist && !default_chains && *m_options.bgfx_screen_chains();
+
+ // if chains weren't explicitly specified, restore the chains from the config file
+ if (explicit_chains)
+ {
+ osd_printf_verbose(
+ "BGFX: Ignoring chain selection from window 0 configuration due to explicitly specified chains\n",
+ m_window_index);
+ }
+ else
+ {
+ bool changed = false;
+ util::xml::data_node const *screennode = windownode.get_child("screen");
+ while (screennode)
+ {
+ auto const index = screennode->get_attribute_int("index", -1);
+ if ((0 <= index) && (m_screen_count > index))
+ {
+ char const *const chainname = screennode->get_attribute_string("chain", nullptr);
+ if (chainname)
+ {
+ auto const found = std::find_if(
+ m_available_chains.begin(),
+ m_available_chains.end(),
+ [&chainname] (auto const &avail) { return avail.m_name == chainname; });
+ if (m_available_chains.end() != found)
+ {
+ auto const chainnum = found - m_available_chains.begin();
+ if (chainnum != m_current_chain[index])
+ {
+ m_current_chain[index] = chainnum;
+ changed = true;
+ }
+ }
+ }
+ }
+
+ screennode = screennode->get_next_sibling("screen");
+ }
+
+ if (changed)
+ reload_chains();
+ }
+
+ // now apply slider settings for screens with chains matching config
+ util::xml::data_node const *screennode = windownode.get_child("screen");
+ while (screennode)
+ {
+ auto const index = screennode->get_attribute_int("index", -1);
+ if ((0 <= index) && (m_screen_count > index) && (m_screen_chains.size() > index))
+ {
+ bgfx_chain *const chain = m_screen_chains[index];
+ char const *const chainname = screennode->get_attribute_string("chain", nullptr);
+ if (chain && chainname && (m_available_chains[m_current_chain[index]].m_name == chainname))
+ {
+ auto const &sliders = chain->sliders();
+
+ util::xml::data_node const *slidernode = screennode->get_child("slider");
+ while (slidernode)
+ {
+ char const *const slidername = slidernode->get_attribute_string("name", nullptr);
+ if (slidername)
+ {
+ auto const found = std::find_if(
+ sliders.begin(),
+ sliders.end(),
+ [&slidername] (auto const &slider) { return slider->name() == slidername; });
+ if (sliders.end() != found)
+ {
+ bgfx_slider &slider = **found;
+ switch (slider.type())
+ {
+ case bgfx_slider::SLIDER_INT_ENUM:
+ case bgfx_slider::SLIDER_INT:
+ {
+ slider_state const &core = *slider.core_slider();
+ int32_t const val = slidernode->get_attribute_int("value", core.defval);
+ slider.update(nullptr, std::clamp(val, core.minval, core.maxval));
+ }
+ break;
+ default:
+ {
+ float const val = slidernode->get_attribute_float("value", slider.default_value());
+ slider.import(std::clamp(val, slider.min_value(), slider.max_value()));
+ }
+ }
+ }
+ }
+
+ slidernode = slidernode->get_next_sibling("slider");
+ }
+ }
+ }
+ screennode = screennode->get_next_sibling("screen");
+ }
+}
+
+void chain_manager::save_config(util::xml::data_node &parentnode)
+{
+ if (!needs_sliders())
+ return;
+
+ util::xml::data_node *const windownode = parentnode.add_child("window", nullptr);
+ windownode->set_attribute_int("index", m_window_index);
+
+ for (size_t index = 0; index < m_screen_chains.size() && index < m_screen_count; index++)
+ {
+ bgfx_chain *const chain = m_screen_chains[index];
+ if (!chain)
+ continue;
+
+ util::xml::data_node *const screennode = windownode->add_child("screen", nullptr);
+ screennode->set_attribute_int("index", index);
+ screennode->set_attribute("chain", m_available_chains[m_current_chain[index]].m_name.c_str());
+
+ for (bgfx_slider *slider : chain->sliders())
+ {
+ auto const val = slider->update(nullptr, SLIDER_NOCHANGE);
+ if (val == slider->core_slider()->defval)
+ continue;
+
+ util::xml::data_node *const slidernode = screennode->add_child("slider", nullptr);
+ slidernode->set_attribute("name", slider->name().c_str());
+ switch (slider->type())
+ {
+ case bgfx_slider::SLIDER_INT_ENUM:
+ case bgfx_slider::SLIDER_INT:
+ slidernode->set_attribute_int("value", val);
+ break;
+ default:
+ slidernode->set_attribute_float("value", slider->value());
+ }
+ }
+ }
+
+ if (!windownode->get_first_child())
+ windownode->delete_node();
+}
+
std::vector<std::vector<float>> chain_manager::slider_settings()
{
std::vector<std::vector<float>> curr;
@@ -663,7 +890,7 @@ std::vector<std::vector<float>> chain_manager::slider_settings()
continue;
}
- std::vector<bgfx_slider*> chain_sliders = chain->sliders();
+ const std::vector<bgfx_slider*> &chain_sliders = chain->sliders();
for (bgfx_slider* slider : chain_sliders)
{
curr[index].push_back(slider->value());
@@ -692,24 +919,24 @@ std::vector<ui::menu_item> chain_manager::get_slider_list()
continue;
}
- std::vector<bgfx_chain_entry*> chain_entries = chain->entries();
+ const std::vector<bgfx_chain_entry*> &chain_entries = chain->entries();
for (bgfx_chain_entry* entry : chain_entries)
{
- std::vector<bgfx_input_pair*> entry_inputs = entry->inputs();
+ const std::vector<bgfx_input_pair*> &entry_inputs = entry->inputs();
for (bgfx_input_pair* input : entry_inputs)
{
std::vector<ui::menu_item> input_sliders = input->get_slider_list();
- for (ui::menu_item slider : input_sliders)
+ for (ui::menu_item &slider : input_sliders)
{
sliders.emplace_back(slider);
}
}
}
- std::vector<bgfx_slider*> chain_sliders = chain->sliders();
+ const std::vector<bgfx_slider*> &chain_sliders = chain->sliders();
for (bgfx_slider* slider : chain_sliders)
{
- slider_state* core_slider = slider->core_slider();
+ slider_state *const core_slider = slider->core_slider();
ui::menu_item item(ui::menu_item_type::SLIDER, core_slider);
item.set_text(core_slider->description);
diff --git a/src/osd/modules/render/bgfx/chainmanager.h b/src/osd/modules/render/bgfx/chainmanager.h
index 59a65dc59cf..0d489d0bd72 100644
--- a/src/osd/modules/render/bgfx/chainmanager.h
+++ b/src/osd/modules/render/bgfx/chainmanager.h
@@ -9,19 +9,24 @@
//
//============================================================
-#pragma once
+#ifndef MAME_RENDER_BGFX_CHAINMANAGER_H
+#define MAME_RENDER_BGFX_CHAINMANAGER_H
-#ifndef __DRAWBGFX_CHAIN_MANAGER__
-#define __DRAWBGFX_CHAIN_MANAGER__
+#pragma once
-#include "texturemanager.h"
-#include "targetmanager.h"
#include "effectmanager.h"
+#include "targetmanager.h"
+#include "texturemanager.h"
+
+#include "util/utilfwd.h"
#include <map>
#include <string>
+#include <string_view>
+#include <utility>
#include <vector>
+
class running_machine;
class osd_window;
struct slider_state;
@@ -33,23 +38,29 @@ namespace ui { class menu_item; }
class bgfx_chain;
class bgfx_slider;
-class chain_desc
+class chain_manager
{
public:
- chain_desc(std::string name, std::string path)
- : m_name(name)
- , m_path(path)
+ class screen_prim
{
- }
+ public:
+ screen_prim() = default;
+ screen_prim(render_primitive *prim);
- const std::string m_name;
- const std::string m_path;
-};
+ render_primitive *m_prim = nullptr;
+ uint16_t m_screen_width = 0;
+ uint16_t m_screen_height = 0;
+ uint16_t m_quad_width = 0;
+ uint16_t m_quad_height = 0;
+ float m_tex_width = 0.0f;
+ float m_tex_height = 0.0f;
+ int m_rowpixels = 0;
+ uint32_t m_palette_length = 0;
+ uint32_t m_flags = 0;
+ };
-class chain_manager
-{
-public:
- chain_manager(running_machine& machine, osd_options& options, texture_manager& textures, target_manager& targets, effect_manager& effects, uint32_t window_index, slider_dirty_notifier& slider_notifier);
+ chain_manager(running_machine& machine, const osd_options& options, texture_manager& textures, target_manager& targets, effect_manager& effects, uint32_t window_index,
+ slider_dirty_notifier& slider_notifier, uint16_t user_prescale, uint16_t max_prescale_size);
~chain_manager();
uint32_t update_screen_textures(uint32_t view, render_primitive *starting_prim, osd_window& window);
@@ -57,7 +68,7 @@ public:
// Getters
running_machine& machine() const { return m_machine; }
- osd_options& options() const { return m_options; }
+ const osd_options& options() const { return m_options; }
texture_manager& textures() const { return m_textures; }
target_manager& targets() const { return m_targets; }
effect_manager& effects() const { return m_effects; }
@@ -65,7 +76,7 @@ public:
uint32_t window_index() const { return m_window_index; }
uint32_t screen_count() const { return m_screen_count; }
bgfx_chain* screen_chain(uint32_t screen);
- bgfx_chain* load_chain(std::string name, uint32_t screen_index);
+ std::unique_ptr<bgfx_chain> load_chain(std::string name, uint32_t screen_index);
bool has_applicable_chain(uint32_t screen);
std::vector<ui::menu_item> get_slider_list();
std::vector<std::vector<float>> slider_settings();
@@ -73,43 +84,44 @@ public:
// Setters
void restore_slider_settings(int32_t id, std::vector<std::vector<float>>& settings);
- class screen_prim
+ void load_config(util::xml::data_node const &screennode);
+ void save_config(util::xml::data_node &parentnode);
+
+private:
+ class chain_desc
{
public:
- screen_prim() : m_prim(nullptr), m_screen_width(0), m_screen_height(0), m_quad_width(0), m_quad_height(0)
- , m_tex_width(0), m_tex_height(0), m_rowpixels(0), m_palette_length(0), m_flags(0)
+ chain_desc(const chain_desc &) = default;
+ chain_desc(chain_desc &&) = default;
+ chain_desc &operator=(const chain_desc &) = default;
+ chain_desc &operator=(chain_desc &&) = default;
+
+ chain_desc(std::string &&name, std::string &&path)
+ : m_name(std::move(name))
+ , m_path(std::move(path))
{
}
- screen_prim(render_primitive *prim);
-
- render_primitive *m_prim;
- uint16_t m_screen_width;
- uint16_t m_screen_height;
- uint16_t m_quad_width;
- uint16_t m_quad_height;
- float m_tex_width;
- float m_tex_height;
- int m_rowpixels;
- uint32_t m_palette_length;
- uint32_t m_flags;
+ std::string m_name;
+ std::string m_path;
};
-private:
void load_chains();
void destroy_chains();
void reload_chains();
void init_texture_converters();
+ void get_default_chain_info(std::string &out_chain_name, int32_t &out_chain_index);
void refresh_available_chains();
void destroy_unloaded_chains();
- void find_available_chains(std::string root, std::string path);
- void parse_chain_selections(std::string chain_str);
- std::vector<std::string> split_option_string(std::string chain_str) const;
+ void find_available_chains(std::string_view root, std::string_view path);
+ void parse_chain_selections(std::string_view chain_str);
+ std::vector<std::string_view> split_option_string(std::string_view chain_str) const;
void update_screen_count(uint32_t screen_count);
+ void set_current_chain(uint32_t screen, int32_t chain_index);
int32_t slider_changed(int id, std::string *str, int32_t newval);
void create_selection_slider(uint32_t screen_index);
bool needs_sliders();
@@ -118,13 +130,16 @@ private:
void process_screen_quad(uint32_t view, uint32_t screen, screen_prim &prim, osd_window& window);
running_machine& m_machine;
- osd_options& m_options;
+ const osd_options& m_options;
texture_manager& m_textures;
target_manager& m_targets;
effect_manager& m_effects;
uint32_t m_window_index;
+ uint16_t m_user_prescale;
+ uint16_t m_max_prescale_size;
slider_dirty_notifier& m_slider_notifier;
uint32_t m_screen_count;
+ int32_t m_default_chain_index;
std::vector<chain_desc> m_available_chains;
std::vector<bgfx_chain*> m_screen_chains;
std::vector<std::string> m_chain_names;
@@ -138,7 +153,7 @@ private:
std::vector<screen_prim> m_screen_prims;
std::vector<uint8_t> m_palette_temp;
- static const uint32_t CHAIN_NONE;
+ static inline constexpr uint32_t CHAIN_NONE = 0;
};
-#endif // __DRAWBGFX_CHAIN_MANAGER__
+#endif // MAME_RENDER_BGFX_CHAINMANAGER_H
diff --git a/src/osd/modules/render/bgfx/chainreader.cpp b/src/osd/modules/render/bgfx/chainreader.cpp
index 92e30df0b33..362baa42c82 100644
--- a/src/osd/modules/render/bgfx/chainreader.cpp
+++ b/src/osd/modules/render/bgfx/chainreader.cpp
@@ -8,21 +8,26 @@
#include "chainreader.h"
-#include <string>
-#include <vector>
-#include <map>
-
#include "chain.h"
+#include "chainentryreader.h"
#include "chainmanager.h"
-#include "sliderreader.h"
+#include "parameter.h"
#include "paramreader.h"
-#include "chainentryreader.h"
-#include "targetreader.h"
-#include "targetmanager.h"
#include "slider.h"
-#include "parameter.h"
+#include "sliderreader.h"
+#include "targetmanager.h"
+#include "targetreader.h"
+
+#include <vector>
+#include <map>
-bgfx_chain* chain_reader::read_from_value(const Value& value, std::string prefix, chain_manager& chains, uint32_t screen_index)
+std::unique_ptr<bgfx_chain> chain_reader::read_from_value(
+ const Value& value,
+ const std::string &prefix,
+ chain_manager& chains,
+ uint32_t screen_index,
+ uint16_t user_prescale,
+ uint16_t max_prescale_size)
{
if (!validate_parameters(value, prefix))
{
@@ -96,7 +101,7 @@ bgfx_chain* chain_reader::read_from_value(const Value& value, std::string prefix
// TODO: Move into its own reader
for (uint32_t i = 0; i < target_array.Size(); i++)
{
- bgfx_target* target = target_reader::read_from_value(target_array[i], prefix + "targets[" + std::to_string(i) + "]: ", chains, screen_index);
+ bgfx_target* target = target_reader::read_from_value(target_array[i], prefix + "targets[" + std::to_string(i) + "]: ", chains, screen_index, user_prescale, max_prescale_size);
if (target == nullptr)
{
return nullptr;
@@ -121,19 +126,28 @@ bgfx_chain* chain_reader::read_from_value(const Value& value, std::string prefix
}
}
- return new bgfx_chain(name, author, transform, chains.targets(), sliders, parameters, entries, target_list, screen_index);
+ return std::make_unique<bgfx_chain>(
+ std::move(name),
+ std::move(author),
+ transform,
+ chains.targets(),
+ std::move(sliders),
+ std::move(parameters),
+ std::move(entries),
+ std::move(target_list),
+ screen_index);
}
-bool chain_reader::validate_parameters(const Value& value, std::string prefix)
+bool chain_reader::validate_parameters(const Value& value, const std::string &prefix)
{
- if (!READER_CHECK(value.HasMember("name"), (prefix + "Must have string value 'name'\n").c_str())) return false;
- if (!READER_CHECK(value["name"].IsString(), (prefix + "Value 'name' must be a string\n").c_str())) return false;
- if (!READER_CHECK(value.HasMember("author"), (prefix + "Must have string value 'author'\n").c_str())) return false;
- if (!READER_CHECK(value["author"].IsString(), (prefix + "Value 'author' must be a string\n").c_str())) return false;
- if (!READER_CHECK(value.HasMember("passes"), (prefix + "Must have array value 'passes'\n").c_str())) return false;
- if (!READER_CHECK(value["passes"].IsArray(), (prefix + "Value 'passes' must be an array\n").c_str())) return false;
- if (!READER_CHECK(!value.HasMember("sliders") || value["sliders"].IsArray(), (prefix + "Value 'sliders' must be an array\n").c_str())) return false;
- if (!READER_CHECK(!value.HasMember("parameters") || value["parameters"].IsArray(), (prefix + "Value 'parameters' must be an array\n").c_str())) return false;
- if (!READER_CHECK(!value.HasMember("targets") || value["targets"].IsArray(), (prefix + "Value 'targets' must be an array\n").c_str())) return false;
+ if (!READER_CHECK(value.HasMember("name"), "%sMust have string value 'name'\n", prefix)) return false;
+ if (!READER_CHECK(value["name"].IsString(), "%sValue 'name' must be a string\n", prefix)) return false;
+ if (!READER_CHECK(value.HasMember("author"), "%sMust have string value 'author'\n", prefix)) return false;
+ if (!READER_CHECK(value["author"].IsString(), "%sValue 'author' must be a string\n", prefix)) return false;
+ if (!READER_CHECK(value.HasMember("passes"), "%sMust have array value 'passes'\n", prefix)) return false;
+ if (!READER_CHECK(value["passes"].IsArray(), "%sValue 'passes' must be an array\n", prefix)) return false;
+ if (!READER_CHECK(!value.HasMember("sliders") || value["sliders"].IsArray(), "%sValue 'sliders' must be an array\n", prefix)) return false;
+ if (!READER_CHECK(!value.HasMember("parameters") || value["parameters"].IsArray(), "%sValue 'parameters' must be an array\n", prefix)) return false;
+ if (!READER_CHECK(!value.HasMember("targets") || value["targets"].IsArray(), "%sValue 'targets' must be an array\n", prefix)) return false;
return true;
}
diff --git a/src/osd/modules/render/bgfx/chainreader.h b/src/osd/modules/render/bgfx/chainreader.h
index a2fa3ba28a5..6bbd2058501 100644
--- a/src/osd/modules/render/bgfx/chainreader.h
+++ b/src/osd/modules/render/bgfx/chainreader.h
@@ -6,23 +6,26 @@
//
//============================================================
-#pragma once
+#ifndef MAME_RENDER_BGFX_CHAINREADER_H
+#define MAME_RENDER_BGFX_CHAINREADER_H
-#ifndef __DRAWBGFX_CHAIN_READER__
-#define __DRAWBGFX_CHAIN_READER__
+#pragma once
#include "statereader.h"
+#include <memory>
+#include <string>
+
class bgfx_chain;
class chain_manager;
class chain_reader : public state_reader
{
public:
- static bgfx_chain* read_from_value(const Value& value, std::string prefix, chain_manager& chains, uint32_t screen_index);
+ static std::unique_ptr<bgfx_chain> read_from_value(const Value& value, const std::string &prefix, chain_manager& chains, uint32_t screen_index, uint16_t user_prescale, uint16_t max_prescale_size);
private:
- static bool validate_parameters(const Value& value, std::string prefix);
+ static bool validate_parameters(const Value& value, const std::string &prefix);
};
-#endif // __DRAWBGFX_CHAIN_READER__
+#endif // MAME_RENDER_BGFX_CHAINREADER_H
diff --git a/src/osd/modules/render/bgfx/clearreader.cpp b/src/osd/modules/render/bgfx/clearreader.cpp
index 948d96a7393..58c4d5f01aa 100644
--- a/src/osd/modules/render/bgfx/clearreader.cpp
+++ b/src/osd/modules/render/bgfx/clearreader.cpp
@@ -6,13 +6,15 @@
//
//============================================================
-#include <bgfx/bgfx.h>
-
#include "clearreader.h"
#include "clear.h"
-clear_state* clear_reader::read_from_value(const Value& value, std::string prefix)
+#include <bgfx/bgfx.h>
+
+#include <algorithm>
+
+clear_state* clear_reader::read_from_value(const Value& value, const std::string &prefix)
{
if (!validate_parameters(value, prefix))
{
@@ -29,10 +31,8 @@ clear_state* clear_reader::read_from_value(const Value& value, std::string prefi
const Value& colors = value["clearcolor"];
for (int i = 0; i < colors.Size(); i++)
{
- if (!READER_CHECK(colors[i].IsNumber(), (prefix + "clearcolor[" + std::to_string(i) + "] must be a numeric value\n").c_str())) return nullptr;
- auto val = int32_t(float(colors[i].GetDouble()) * 255.0f);
- if (val > 255) val = 255;
- if (val < 0) val = 0;
+ if (!READER_CHECK(colors[i].IsNumber(), "%sclearcolor[%d] must be a numeric value\n", prefix, i)) return nullptr;
+ auto val = std::clamp<int32_t>(float(colors[i].GetDouble()) * 255.0f, 0, 255);
clear_color |= val << (24 - (i * 3));
}
clear_flags |= BGFX_CLEAR_COLOR;
@@ -53,10 +53,10 @@ clear_state* clear_reader::read_from_value(const Value& value, std::string prefi
return new clear_state(clear_flags, clear_color, clear_depth, clear_stencil);
}
-bool clear_reader::validate_parameters(const Value& value, std::string prefix)
+bool clear_reader::validate_parameters(const Value& value, const std::string &prefix)
{
- if (!READER_CHECK(!value.HasMember("clearcolor") || (value["clearcolor"].IsArray() && value["clearcolor"].GetArray().Size() == 4), (prefix + "'clearcolor' must be an array of four numeric RGBA values representing the color to which to clear the color buffer\n").c_str())) return false;
- if (!READER_CHECK(!value.HasMember("cleardepth") || value["cleardepth"].IsNumber(), (prefix + "'cleardepth' must be a numeric value representing the depth to which to clear the depth buffer\n").c_str())) return false;
- if (!READER_CHECK(!value.HasMember("clearstencil") || value["clearstencil"].IsNumber(), (prefix + "'clearstencil' must be a numeric value representing the stencil value to which to clear the stencil buffer\n").c_str())) return false;
+ if (!READER_CHECK(!value.HasMember("clearcolor") || (value["clearcolor"].IsArray() && value["clearcolor"].GetArray().Size() == 4), "%s'clearcolor' must be an array of four numeric RGBA values representing the color to which to clear the color buffer\n", prefix)) return false;
+ if (!READER_CHECK(!value.HasMember("cleardepth") || value["cleardepth"].IsNumber(), "%s'cleardepth' must be a numeric value representing the depth to which to clear the depth buffer\n", prefix)) return false;
+ if (!READER_CHECK(!value.HasMember("clearstencil") || value["clearstencil"].IsNumber(), "%s'clearstencil' must be a numeric value representing the stencil value to which to clear the stencil buffer\n", prefix)) return false;
return true;
}
diff --git a/src/osd/modules/render/bgfx/clearreader.h b/src/osd/modules/render/bgfx/clearreader.h
index 80605ea35f3..1c2063e95de 100644
--- a/src/osd/modules/render/bgfx/clearreader.h
+++ b/src/osd/modules/render/bgfx/clearreader.h
@@ -6,26 +6,26 @@
//
//============================================================
+#ifndef MAME_RENDER_BGFX_CLEARREADER_H
+#define MAME_RENDER_BGFX_CLEARREADER_H
+
#pragma once
-#ifndef __DRAWBGFX_CLEAR_READER__
-#define __DRAWBGFX_CLEAR_READER__
+#include "statereader.h"
#include <string>
-#include "statereader.h"
-
class clear_state;
class clear_reader : public state_reader {
public:
- static clear_state* read_from_value(const Value& value, std::string prefix);
+ static clear_state* read_from_value(const Value& value, const std::string &prefix);
private:
- static bool validate_parameters(const Value& value, std::string prefix);
+ static bool validate_parameters(const Value& value, const std::string &prefix);
static const int FLAG_COUNT = 3;
static const string_to_enum FLAG_NAMES[FLAG_COUNT];
};
-#endif // __DRAWBGFX_CLEAR_READER__
+#endif // MAME_RENDER_BGFX_CLEARREADER_H
diff --git a/src/osd/modules/render/bgfx/depthreader.cpp b/src/osd/modules/render/bgfx/depthreader.cpp
index 97502d9028e..bcfc568b0da 100644
--- a/src/osd/modules/render/bgfx/depthreader.cpp
+++ b/src/osd/modules/render/bgfx/depthreader.cpp
@@ -6,10 +6,10 @@
//
//============================================================
-#include <bgfx/bgfx.h>
-
#include "depthreader.h"
+#include <bgfx/bgfx.h>
+
const depth_reader::string_to_enum depth_reader::FUNCTION_NAMES[depth_reader::FUNCTION_COUNT] = {
{ "never", BGFX_STATE_DEPTH_TEST_NEVER },
{ "less", BGFX_STATE_DEPTH_TEST_LESS },
@@ -21,12 +21,12 @@ const depth_reader::string_to_enum depth_reader::FUNCTION_NAMES[depth_reader::FU
{ "always", BGFX_STATE_DEPTH_TEST_ALWAYS }
};
-uint64_t depth_reader::read_from_value(const Value& value, std::string prefix)
+uint64_t depth_reader::read_from_value(const Value& value, const std::string &prefix)
{
uint64_t write_enable = 0;
if (value.HasMember("writeenable"))
{
- if (!READER_CHECK(value["writeenable"].IsBool(), (prefix + "Value 'writeenable' must be a boolean\n").c_str())) return 0;
+ if (!READER_CHECK(value["writeenable"].IsBool(), "%sValue 'writeenable' must be a boolean\n", prefix)) return 0;
write_enable = value["writeenable"].GetBool() ? BGFX_STATE_WRITE_Z : 0;
}
diff --git a/src/osd/modules/render/bgfx/depthreader.h b/src/osd/modules/render/bgfx/depthreader.h
index 9e2c99a0b29..0815732850f 100644
--- a/src/osd/modules/render/bgfx/depthreader.h
+++ b/src/osd/modules/render/bgfx/depthreader.h
@@ -6,10 +6,10 @@
//
//============================================================
-#pragma once
+#ifndef MAME_RENDER_BGFX_DEPTHREADER_H
+#define MAME_RENDER_BGFX_DEPTHREADER_H
-#ifndef __DRAWBGFX_DEPTH_READER__
-#define __DRAWBGFX_DEPTH_READER__
+#pragma once
#include <string>
@@ -17,11 +17,11 @@
class depth_reader : public state_reader {
public:
- static uint64_t read_from_value(const Value& value, std::string prefix);
+ static uint64_t read_from_value(const Value& value, const std::string &prefix);
private:
static const int FUNCTION_COUNT = 8;
static const string_to_enum FUNCTION_NAMES[FUNCTION_COUNT];
};
-#endif // __DRAWBGFX_DEPTH_READER__
+#endif // MAME_RENDER_BGFX_DEPTHREADER_H
diff --git a/src/osd/modules/render/bgfx/effect.cpp b/src/osd/modules/render/bgfx/effect.cpp
index c5ea8555dce..18b43cca9bf 100644
--- a/src/osd/modules/render/bgfx/effect.cpp
+++ b/src/osd/modules/render/bgfx/effect.cpp
@@ -13,46 +13,50 @@
#include "modules/osdmodule.h"
#include "osdcore.h"
-bgfx_effect::bgfx_effect(uint64_t state, bgfx::ShaderHandle vertex_shader, bgfx::ShaderHandle fragment_shader, std::vector<bgfx_uniform*> uniforms)
- : m_state(state)
+#include <utility>
+
+
+bgfx_effect::bgfx_effect(std::string &&name, uint64_t state, bgfx::ShaderHandle vertex_shader, bgfx::ShaderHandle fragment_shader, std::vector<std::unique_ptr<bgfx_uniform> > &uniforms)
+ : m_name(std::move(name))
+ , m_state(state)
{
m_program_handle = bgfx::createProgram(vertex_shader, fragment_shader, false);
- for (int i = 0; i < uniforms.size(); i++)
+ for (auto &uniform : uniforms)
{
- if (m_uniforms[uniforms[i]->name()] != nullptr)
+ const auto existing = m_uniforms.find(uniform->name());
+ if (existing != m_uniforms.end())
{
- osd_printf_verbose("Uniform %s appears to be duplicated in one or more effects, please double-check the effect JSON files.\n", uniforms[i]->name());
- delete uniforms[i];
+ osd_printf_verbose("Uniform %s appears to be duplicated in one or more effects, please double-check the effect JSON files.\n", uniform->name());
+ uniform.reset();
continue;
}
- uniforms[i]->create();
- m_uniforms[uniforms[i]->name()] = uniforms[i];
+ uniform->create();
+ m_uniforms.emplace(uniform->name(), std::move(uniform));
}
}
bgfx_effect::~bgfx_effect()
{
- for (std::pair<std::string, bgfx_uniform*> uniform : m_uniforms)
- {
- delete uniform.second;
- }
m_uniforms.clear();
bgfx::destroy(m_program_handle);
}
void bgfx_effect::submit(int view, uint64_t blend)
{
- for (std::pair<std::string, bgfx_uniform*> uniform_pair : m_uniforms)
+ for (auto &[name, uniform] : m_uniforms)
{
- (uniform_pair.second)->upload();
+ uniform->upload();
}
- bgfx::setState(m_state | blend);
+
+ const uint64_t final_state = (blend != ~0ULL) ? ((m_state & ~BGFX_STATE_BLEND_MASK) | blend) : m_state;
+
+ bgfx::setState(final_state);
bgfx::submit(view, m_program_handle);
}
-bgfx_uniform* bgfx_effect::uniform(std::string name)
+bgfx_uniform* bgfx_effect::uniform(const std::string &name)
{
- auto iter = m_uniforms.find(name);
- return iter != m_uniforms.end() ? iter->second : nullptr;
+ const auto iter = m_uniforms.find(name);
+ return (iter != m_uniforms.end()) ? iter->second.get() : nullptr;
}
diff --git a/src/osd/modules/render/bgfx/effect.h b/src/osd/modules/render/bgfx/effect.h
index ca1be77c73d..07646e6302e 100644
--- a/src/osd/modules/render/bgfx/effect.h
+++ b/src/osd/modules/render/bgfx/effect.h
@@ -6,33 +6,36 @@
//
//============================================================
-#pragma once
+#ifndef MAME_RENDER_BGFX_EFFECT_H
+#define MAME_RENDER_BGFX_EFFECT_H
-#ifndef __DRAWBGFX_EFFECT__
-#define __DRAWBGFX_EFFECT__
+#pragma once
#include <bgfx/bgfx.h>
-#include <vector>
#include <map>
+#include <memory>
#include <string>
+#include <vector>
+
class bgfx_uniform;
class bgfx_effect
{
public:
- bgfx_effect(uint64_t state, bgfx::ShaderHandle vertex_shader, bgfx::ShaderHandle fragment_shader, std::vector<bgfx_uniform*> uniforms);
+ bgfx_effect(std::string &&name, uint64_t state, bgfx::ShaderHandle vertex_shader, bgfx::ShaderHandle fragment_shader, std::vector<std::unique_ptr<bgfx_uniform> > &uniforms);
~bgfx_effect();
- void submit(int view, uint64_t blend = 0L);
- bgfx_uniform *uniform(std::string name);
- bool is_valid() { return m_program_handle.idx != bgfx::kInvalidHandle; }
+ void submit(int view, uint64_t blend = ~0ULL);
+ bgfx_uniform *uniform(const std::string &name);
+ bool is_valid() const { return m_program_handle.idx != bgfx::kInvalidHandle; }
private:
+ std::string m_name;
uint64_t m_state;
bgfx::ProgramHandle m_program_handle;
- std::map<std::string, bgfx_uniform*> m_uniforms;
+ std::map<std::string, std::unique_ptr<bgfx_uniform> > m_uniforms;
};
-#endif // __DRAWBGFX_EFFECT__
+#endif // MAME_RENDER_BGFX_EFFECT_H
diff --git a/src/osd/modules/render/bgfx/effectmanager.cpp b/src/osd/modules/render/bgfx/effectmanager.cpp
index f57f56f708d..e5e5d1698f6 100644
--- a/src/osd/modules/render/bgfx/effectmanager.cpp
+++ b/src/osd/modules/render/bgfx/effectmanager.cpp
@@ -11,8 +11,11 @@
#include "effectmanager.h"
-#include "effectreader.h"
#include "effect.h"
+#include "effectreader.h"
+#include "shadermanager.h"
+
+#include "path.h"
#include "osdfile.h"
#include "modules/lib/osdobj_common.h"
@@ -25,66 +28,75 @@
#include <bgfx/bgfx.h>
-static bool prepare_effect_document(std::string &name, osd_options &options, rapidjson::Document &document)
+#include <utility>
+
+
+static bool prepare_effect_document(const std::string &name, const osd_options &options, rapidjson::Document &document)
{
std::string full_name = name;
if (full_name.length() < 5 || (full_name.compare(full_name.length() - 5, 5, ".json") != 0))
{
- full_name = full_name + ".json";
+ full_name += ".json";
}
- std::string path = osd_subst_env(util::string_format("%s" PATH_SEPARATOR "effects" PATH_SEPARATOR, options.bgfx_path()));
- path += full_name;
+ const std::string path = util::path_concat(options.bgfx_path(), "effects", full_name);
bx::FileReader reader;
if (!bx::open(&reader, path.c_str()))
{
- osd_printf_error("Unable to open effect file %s\n", path.c_str());
+ osd_printf_error("Unable to open effect file %s\n", path);
return false;
}
- int32_t size (bx::getSize(&reader));
- char* data = new char[size + 1];
- bx::read(&reader, reinterpret_cast<void*>(data), size);
+ const int32_t size = bx::getSize(&reader);
+ std::unique_ptr<char []> data(new (std::nothrow) char [size + 1]);
+ if (!data)
+ {
+ osd_printf_error("Out of memory reading effect file %s\n", path);
+ bx::close(&reader);
+ return false;
+ }
+
+ bx::ErrorAssert err;
+ bx::read(&reader, reinterpret_cast<void*>(data.get()), size, &err);
bx::close(&reader);
data[size] = 0;
- document.Parse<rapidjson::kParseCommentsFlag>(data);
-
- delete [] data;
+ document.Parse<rapidjson::kParseCommentsFlag>(data.get());
+ data.reset();
if (document.HasParseError())
{
std::string error(rapidjson::GetParseError_En(document.GetParseError()));
- osd_printf_error("Unable to parse effect %s. Errors returned:\n", path.c_str());
- osd_printf_error("%s\n", error.c_str());
+ osd_printf_error("Unable to parse effect %s. Errors returned:\n%s\n", path, error);
return false;
}
return true;
}
+
+// keep constructor and destructor out-of-line so the header works with forward declarations
+
+effect_manager::effect_manager(shader_manager& shaders) : m_shaders(shaders)
+{
+}
+
effect_manager::~effect_manager()
{
- for (std::pair<std::string, bgfx_effect*> effect : m_effects)
- {
- delete effect.second;
- }
- m_effects.clear();
+ // the map will automatically dispose of the effects
}
-bgfx_effect* effect_manager::get_or_load_effect(osd_options &options, std::string name)
+bgfx_effect* effect_manager::get_or_load_effect(const osd_options &options, const std::string &name)
{
- std::map<std::string, bgfx_effect*>::iterator iter = m_effects.find(name);
+ const auto iter = m_effects.find(name);
if (iter != m_effects.end())
- {
- return iter->second;
- }
+ return iter->second.get();
return load_effect(options, name);
}
-bgfx_effect* effect_manager::load_effect(osd_options &options, std::string name)
+bgfx_effect* effect_manager::load_effect(const osd_options &options, const std::string &name)
{
rapidjson::Document document;
if (!prepare_effect_document(name, options, document))
@@ -92,20 +104,18 @@ bgfx_effect* effect_manager::load_effect(osd_options &options, std::string name)
return nullptr;
}
- bgfx_effect* effect = effect_reader::read_from_value(document, "Effect '" + name + "': ", options, m_shaders);
+ std::unique_ptr<bgfx_effect> effect = effect_reader::read_from_value(name, document, "Effect '" + name + "': ", options, m_shaders);
- if (effect == nullptr)
+ if (!effect)
{
- osd_printf_error("Unable to load effect %s\n", name.c_str());
+ osd_printf_error("Unable to load effect %s\n", name);
return nullptr;
}
- m_effects[name] = effect;
-
- return effect;
+ return m_effects.emplace(name, std::move(effect)).first->second.get();
}
-bool effect_manager::validate_effect(osd_options &options, std::string name)
+bool effect_manager::validate_effect(const osd_options &options, const std::string &name)
{
rapidjson::Document document;
if (!prepare_effect_document(name, options, document))
diff --git a/src/osd/modules/render/bgfx/effectmanager.h b/src/osd/modules/render/bgfx/effectmanager.h
index 5d8bf3f5c93..697d468dc5c 100644
--- a/src/osd/modules/render/bgfx/effectmanager.h
+++ b/src/osd/modules/render/bgfx/effectmanager.h
@@ -9,34 +9,35 @@
//
//============================================================
-#pragma once
+#ifndef MAME_RENDER_BGFX_EFFECTMANAGER_H
+#define MAME_RENDER_BGFX_EFFECTMANAGER_H
-#ifndef __DRAWBGFX_EFFECT_MANAGER__
-#define __DRAWBGFX_EFFECT_MANAGER__
+#pragma once
#include <map>
+#include <memory>
#include <string>
-#include <bgfx/bgfx.h>
-
-#include "shadermanager.h"
class bgfx_effect;
+class osd_options;
+class shader_manager;
-class effect_manager {
+class effect_manager
+{
public:
- effect_manager(shader_manager& shaders) : m_shaders(shaders) { }
+ effect_manager(shader_manager& shaders);
~effect_manager();
// Getters
- bgfx_effect* get_or_load_effect(osd_options &options, std::string name);
- static bool validate_effect(osd_options &options, std::string name);
+ bgfx_effect* get_or_load_effect(const osd_options &options, const std::string &name);
+ static bool validate_effect(const osd_options &options, const std::string &name);
private:
- bgfx_effect* load_effect(osd_options& options, std::string name);
+ bgfx_effect* load_effect(const osd_options &options, const std::string &name);
- shader_manager& m_shaders;
- std::map<std::string, bgfx_effect*> m_effects;
+ shader_manager &m_shaders;
+ std::map<std::string, std::unique_ptr<bgfx_effect> > m_effects;
};
-#endif // __DRAWBGFX_EFFECT_MANAGER__
+#endif // MAME_RENDER_BGFX_EFFECTMANAGER_H
diff --git a/src/osd/modules/render/bgfx/effectreader.cpp b/src/osd/modules/render/bgfx/effectreader.cpp
index 36acee2f9ea..befdc598537 100644
--- a/src/osd/modules/render/bgfx/effectreader.cpp
+++ b/src/osd/modules/render/bgfx/effectreader.cpp
@@ -8,80 +8,79 @@
#include "effectreader.h"
-#include "effect.h"
#include "blendreader.h"
-#include "depthreader.h"
#include "cullreader.h"
-#include "writereader.h"
+#include "depthreader.h"
+#include "effect.h"
#include "shadermanager.h"
-#include "uniformreader.h"
#include "uniform.h"
+#include "uniformreader.h"
+#include "writereader.h"
-bgfx_effect *effect_reader::read_from_value(const Value& value, std::string prefix, osd_options &options, shader_manager& shaders)
+#include <utility>
+
+
+std::unique_ptr<bgfx_effect> effect_reader::read_from_value(
+ const std::string &name,
+ const Value &value,
+ const std::string &prefix,
+ const osd_options &options,
+ shader_manager &shaders)
{
uint64_t flags = 0;
std::string vertex_name;
std::string fragment_name;
- bgfx::ShaderHandle vertex_shader = BGFX_INVALID_HANDLE;
- bgfx::ShaderHandle fragment_shader = BGFX_INVALID_HANDLE;
- std::vector<bgfx_uniform *> uniforms;
+ std::vector<std::unique_ptr<bgfx_uniform> > uniforms;
if (!get_base_effect_data(value, prefix, flags, vertex_name, fragment_name, uniforms))
{
return nullptr;
}
+ bgfx::ShaderHandle vertex_shader = BGFX_INVALID_HANDLE;
+ bgfx::ShaderHandle fragment_shader = BGFX_INVALID_HANDLE;
+
if (!get_shader_data(value, options, shaders, vertex_name, vertex_shader, fragment_name, fragment_shader))
{
- clear_uniform_list(uniforms);
return nullptr;
}
- bgfx_effect *effect = new bgfx_effect(flags, vertex_shader, fragment_shader, uniforms);
- if (effect->is_valid())
- {
- return effect;
- }
-
- delete effect;
+ std::unique_ptr<bgfx_effect> effect(new bgfx_effect(std::string(name), flags, vertex_shader, fragment_shader, uniforms));
+ if (!effect->is_valid())
+ return nullptr;
- return nullptr;
+ return effect;
}
-bool effect_reader::validate_value(const Value& value, std::string prefix, osd_options &options)
+bool effect_reader::validate_value(const Value& value, const std::string &prefix, const osd_options &options)
{
if (!validate_parameters(value, prefix))
- {
return false;
- }
uint64_t flags = 0;
std::string vertex_name;
std::string fragment_name;
- std::vector<bgfx_uniform *> uniforms;
+ std::vector<std::unique_ptr<bgfx_uniform> > uniforms;
if (!get_base_effect_data(value, prefix, flags, vertex_name, fragment_name, uniforms))
- {
return false;
- }
if (!shader_manager::is_shader_present(options, vertex_name))
- {
- clear_uniform_list(uniforms);
return false;
- }
if (!shader_manager::is_shader_present(options, fragment_name))
- {
- clear_uniform_list(uniforms);
return false;
- }
return true;
}
-bool effect_reader::get_base_effect_data(const Value& value, std::string &prefix, uint64_t &flags, std::string &vertex_name, std::string &fragment_name,
- std::vector<bgfx_uniform *> &uniforms)
+bool effect_reader::get_base_effect_data(
+ const Value& value,
+ const std::string &prefix,
+ uint64_t &flags,
+ std::string &vertex_name,
+ std::string &fragment_name,
+ std::vector<std::unique_ptr<bgfx_uniform> > &uniforms)
{
if (!validate_parameters(value, prefix))
{
@@ -101,12 +100,12 @@ bool effect_reader::get_base_effect_data(const Value& value, std::string &prefix
const Value& uniform_array = value["uniforms"];
for (uint32_t i = 0; i < uniform_array.Size(); i++)
{
- bgfx_uniform *uniform = uniform_reader::read_from_value(uniform_array[i], prefix + "uniforms[" + std::to_string(i) + "]: ");
- if (uniform == nullptr)
+ auto uniform = uniform_reader::read_from_value(uniform_array[i], prefix + "uniforms[" + std::to_string(i) + "]: ");
+ if (!uniform)
{
return false;
}
- uniforms.push_back(uniform);
+ uniforms.emplace_back(std::move(uniform));
}
vertex_name = value["vertex"].GetString();
@@ -127,8 +126,14 @@ bool effect_reader::get_base_effect_data(const Value& value, std::string &prefix
return true;
}
-bool effect_reader::get_shader_data(const Value& value, osd_options &options, shader_manager &shaders, std::string &vertex_name, bgfx::ShaderHandle &vertex_shader,
- std::string &fragment_name, bgfx::ShaderHandle &fragment_shader)
+bool effect_reader::get_shader_data(
+ const Value &value,
+ const osd_options &options,
+ shader_manager &shaders,
+ std::string &vertex_name,
+ bgfx::ShaderHandle &vertex_shader,
+ std::string &fragment_name,
+ bgfx::ShaderHandle &fragment_shader)
{
vertex_shader = shaders.load_shader(options, vertex_name);
if (vertex_shader.idx == bgfx::kInvalidHandle)
@@ -145,25 +150,17 @@ bool effect_reader::get_shader_data(const Value& value, osd_options &options, sh
return true;
}
-void effect_reader::clear_uniform_list(std::vector<bgfx_uniform *> &uniforms)
-{
- for (bgfx_uniform *uniform : uniforms)
- {
- delete uniform;
- }
-}
-
-bool effect_reader::validate_parameters(const Value& value, std::string prefix)
+bool effect_reader::validate_parameters(const Value& value, const std::string &prefix)
{
- if (!READER_CHECK(value.HasMember("depth"), (prefix + "Must have object value 'depth' (what are our Z-buffer settings?)\n").c_str())) return false;
- if (!READER_CHECK(value.HasMember("cull"), (prefix + "Must have object value 'cull' (do we cull triangles based on winding?)\n").c_str())) return false;
- if (!READER_CHECK(value.HasMember("write"), (prefix + "Must have object value 'write' (what are our color buffer write settings?)\n").c_str())) return false;
- if (!READER_CHECK(value.HasMember("vertex"), (prefix + "Must have string value 'vertex' (what is our vertex shader?)\n").c_str())) return false;
- if (!READER_CHECK(value["vertex"].IsString(), (prefix + "Value 'vertex' must be a string\n").c_str())) return false;
- if (!READER_CHECK(value.HasMember("fragment") || value.HasMember("pixel"), (prefix + "Must have string value named 'fragment' or 'pixel' (what is our fragment/pixel shader?)\n").c_str())) return false;
- if (!READER_CHECK(!value.HasMember("fragment") || value["fragment"].IsString(), (prefix + "Value 'fragment' must be a string\n").c_str())) return false;
- if (!READER_CHECK(!value.HasMember("pixel") || value["pixel"].IsString(), (prefix + "Value 'pixel' must be a string\n").c_str())) return false;
- if (!READER_CHECK(value.HasMember("uniforms"), (prefix + "Must have array value 'uniforms' (what are our shader's parameters?)\n").c_str())) return false;
- if (!READER_CHECK(value["uniforms"].IsArray(), (prefix + "Value 'uniforms' must be an array\n").c_str())) return false;
+ if (!READER_CHECK(value.HasMember("depth"), "%sMust have object value 'depth' (what are our Z-buffer settings?)\n", prefix)) return false;
+ if (!READER_CHECK(value.HasMember("cull"), "%sMust have object value 'cull' (do we cull triangles based on winding?)\n", prefix)) return false;
+ if (!READER_CHECK(value.HasMember("write"), "%sMust have object value 'write' (what are our color buffer write settings?)\n", prefix)) return false;
+ if (!READER_CHECK(value.HasMember("vertex"), "%sMust have string value 'vertex' (what is our vertex shader?)\n", prefix)) return false;
+ if (!READER_CHECK(value["vertex"].IsString(), "%sValue 'vertex' must be a string\n", prefix)) return false;
+ if (!READER_CHECK(value.HasMember("fragment") || value.HasMember("pixel"), "%sMust have string value named 'fragment' or 'pixel' (what is our fragment/pixel shader?)\n", prefix)) return false;
+ if (!READER_CHECK(!value.HasMember("fragment") || value["fragment"].IsString(), "%sValue 'fragment' must be a string\n", prefix)) return false;
+ if (!READER_CHECK(!value.HasMember("pixel") || value["pixel"].IsString(), "%sValue 'pixel' must be a string\n", prefix)) return false;
+ if (!READER_CHECK(value.HasMember("uniforms"), "%sMust have array value 'uniforms' (what are our shader's parameters?)\n", prefix)) return false;
+ if (!READER_CHECK(value["uniforms"].IsArray(), "%sValue 'uniforms' must be an array\n", prefix)) return false;
return true;
}
diff --git a/src/osd/modules/render/bgfx/effectreader.h b/src/osd/modules/render/bgfx/effectreader.h
index 095f06a56ea..db590e5eeb3 100644
--- a/src/osd/modules/render/bgfx/effectreader.h
+++ b/src/osd/modules/render/bgfx/effectreader.h
@@ -6,36 +6,38 @@
//
//============================================================
-#pragma once
+#ifndef MAME_RENDER_BGFX_EFFECTREADER_H
+#define MAME_RENDER_BGFX_EFFECTREADER_H
-#ifndef __DRAWBGFX_EFFECT_READER__
-#define __DRAWBGFX_EFFECT_READER__
+#pragma once
#include "statereader.h"
#include <bgfx/bgfx.h>
+#include <memory>
#include <string>
#include <vector>
+
class bgfx_effect;
class bgfx_uniform;
class osd_options;
class shader_manager;
+
class effect_reader : public state_reader
{
public:
- static bgfx_effect *read_from_value(const Value& value, std::string prefix, osd_options &options, shader_manager& shaders);
- static bool validate_value(const Value& value, std::string prefix, osd_options &options);
+ static std::unique_ptr<bgfx_effect> read_from_value(const std::string &name, const Value& value, const std::string &prefix, const osd_options &options, shader_manager& shaders);
+ static bool validate_value(const Value& value, const std::string &prefix, const osd_options &options);
private:
- static bool get_base_effect_data(const Value& value, std::string &prefix, uint64_t &flags, std::string &vertex_name, std::string &fragment_name,
- std::vector<bgfx_uniform *> &uniforms);
- static bool get_shader_data(const Value& value, osd_options &options, shader_manager &shaders, std::string &vertex_name, bgfx::ShaderHandle &vertex_shader,
+ static bool get_base_effect_data(const Value& value, const std::string &prefix, uint64_t &flags, std::string &vertex_name, std::string &fragment_name,
+ std::vector<std::unique_ptr<bgfx_uniform> > &uniforms);
+ static bool get_shader_data(const Value& value, const osd_options &options, shader_manager &shaders, std::string &vertex_name, bgfx::ShaderHandle &vertex_shader,
std::string &fragment_name, bgfx::ShaderHandle &fragment_shader);
- static void clear_uniform_list(std::vector<bgfx_uniform *> &uniforms);
- static bool validate_parameters(const Value& value, std::string prefix);
+ static bool validate_parameters(const Value& value, const std::string &prefix);
};
-#endif // __DRAWBGFX_EFFECT_READER__
+#endif // MAME_RENDER_BGFX_EFFECTREADER_H
diff --git a/src/osd/modules/render/bgfx/entryuniform.h b/src/osd/modules/render/bgfx/entryuniform.h
index 9c1462f360f..88ccc3e536d 100644
--- a/src/osd/modules/render/bgfx/entryuniform.h
+++ b/src/osd/modules/render/bgfx/entryuniform.h
@@ -9,15 +9,15 @@
//
//============================================================
+#ifndef MAME_RENDER_BGFX_ENTRYUNIFORM_H
+#define MAME_RENDER_BGFX_ENTRYUNIFORM_H
+
#pragma once
-#ifndef DRAWBGFX_ENTRY_UNIFORM
-#define DRAWBGFX_ENTRY_UNIFORM
+#include "uniform.h"
#include <bgfx/bgfx.h>
-#include "uniform.h"
-
class bgfx_entry_uniform
{
public:
@@ -25,10 +25,10 @@ public:
virtual ~bgfx_entry_uniform() { }
virtual void bind() = 0;
- std::string name() const { return m_uniform->name(); }
+ const std::string &name() const { return m_uniform->name(); }
protected:
bgfx_uniform* m_uniform;
};
-#endif // __DRAWBGFX_ENTRY_UNIFORM__
+#endif // MAME_RENDER_BGFX_ENTRYUNIFORM_H
diff --git a/src/osd/modules/render/bgfx/entryuniformreader.cpp b/src/osd/modules/render/bgfx/entryuniformreader.cpp
index 947f4c56e90..62c618f39a7 100644
--- a/src/osd/modules/render/bgfx/entryuniformreader.cpp
+++ b/src/osd/modules/render/bgfx/entryuniformreader.cpp
@@ -15,7 +15,7 @@
#include "paramuniformreader.h"
#include "uniform.h"
-bgfx_entry_uniform* entry_uniform_reader::read_from_value(const Value& value, std::string prefix, bgfx_effect* effect, std::map<std::string, bgfx_slider*>& sliders, std::map<std::string, bgfx_parameter*>& params)
+bgfx_entry_uniform* entry_uniform_reader::read_from_value(const Value& value, const std::string &prefix, bgfx_effect* effect, std::map<std::string, bgfx_slider*>& sliders, std::map<std::string, bgfx_parameter*>& params)
{
if (!validate_parameters(value, prefix))
{
@@ -25,7 +25,7 @@ bgfx_entry_uniform* entry_uniform_reader::read_from_value(const Value& value, st
std::string name = value["uniform"].GetString();
bgfx_uniform* uniform = effect->uniform(name);
- if (!READER_CHECK(uniform != nullptr, (prefix + "Uniform '" + name + " does not appear to exist\n").c_str()))
+ if (!READER_CHECK(uniform != nullptr, "%sUniform '%s' does not appear to exist\n", prefix, name))
{
return nullptr;
}
@@ -44,16 +44,16 @@ bgfx_entry_uniform* entry_uniform_reader::read_from_value(const Value& value, st
}
else
{
- READER_CHECK(false, (prefix + "Unrecognized uniform type for uniform binding " + name).c_str());
+ READER_CHECK(false, "%sUnrecognized uniform type for uniform binding %s", prefix, name);
}
return nullptr;
}
-bool entry_uniform_reader::validate_parameters(const Value& value, std::string prefix)
+bool entry_uniform_reader::validate_parameters(const Value& value, const std::string &prefix)
{
- if (!READER_CHECK(value.HasMember("uniform"), (prefix + "Must have string value 'uniform' (what uniform are we mapping?)\n").c_str())) return false;
- if (!READER_CHECK(value["uniform"].IsString(), (prefix + "Value 'effect' must be a string\n").c_str())) return false;
+ if (!READER_CHECK(value.HasMember("uniform"), "%sMust have string value 'uniform' (what uniform are we mapping?)\n", prefix)) return false;
+ if (!READER_CHECK(value["uniform"].IsString(), "%sValue 'effect' must be a string\n", prefix)) return false;
return true;
}
diff --git a/src/osd/modules/render/bgfx/entryuniformreader.h b/src/osd/modules/render/bgfx/entryuniformreader.h
index 73c66269a5e..c85a2647826 100644
--- a/src/osd/modules/render/bgfx/entryuniformreader.h
+++ b/src/osd/modules/render/bgfx/entryuniformreader.h
@@ -6,16 +6,16 @@
//
//============================================================
+#ifndef MAME_RENDER_BGFX_ENTRYUNIFORMREADER_H
+#define MAME_RENDER_BGFX_ENTRYUNIFORMREADER_H
+
#pragma once
-#ifndef __DRAWBGFX_ENTRY_UNIFORM_READER__
-#define __DRAWBGFX_ENTRY_UNIFORM_READER__
+#include "statereader.h"
#include <string>
#include <map>
-#include "statereader.h"
-
class bgfx_entry_uniform;
class bgfx_slider;
class bgfx_effect;
@@ -24,10 +24,10 @@ class bgfx_parameter;
class entry_uniform_reader : public state_reader
{
public:
- static bgfx_entry_uniform* read_from_value(const Value& value, std::string prefix, bgfx_effect* effect, std::map<std::string, bgfx_slider*>& sliders, std::map<std::string, bgfx_parameter*>& params);
+ static bgfx_entry_uniform* read_from_value(const Value& value, const std::string &prefix, bgfx_effect* effect, std::map<std::string, bgfx_slider*>& sliders, std::map<std::string, bgfx_parameter*>& params);
private:
- static bool validate_parameters(const Value& value, std::string prefix);
+ static bool validate_parameters(const Value& value, const std::string &prefix);
};
-#endif // __DRAWBGFX_ENTRY_UNIFORM_READER__
+#endif // MAME_RENDER_BGFX_ENTRYUNIFORMREADER_H
diff --git a/src/osd/modules/render/bgfx/frameparameter.cpp b/src/osd/modules/render/bgfx/frameparameter.cpp
index 841d4d0d2e5..6b16fe1d5fa 100644
--- a/src/osd/modules/render/bgfx/frameparameter.cpp
+++ b/src/osd/modules/render/bgfx/frameparameter.cpp
@@ -8,8 +8,10 @@
#include "frameparameter.h"
-bgfx_frame_parameter::bgfx_frame_parameter(std::string name, parameter_type type, uint32_t period)
- : bgfx_parameter(name, type)
+#include <utility>
+
+bgfx_frame_parameter::bgfx_frame_parameter(std::string &&name, parameter_type type, uint32_t period)
+ : bgfx_parameter(std::move(name), type)
, m_current_frame(0)
, m_period(period)
{
@@ -20,7 +22,7 @@ float bgfx_frame_parameter::value()
return float(m_current_frame);
}
-void bgfx_frame_parameter::tick(double /*delta*/)
+void bgfx_frame_parameter::tick(double delta)
{
m_current_frame++;
m_current_frame %= m_period;
diff --git a/src/osd/modules/render/bgfx/frameparameter.h b/src/osd/modules/render/bgfx/frameparameter.h
index e559d13c1d8..2a1e8f6094b 100644
--- a/src/osd/modules/render/bgfx/frameparameter.h
+++ b/src/osd/modules/render/bgfx/frameparameter.h
@@ -6,22 +6,20 @@
//
//============================================================
-#pragma once
+#ifndef MAME_RENDER_BGFX_FRAMEPARAMETER_H
+#define MAME_RENDER_BGFX_FRAMEPARAMETER_H
-#ifndef __DRAWBGFX_FRAME_PARAMETER__
-#define __DRAWBGFX_FRAME_PARAMETER__
+#pragma once
-#include <bgfx/bgfx.h>
+#include "parameter.h"
+#include <cstdint>
#include <string>
-#include "parameter.h"
-
class bgfx_frame_parameter : public bgfx_parameter
{
public:
- bgfx_frame_parameter(std::string name, parameter_type type, uint32_t period);
- virtual ~bgfx_frame_parameter() { }
+ bgfx_frame_parameter(std::string &&name, parameter_type type, uint32_t period);
virtual float value() override;
virtual void tick(double delta) override;
@@ -31,4 +29,4 @@ private:
uint32_t m_period;
};
-#endif // __DRAWBGFX_FRAME_PARAMETER__
+#endif // MAME_RENDER_BGFX_FRAMEPARAMETER_H
diff --git a/src/osd/modules/render/bgfx/inputpair.cpp b/src/osd/modules/render/bgfx/inputpair.cpp
index 5f1324c2581..154252db04f 100644
--- a/src/osd/modules/render/bgfx/inputpair.cpp
+++ b/src/osd/modules/render/bgfx/inputpair.cpp
@@ -11,15 +11,18 @@
#include "inputpair.h"
-#include "../frontend/mame/ui/slider.h"
-
-#include "texture.h"
-#include "target.h"
-#include "effect.h"
-#include "uniform.h"
#include "chainmanager.h"
+#include "effect.h"
#include "slider.h"
#include "sliderdirtynotifier.h"
+#include "target.h"
+#include "texture.h"
+#include "uniform.h"
+
+#include "../frontend/mame/ui/slider.h"
+
+#include "util/strformat.h"
+
bgfx_input_pair::bgfx_input_pair(int index, std::string sampler, std::string texture, std::vector<std::string> available_textures, std::string selection, chain_manager& chains, uint32_t screen_index)
: m_index(index)
@@ -53,20 +56,31 @@ void bgfx_input_pair::bind(bgfx_effect *effect, const int32_t screen) const
if (!provider)
return;
+ float rowpixels(provider->rowpixels());
+ float width_margin(provider->width_margin());
+ float height(provider->height());
+
bgfx_uniform *tex_size = effect->uniform("u_tex_size" + std::to_string(m_index));
if (tex_size && provider)
{
- float values[2] = { float(provider->rowpixels()), float(provider->height()) };
+ float values[2] = { rowpixels, height };
tex_size->set(values, sizeof(float) * 2);
}
bgfx_uniform *inv_tex_size = effect->uniform("u_inv_tex_size" + std::to_string(m_index));
if (inv_tex_size && provider)
{
- float values[2] = { 1.0f / float(provider->rowpixels()), 1.0f / float(provider->height()) };
+ float values[2] = { 1.0f / rowpixels, 1.0f / height };
inv_tex_size->set(values, sizeof(float) * 2);
}
+ bgfx_uniform *tex_bounds = effect->uniform("u_tex_bounds" + std::to_string(m_index));
+ if (tex_bounds && provider)
+ {
+ float values[4] = { width_margin / rowpixels, 0.0f, 1.0f + width_margin / rowpixels, 1.0f };
+ tex_bounds->set(values, sizeof(float) * 4);
+ }
+
bgfx::setTexture(m_index, effect->uniform(m_sampler)->handle(), chains().textures().handle(name));
}
@@ -109,11 +123,11 @@ void bgfx_input_pair::create_selection_slider(uint32_t screen_index)
int32_t maxval = m_available_textures.size() - 1;
int32_t incval = 1;
- std::string description = "Window " + std::to_string(chains().window_index()) + ", Screen " + std::to_string(screen_index) + " " + m_selection + ":";
-
using namespace std::placeholders;
- m_slider_state = std::make_unique<slider_state>(std::move(description), minval, defval, maxval, incval,
- std::bind(&bgfx_input_pair::texture_changed, this, screen_index, _1, _2));
+ m_slider_state = std::make_unique<slider_state>(
+ util::string_format("Window %1$u, Screen %1$u %3$s", chains().window_index(), screen_index, m_selection),
+ minval, defval, maxval, incval,
+ std::bind(&bgfx_input_pair::texture_changed, this, screen_index, _1, _2));
ui::menu_item item(ui::menu_item_type::SLIDER, m_slider_state.get());
item.set_text(m_slider_state->description);
@@ -130,9 +144,7 @@ std::vector<ui::menu_item> bgfx_input_pair::get_slider_list()
std::vector<ui::menu_item> sliders;
if (!needs_sliders())
- {
return sliders;
- }
sliders.push_back(m_selection_slider);
diff --git a/src/osd/modules/render/bgfx/parameter.h b/src/osd/modules/render/bgfx/parameter.h
index 2df18365a4c..baa2ff017ad 100644
--- a/src/osd/modules/render/bgfx/parameter.h
+++ b/src/osd/modules/render/bgfx/parameter.h
@@ -10,12 +10,13 @@
//
//============================================================
-#pragma once
+#ifndef MAME_RENDER_BGFX_PARAMETER_H
+#define MAME_RENDER_BGFX_PARAMETER_H
-#ifndef __DRAWBGFX_PARAMETER__
-#define __DRAWBGFX_PARAMETER__
+#pragma once
#include <string>
+#include <utility>
class bgfx_parameter
{
@@ -27,18 +28,18 @@ public:
PARAM_TIME
};
- bgfx_parameter(std::string name, parameter_type type) : m_name(name), m_type(type) { }
- virtual ~bgfx_parameter() { }
+ bgfx_parameter(std::string &&name, parameter_type type) : m_name(std::move(name)), m_type(type) { }
+ virtual ~bgfx_parameter() = default;
virtual void tick(double delta) = 0;
// Getters
virtual float value() = 0;
- std::string name() const { return m_name; }
+ const std::string &name() const { return m_name; }
protected:
std::string m_name;
parameter_type m_type;
};
-#endif // __DRAWBGFX_PARAMETER__
+#endif // MAME_RENDER_BGFX_PARAMETER_H
diff --git a/src/osd/modules/render/bgfx/paramreader.cpp b/src/osd/modules/render/bgfx/paramreader.cpp
index 1b14b2aa56a..0eeb5f22e84 100644
--- a/src/osd/modules/render/bgfx/paramreader.cpp
+++ b/src/osd/modules/render/bgfx/paramreader.cpp
@@ -6,15 +6,13 @@
//
//============================================================
-#include <string>
-
#include "paramreader.h"
-#include "parameter.h"
+#include "chainmanager.h"
#include "frameparameter.h"
-#include "windowparameter.h"
+#include "parameter.h"
#include "timeparameter.h"
-#include "chainmanager.h"
+#include "windowparameter.h"
const parameter_reader::string_to_enum parameter_reader::TYPE_NAMES[parameter_reader::TYPE_COUNT] = {
{ "frame", bgfx_parameter::parameter_type::PARAM_FRAME },
@@ -22,7 +20,7 @@ const parameter_reader::string_to_enum parameter_reader::TYPE_NAMES[parameter_re
{ "time", bgfx_parameter::parameter_type::PARAM_TIME }
};
-bgfx_parameter* parameter_reader::read_from_value(const Value& value, std::string prefix, chain_manager& chains)
+bgfx_parameter* parameter_reader::read_from_value(const Value& value, const std::string &prefix, chain_manager& chains)
{
if (!validate_parameters(value, prefix))
{
@@ -35,32 +33,32 @@ bgfx_parameter* parameter_reader::read_from_value(const Value& value, std::strin
if (type == bgfx_parameter::parameter_type::PARAM_FRAME)
{
uint32_t period = int(value["period"].GetDouble());
- return new bgfx_frame_parameter(name, type, period);
+ return new bgfx_frame_parameter(std::move(name), type, period);
}
else if (type == bgfx_parameter::parameter_type::PARAM_WINDOW)
{
- return new bgfx_window_parameter(name, type, chains.window_index());
+ return new bgfx_window_parameter(std::move(name), type, chains.window_index());
}
else if (type == bgfx_parameter::parameter_type::PARAM_TIME)
{
auto limit = float(value["limit"].GetDouble());
- return new bgfx_time_parameter(name, type, limit);
+ return new bgfx_time_parameter(std::move(name), type, limit);
}
else
{
- READER_CHECK(false, (prefix + "Unknown parameter type '" + std::string(value["type"].GetString()) + "'\n").c_str());
+ READER_CHECK(false, "%sUnknown parameter type '%s'\n", prefix, value["type"].GetString());
}
return nullptr;
}
-bool parameter_reader::validate_parameters(const Value& value, std::string prefix)
+bool parameter_reader::validate_parameters(const Value& value, const std::string &prefix)
{
- if (!READER_CHECK(value.HasMember("name"), (prefix + "Must have string value 'name'\n").c_str())) return false;
- if (!READER_CHECK(value["name"].IsString(), (prefix + "Value 'name' must be a string\n").c_str())) return false;
- if (!READER_CHECK(value.HasMember("type"), (prefix + "Must have string value 'type'\n").c_str())) return false;
- if (!READER_CHECK(value["type"].IsString(), (prefix + "Value 'type' must be a string\n").c_str())) return false;
- if (!READER_CHECK(!value.HasMember("period") || value["period"].IsNumber(), (prefix + "Value 'period' must be numeric\n").c_str())) return false;
- if (!READER_CHECK(!value.HasMember("limit") || value["limit"].IsNumber(), (prefix + "Value 'period' must be numeric\n").c_str())) return false;
+ if (!READER_CHECK(value.HasMember("name"), "%sMust have string value 'name'\n", prefix)) return false;
+ if (!READER_CHECK(value["name"].IsString(), "%sValue 'name' must be a string\n", prefix)) return false;
+ if (!READER_CHECK(value.HasMember("type"), "%sMust have string value 'type'\n", prefix)) return false;
+ if (!READER_CHECK(value["type"].IsString(), "%sValue 'type' must be a string\n", prefix)) return false;
+ if (!READER_CHECK(!value.HasMember("period") || value["period"].IsNumber(), "%sValue 'period' must be numeric\n", prefix)) return false;
+ if (!READER_CHECK(!value.HasMember("limit") || value["limit"].IsNumber(), "%sValue 'period' must be numeric\n", prefix)) return false;
return true;
}
diff --git a/src/osd/modules/render/bgfx/paramreader.h b/src/osd/modules/render/bgfx/paramreader.h
index 013d6589cc3..bfd23b14a42 100644
--- a/src/osd/modules/render/bgfx/paramreader.h
+++ b/src/osd/modules/render/bgfx/paramreader.h
@@ -6,26 +6,28 @@
//
//============================================================
-#pragma once
+#ifndef MAME_RENDER_BGFX_PARAMREADER_H
+#define MAME_RENDER_BGFX_PARAMREADER_H
-#ifndef __DRAWBGFX_PARAM_READER__
-#define __DRAWBGFX_PARAM_READER__
+#pragma once
#include "statereader.h"
+#include <string>
+
class bgfx_parameter;
class chain_manager;
class parameter_reader : public state_reader
{
public:
- static bgfx_parameter* read_from_value(const Value& value, std::string prefix, chain_manager& chains);
+ static bgfx_parameter* read_from_value(const Value& value, const std::string &prefix, chain_manager& chains);
private:
- static bool validate_parameters(const Value& value, std::string prefix);
+ static bool validate_parameters(const Value& value, const std::string &prefix);
static const int TYPE_COUNT = 3;
static const string_to_enum TYPE_NAMES[TYPE_COUNT];
};
-#endif // __DRAWBGFX_PARAM_READER__
+#endif // MAME_RENDER_BGFX_PARAMREADER_H
diff --git a/src/osd/modules/render/bgfx/paramuniform.h b/src/osd/modules/render/bgfx/paramuniform.h
index b49fb2c7d61..5f5b69c96a6 100644
--- a/src/osd/modules/render/bgfx/paramuniform.h
+++ b/src/osd/modules/render/bgfx/paramuniform.h
@@ -6,10 +6,10 @@
//
//============================================================
-#pragma once
+#ifndef MAME_RENDER_BGFX_PARAMUNIFORM_H
+#define MAME_RENDER_BGFX_PARAMUNIFORM_H
-#ifndef __DRAWBGFX_PARAM_UNIFORM__
-#define __DRAWBGFX_PARAM_UNIFORM__
+#pragma once
#include "entryuniform.h"
@@ -26,4 +26,4 @@ private:
bgfx_parameter* m_param;
};
-#endif // __DRAWBGFX_PARAM_UNIFORM__
+#endif // MAME_RENDER_BGFX_PARAMUNIFORM_H
diff --git a/src/osd/modules/render/bgfx/paramuniformreader.cpp b/src/osd/modules/render/bgfx/paramuniformreader.cpp
index 2b613fc216c..8c5cd265195 100644
--- a/src/osd/modules/render/bgfx/paramuniformreader.cpp
+++ b/src/osd/modules/render/bgfx/paramuniformreader.cpp
@@ -9,10 +9,10 @@
#include "paramuniformreader.h"
#include "entryuniform.h"
-#include "paramuniform.h"
#include "parameter.h"
+#include "paramuniform.h"
-bgfx_entry_uniform* param_uniform_reader::read_from_value(const Value& value, std::string prefix, bgfx_uniform* uniform, std::map<std::string, bgfx_parameter*>& params)
+bgfx_entry_uniform* param_uniform_reader::read_from_value(const Value& value, const std::string &prefix, bgfx_uniform* uniform, std::map<std::string, bgfx_parameter*>& params)
{
if (!validate_parameters(value, prefix))
{
@@ -24,9 +24,9 @@ bgfx_entry_uniform* param_uniform_reader::read_from_value(const Value& value, st
return new bgfx_param_uniform(uniform, params[parameter]);
}
-bool param_uniform_reader::validate_parameters(const Value& value, std::string prefix)
+bool param_uniform_reader::validate_parameters(const Value& value, const std::string &prefix)
{
- if (!READER_CHECK(value.HasMember("parameter"), (prefix + "Must have string value 'parameter' (what parameter is being mapped?)\n").c_str())) return false;
- if (!READER_CHECK(value["parameter"].IsString(), (prefix + "Value 'parameter' must be a string\n").c_str())) return false;
+ if (!READER_CHECK(value.HasMember("parameter"), "%sMust have string value 'parameter' (what parameter is being mapped?)\n", prefix)) return false;
+ if (!READER_CHECK(value["parameter"].IsString(), "%sValue 'parameter' must be a string\n", prefix)) return false;
return true;
}
diff --git a/src/osd/modules/render/bgfx/paramuniformreader.h b/src/osd/modules/render/bgfx/paramuniformreader.h
index baf281b562b..b1ed2a87f69 100644
--- a/src/osd/modules/render/bgfx/paramuniformreader.h
+++ b/src/osd/modules/render/bgfx/paramuniformreader.h
@@ -6,15 +6,15 @@
//
//==================================================================
+#ifndef MAME_RENDER_BGFX_PARAMUNIFORMREADER_H
+#define MAME_RENDER_BGFX_PARAMUNIFORMREADER_H
+
#pragma once
-#ifndef __DRAWBGFX_PARAM_UNIFORM_READER__
-#define __DRAWBGFX_PARAM_UNIFORM_READER__
+#include "statereader.h"
-#include <string>
#include <map>
-
-#include "statereader.h"
+#include <string>
class bgfx_entry_uniform;
class bgfx_uniform;
@@ -23,10 +23,10 @@ class bgfx_parameter;
class param_uniform_reader : public state_reader
{
public:
- static bgfx_entry_uniform* read_from_value(const Value& value, std::string prefix, bgfx_uniform* uniform, std::map<std::string, bgfx_parameter*>& params);
+ static bgfx_entry_uniform* read_from_value(const Value& value, const std::string &prefix, bgfx_uniform* uniform, std::map<std::string, bgfx_parameter*>& params);
private:
- static bool validate_parameters(const Value& value, std::string prefix);
+ static bool validate_parameters(const Value& value, const std::string &prefix);
};
-#endif // __DRAWBGFX_PARAM_UNIFORM_READER__
+#endif // MAME_RENDER_BGFX_PARAMUNIFORMREADER_H
diff --git a/src/osd/modules/render/bgfx/shadermanager.cpp b/src/osd/modules/render/bgfx/shadermanager.cpp
index dd894426794..763a744e4aa 100644
--- a/src/osd/modules/render/bgfx/shadermanager.cpp
+++ b/src/osd/modules/render/bgfx/shadermanager.cpp
@@ -16,11 +16,10 @@
#include "osdfile.h"
#include "modules/lib/osdobj_common.h"
+#include <bx/file.h>
#include <bx/math.h>
#include <bx/readerwriter.h>
-#include <bx/file.h>
-#include <bgfx/bgfx.h>
shader_manager::~shader_manager()
{
@@ -31,7 +30,7 @@ shader_manager::~shader_manager()
m_shaders.clear();
}
-bgfx::ShaderHandle shader_manager::get_or_load_shader(osd_options &options, std::string name)
+bgfx::ShaderHandle shader_manager::get_or_load_shader(const osd_options &options, const std::string &name)
{
std::map<std::string, bgfx::ShaderHandle>::iterator iter = m_shaders.find(name);
if (iter != m_shaders.end())
@@ -48,7 +47,7 @@ bgfx::ShaderHandle shader_manager::get_or_load_shader(osd_options &options, std:
return handle;
}
-bgfx::ShaderHandle shader_manager::load_shader(osd_options &options, std::string name)
+bgfx::ShaderHandle shader_manager::load_shader(const osd_options &options, const std::string &name)
{
std::string shader_path = make_path_string(options, name);
const bgfx::Memory* mem = load_mem(shader_path + name + ".bin");
@@ -60,16 +59,17 @@ bgfx::ShaderHandle shader_manager::load_shader(osd_options &options, std::string
return BGFX_INVALID_HANDLE;
}
-bool shader_manager::is_shader_present(osd_options &options, std::string name)
+bool shader_manager::is_shader_present(const osd_options &options, const std::string &name)
{
std::string shader_path = make_path_string(options, name);
std::string file_name = shader_path + name + ".bin";
bx::FileReader reader;
+ bx::ErrorAssert err;
if (bx::open(&reader, file_name.c_str()))
{
uint32_t expected_size(bx::getSize(&reader));
uint8_t *data = new uint8_t[expected_size];
- uint32_t read_size = (uint32_t)bx::read(&reader, data, expected_size);
+ uint32_t read_size = (uint32_t)bx::read(&reader, data, expected_size, &err);
delete [] data;
bx::close(&reader);
@@ -79,7 +79,7 @@ bool shader_manager::is_shader_present(osd_options &options, std::string name)
return false;
}
-std::string shader_manager::make_path_string(osd_options &options, std::string name)
+std::string shader_manager::make_path_string(const osd_options &options, const std::string &name)
{
std::string shader_path(options.bgfx_path());
shader_path += PATH_SEPARATOR "shaders" PATH_SEPARATOR;
@@ -119,17 +119,18 @@ std::string shader_manager::make_path_string(osd_options &options, std::string n
fatalerror("Unknown BGFX renderer type %d", bgfx::getRendererType());
}
shader_path += PATH_SEPARATOR;
- return osd_subst_env(shader_path);
+ return shader_path;
}
-const bgfx::Memory* shader_manager::load_mem(std::string name)
+const bgfx::Memory* shader_manager::load_mem(const std::string &name)
{
bx::FileReader reader;
if (bx::open(&reader, name.c_str()))
{
+ bx::ErrorAssert err;
uint32_t size(bx::getSize(&reader));
const bgfx::Memory* mem = bgfx::alloc(size + 1);
- bx::read(&reader, mem->data, size);
+ bx::read(&reader, mem->data, size, &err);
bx::close(&reader);
mem->data[mem->size - 1] = '\0';
@@ -137,7 +138,7 @@ const bgfx::Memory* shader_manager::load_mem(std::string name)
}
else
{
- osd_printf_error("Unable to load shader %s\n", name.c_str());
+ osd_printf_error("Unable to load shader %s\n", name);
}
return nullptr;
}
diff --git a/src/osd/modules/render/bgfx/shadermanager.h b/src/osd/modules/render/bgfx/shadermanager.h
index 81fa4260f47..12ac739d35a 100644
--- a/src/osd/modules/render/bgfx/shadermanager.h
+++ b/src/osd/modules/render/bgfx/shadermanager.h
@@ -9,10 +9,10 @@
//
//============================================================
-#pragma once
+#ifndef MAME_RENDER_BGFX_SHADERMANAGER_H
+#define MAME_RENDER_BGFX_SHADERMANAGER_H
-#ifndef __DRAWBGFX_SHADER_MANAGER__
-#define __DRAWBGFX_SHADER_MANAGER__
+#pragma once
#include <bgfx/bgfx.h>
@@ -22,21 +22,23 @@
class osd_options;
-class shader_manager {
+
+class shader_manager
+{
public:
shader_manager() { }
~shader_manager();
// Getters
- bgfx::ShaderHandle get_or_load_shader(osd_options &options, std::string name);
- static bgfx::ShaderHandle load_shader(osd_options &options, std::string name);
- static bool is_shader_present(osd_options &options, std::string name);
+ bgfx::ShaderHandle get_or_load_shader(const osd_options &options, const std::string &name);
+ static bgfx::ShaderHandle load_shader(const osd_options &options, const std::string &name);
+ static bool is_shader_present(const osd_options &options, const std::string &name);
private:
- static std::string make_path_string(osd_options &options, std::string name);
- static const bgfx::Memory* load_mem(std::string name);
+ static std::string make_path_string(const osd_options &options, const std::string &name);
+ static const bgfx::Memory* load_mem(const std::string &name);
- std::map<std::string, bgfx::ShaderHandle> m_shaders;
+ std::map<std::string, bgfx::ShaderHandle> m_shaders;
};
-#endif // __DRAWBGFX_SHADER_MANAGER__
+#endif // MAME_RENDER_BGFX_SHADERMANAGER_H
diff --git a/src/osd/modules/render/bgfx/shaders/chains/blurs/fs_smart-blur.sc b/src/osd/modules/render/bgfx/shaders/chains/blurs/fs_smart-blur.sc
index 4c688c4d6f4..6ea70cb6aac 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/blurs/fs_smart-blur.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/blurs/fs_smart-blur.sc
@@ -39,26 +39,26 @@ uniform vec4 SB_THRESHOLD;
bool eq(vec3 c1, vec3 c2)
{
- vec3 df = abs(c1 - c2);
- return df.r < SB_THRESHOLD.r && df.g < SB_THRESHOLD.g && df.b < SB_THRESHOLD.b;
+ vec3 df = abs(c1 - c2);
+ return df.r < SB_THRESHOLD.r && df.g < SB_THRESHOLD.g && df.b < SB_THRESHOLD.b;
}
void main()
{
- vec3 A = texture2D(s_p, v_texcoord1.xw).xyz;
- vec3 B = texture2D(s_p, v_texcoord1.yw).xyz;
- vec3 C = texture2D(s_p, v_texcoord1.zw).xyz;
- vec3 D = texture2D(s_p, v_texcoord2.xw).xyz;
- vec3 E = texture2D(s_p, v_texcoord2.yw).xyz;
- vec3 F = texture2D(s_p, v_texcoord2.zw).xyz;
- vec3 G = texture2D(s_p, v_texcoord3.xw).xyz;
- vec3 H = texture2D(s_p, v_texcoord3.yw).xyz;
- vec3 I = texture2D(s_p, v_texcoord3.zw).xyz;
+ vec3 A = texture2D(s_p, v_texcoord1.xw).xyz;
+ vec3 B = texture2D(s_p, v_texcoord1.yw).xyz;
+ vec3 C = texture2D(s_p, v_texcoord1.zw).xyz;
+ vec3 D = texture2D(s_p, v_texcoord2.xw).xyz;
+ vec3 E = texture2D(s_p, v_texcoord2.yw).xyz;
+ vec3 F = texture2D(s_p, v_texcoord2.zw).xyz;
+ vec3 G = texture2D(s_p, v_texcoord3.xw).xyz;
+ vec3 H = texture2D(s_p, v_texcoord3.yw).xyz;
+ vec3 I = texture2D(s_p, v_texcoord3.zw).xyz;
- if (eq(E,F) && eq(E,H) && eq(E,I) && eq(E,B) && eq(E,C) && eq(E,A) && eq(E,D) && eq(E,G))
- {
- E = (A + B + C + D + E + F + G + H + I) / 9.0;
- }
+ if (eq(E,F) && eq(E,H) && eq(E,I) && eq(E,B) && eq(E,C) && eq(E,A) && eq(E,D) && eq(E,G))
+ {
+ E = (A + B + C + D + E + F + G + H + I) / 9.0;
+ }
- gl_FragColor = vec4(E, 1.0);
+ gl_FragColor = vec4(E, 1.0);
}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/blurs/vs_smart-blur.sc b/src/osd/modules/render/bgfx/shaders/chains/blurs/vs_smart-blur.sc
index 1b967f894d4..40b0947da38 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/blurs/vs_smart-blur.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/blurs/vs_smart-blur.sc
@@ -32,10 +32,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_color0
#include "common.sh"
uniform vec4 u_tex_size0;
+uniform vec4 u_inv_view_dims;
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
vec2 ps = 1.0 / u_tex_size0.xy;
diff --git a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/crt-geom_common.sc b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/crt-geom_common.sc
index 6863a180ef6..9118e42d5c8 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/crt-geom_common.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/crt-geom_common.sc
@@ -13,12 +13,12 @@
vec4 TEX2D(vec2 c)
{
- vec2 underscan = step(0.0,c) * step(0.0,vec2_splat(1.0)-c);
- vec4 col = texture2D(mpass_texture, c) * vec4_splat(underscan.x*underscan.y);
+ vec2 underscan = step(0.0,c) * step(0.0,vec2_splat(1.0)-c);
+ vec4 col = texture2D(mpass_texture, c) * vec4_splat(underscan.x*underscan.y);
#ifdef LINEAR_PROCESSING
- col = pow(col, vec4_splat(CRTgamma.x));
+ col = pow(col, vec4_splat(CRTgamma.x));
#endif
- return col;
+ return col;
}
// Enable screen curvature.
@@ -48,43 +48,43 @@ uniform vec4 cornersmooth;
float intersect(vec2 xy , vec2 sinangle, vec2 cosangle)
{
- float A = dot(xy,xy)+d.x*d.x;
- float B = 2.0*(R.x*(dot(xy,sinangle)-d.x*cosangle.x*cosangle.y)-d.x*d.x);
- float C = d.x*d.x + 2.0*R.x*d.x*cosangle.x*cosangle.y;
- return (-B-sqrt(B*B-4.0*A*C))/(2.0*A);
+ float A = dot(xy,xy)+d.x*d.x;
+ float B = 2.0*(R.x*(dot(xy,sinangle)-d.x*cosangle.x*cosangle.y)-d.x*d.x);
+ float C = d.x*d.x + 2.0*R.x*d.x*cosangle.x*cosangle.y;
+ return (-B-sqrt(B*B-4.0*A*C))/(2.0*A);
}
vec2 bkwtrans(vec2 xy, vec2 sinangle, vec2 cosangle)
{
- float c = intersect(xy, sinangle, cosangle);
- vec2 pt = vec2_splat(c)*xy;
- pt -= vec2_splat(-R.x)*sinangle;
- pt /= vec2_splat(R.x);
- vec2 tang = sinangle/cosangle;
- vec2 poc = pt/cosangle;
- float A = dot(tang,tang)+1.0;
- float B = -2.0*dot(poc,tang);
- float C = dot(poc,poc)-1.0;
- float a = (-B+sqrt(B*B-4.0*A*C))/(2.0*A);
- vec2 uv = (pt-a*sinangle)/cosangle;
- float r = FIX(R.x*acos(a));
- return uv*r/sin(r/R.x);
+ float c = intersect(xy, sinangle, cosangle);
+ vec2 pt = vec2_splat(c)*xy;
+ pt -= vec2_splat(-R.x)*sinangle;
+ pt /= vec2_splat(R.x);
+ vec2 tang = sinangle/cosangle;
+ vec2 poc = pt/cosangle;
+ float A = dot(tang,tang)+1.0;
+ float B = -2.0*dot(poc,tang);
+ float C = dot(poc,poc)-1.0;
+ float a = (-B+sqrt(B*B-4.0*A*C))/(2.0*A);
+ vec2 uv = (pt-a*sinangle)/cosangle;
+ float r = FIX(R.x*acos(a));
+ return uv*r/sin(r/R.x);
}
vec2 transform(vec2 coord, vec3 stretch, vec2 sinangle, vec2 cosangle)
{
- coord = (coord-vec2_splat(0.5))*aspect.xy*stretch.z+stretch.xy;
- return (bkwtrans(coord, sinangle, cosangle)/overscan.xy/aspect.xy+vec2_splat(0.5));
+ coord = (coord-vec2_splat(0.5))*aspect.xy*stretch.z+stretch.xy;
+ return (bkwtrans(coord, sinangle, cosangle)/overscan.xy/aspect.xy+vec2_splat(0.5));
}
float corner(vec2 coord)
{
- coord = (coord - vec2_splat(0.5)) * overscan.xy + vec2_splat(0.5);
- coord = min(coord, vec2_splat(1.0)-coord) * aspect.xy;
- vec2 cdist = vec2_splat(cornersize.x);
- coord = (cdist - min(coord,cdist));
- float dist = sqrt(dot(coord,coord));
- return clamp((max(cdist.x,1e-3)-dist)*cornersmooth.x,0.0, 1.0);
+ coord = (coord - vec2_splat(0.5)) * overscan.xy + vec2_splat(0.5);
+ coord = min(coord, vec2_splat(1.0)-coord) * aspect.xy;
+ vec2 cdist = vec2_splat(cornersize.x);
+ coord = (cdist - min(coord,cdist));
+ float dist = sqrt(dot(coord,coord));
+ return clamp((max(cdist.x,1e-3)-dist)*cornersmooth.x,0.0, 1.0);
}
// Calculate the influence of a scanline on the current pixel.
@@ -95,109 +95,109 @@ float corner(vec2 coord)
// the current pixel.
vec4 scanlineWeights(float distance, vec4 color)
{
- // "wid" controls the width of the scanline beam, for each RGB channel
- // The "weights" lines basically specify the formula that gives
- // you the profile of the beam, i.e. the intensity as
- // a function of distance from the vertical center of the
- // scanline. In this case, it is gaussian if width=2, and
- // becomes nongaussian for larger widths. Ideally this should
- // be normalized so that the integral across the beam is
- // independent of its width. That is, for a narrower beam
- // "weights" should have a higher peak at the center of the
- // scanline than for a wider beam.
+ // "wid" controls the width of the scanline beam, for each RGB channel
+ // The "weights" lines basically specify the formula that gives
+ // you the profile of the beam, i.e. the intensity as
+ // a function of distance from the vertical center of the
+ // scanline. In this case, it is gaussian if width=2, and
+ // becomes nongaussian for larger widths. Ideally this should
+ // be normalized so that the integral across the beam is
+ // independent of its width. That is, for a narrower beam
+ // "weights" should have a higher peak at the center of the
+ // scanline than for a wider beam.
#ifdef USEGAUSSIAN
- vec4 wid = spot_size.x + spot_growth.x * pow(color, vec4_splat(spot_growth_power.x));
- vec4 weights = vec4(distance / wid);
- float maxwid = spot_size.x + spot_growth.x;
- float norm = maxwid / ( 1.0 + exp(-1.0/(maxwid*maxwid)) );
- return norm * exp(-weights * weights) / wid;
+ vec4 wid = spot_size.x + spot_growth.x * pow(color, vec4_splat(spot_growth_power.x));
+ vec4 weights = vec4(distance / wid);
+ float maxwid = spot_size.x + spot_growth.x;
+ float norm = maxwid / ( 1.0 + exp(-1.0/(maxwid*maxwid)) );
+ return norm * exp(-weights * weights) / wid;
#else
- vec4 wid = 2.0 + 2.0 * pow(color, vec4_splat(4.0));
- vec4 weights = vec4_splat(distance / 0.3);
- return 1.4 * exp(-pow(weights * inversesqrt(0.5 * wid), wid)) / (0.6 + 0.2 * wid);
+ vec4 wid = 2.0 + 2.0 * pow(color, vec4_splat(4.0));
+ vec4 weights = vec4_splat(distance / 0.3);
+ return 1.4 * exp(-pow(weights * inversesqrt(0.5 * wid), wid)) / (0.6 + 0.2 * wid);
#endif
}
vec4 cubic(vec4 x, float B, float C)
{
- // https://en.wikipedia.org/wiki/Mitchell%E2%80%93Netravali_filters
- vec2 a = x.yz; // components in [0,1]
- vec2 b = x.xw; // components in [1,2]
- vec2 a2 = a*a;
- vec2 b2 = b*b;
- a = (2.0-1.5*B-1.0*C)*a*a2 + (-3.0+2.0*B+C)*a2 + (1.0-(1.0/3.0)*B);
- b = ((-1.0/6.0)*B-C)*b*b2 + (B+5.0*C)*b2 + (-2.0*B-8.0*C)*b + ((4.0/3.0)*B+4.0*C);
- return vec4(b.x,a.x,a.y,b.y);
+ // https://en.wikipedia.org/wiki/Mitchell%E2%80%93Netravali_filters
+ vec2 a = x.yz; // components in [0,1]
+ vec2 b = x.xw; // components in [1,2]
+ vec2 a2 = a*a;
+ vec2 b2 = b*b;
+ a = (2.0-1.5*B-1.0*C)*a*a2 + (-3.0+2.0*B+C)*a2 + (1.0-(1.0/3.0)*B);
+ b = ((-1.0/6.0)*B-C)*b*b2 + (B+5.0*C)*b2 + (-2.0*B-8.0*C)*b + ((4.0/3.0)*B+4.0*C);
+ return vec4(b.x,a.x,a.y,b.y);
}
vec4 x_coeffs(vec4 x, float pos_x)
{
- if (u_interp.x < 0.5) { // box
- float wid = length(vec2(dFdx(pos_x),dFdy(pos_x)));
- float dx = clamp((0.5 + 0.5*wid - x.y)/wid, 0.0, 1.0);
- return vec4(0.0,dx,1.0-dx,0.0);
- } else if (u_interp.x < 1.5) { // linear
- return vec4(0.0, 1.0-x.y, 1.0-x.z, 0.0);
- } else if (u_interp.x < 2.5) { // Lanczos
- // Prevent division by zero.
- vec4 coeffs = FIX(PI * x);
- // Lanczos2 kernel.
- coeffs = 2.0 * sin(coeffs) * sin(coeffs / 2.0) / (coeffs * coeffs);
- // Normalize.
- coeffs /= dot(coeffs, vec4_splat(1.0));
- return coeffs;
- } else if (u_interp.x < 3.5) { // Catmull-Rom
- return cubic(x,0.0,0.5);
- } else if (u_interp.x < 4.5) { // Mitchell-Netravali
- return cubic(x,1.0/3.0,1.0/3.0);
- } else /*if (u_interp.x < 5.5)*/ { // B-spline
- return cubic(x,1.0,0.0);
- }
+ if (u_interp.x < 0.5) { // box
+ float wid = length(vec2(dFdx(pos_x),dFdy(pos_x)));
+ float dx = clamp((0.5 + 0.5*wid - x.y)/wid, 0.0, 1.0);
+ return vec4(0.0,dx,1.0-dx,0.0);
+ } else if (u_interp.x < 1.5) { // linear
+ return vec4(0.0, 1.0-x.y, 1.0-x.z, 0.0);
+ } else if (u_interp.x < 2.5) { // Lanczos
+ // Prevent division by zero.
+ vec4 coeffs = FIX(PI * x);
+ // Lanczos2 kernel.
+ coeffs = 2.0 * sin(coeffs) * sin(coeffs / 2.0) / (coeffs * coeffs);
+ // Normalize.
+ coeffs /= dot(coeffs, vec4_splat(1.0));
+ return coeffs;
+ } else if (u_interp.x < 3.5) { // Catmull-Rom
+ return cubic(x,0.0,0.5);
+ } else if (u_interp.x < 4.5) { // Mitchell-Netravali
+ return cubic(x,1.0/3.0,1.0/3.0);
+ } else /*if (u_interp.x < 5.5)*/ { // B-spline
+ return cubic(x,1.0,0.0);
+ }
}
vec4 sample_scanline(vec2 xy, vec4 coeffs, float onex)
{
- // Calculate the effective colour of the given
- // scanline at the horizontal location of the current pixel,
- // using the Lanczos coefficients.
- vec4 col = clamp(TEX2D(xy + vec2(-onex, 0.0))*coeffs.x +
- TEX2D(xy)*coeffs.y +
- TEX2D(xy +vec2(onex, 0.0))*coeffs.z +
- TEX2D(xy + vec2(2.0 * onex, 0.0))*coeffs.w , 0.0, 1.0);
- return col;
+ // Calculate the effective colour of the given
+ // scanline at the horizontal location of the current pixel,
+ // using the Lanczos coefficients.
+ vec4 col = clamp(TEX2D(xy + vec2(-onex, 0.0))*coeffs.x +
+ TEX2D(xy)*coeffs.y +
+ TEX2D(xy +vec2(onex, 0.0))*coeffs.z +
+ TEX2D(xy + vec2(2.0 * onex, 0.0))*coeffs.w , 0.0, 1.0);
+ return col;
}
vec3 apply_shadow_mask(vec2 coord, vec3 col)
{
- vec2 xy = coord * u_quad_dims.xy / u_tex_size1.xy;
- vec4 mask = texture2D(mask_texture, xy);
- // count of total bright pixels is encoded in the mask's alpha channel
- float nbright = 255.0 - 255.0*mask.a;
- // fraction of bright pixels in the mask
- float fbright = nbright / ( u_tex_size1.x * u_tex_size1.y );
- // average darkening factor of the mask
- float aperture_average = mix(1.0-aperture_strength.x*(1.0-aperture_brightboost.x), 1.0, fbright);
- // colour of dark mask pixels
- vec3 clow = vec3_splat(1.0-aperture_strength.x) * col + vec3_splat(aperture_strength.x*(aperture_brightboost.x)) * col * col;
- float ifbright = 1.0 / fbright;
- // colour of bright mask pixels
- vec3 chi = vec3_splat(ifbright*aperture_average) * col - vec3_splat(ifbright - 1.0) * clow;
- return mix(clow,chi,mask.rgb); // mask texture selects dark vs bright
+ vec2 xy = coord * u_quad_dims.xy / u_tex_size1.xy;
+ vec4 mask = texture2D(mask_texture, xy);
+ // count of total bright pixels is encoded in the mask's alpha channel
+ float nbright = 255.0 - 255.0*mask.a;
+ // fraction of bright pixels in the mask
+ float fbright = nbright / ( u_tex_size1.x * u_tex_size1.y );
+ // average darkening factor of the mask
+ float aperture_average = mix(1.0-aperture_strength.x*(1.0-aperture_brightboost.x), 1.0, fbright);
+ // colour of dark mask pixels
+ vec3 clow = vec3_splat(1.0-aperture_strength.x) * col + vec3_splat(aperture_strength.x*(aperture_brightboost.x)) * col * col;
+ float ifbright = 1.0 / fbright;
+ // colour of bright mask pixels
+ vec3 chi = vec3_splat(ifbright*aperture_average) * col - vec3_splat(ifbright - 1.0) * clow;
+ return mix(clow,chi,mask.rgb); // mask texture selects dark vs bright
}
vec3 linear_to_sRGB(vec3 col)
{
- // only applies the gamma ramp; does not adjust the primaries
- vec3 linear_ramp = vec3(lessThan(col, vec3_splat(0.0031308)));
- vec3 clin = col * vec3_splat(12.92);
- vec3 cpow = pow(col, vec3_splat(1.0/2.4)) * vec3_splat(1.055) - vec3_splat(0.055);
- return mix(cpow, clin, linear_ramp);
+ // only applies the gamma ramp; does not adjust the primaries
+ vec3 linear_ramp = vec3(lessThan(col, vec3_splat(0.0031308)));
+ vec3 clin = col * vec3_splat(12.92);
+ vec3 cpow = pow(col, vec3_splat(1.0/2.4)) * vec3_splat(1.055) - vec3_splat(0.055);
+ return mix(cpow, clin, linear_ramp);
}
vec3 linear_to_output(vec3 col)
{
- if (monitorsRGB.x > 0.5)
- return linear_to_sRGB(col);
- else
- return pow(col, vec3_splat(1.0 / monitorgamma.x));
+ if (monitorsRGB.x > 0.5)
+ return linear_to_sRGB(col);
+ else
+ return pow(col, vec3_splat(1.0 / monitorgamma.x));
}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_crt-geom-deluxe.sc b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_crt-geom-deluxe.sc
index 72705bdcb83..5b8a633a642 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_crt-geom-deluxe.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_crt-geom-deluxe.sc
@@ -28,9 +28,9 @@ uniform vec4 rasterbloom;
uniform vec4 blurwidth;
-vec3 texblur(vec2 c)
+vec4 texblur(vec2 c)
{
- vec3 col = pow(texture2D(blur_texture,c).rgb, vec3_splat(CRTgamma.x));
+ vec4 col = pow(texture2D(blur_texture,c), vec4(vec3_splat(CRTgamma.x),1.0));
// taper the blur texture outside its border with a gaussian
float w = blurwidth.x / 320.0;
c = min(c, vec2_splat(1.0)-c) * aspect.xy * vec2_splat(1.0/w);
@@ -38,7 +38,7 @@ vec3 texblur(vec2 c)
// approximation of erf gives smooth step
// (convolution of gaussian with step)
c = (step(0.0,c)-vec2_splat(0.5)) * sqrt(vec2_splat(1.0)-e2c) * (vec2_splat(1.0) + vec2_splat(0.1749)*e2c) + vec2_splat(0.5);
- return col * vec3_splat( c.x * c.y );
+ return col * vec4_splat( c.x * c.y );
}
void main()
@@ -125,16 +125,16 @@ void main()
weights_prev=weights_prev+scanlineWeights(uv_ratio.y+1.0, col_prev)/3.0;
weights_next=weights_next+scanlineWeights(uv_ratio.y-1.0, col_next)/3.0;
#endif
- vec3 mul_res = (col * weights + col_prev * weights_prev + col_next * weights_next).rgb;
+ vec4 mul_res = col * weights + col_prev * weights_prev + col_next * weights_next;
// halation and corners
- vec3 blur = texblur(xy0);
+ vec4 blur = texblur(xy0);
// include factor of rbloom:
// (probably imperceptible) brightness reduction when raster grows
- mul_res = mix(mul_res, blur, halation.x) * vec3_splat(cval*rbloom);
+ mul_res = mix(mul_res, blur, halation.x) * vec4_splat(cval*rbloom);
// Shadow mask
- vec3 cout = apply_shadow_mask(v_texCoord.xy, mul_res);
+ vec3 cout = apply_shadow_mask(v_texCoord.xy, mul_res.rgb);
// Convert the image gamma for display on our output device.
cout = linear_to_output(cout);
diff --git a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_crt-geom.sc b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_crt-geom.sc
index c096ebca7e0..5226a9999cc 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_crt-geom.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_crt-geom.sc
@@ -24,79 +24,79 @@ uniform vec4 u_quad_dims;
void main()
{
- // Here's a helpful diagram to keep in mind while trying to
- // understand the code:
- //
- // | | | | |
- // -------------------------------
- // | | | | |
- // | 01 | 11 | 21 | 31 | <-- current scanline
- // | | @ | | |
- // -------------------------------
- // | | | | |
- // | 02 | 12 | 22 | 32 | <-- next scanline
- // | | | | |
- // -------------------------------
- // | | | | |
- //
- // Each character-cell represents a pixel on the output
- // surface, "@" represents the current pixel (always somewhere
- // in the bottom half of the current scan-line, or the top-half
- // of the next scanline). The grid of lines represents the
- // edges of the texels of the underlying texture.
-
- // Texture coordinates of the texel containing the active pixel.
- vec2 xy;
- if (curvature.x > 0.5)
- xy = transform(v_texCoord, v_stretch, v_sinangle, v_cosangle);
- else
- xy = (v_texCoord-vec2_splat(0.5))/overscan.xy+vec2_splat(0.5);
- float cval = corner(xy);
-
- // Of all the pixels that are mapped onto the texel we are
- // currently rendering, which pixel are we currently rendering?
- vec2 ratio_scale = xy * u_tex_size0.xy - vec2_splat(0.5);
+ // Here's a helpful diagram to keep in mind while trying to
+ // understand the code:
+ //
+ // | | | | |
+ // -------------------------------
+ // | | | | |
+ // | 01 | 11 | 21 | 31 | <-- current scanline
+ // | | @ | | |
+ // -------------------------------
+ // | | | | |
+ // | 02 | 12 | 22 | 32 | <-- next scanline
+ // | | | | |
+ // -------------------------------
+ // | | | | |
+ //
+ // Each character-cell represents a pixel on the output
+ // surface, "@" represents the current pixel (always somewhere
+ // in the bottom half of the current scan-line, or the top-half
+ // of the next scanline). The grid of lines represents the
+ // edges of the texels of the underlying texture.
+
+ // Texture coordinates of the texel containing the active pixel.
+ vec2 xy;
+ if (curvature.x > 0.5)
+ xy = transform(v_texCoord, v_stretch, v_sinangle, v_cosangle);
+ else
+ xy = (v_texCoord-vec2_splat(0.5))/overscan.xy+vec2_splat(0.5);
+ float cval = corner(xy);
+
+ // Of all the pixels that are mapped onto the texel we are
+ // currently rendering, which pixel are we currently rendering?
+ vec2 ratio_scale = xy * u_tex_size0.xy - vec2_splat(0.5);
#ifdef OVERSAMPLE
- float filter = fwidth(ratio_scale.y);
+ float filter = fwidth(ratio_scale.y);
#endif
- vec2 uv_ratio = fract(ratio_scale);
+ vec2 uv_ratio = fract(ratio_scale);
- // Snap to the center of the underlying texel.
- xy = (floor(ratio_scale) + vec2_splat(0.5)) / u_tex_size0.xy;
+ // Snap to the center of the underlying texel.
+ xy = (floor(ratio_scale) + vec2_splat(0.5)) / u_tex_size0.xy;
- // Calculate scaling coefficients describing the effect
- // of various neighbour texels in a scanline on the current
- // pixel.
- vec4 coeffs = x_coeffs(vec4(1.0 + uv_ratio.x, uv_ratio.x, 1.0 - uv_ratio.x, 2.0 - uv_ratio.x), ratio_scale.x);
+ // Calculate scaling coefficients describing the effect
+ // of various neighbour texels in a scanline on the current
+ // pixel.
+ vec4 coeffs = x_coeffs(vec4(1.0 + uv_ratio.x, uv_ratio.x, 1.0 - uv_ratio.x, 2.0 - uv_ratio.x), ratio_scale.x);
- vec4 col = sample_scanline(xy, coeffs, v_one.x);
- vec4 col2 = sample_scanline(xy + vec2(0.0, v_one.y), coeffs, v_one.x);
+ vec4 col = sample_scanline(xy, coeffs, v_one.x);
+ vec4 col2 = sample_scanline(xy + vec2(0.0, v_one.y), coeffs, v_one.x);
#ifndef LINEAR_PROCESSING
- col = pow(col , vec4_splat(CRTgamma.x));
- col2 = pow(col2, vec4_splat(CRTgamma.x));
+ col = pow(col , vec4_splat(CRTgamma.x));
+ col2 = pow(col2, vec4_splat(CRTgamma.x));
#endif
- // Calculate the influence of the current and next scanlines on
- // the current pixel.
- vec4 weights = scanlineWeights(uv_ratio.y, col);
- vec4 weights2 = scanlineWeights(1.0 - uv_ratio.y, col2);
+ // Calculate the influence of the current and next scanlines on
+ // the current pixel.
+ vec4 weights = scanlineWeights(uv_ratio.y, col);
+ vec4 weights2 = scanlineWeights(1.0 - uv_ratio.y, col2);
#ifdef OVERSAMPLE
- uv_ratio.y =uv_ratio.y+1.0/3.0*filter;
- weights = (weights+scanlineWeights(uv_ratio.y, col))/3.0;
- weights2=(weights2+scanlineWeights(abs(1.0-uv_ratio.y), col2))/3.0;
- uv_ratio.y =uv_ratio.y-2.0/3.0*filter;
- weights=weights+scanlineWeights(abs(uv_ratio.y), col)/3.0;
- weights2=weights2+scanlineWeights(abs(1.0-uv_ratio.y), col2)/3.0;
+ uv_ratio.y =uv_ratio.y+1.0/3.0*filter;
+ weights = (weights+scanlineWeights(uv_ratio.y, col))/3.0;
+ weights2=(weights2+scanlineWeights(abs(1.0-uv_ratio.y), col2))/3.0;
+ uv_ratio.y =uv_ratio.y-2.0/3.0*filter;
+ weights=weights+scanlineWeights(abs(uv_ratio.y), col)/3.0;
+ weights2=weights2+scanlineWeights(abs(1.0-uv_ratio.y), col2)/3.0;
#endif
- vec3 mul_res = (col * weights + col2 * weights2).rgb * vec3_splat(cval);
+ vec4 mul_res = col * weights + col2 * weights2 * vec4_splat(cval);
- // Shadow mask
- vec3 cout = apply_shadow_mask(v_texCoord.xy, mul_res);
+ // Shadow mask
+ vec3 cout = apply_shadow_mask(v_texCoord.xy, mul_res.rgb);
- // Convert the image gamma for display on our output device.
- cout = linear_to_output(cout);
+ // Convert the image gamma for display on our output device.
+ cout = linear_to_output(cout);
- gl_FragColor = vec4(cout,1.0);
+ gl_FragColor = vec4(cout,mul_res.a);
}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_gaussx.sc b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_gaussx.sc
index 74faf15a740..6290ae330eb 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_gaussx.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_gaussx.sc
@@ -6,33 +6,33 @@ uniform vec4 u_gamma;
uniform vec4 u_tex_size0;
SAMPLER2D(s_tex, 0);
-#define TEX2D(v) pow(texture2D(s_tex, v).rgb, vec3_splat(u_gamma.x))
+#define TEX2D(v) pow(texture2D(s_tex, v), vec4(vec3_splat(u_gamma.x), 1.0))
void main()
{
- vec3 sum = vec3_splat(0.0);
+ vec4 sum = vec4_splat(0.0);
float onex = 1.0/u_tex_size0.x;
- sum += TEX2D(v_texCoord + vec2(-8.0 * onex, 0.0)) * vec3_splat(v_coeffs2.w);
- sum += TEX2D(v_texCoord + vec2(-7.0 * onex, 0.0)) * vec3_splat(v_coeffs2.z);
- sum += TEX2D(v_texCoord + vec2(-6.0 * onex, 0.0)) * vec3_splat(v_coeffs2.y);
- sum += TEX2D(v_texCoord + vec2(-5.0 * onex, 0.0)) * vec3_splat(v_coeffs2.x);
- sum += TEX2D(v_texCoord + vec2(-4.0 * onex, 0.0)) * vec3_splat(v_coeffs.w);
- sum += TEX2D(v_texCoord + vec2(-3.0 * onex, 0.0)) * vec3_splat(v_coeffs.z);
- sum += TEX2D(v_texCoord + vec2(-2.0 * onex, 0.0)) * vec3_splat(v_coeffs.y);
- sum += TEX2D(v_texCoord + vec2(-1.0 * onex, 0.0)) * vec3_splat(v_coeffs.x);
+ sum += TEX2D(v_texCoord + vec2(-8.0 * onex, 0.0)) * vec4_splat(v_coeffs2.w);
+ sum += TEX2D(v_texCoord + vec2(-7.0 * onex, 0.0)) * vec4_splat(v_coeffs2.z);
+ sum += TEX2D(v_texCoord + vec2(-6.0 * onex, 0.0)) * vec4_splat(v_coeffs2.y);
+ sum += TEX2D(v_texCoord + vec2(-5.0 * onex, 0.0)) * vec4_splat(v_coeffs2.x);
+ sum += TEX2D(v_texCoord + vec2(-4.0 * onex, 0.0)) * vec4_splat(v_coeffs.w);
+ sum += TEX2D(v_texCoord + vec2(-3.0 * onex, 0.0)) * vec4_splat(v_coeffs.z);
+ sum += TEX2D(v_texCoord + vec2(-2.0 * onex, 0.0)) * vec4_splat(v_coeffs.y);
+ sum += TEX2D(v_texCoord + vec2(-1.0 * onex, 0.0)) * vec4_splat(v_coeffs.x);
sum += TEX2D(v_texCoord);
- sum += TEX2D(v_texCoord + vec2(+1.0 * onex, 0.0)) * vec3_splat(v_coeffs.x);
- sum += TEX2D(v_texCoord + vec2(+2.0 * onex, 0.0)) * vec3_splat(v_coeffs.y);
- sum += TEX2D(v_texCoord + vec2(+3.0 * onex, 0.0)) * vec3_splat(v_coeffs.z);
- sum += TEX2D(v_texCoord + vec2(+4.0 * onex, 0.0)) * vec3_splat(v_coeffs.w);
- sum += TEX2D(v_texCoord + vec2(+5.0 * onex, 0.0)) * vec3_splat(v_coeffs2.x);
- sum += TEX2D(v_texCoord + vec2(+6.0 * onex, 0.0)) * vec3_splat(v_coeffs2.y);
- sum += TEX2D(v_texCoord + vec2(+7.0 * onex, 0.0)) * vec3_splat(v_coeffs2.z);
- sum += TEX2D(v_texCoord + vec2(+8.0 * onex, 0.0)) * vec3_splat(v_coeffs2.w);
+ sum += TEX2D(v_texCoord + vec2(+1.0 * onex, 0.0)) * vec4_splat(v_coeffs.x);
+ sum += TEX2D(v_texCoord + vec2(+2.0 * onex, 0.0)) * vec4_splat(v_coeffs.y);
+ sum += TEX2D(v_texCoord + vec2(+3.0 * onex, 0.0)) * vec4_splat(v_coeffs.z);
+ sum += TEX2D(v_texCoord + vec2(+4.0 * onex, 0.0)) * vec4_splat(v_coeffs.w);
+ sum += TEX2D(v_texCoord + vec2(+5.0 * onex, 0.0)) * vec4_splat(v_coeffs2.x);
+ sum += TEX2D(v_texCoord + vec2(+6.0 * onex, 0.0)) * vec4_splat(v_coeffs2.y);
+ sum += TEX2D(v_texCoord + vec2(+7.0 * onex, 0.0)) * vec4_splat(v_coeffs2.z);
+ sum += TEX2D(v_texCoord + vec2(+8.0 * onex, 0.0)) * vec4_splat(v_coeffs2.w);
float norm = 1.0 / (1.0 + 2.0*(v_coeffs.x+v_coeffs.y+v_coeffs.z+v_coeffs.w
+v_coeffs2.x+v_coeffs2.y+v_coeffs2.z+v_coeffs2.w));
- gl_FragColor = vec4( pow(sum*vec3_splat(norm), vec3_splat(1.0/u_gamma.x)), 1.0 );
+ gl_FragColor = pow(sum*vec4_splat(norm), vec4(vec3_splat(1.0/u_gamma.x), 1.0));
}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_gaussy.sc b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_gaussy.sc
index c4fa73cdcce..9f4eace6cbe 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_gaussy.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_gaussy.sc
@@ -6,33 +6,33 @@ uniform vec4 u_gamma;
uniform vec4 u_tex_size0;
SAMPLER2D(s_tex, 0);
-#define TEX2D(v) pow(texture2D(s_tex, v).rgb, vec3_splat(u_gamma.x))
+#define TEX2D(v) pow(texture2D(s_tex, v), vec4(vec3_splat(u_gamma.x), 1.0))
void main()
{
- vec3 sum = vec3_splat(0.0);
+ vec4 sum = vec4_splat(0.0);
float oney = 1.0/u_tex_size0.y;
- sum += TEX2D(v_texCoord + vec2(0.0, -8.0 * oney)) * vec3_splat(v_coeffs2.w);
- sum += TEX2D(v_texCoord + vec2(0.0, -7.0 * oney)) * vec3_splat(v_coeffs2.z);
- sum += TEX2D(v_texCoord + vec2(0.0, -6.0 * oney)) * vec3_splat(v_coeffs2.y);
- sum += TEX2D(v_texCoord + vec2(0.0, -5.0 * oney)) * vec3_splat(v_coeffs2.x);
- sum += TEX2D(v_texCoord + vec2(0.0, -4.0 * oney)) * vec3_splat(v_coeffs.w);
- sum += TEX2D(v_texCoord + vec2(0.0, -3.0 * oney)) * vec3_splat(v_coeffs.z);
- sum += TEX2D(v_texCoord + vec2(0.0, -2.0 * oney)) * vec3_splat(v_coeffs.y);
- sum += TEX2D(v_texCoord + vec2(0.0, -1.0 * oney)) * vec3_splat(v_coeffs.x);
+ sum += TEX2D(v_texCoord + vec2(0.0, -8.0 * oney)) * vec4_splat(v_coeffs2.w);
+ sum += TEX2D(v_texCoord + vec2(0.0, -7.0 * oney)) * vec4_splat(v_coeffs2.z);
+ sum += TEX2D(v_texCoord + vec2(0.0, -6.0 * oney)) * vec4_splat(v_coeffs2.y);
+ sum += TEX2D(v_texCoord + vec2(0.0, -5.0 * oney)) * vec4_splat(v_coeffs2.x);
+ sum += TEX2D(v_texCoord + vec2(0.0, -4.0 * oney)) * vec4_splat(v_coeffs.w);
+ sum += TEX2D(v_texCoord + vec2(0.0, -3.0 * oney)) * vec4_splat(v_coeffs.z);
+ sum += TEX2D(v_texCoord + vec2(0.0, -2.0 * oney)) * vec4_splat(v_coeffs.y);
+ sum += TEX2D(v_texCoord + vec2(0.0, -1.0 * oney)) * vec4_splat(v_coeffs.x);
sum += TEX2D(v_texCoord);
- sum += TEX2D(v_texCoord + vec2(0.0, +1.0 * oney)) * vec3_splat(v_coeffs.x);
- sum += TEX2D(v_texCoord + vec2(0.0, +2.0 * oney)) * vec3_splat(v_coeffs.y);
- sum += TEX2D(v_texCoord + vec2(0.0, +3.0 * oney)) * vec3_splat(v_coeffs.z);
- sum += TEX2D(v_texCoord + vec2(0.0, +4.0 * oney)) * vec3_splat(v_coeffs.w);
- sum += TEX2D(v_texCoord + vec2(0.0, +5.0 * oney)) * vec3_splat(v_coeffs2.x);
- sum += TEX2D(v_texCoord + vec2(0.0, +6.0 * oney)) * vec3_splat(v_coeffs2.y);
- sum += TEX2D(v_texCoord + vec2(0.0, +7.0 * oney)) * vec3_splat(v_coeffs2.z);
- sum += TEX2D(v_texCoord + vec2(0.0, +8.0 * oney)) * vec3_splat(v_coeffs2.w);
+ sum += TEX2D(v_texCoord + vec2(0.0, +1.0 * oney)) * vec4_splat(v_coeffs.x);
+ sum += TEX2D(v_texCoord + vec2(0.0, +2.0 * oney)) * vec4_splat(v_coeffs.y);
+ sum += TEX2D(v_texCoord + vec2(0.0, +3.0 * oney)) * vec4_splat(v_coeffs.z);
+ sum += TEX2D(v_texCoord + vec2(0.0, +4.0 * oney)) * vec4_splat(v_coeffs.w);
+ sum += TEX2D(v_texCoord + vec2(0.0, +5.0 * oney)) * vec4_splat(v_coeffs2.x);
+ sum += TEX2D(v_texCoord + vec2(0.0, +6.0 * oney)) * vec4_splat(v_coeffs2.y);
+ sum += TEX2D(v_texCoord + vec2(0.0, +7.0 * oney)) * vec4_splat(v_coeffs2.z);
+ sum += TEX2D(v_texCoord + vec2(0.0, +8.0 * oney)) * vec4_splat(v_coeffs2.w);
float norm = 1.0 / (1.0 + 2.0*(v_coeffs.x+v_coeffs.y+v_coeffs.z+v_coeffs.w
+v_coeffs2.x+v_coeffs2.y+v_coeffs2.z+v_coeffs2.w));
- gl_FragColor = vec4( pow(sum*vec3_splat(norm), vec3_splat(1.0/u_gamma.x)), 1.0 );
+ gl_FragColor = pow(sum*vec4_splat(norm), vec4(vec3_splat(1.0/u_gamma.x), 1.0));
}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_lowpass.sc b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_lowpass.sc
index 2f48bbac321..37ab685957c 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_lowpass.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_lowpass.sc
@@ -33,5 +33,5 @@ void main()
sum +=sample_screen(v_texCoord+vec2(-7.0*onex,0.0))*vec3_splat(v_lpcoeffs2.w);
sum +=sample_screen(v_texCoord+vec2( 7.0*onex,0.0))*vec3_splat(v_lpcoeffs2.w);
- gl_FragColor = vec4( sum, 1.0 );
+ gl_FragColor = vec4( sum, texture2D(s_screen, v_texCoord).a );
}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_mipmap8.sc b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_mipmap8.sc
index 0f86bdbc7ba..2e0f8038053 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_mipmap8.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_mipmap8.sc
@@ -22,7 +22,7 @@ uniform vec4 u_smooth;
const vec2 v05 = vec2(0.5,0.5);
// pix has integer coordinates -> average four pixels using bilinear filtering
-vec3 sample_screen(vec2 pix)
+vec4 sample_screen(vec2 pix)
{
vec2 border = step(-0.5, u_tex_size0.xy - pix);
float weight = border.x * border.y;
@@ -34,12 +34,12 @@ vec3 sample_screen(vec2 pix)
border = clamp(u_tex_size0.xy-x,0.0,1.0);
weight *= border.x * border.y;
- vec3 tex = texture2D(s_screen, x / u_tex_size0.xy).rgb;
+ vec4 tex = texture2D(s_screen, x / u_tex_size0.xy);
- return tex * vec3_splat(weight);
+ return tex * vec4_splat(weight);
}
-vec3 sample_mipmap(vec2 pix, vec2 offset, vec2 size)
+vec4 sample_mipmap(vec2 pix, vec2 offset, vec2 size)
{
vec2 border = step(-0.5, size - pix) * step(-0.5, pix);
float weight = border.x * border.y;
@@ -51,9 +51,9 @@ vec3 sample_mipmap(vec2 pix, vec2 offset, vec2 size)
border = clamp(size-x,0.0,1.0);
weight *= border.x * border.y;
- vec3 tex = texture2D(s_mipmap, (x + offset) / u_tex_size0.xy).rgb;
+ vec4 tex = texture2D(s_mipmap, (x + offset) / u_tex_size0.xy);
- return tex * vec3_splat(weight);
+ return tex * vec4_splat(weight);
}
void main()
@@ -66,7 +66,7 @@ void main()
// sample 4x4 grid
// each sample uses bilinear filtering to average a 2x2 region
// overall reduction by 8x8
- vec3 tex = ( sample_screen(x + vec2(-3.0,-3.0))
+ vec4 tex = ( sample_screen(x + vec2(-3.0,-3.0))
+ sample_screen(x + vec2(-3.0,-1.0))
+ sample_screen(x + vec2(-3.0, 1.0))
+ sample_screen(x + vec2(-3.0, 3.0))
@@ -113,7 +113,7 @@ void main()
if (fc)
x = vec2(4.0,4.0);
- vec3 tex = ( sample_mipmap(x + vec2(-3.0,-3.0),offset0,newsize)
+ vec4 tex = ( sample_mipmap(x + vec2(-3.0,-3.0),offset0,newsize)
+ sample_mipmap(x + vec2(-3.0,-1.0),offset0,newsize)
+ sample_mipmap(x + vec2(-3.0, 1.0),offset0,newsize)
+ sample_mipmap(x + vec2(-3.0, 3.0),offset0,newsize)
@@ -133,16 +133,16 @@ void main()
if (fc) { // this sample yields average over the whole screen
// apply a compensation for the zeros included in the 8^n average
float f = fac*fac / (u_tex_size0.x * u_tex_size0.y);
- vec3 col = tex * vec3_splat(f);
+ vec4 col = tex * vec4_splat(f);
if (v_texCoord.y * u_tex_size1.y < ( offset0.y + u_tex_size1.y ) * 0.5) {
- gl_FragColor = vec4(col,1.0);
+ gl_FragColor = col;
} else {
// we are near (1,1): in this region include the temporal filter
vec4 old = texture2D(s_mipmap, v_texCoord.xy);
- gl_FragColor = vec4(mix(col,old.rgb,u_smooth.x),1.0);
+ gl_FragColor = mix(col,old,u_smooth.x);
}
} else {
- gl_FragColor = vec4(tex.rgb,1.0);
+ gl_FragColor = tex;
}
}
}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_phosphor_apply.sc b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_phosphor_apply.sc
index c45fb8f883f..f7e116696cb 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_phosphor_apply.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_phosphor_apply.sc
@@ -28,15 +28,15 @@ void main()
vec4 screen = texture2D(s_screen, v_texCoord);
vec4 phosphor = texture2D(s_phosphor, v_texCoord);
- vec3 cscrn = pow(screen.rgb, vec3_splat(u_gamma.x));
- vec3 cphos = pow(phosphor.rgb, vec3_splat(u_gamma.x));
+ vec4 cscrn = pow(screen, vec4(vec3_splat(u_gamma.x), 1.0));
+ vec4 cphos = pow(phosphor, vec4(vec3_splat(u_gamma.x), 1.0));
// encode the upper 2 bits of the time elapsed in the lower 2 bits of b
float t = 255.0*phosphor.a + fract(phosphor.b*255.0/4.0)*1024.0;
- cphos *= vec3_splat( u_phosphor_amplitude.x * decay(t) );
+ cphos *= vec4_splat( u_phosphor_amplitude.x * decay(t) );
- vec3 col = pow(cscrn + cphos, vec3_splat(1.0/u_gamma.x));
+ vec4 col = pow(cscrn + cphos, vec4(vec3_splat(1.0/u_gamma.x), 1.0));
- gl_FragColor = vec4(col, 1.0);
+ gl_FragColor = col;
}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_crt-geom.sc b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_crt-geom.sc
index cc3ed09aa14..4f17f0d0ec3 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_crt-geom.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_crt-geom.sc
@@ -19,78 +19,82 @@ uniform vec4 R;
uniform vec4 angle;
uniform vec4 u_tex_size0;
+uniform vec4 u_inv_view_dims;
uniform vec4 u_rotation_type;
#define FIX(c) max(abs(c), 1e-5)
float intersect(vec2 xy , vec2 sinangle, vec2 cosangle)
{
- float A = dot(xy,xy)+d.x*d.x;
- float B = 2.0*(R.x*(dot(xy,sinangle)-d.x*cosangle.x*cosangle.y)-d.x*d.x);
- float C = d.x*d.x + 2.0*R.x*d.x*cosangle.x*cosangle.y;
- return (-B-sqrt(B*B-4.0*A*C))/(2.0*A);
+ float A = dot(xy,xy)+d.x*d.x;
+ float B = 2.0*(R.x*(dot(xy,sinangle)-d.x*cosangle.x*cosangle.y)-d.x*d.x);
+ float C = d.x*d.x + 2.0*R.x*d.x*cosangle.x*cosangle.y;
+ return (-B-sqrt(B*B-4.0*A*C))/(2.0*A);
}
vec2 bkwtrans(vec2 xy, vec2 sinangle, vec2 cosangle)
{
- float c = intersect(xy, sinangle, cosangle);
- vec2 pt = vec2_splat(c)*xy;
- pt -= vec2_splat(-R.x)*sinangle;
- pt /= vec2_splat(R.x);
- vec2 tang = sinangle/cosangle;
- vec2 poc = pt/cosangle;
- float A = dot(tang,tang)+1.0;
- float B = -2.0*dot(poc,tang);
- float C = dot(poc,poc)-1.0;
- float a = (-B+sqrt(B*B-4.0*A*C))/(2.0*A);
- vec2 uv = (pt-a*sinangle)/cosangle;
- float r = FIX(R.x*acos(a));
- return uv*r/sin(r/R.x);
+ float c = intersect(xy, sinangle, cosangle);
+ vec2 pt = vec2_splat(c)*xy;
+ pt -= vec2_splat(-R.x)*sinangle;
+ pt /= vec2_splat(R.x);
+ vec2 tang = sinangle/cosangle;
+ vec2 poc = pt/cosangle;
+ float A = dot(tang,tang)+1.0;
+ float B = -2.0*dot(poc,tang);
+ float C = dot(poc,poc)-1.0;
+ float a = (-B+sqrt(B*B-4.0*A*C))/(2.0*A);
+ vec2 uv = (pt-a*sinangle)/cosangle;
+ float r = FIX(R.x*acos(a));
+ return uv*r/sin(r/R.x);
}
vec2 fwtrans(vec2 uv, vec2 sinangle, vec2 cosangle)
{
- float r = FIX(sqrt(dot(uv,uv)));
- uv *= sin(r/R.x)/r;
- float x = 1.0-cos(r/R.x);
- float D = d.x/R.x + x*cosangle.x*cosangle.y+dot(uv,sinangle);
- return d.x*(uv*cosangle-x*sinangle)/D;
+ float r = FIX(sqrt(dot(uv,uv)));
+ uv *= sin(r/R.x)/r;
+ float x = 1.0-cos(r/R.x);
+ float D = d.x/R.x + x*cosangle.x*cosangle.y+dot(uv,sinangle);
+ return d.x*(uv*cosangle-x*sinangle)/D;
}
vec3 maxscale(vec2 sinangle, vec2 cosangle)
{
- vec2 c = bkwtrans(-R.x * sinangle / (1.0 + R.x/d.x*cosangle.x*cosangle.y), sinangle, cosangle);
- vec2 a = vec2(0.5,0.5)*aspect.xy;
- vec2 lo = vec2(fwtrans(vec2(-a.x,c.y), sinangle, cosangle).x,
- fwtrans(vec2(c.x,-a.y), sinangle, cosangle).y)/aspect.xy;
- vec2 hi = vec2(fwtrans(vec2(+a.x,c.y), sinangle, cosangle).x,
- fwtrans(vec2(c.x,+a.y), sinangle, cosangle).y)/aspect.xy;
- return vec3((hi+lo)*aspect.xy*0.5,max(hi.x-lo.x,hi.y-lo.y));
+ vec2 c = bkwtrans(-R.x * sinangle / (1.0 + R.x/d.x*cosangle.x*cosangle.y), sinangle, cosangle);
+ vec2 a = vec2(0.5,0.5)*aspect.xy;
+ vec2 lo = vec2(fwtrans(vec2(-a.x,c.y), sinangle, cosangle).x,
+ fwtrans(vec2(c.x,-a.y), sinangle, cosangle).y)/aspect.xy;
+ vec2 hi = vec2(fwtrans(vec2(+a.x,c.y), sinangle, cosangle).x,
+ fwtrans(vec2(c.x,+a.y), sinangle, cosangle).y)/aspect.xy;
+ return vec3((hi+lo)*aspect.xy*0.5,max(hi.x-lo.x,hi.y-lo.y));
}
void main()
{
- // Do the standard vertex processing.
- gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
- v_texCoord = a_texcoord0;
+ // Do the standard vertex processing.
+ gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
+ v_texCoord = a_texcoord0;
- // Precalculate a bunch of useful values we'll need in the fragment
- // shader.
- vec2 ang;
- // if (u_rotation_type.x < 0.5)
- // ang = vec2(0.0,angle.x);
- // else if (u_rotation_type.x < 1.5)
- // ang = vec2(angle.x,0.0);
- // else if (u_rotation_type.x < 2.5)
- // ang = vec2(0.0,-angle.x);
- // else
- // ang = vec2(-angle.x,0.0);
- ang = angle.xy;
- v_sinangle = sin(ang);
- v_cosangle = cos(ang);
- v_stretch = maxscale(v_sinangle, v_cosangle);
+ // Precalculate a bunch of useful values we'll need in the fragment
+ // shader.
+ vec2 ang;
+ // if (u_rotation_type.x < 0.5)
+ // ang = vec2(0.0,angle.x);
+ // else if (u_rotation_type.x < 1.5)
+ // ang = vec2(angle.x,0.0);
+ // else if (u_rotation_type.x < 2.5)
+ // ang = vec2(0.0,-angle.x);
+ // else
+ // ang = vec2(-angle.x,0.0);
+ ang = angle.xy;
+ v_sinangle = sin(ang);
+ v_cosangle = cos(ang);
+ v_stretch = maxscale(v_sinangle, v_cosangle);
- // The size of one texel, in texture-coordinates.
- v_one = 1.0 / u_tex_size0.xy;
+ // The size of one texel, in texture-coordinates.
+ v_one = 1.0 / u_tex_size0.xy;
}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_gaussx.sc b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_gaussx.sc
index e9969187c94..a5fb1d22622 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_gaussx.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_gaussx.sc
@@ -4,16 +4,20 @@ $output v_texCoord, v_coeffs, v_coeffs2
#include "common.sh"
uniform vec4 u_tex_size0;
+uniform vec4 u_inv_view_dims;
uniform vec4 u_width;
uniform vec4 u_aspect;
void main()
{
- float wid = u_width.x*u_tex_size0.x/(320.*u_aspect.x);
- v_coeffs = exp(vec4(1.,4.,9.,16.)*vec4_splat(-1.0/wid/wid));
- v_coeffs2 = exp(vec4(25.,36.,49.,64.)*vec4_splat(-1.0/wid/wid));
+ float wid = u_width.x*u_tex_size0.x/(320.*u_aspect.x);
+ v_coeffs = exp(vec4(1.,4.,9.,16.)*vec4_splat(-1.0/wid/wid));
+ v_coeffs2 = exp(vec4(25.,36.,49.,64.)*vec4_splat(-1.0/wid/wid));
- // Do the standard vertex processing.
- gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
- v_texCoord = a_texcoord0;
+ // Do the standard vertex processing.
+ gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
+ v_texCoord = a_texcoord0;
}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_gaussy.sc b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_gaussy.sc
index 0b7ff9b411f..93676cde1d5 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_gaussy.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_gaussy.sc
@@ -4,16 +4,20 @@ $output v_texCoord, v_coeffs, v_coeffs2
#include "common.sh"
uniform vec4 u_tex_size0;
+uniform vec4 u_inv_view_dims;
uniform vec4 u_width;
uniform vec4 u_aspect;
void main()
{
- float wid = u_width.x*u_tex_size0.y/(320.*u_aspect.y);
- v_coeffs = exp(vec4(1.,4.,9.,16.)*vec4_splat(-1.0/wid/wid));
- v_coeffs2 = exp(vec4(25.,36.,49.,64.)*vec4_splat(-1.0/wid/wid));
+ float wid = u_width.x*u_tex_size0.y/(320.*u_aspect.y);
+ v_coeffs = exp(vec4(1.,4.,9.,16.)*vec4_splat(-1.0/wid/wid));
+ v_coeffs2 = exp(vec4(25.,36.,49.,64.)*vec4_splat(-1.0/wid/wid));
- // Do the standard vertex processing.
- gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
- v_texCoord = a_texcoord0;
+ // Do the standard vertex processing.
+ gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
+ v_texCoord = a_texcoord0;
}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_lowpass.sc b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_lowpass.sc
index 4d948a63a89..2ca983d41d7 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_lowpass.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_lowpass.sc
@@ -4,46 +4,50 @@ $output v_texCoord, v_lpcoeffs1, v_lpcoeffs2
#include "common.sh"
uniform vec4 u_tex_size0;
+uniform vec4 u_inv_view_dims;
uniform vec4 u_lowpass_cutoff;
uniform vec4 u_lowpass_width;
void main()
{
- // Do the standard vertex processing.
- gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
- v_texCoord = a_texcoord0;
+ // Do the standard vertex processing.
+ gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
+ v_texCoord = a_texcoord0;
- // interpret the cutoff and width as target resolutions in pixels per scanline
- // include factor of 1/2 because max frequency at given resolution is Nyquist
- float a = 0.5 * u_lowpass_cutoff.x / u_tex_size0.x;
- float b = 0.5 * u_lowpass_width.x / u_tex_size0.x;
- float w0 = (a-0.5*b);
- float w1 = (a+0.5*b);
+ // interpret the cutoff and width as target resolutions in pixels per scanline
+ // include factor of 1/2 because max frequency at given resolution is Nyquist
+ float a = 0.5 * u_lowpass_cutoff.x / u_tex_size0.x;
+ float b = 0.5 * u_lowpass_width.x / u_tex_size0.x;
+ float w0 = (a-0.5*b);
+ float w1 = (a+0.5*b);
- float two_pi = 6.283185307179586;
- vec3 n1 = vec3(1.0,2.0,3.0);
- vec4 n2 = vec4(4.0,5.0,6.0,7.0);
+ float two_pi = 6.283185307179586;
+ vec3 n1 = vec3(1.0,2.0,3.0);
+ vec4 n2 = vec4(4.0,5.0,6.0,7.0);
- // target frequency response:
- // 1 for w < w0
- // 0 for w > w1
- // linearly decreasing for w0 < w < w1
- // this will be approximated by including the lowest Fourier modes
- if (w0 > 0.5) { // no filtering
- v_lpcoeffs1 = vec4(1.0,0.0,0.0,0.0);
- v_lpcoeffs2 = vec4_splat(0.0);
- } else if (w1 > 0.5) { // don't reach zero
- // here the target has a nonzero response at the Nyquist frequency
- v_lpcoeffs1.x = w1 + w0 - (w1 - 0.5)*(w1 - 0.5)/(w1 - w0);
- v_lpcoeffs1.yzw = 2.0 / ( two_pi*two_pi*(w1-w0)*n1*n1 ) * ( cos(two_pi*w0*n1) - cos(two_pi*0.5*n1) );
- v_lpcoeffs2 = 2.0 / ( two_pi*two_pi*(w1-w0)*n2*n2 ) * ( cos(two_pi*w0*n2) - cos(two_pi*0.5*n2) );
- } else if (w1 == w0) { // sharp cutoff
- v_lpcoeffs1.x = 2.0 * w0;
- v_lpcoeffs1.yzw = 2.0 / ( two_pi * n1 ) * sin(two_pi*w0*n1);
- v_lpcoeffs2 = 2.0 / ( two_pi * n2 ) * sin(two_pi*w0*n2);
- } else {
- v_lpcoeffs1.x = w1 + w0;
- v_lpcoeffs1.yzw = 2.0 / ( two_pi*two_pi*(w1-w0)*n1*n1 ) * ( cos(two_pi*w0*n1) - cos(two_pi*w1*n1) );
- v_lpcoeffs2 = 2.0 / ( two_pi*two_pi*(w1-w0)*n2*n2 ) * ( cos(two_pi*w0*n2) - cos(two_pi*w1*n2) );
- }
+ // target frequency response:
+ // 1 for w < w0
+ // 0 for w > w1
+ // linearly decreasing for w0 < w < w1
+ // this will be approximated by including the lowest Fourier modes
+ if (w0 > 0.5) { // no filtering
+ v_lpcoeffs1 = vec4(1.0,0.0,0.0,0.0);
+ v_lpcoeffs2 = vec4_splat(0.0);
+ } else if (w1 > 0.5) { // don't reach zero
+ // here the target has a nonzero response at the Nyquist frequency
+ v_lpcoeffs1.x = w1 + w0 - (w1 - 0.5)*(w1 - 0.5)/(w1 - w0);
+ v_lpcoeffs1.yzw = 2.0 / ( two_pi*two_pi*(w1-w0)*n1*n1 ) * ( cos(two_pi*w0*n1) - cos(two_pi*0.5*n1) );
+ v_lpcoeffs2 = 2.0 / ( two_pi*two_pi*(w1-w0)*n2*n2 ) * ( cos(two_pi*w0*n2) - cos(two_pi*0.5*n2) );
+ } else if (w1 == w0) { // sharp cutoff
+ v_lpcoeffs1.x = 2.0 * w0;
+ v_lpcoeffs1.yzw = 2.0 / ( two_pi * n1 ) * sin(two_pi*w0*n1);
+ v_lpcoeffs2 = 2.0 / ( two_pi * n2 ) * sin(two_pi*w0*n2);
+ } else {
+ v_lpcoeffs1.x = w1 + w0;
+ v_lpcoeffs1.yzw = 2.0 / ( two_pi*two_pi*(w1-w0)*n1*n1 ) * ( cos(two_pi*w0*n1) - cos(two_pi*w1*n1) );
+ v_lpcoeffs2 = 2.0 / ( two_pi*two_pi*(w1-w0)*n2*n2 ) * ( cos(two_pi*w0*n2) - cos(two_pi*w1*n2) );
+ }
}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_mipmap8.sc b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_mipmap8.sc
index bdd09148403..8424e153cdb 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_mipmap8.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_mipmap8.sc
@@ -3,9 +3,14 @@ $output v_texCoord
#include "common.sh"
+uniform vec4 u_inv_view_dims;
+
void main()
{
- // Do the standard vertex processing.
- gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
- v_texCoord = a_texcoord0;
+ // Do the standard vertex processing.
+ gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
+ v_texCoord = a_texcoord0;
}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_phosphor_apply.sc b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_phosphor_apply.sc
index bdd09148403..8424e153cdb 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_phosphor_apply.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_phosphor_apply.sc
@@ -3,9 +3,14 @@ $output v_texCoord
#include "common.sh"
+uniform vec4 u_inv_view_dims;
+
void main()
{
- // Do the standard vertex processing.
- gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
- v_texCoord = a_texcoord0;
+ // Do the standard vertex processing.
+ gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
+ v_texCoord = a_texcoord0;
}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_phosphor_update.sc b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_phosphor_update.sc
index bdd09148403..8424e153cdb 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_phosphor_update.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_phosphor_update.sc
@@ -3,9 +3,14 @@ $output v_texCoord
#include "common.sh"
+uniform vec4 u_inv_view_dims;
+
void main()
{
- // Do the standard vertex processing.
- gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
- v_texCoord = a_texcoord0;
+ // Do the standard vertex processing.
+ gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
+ v_texCoord = a_texcoord0;
}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/crt/vs_crt-caligari.sc b/src/osd/modules/render/bgfx/shaders/chains/crt/vs_crt-caligari.sc
index 6dead210d9e..ce22c1e7200 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/crt/vs_crt-caligari.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/crt/vs_crt-caligari.sc
@@ -32,10 +32,14 @@ $output v_texcoord0, v_texcoord1, v_color0
// Autos
uniform vec4 u_source_size;
+uniform vec4 u_inv_view_dims;
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
onex = vec2(1.0 / u_source_size.x, 0.0);
diff --git a/src/osd/modules/render/bgfx/shaders/chains/default/vs_blit.sc b/src/osd/modules/render/bgfx/shaders/chains/default/vs_blit.sc
index 405ef8feb3b..df2b37f203c 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/default/vs_blit.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/default/vs_blit.sc
@@ -6,9 +6,14 @@ $output v_texcoord0, v_color0
#include "common.sh"
+uniform vec4 u_inv_view_dims;
+
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
v_color0 = a_color0;
}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/eagle/fs_eagle.sc b/src/osd/modules/render/bgfx/shaders/chains/eagle/fs_eagle.sc
index 5219614c794..ca769f5dc07 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/eagle/fs_eagle.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/eagle/fs_eagle.sc
@@ -122,16 +122,16 @@ void main()
else
{
p01 = 0.5 * (C4 + C5);
- }
+ }
- if ((c8 == d2) || (c3 == c4))
- {
+ if ((c8 == d2) || (c3 == c4))
+ {
p10 = 0.25 * (3.0 * C4 + C7);
- }
- else
- {
+ }
+ else
+ {
p10 = 0.5 * (C7 + C8);
- }
+ }
}
else
{
diff --git a/src/osd/modules/render/bgfx/shaders/chains/eagle/vs_eagle.sc b/src/osd/modules/render/bgfx/shaders/chains/eagle/vs_eagle.sc
index 1ab076dfa73..095d5d562e0 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/eagle/vs_eagle.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/eagle/vs_eagle.sc
@@ -14,10 +14,14 @@ $output v_color0, texCoord, t1, t2, t3, t4, t5, t6, t7, t8
// Autos
uniform vec4 u_tex_size0;
+uniform vec4 u_inv_view_dims;
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_color0 = a_color0;
vec2 ps = vec2(1.0, 1.0) / u_tex_size0.xy;
diff --git a/src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_defocus.sc b/src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_defocus.sc
index cfb7b487596..20820f0c0a3 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_defocus.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_defocus.sc
@@ -25,7 +25,7 @@ void main()
{
// previously this pass was applied two times with offsets of 0.25, 0.5, 0.75, 1.0
// now this pass is applied only once with offsets of 0.25, 0.55, 1.0, 1.6 to achieve the same appearance as before till a maximum defocus of 2.0
- // 0.075x² + 0.225x + 0.25
+ // 0.075x² + 0.225x + 0.25
const vec2 Coord1Offset = vec2(-1.60, 0.25);
const vec2 Coord2Offset = vec2(-1.00, -0.55);
const vec2 Coord3Offset = vec2(-0.55, 1.00);
diff --git a/src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_distortion.sc b/src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_distortion.sc
index 47201c0661d..ed4f6195944 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_distortion.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_distortion.sc
@@ -134,11 +134,11 @@ vec2 GetDistortedCoords(vec2 centerCoord, float amount, float amountCube)
float r2 = centerCoord.x * centerCoord.x + centerCoord.y * centerCoord.y;
float f = kcube == 0.0 ? 1.0 + r2 * k : 1.0 + r2 * (k + kcube * sqrt(r2));
- // fit screen bounds
+ // fit screen bounds
f /= 1.0 + amount * 0.25 + amountCube * 0.125;
// apply cubic distortion factor
- centerCoord *= f;
+ centerCoord *= f;
return centerCoord;
}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_scanline.sc b/src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_scanline.sc
index 5942c75bab6..2126398062b 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_scanline.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_scanline.sc
@@ -37,34 +37,15 @@ SAMPLER2D(s_shadow, 1);
// Scanline Pixel Shader
//-----------------------------------------------------------------------------
-vec2 GetAdjustedCoords(vec2 coord)
-{
- // center coordinates
- coord -= 0.5;
-
- // apply screen scale
- coord *= u_screen_scale.xy;
-
- // un-center coordinates
- coord += 0.5;
-
- // apply screen offset
- coord += u_screen_offset.xy;
-
- return coord;
-}
-
void main()
{
- vec2 BaseCoord = GetAdjustedCoords(v_texcoord0);
-
// Color
- vec4 BaseColor = texture2D(s_tex, BaseCoord);
+ vec4 BaseColor = texture2D(s_tex, v_texcoord0);
// Clamp
- if (BaseCoord.x < 0.0 || BaseCoord.y < 0.0 || BaseCoord.x > 1.0 || BaseCoord.y > 1.0)
+ if (v_texcoord0.x < 0.0 || v_texcoord0.y < 0.0 || v_texcoord0.x > 1.0 || v_texcoord0.y > 1.0)
{
- gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
+ gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
}
else
{
@@ -76,7 +57,7 @@ void main()
float ColorBrightness = 0.299 * BaseColor.r + 0.587 * BaseColor.g + 0.114 * BaseColor.b;
- float ScanCoord = BaseCoord.y;
+ float ScanCoord = v_texcoord0.y;
ScanCoord += u_swap_xy.x > 0.0
? u_quad_dims.x <= u_source_dims.x * 2.0
? 0.5 / u_quad_dims.x // uncenter scanlines if the quad is less than twice the size of the source
diff --git a/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_chroma.sc b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_chroma.sc
index 405ef8feb3b..df2b37f203c 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_chroma.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_chroma.sc
@@ -6,9 +6,14 @@ $output v_texcoord0, v_color0
#include "common.sh"
+uniform vec4 u_inv_view_dims;
+
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
v_color0 = a_color0;
}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_color.sc b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_color.sc
index 405ef8feb3b..df2b37f203c 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_color.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_color.sc
@@ -6,9 +6,14 @@ $output v_texcoord0, v_color0
#include "common.sh"
+uniform vec4 u_inv_view_dims;
+
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
v_color0 = a_color0;
}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_deconverge.sc b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_deconverge.sc
index b77d85d1ea8..55c2f0e2e34 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_deconverge.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_deconverge.sc
@@ -8,6 +8,7 @@ $output v_color0, v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3
// Autos
uniform vec4 u_source_size;
+uniform vec4 u_inv_view_dims;
// User-supplied
uniform vec4 u_converge_red;
@@ -20,6 +21,9 @@ uniform vec4 u_radial_converge_blue;
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
vec2 half_value = vec2(0.5, 0.5);
diff --git a/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_defocus.sc b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_defocus.sc
index 405ef8feb3b..df2b37f203c 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_defocus.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_defocus.sc
@@ -6,9 +6,14 @@ $output v_texcoord0, v_color0
#include "common.sh"
+uniform vec4 u_inv_view_dims;
+
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
v_color0 = a_color0;
}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_distortion.sc b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_distortion.sc
index 405ef8feb3b..df2b37f203c 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_distortion.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_distortion.sc
@@ -6,9 +6,14 @@ $output v_texcoord0, v_color0
#include "common.sh"
+uniform vec4 u_inv_view_dims;
+
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
v_color0 = a_color0;
}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_ntsc_decode.sc b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_ntsc_decode.sc
index 405ef8feb3b..df2b37f203c 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_ntsc_decode.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_ntsc_decode.sc
@@ -6,9 +6,14 @@ $output v_texcoord0, v_color0
#include "common.sh"
+uniform vec4 u_inv_view_dims;
+
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
v_color0 = a_color0;
}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_ntsc_encode.sc b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_ntsc_encode.sc
index 405ef8feb3b..df2b37f203c 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_ntsc_encode.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_ntsc_encode.sc
@@ -6,9 +6,14 @@ $output v_texcoord0, v_color0
#include "common.sh"
+uniform vec4 u_inv_view_dims;
+
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
v_color0 = a_color0;
}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_phosphor.sc b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_phosphor.sc
index 405ef8feb3b..df2b37f203c 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_phosphor.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_phosphor.sc
@@ -6,9 +6,14 @@ $output v_texcoord0, v_color0
#include "common.sh"
+uniform vec4 u_inv_view_dims;
+
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
v_color0 = a_color0;
}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_post.sc b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_post.sc
index 405ef8feb3b..df2b37f203c 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_post.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_post.sc
@@ -6,9 +6,14 @@ $output v_texcoord0, v_color0
#include "common.sh"
+uniform vec4 u_inv_view_dims;
+
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
v_color0 = a_color0;
}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_prescale.sc b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_prescale.sc
index 405ef8feb3b..df2b37f203c 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_prescale.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_prescale.sc
@@ -6,9 +6,14 @@ $output v_texcoord0, v_color0
#include "common.sh"
+uniform vec4 u_inv_view_dims;
+
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
v_color0 = a_color0;
}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_scanline.sc b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_scanline.sc
index 405ef8feb3b..df2b37f203c 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_scanline.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_scanline.sc
@@ -6,9 +6,14 @@ $output v_texcoord0, v_color0
#include "common.sh"
+uniform vec4 u_inv_view_dims;
+
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
v_color0 = a_color0;
}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/hqx/fs_hq2x.sc b/src/osd/modules/render/bgfx/shaders/chains/hqx/fs_hq2x.sc
index 479ed825a8b..3f6c2645ba4 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/hqx/fs_hq2x.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/hqx/fs_hq2x.sc
@@ -60,8 +60,8 @@ void main()
vec2 index;
index.x = dot(pattern[0], vec3( 1.0, 2.0, 4.0)) +
- dot(pattern[1], vec3( 8.0, 0.0, 16.0)) +
- dot(pattern[2], vec3(32.0, 64.0, 128.0));
+ dot(pattern[1], vec3( 8.0, 0.0, 16.0)) +
+ dot(pattern[2], vec3(32.0, 64.0, 128.0));
index.y = dot(cross, vec4(1.0, 2.0, 4.0, 8.0)) * SCALE * SCALE + dot(floor(fp * vec2(SCALE, SCALE)), vec2(1.0, SCALE));
vec2 step = vec2(1.0, 1.0) / vec2(256.0, 16.0 * (SCALE * SCALE));
diff --git a/src/osd/modules/render/bgfx/shaders/chains/hqx/fs_hq3x.sc b/src/osd/modules/render/bgfx/shaders/chains/hqx/fs_hq3x.sc
index 1d35cec01e6..1cb08a52da4 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/hqx/fs_hq3x.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/hqx/fs_hq3x.sc
@@ -60,8 +60,8 @@ void main()
vec2 index;
index.x = dot(pattern[0], vec3( 1.0, 2.0, 4.0)) +
- dot(pattern[1], vec3( 8.0, 0.0, 16.0)) +
- dot(pattern[2], vec3(32.0, 64.0, 128.0));
+ dot(pattern[1], vec3( 8.0, 0.0, 16.0)) +
+ dot(pattern[2], vec3(32.0, 64.0, 128.0));
index.y = dot(cross, vec4(1.0, 2.0, 4.0, 8.0)) * SCALE * SCALE + dot(floor(fp * vec2(SCALE, SCALE)), vec2(1.0, SCALE));
vec2 step = vec2(1.0, 1.0) / vec2(256.0, 16.0 * (SCALE * SCALE));
diff --git a/src/osd/modules/render/bgfx/shaders/chains/hqx/fs_hq4x.sc b/src/osd/modules/render/bgfx/shaders/chains/hqx/fs_hq4x.sc
index 6f25b0e9cc3..6e87d47dc0c 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/hqx/fs_hq4x.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/hqx/fs_hq4x.sc
@@ -60,8 +60,8 @@ void main()
vec2 index;
index.x = dot(pattern[0], vec3( 1.0, 2.0, 4.0)) +
- dot(pattern[1], vec3( 8.0, 0.0, 16.0)) +
- dot(pattern[2], vec3(32.0, 64.0, 128.0));
+ dot(pattern[1], vec3( 8.0, 0.0, 16.0)) +
+ dot(pattern[2], vec3(32.0, 64.0, 128.0));
index.y = dot(cross, vec4(1.0, 2.0, 4.0, 8.0)) * SCALE * SCALE + dot(floor(fp * vec2(SCALE, SCALE)), vec2(1.0, SCALE));
vec2 step = vec2(1.0, 1.0) / vec2(256.0, 16.0 * (SCALE * SCALE));
diff --git a/src/osd/modules/render/bgfx/shaders/chains/hqx/vs_hq2x.sc b/src/osd/modules/render/bgfx/shaders/chains/hqx/vs_hq2x.sc
index dcff07b17f5..727f5763857 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/hqx/vs_hq2x.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/hqx/vs_hq2x.sc
@@ -8,10 +8,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_color0
// Autos
uniform vec4 u_tex_size0;
+uniform vec4 u_inv_view_dims;
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_color0 = a_color0;
vec2 ps = vec2(1.0, 1.0) / u_tex_size0.xy;
diff --git a/src/osd/modules/render/bgfx/shaders/chains/hqx/vs_hq3x.sc b/src/osd/modules/render/bgfx/shaders/chains/hqx/vs_hq3x.sc
index dcff07b17f5..727f5763857 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/hqx/vs_hq3x.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/hqx/vs_hq3x.sc
@@ -8,10 +8,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_color0
// Autos
uniform vec4 u_tex_size0;
+uniform vec4 u_inv_view_dims;
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_color0 = a_color0;
vec2 ps = vec2(1.0, 1.0) / u_tex_size0.xy;
diff --git a/src/osd/modules/render/bgfx/shaders/chains/hqx/vs_hq4x.sc b/src/osd/modules/render/bgfx/shaders/chains/hqx/vs_hq4x.sc
index dcff07b17f5..727f5763857 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/hqx/vs_hq4x.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/hqx/vs_hq4x.sc
@@ -8,10 +8,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_color0
// Autos
uniform vec4 u_tex_size0;
+uniform vec4 u_inv_view_dims;
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_color0 = a_color0;
vec2 ps = vec2(1.0, 1.0) / u_tex_size0.xy;
diff --git a/src/osd/modules/render/bgfx/shaders/chains/lcd-grid/fs_lcd-grid.sc b/src/osd/modules/render/bgfx/shaders/chains/lcd-grid/fs_lcd-grid.sc
index 9ed2a47e801..801d1a2e9a4 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/lcd-grid/fs_lcd-grid.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/lcd-grid/fs_lcd-grid.sc
@@ -22,85 +22,85 @@ uniform vec4 u_subpixsize;
vec3 fetch_offset(vec2 coord, vec2 offset)
{
- vec2 x = coord + offset;
- vec3 col = texture2D(s_tex, x).rgb;
- vec3 col2 = pow(vec3_splat(u_gain.x) * col + vec3_splat(u_blacklevel.x), vec3_splat(u_LCDgamma.x)) + vec3_splat(u_ambient.x);
- // want zero for outside pixels
- vec4 b = step(0.0,vec4(x.x,x.y,1.0-x.x,1.0-x.y));
- return vec3_splat(b.x*b.y*b.z*b.w) * col2;
+ vec2 x = coord + offset;
+ vec3 col = texture2D(s_tex, x).rgb;
+ vec3 col2 = pow(vec3_splat(u_gain.x) * col + vec3_splat(u_blacklevel.x), vec3_splat(u_LCDgamma.x)) + vec3_splat(u_ambient.x);
+ // want zero for outside pixels
+ vec4 b = step(0.0,vec4(x.x,x.y,1.0-x.x,1.0-x.y));
+ return vec3_splat(b.x*b.y*b.z*b.w) * col2;
}
float intsmear_func(float z, float c1, float c2, float c3, float c4, float c5, float c6)
{
- float z2 = z*z;
- // both cases have c0=1
- return z * (1.0 + z2*(c1 + z2*(c2 + z2*(c3 + z2*(c4 + z2*(c5 + z2*c6))))));
+ float z2 = z*z;
+ // both cases have c0=1
+ return z * (1.0 + z2*(c1 + z2*(c2 + z2*(c3 + z2*(c4 + z2*(c5 + z2*c6))))));
}
float intsmear_fx(float z)
{
- // integral of (1 - x^2 - x^4 + x^6)^2
- return intsmear_func(z, -2.0/3.0, -1.0/5.0, 4.0/7.0, -1.0/9.0, -2.0/11.0, 1.0/13.0);
+ // integral of (1 - x^2 - x^4 + x^6)^2
+ return intsmear_func(z, -2.0/3.0, -1.0/5.0, 4.0/7.0, -1.0/9.0, -2.0/11.0, 1.0/13.0);
}
float intsmear_fy(float z)
{
- // integral of (1 - 2x^4 + x^6)^2
- return intsmear_func(z, 0.0, -4.0/5.0, 2.0/7.0, 4.0/9.0, -4.0/11.0, 1.0/13.0);
+ // integral of (1 - 2x^4 + x^6)^2
+ return intsmear_func(z, 0.0, -4.0/5.0, 2.0/7.0, 4.0/9.0, -4.0/11.0, 1.0/13.0);
}
float intsmear_x(float x, float dx, float d)
{
- float zl = clamp((x-dx*0.5)/d,-1.0,1.0);
- float zh = clamp((x+dx*0.5)/d,-1.0,1.0);
- return d * ( intsmear_fx(zh) - intsmear_fx(zl) )/dx;
+ float zl = clamp((x-dx*0.5)/d,-1.0,1.0);
+ float zh = clamp((x+dx*0.5)/d,-1.0,1.0);
+ return d * ( intsmear_fx(zh) - intsmear_fx(zl) )/dx;
}
float intsmear_y(float x, float dx, float d)
{
- float zl = clamp((x-dx*0.5)/d,-1.0,1.0);
- float zh = clamp((x+dx*0.5)/d,-1.0,1.0);
- return d * ( intsmear_fy(zh) - intsmear_fy(zl) )/dx;
+ float zl = clamp((x-dx*0.5)/d,-1.0,1.0);
+ float zh = clamp((x+dx*0.5)/d,-1.0,1.0);
+ return d * ( intsmear_fy(zh) - intsmear_fy(zl) )/dx;
}
void main()
{
- vec3 cr = pow(u_rsubpix.rgb, vec3_splat(u_monitorgamma.x));
- vec3 cg = pow(u_gsubpix.rgb, vec3_splat(u_monitorgamma.x));
- vec3 cb = pow(u_bsubpix.rgb, vec3_splat(u_monitorgamma.x));
-
- vec2 tl = v_texcoord0 * u_tex_size0.xy - vec2(0.5,0.5);
- vec2 tli = floor(tl);
- float subpix = fract(tl.x) * 3.0;
- float rsubpix = u_tex_size0.x / u_quad_dims.x * 3.0;
-
- vec3 lcol, rcol;
- lcol = vec3(intsmear_x(subpix+1.0, rsubpix, 3.0*u_subpixsize.x),
- intsmear_x(subpix , rsubpix, 3.0*u_subpixsize.x),
- intsmear_x(subpix-1.0, rsubpix, 3.0*u_subpixsize.x));
- rcol = vec3(intsmear_x(subpix-2.0, rsubpix, 3.0*u_subpixsize.x),
- intsmear_x(subpix-3.0, rsubpix, 3.0*u_subpixsize.x),
- intsmear_x(subpix-4.0, rsubpix, 3.0*u_subpixsize.x));
-
- if (u_BGR.x > 0.5) {
- lcol.rgb = lcol.bgr;
- rcol.rgb = rcol.bgr;
- }
-
- float tcol, bcol;
- subpix = fract(tl.y);
- rsubpix = u_tex_size0.y / u_quad_dims.y;
- tcol = intsmear_y(subpix ,rsubpix, u_subpixsize.y);
- bcol = intsmear_y(subpix-1.0,rsubpix, u_subpixsize.y);
-
- tl = (tli + vec2_splat(0.5)) / u_tex_size0.xy;
- vec2 one = vec2_splat(1.0) / u_tex_size0.xy;
-
- vec3 ul = fetch_offset(tl, vec2(0,0) ) * lcol * vec3_splat(tcol);
- vec3 br = fetch_offset(tl, one ) * rcol * vec3_splat(bcol);
- vec3 bl = fetch_offset(tl, vec2(0,one.y)) * lcol * vec3_splat(bcol);
- vec3 ur = fetch_offset(tl, vec2(one.x,0)) * rcol * vec3_splat(tcol);
-
- vec3 csum = ul + br + bl + ur;
- vec3 col = mul(mtxFromCols(u_rsubpix.rgb, u_gsubpix.rgb, u_bsubpix.rgb), csum);
- gl_FragColor = vec4(pow(col, vec3_splat(1.0/u_monitorgamma.x)), 1.0);
+ vec3 cr = pow(u_rsubpix.rgb, vec3_splat(u_monitorgamma.x));
+ vec3 cg = pow(u_gsubpix.rgb, vec3_splat(u_monitorgamma.x));
+ vec3 cb = pow(u_bsubpix.rgb, vec3_splat(u_monitorgamma.x));
+
+ vec2 tl = v_texcoord0 * u_tex_size0.xy - vec2(0.5,0.5);
+ vec2 tli = floor(tl);
+ float subpix = fract(tl.x) * 3.0;
+ float rsubpix = u_tex_size0.x / u_quad_dims.x * 3.0;
+
+ vec3 lcol, rcol;
+ lcol = vec3(intsmear_x(subpix+1.0, rsubpix, 3.0*u_subpixsize.x),
+ intsmear_x(subpix , rsubpix, 3.0*u_subpixsize.x),
+ intsmear_x(subpix-1.0, rsubpix, 3.0*u_subpixsize.x));
+ rcol = vec3(intsmear_x(subpix-2.0, rsubpix, 3.0*u_subpixsize.x),
+ intsmear_x(subpix-3.0, rsubpix, 3.0*u_subpixsize.x),
+ intsmear_x(subpix-4.0, rsubpix, 3.0*u_subpixsize.x));
+
+ if (u_BGR.x > 0.5) {
+ lcol.rgb = lcol.bgr;
+ rcol.rgb = rcol.bgr;
+ }
+
+ float tcol, bcol;
+ subpix = fract(tl.y);
+ rsubpix = u_tex_size0.y / u_quad_dims.y;
+ tcol = intsmear_y(subpix ,rsubpix, u_subpixsize.y);
+ bcol = intsmear_y(subpix-1.0,rsubpix, u_subpixsize.y);
+
+ tl = (tli + vec2_splat(0.5)) / u_tex_size0.xy;
+ vec2 one = vec2_splat(1.0) / u_tex_size0.xy;
+
+ vec3 ul = fetch_offset(tl, vec2(0,0) ) * lcol * vec3_splat(tcol);
+ vec3 br = fetch_offset(tl, one ) * rcol * vec3_splat(bcol);
+ vec3 bl = fetch_offset(tl, vec2(0,one.y)) * lcol * vec3_splat(bcol);
+ vec3 ur = fetch_offset(tl, vec2(one.x,0)) * rcol * vec3_splat(tcol);
+
+ vec3 csum = ul + br + bl + ur;
+ vec3 col = mul(mtxFromCols(u_rsubpix.rgb, u_gsubpix.rgb, u_bsubpix.rgb), csum);
+ gl_FragColor = vec4(pow(col, vec3_splat(1.0/u_monitorgamma.x)), 1.0);
}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/lcd-grid/fs_persistence.sc b/src/osd/modules/render/bgfx/shaders/chains/lcd-grid/fs_persistence.sc
index 0187b8c90d2..4c9e998d3ec 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/lcd-grid/fs_persistence.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/lcd-grid/fs_persistence.sc
@@ -9,8 +9,8 @@ uniform vec4 u_persistence;
void main()
{
- vec4 screen = texture2D(s_screen , v_texcoord0);
- vec4 motionblur = texture2D(s_motionblur, v_texcoord0);
+ vec4 screen = texture2D(s_screen , v_texcoord0);
+ vec4 motionblur = texture2D(s_motionblur, v_texcoord0);
- gl_FragColor = mix(screen, motionblur, u_persistence.x);
+ gl_FragColor = mix(screen, motionblur, u_persistence.x);
}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/lcd-grid/vs_lcd-grid.sc b/src/osd/modules/render/bgfx/shaders/chains/lcd-grid/vs_lcd-grid.sc
index 405ef8feb3b..df2b37f203c 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/lcd-grid/vs_lcd-grid.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/lcd-grid/vs_lcd-grid.sc
@@ -6,9 +6,14 @@ $output v_texcoord0, v_color0
#include "common.sh"
+uniform vec4 u_inv_view_dims;
+
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
v_color0 = a_color0;
}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/lcd-grid/vs_persistence.sc b/src/osd/modules/render/bgfx/shaders/chains/lcd-grid/vs_persistence.sc
index 405ef8feb3b..df2b37f203c 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/lcd-grid/vs_persistence.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/lcd-grid/vs_persistence.sc
@@ -6,9 +6,14 @@ $output v_texcoord0, v_color0
#include "common.sh"
+uniform vec4 u_inv_view_dims;
+
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
v_color0 = a_color0;
}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/misc/fs_deposterize-pass0.sc b/src/osd/modules/render/bgfx/shaders/chains/misc/fs_deposterize-pass0.sc
index 3e58af492c6..090485da1bc 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/misc/fs_deposterize-pass0.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/misc/fs_deposterize-pass0.sc
@@ -20,7 +20,7 @@ uniform vec4 DIFF_THRESH1;
vec3 df3(vec3 c1, vec3 c2)
{
- return abs(c1 - c2);
+ return abs(c1 - c2);
}
bvec3 le3(vec3 A, vec3 B, vec3 param)
diff --git a/src/osd/modules/render/bgfx/shaders/chains/misc/fs_deposterize-pass1.sc b/src/osd/modules/render/bgfx/shaders/chains/misc/fs_deposterize-pass1.sc
index 8fdd168a262..085f767358c 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/misc/fs_deposterize-pass1.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/misc/fs_deposterize-pass1.sc
@@ -20,7 +20,7 @@ uniform vec4 DIFF_THRESH2;
vec3 df3(vec3 c1, vec3 c2)
{
- return abs(c1 - c2);
+ return abs(c1 - c2);
}
bvec3 le3(vec3 A, vec3 B, vec3 param)
diff --git a/src/osd/modules/render/bgfx/shaders/chains/misc/vs_blit.sc b/src/osd/modules/render/bgfx/shaders/chains/misc/vs_blit.sc
index 405ef8feb3b..df2b37f203c 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/misc/vs_blit.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/misc/vs_blit.sc
@@ -6,9 +6,14 @@ $output v_texcoord0, v_color0
#include "common.sh"
+uniform vec4 u_inv_view_dims;
+
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
v_color0 = a_color0;
}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/misc/vs_bob-and-ghost-deinterlace.sc b/src/osd/modules/render/bgfx/shaders/chains/misc/vs_bob-and-ghost-deinterlace.sc
index 405ef8feb3b..df2b37f203c 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/misc/vs_bob-and-ghost-deinterlace.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/misc/vs_bob-and-ghost-deinterlace.sc
@@ -6,9 +6,14 @@ $output v_texcoord0, v_color0
#include "common.sh"
+uniform vec4 u_inv_view_dims;
+
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
v_color0 = a_color0;
}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/misc/vs_deposterize-pass0.sc b/src/osd/modules/render/bgfx/shaders/chains/misc/vs_deposterize-pass0.sc
index f46bf23b063..1ed054f1b9a 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/misc/vs_deposterize-pass0.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/misc/vs_deposterize-pass0.sc
@@ -14,10 +14,14 @@ $output v_texcoord0, v_texcoord1, v_color0
#include "common.sh"
uniform vec4 u_tex_size0;
+uniform vec4 u_inv_view_dims;
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
vec2 ps = vec2(1.0 / u_tex_size0.xy);
float dx = ps.x;
diff --git a/src/osd/modules/render/bgfx/shaders/chains/misc/vs_deposterize-pass1.sc b/src/osd/modules/render/bgfx/shaders/chains/misc/vs_deposterize-pass1.sc
index 486edf97c5c..69a23cb477c 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/misc/vs_deposterize-pass1.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/misc/vs_deposterize-pass1.sc
@@ -14,10 +14,14 @@ $output v_texcoord0, v_texcoord1, v_color0
#include "common.sh"
uniform vec4 u_tex_size0;
+uniform vec4 u_inv_view_dims;
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
vec2 ps = vec2(1.0 / u_tex_size0.xy);
float dx = ps.x;
diff --git a/src/osd/modules/render/bgfx/shaders/chains/misc/vs_lut.sc b/src/osd/modules/render/bgfx/shaders/chains/misc/vs_lut.sc
index 405ef8feb3b..df2b37f203c 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/misc/vs_lut.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/misc/vs_lut.sc
@@ -6,9 +6,14 @@ $output v_texcoord0, v_color0
#include "common.sh"
+uniform vec4 u_inv_view_dims;
+
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
v_color0 = a_color0;
}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/misc/vs_resize_blit.sc b/src/osd/modules/render/bgfx/shaders/chains/misc/vs_resize_blit.sc
new file mode 100644
index 00000000000..0a9f2f178e1
--- /dev/null
+++ b/src/osd/modules/render/bgfx/shaders/chains/misc/vs_resize_blit.sc
@@ -0,0 +1,21 @@
+$input a_position, a_texcoord0, a_color0
+$output v_texcoord0, v_color0
+
+// license:BSD-3-Clause
+// copyright-holders:Dario Manesku
+
+#include "common.sh"
+
+uniform vec4 u_inv_view_dims;
+uniform vec4 u_tex_bounds0;
+
+void main()
+{
+ gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
+
+ v_texcoord0 = a_texcoord0 * (u_tex_bounds0.zw - u_tex_bounds0.xy) + u_tex_bounds0.xy;
+ v_color0 = a_color0;
+}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/misc/vs_saturation.sc b/src/osd/modules/render/bgfx/shaders/chains/misc/vs_saturation.sc
index 405ef8feb3b..df2b37f203c 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/misc/vs_saturation.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/misc/vs_saturation.sc
@@ -6,9 +6,14 @@ $output v_texcoord0, v_color0
#include "common.sh"
+uniform vec4 u_inv_view_dims;
+
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
v_color0 = a_color0;
}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/pillarbox_left_horizontal/vs_gaussian.sc b/src/osd/modules/render/bgfx/shaders/chains/pillarbox_left_horizontal/vs_gaussian.sc
index 405ef8feb3b..df2b37f203c 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/pillarbox_left_horizontal/vs_gaussian.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/pillarbox_left_horizontal/vs_gaussian.sc
@@ -6,9 +6,14 @@ $output v_texcoord0, v_color0
#include "common.sh"
+uniform vec4 u_inv_view_dims;
+
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
v_color0 = a_color0;
}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/pillarbox_left_horizontal/vs_offset_sat.sc b/src/osd/modules/render/bgfx/shaders/chains/pillarbox_left_horizontal/vs_offset_sat.sc
index f071beaaa26..77d392ad813 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/pillarbox_left_horizontal/vs_offset_sat.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/pillarbox_left_horizontal/vs_offset_sat.sc
@@ -9,9 +9,14 @@ $output v_texcoord0, v_color0
#include "common.sh"
+uniform vec4 u_inv_view_dims;
+
void main()
{
- gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+ gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0 * vec2(0.16666666 * 0.9, 1.0 * 0.8) + vec2(0.1, 0.1);
v_color0 = a_color0;
-} \ No newline at end of file
+}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/pillarbox_left_vertical/vs_gaussian.sc b/src/osd/modules/render/bgfx/shaders/chains/pillarbox_left_vertical/vs_gaussian.sc
index 405ef8feb3b..df2b37f203c 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/pillarbox_left_vertical/vs_gaussian.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/pillarbox_left_vertical/vs_gaussian.sc
@@ -6,9 +6,14 @@ $output v_texcoord0, v_color0
#include "common.sh"
+uniform vec4 u_inv_view_dims;
+
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
v_color0 = a_color0;
}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/pillarbox_left_vertical/vs_offset_sat.sc b/src/osd/modules/render/bgfx/shaders/chains/pillarbox_left_vertical/vs_offset_sat.sc
index a9f6649c1e5..6d47076f992 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/pillarbox_left_vertical/vs_offset_sat.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/pillarbox_left_vertical/vs_offset_sat.sc
@@ -9,9 +9,14 @@ $output v_texcoord0, v_color0
#include "common.sh"
+uniform vec4 u_inv_view_dims;
+
void main()
{
- gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+ gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0 * vec2(1.0 * 0.8, 0.685185 * 0.9) + vec2(0.1, 0.1);
v_color0 = a_color0;
-} \ No newline at end of file
+}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/pillarbox_right_horizontal/vs_gaussian.sc b/src/osd/modules/render/bgfx/shaders/chains/pillarbox_right_horizontal/vs_gaussian.sc
index 405ef8feb3b..df2b37f203c 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/pillarbox_right_horizontal/vs_gaussian.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/pillarbox_right_horizontal/vs_gaussian.sc
@@ -6,9 +6,14 @@ $output v_texcoord0, v_color0
#include "common.sh"
+uniform vec4 u_inv_view_dims;
+
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
v_color0 = a_color0;
}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/pillarbox_right_horizontal/vs_offset_sat.sc b/src/osd/modules/render/bgfx/shaders/chains/pillarbox_right_horizontal/vs_offset_sat.sc
index a473bc4123c..403b880b5ec 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/pillarbox_right_horizontal/vs_offset_sat.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/pillarbox_right_horizontal/vs_offset_sat.sc
@@ -9,9 +9,14 @@ $output v_texcoord0, v_color0
#include "common.sh"
+uniform vec4 u_inv_view_dims;
+
void main()
{
- gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+ gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0 * vec2(0.16666666 * 0.9, 1.0 * 0.8) + vec2(0.9 - 0.16666666 * 0.9, 0.1);
v_color0 = a_color0;
-} \ No newline at end of file
+}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/pillarbox_right_vertical/vs_gaussian.sc b/src/osd/modules/render/bgfx/shaders/chains/pillarbox_right_vertical/vs_gaussian.sc
index 405ef8feb3b..df2b37f203c 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/pillarbox_right_vertical/vs_gaussian.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/pillarbox_right_vertical/vs_gaussian.sc
@@ -6,9 +6,14 @@ $output v_texcoord0, v_color0
#include "common.sh"
+uniform vec4 u_inv_view_dims;
+
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
v_color0 = a_color0;
}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/pillarbox_right_vertical/vs_offset_sat.sc b/src/osd/modules/render/bgfx/shaders/chains/pillarbox_right_vertical/vs_offset_sat.sc
index 8af6a293d8e..7121ae6651c 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/pillarbox_right_vertical/vs_offset_sat.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/pillarbox_right_vertical/vs_offset_sat.sc
@@ -9,9 +9,14 @@ $output v_texcoord0, v_color0
#include "common.sh"
+uniform vec4 u_inv_view_dims;
+
void main()
{
- gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+ gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0 * vec2(1.0 * 0.8, 0.685185 * 0.9) + vec2(0.1, 0.9 - 0.685185 * 0.9);
v_color0 = a_color0;
-} \ No newline at end of file
+}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/unfiltered/vs_blit.sc b/src/osd/modules/render/bgfx/shaders/chains/unfiltered/vs_blit.sc
index 405ef8feb3b..df2b37f203c 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/unfiltered/vs_blit.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/unfiltered/vs_blit.sc
@@ -6,9 +6,14 @@ $output v_texcoord0, v_color0
#include "common.sh"
+uniform vec4 u_inv_view_dims;
+
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
v_color0 = a_color0;
}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/warp/vs_dilation-horizontal-fast.sc b/src/osd/modules/render/bgfx/shaders/chains/warp/vs_dilation-horizontal-fast.sc
index 9433c8359be..52e0fc2ae90 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/warp/vs_dilation-horizontal-fast.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/warp/vs_dilation-horizontal-fast.sc
@@ -32,10 +32,14 @@ $output v_texcoord0, v_texcoord1, v_color0
#include "common.sh"
uniform vec4 u_tex_size0;
+uniform vec4 u_inv_view_dims;
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
vec2 ps = 1.0 / u_tex_size0.xy;
@@ -45,7 +49,7 @@ void main()
// D E F
// H
- v_texcoord1 = vec4(1.0 / u_tex_size0.xy, 0.0, 0.0); // F H
+ v_texcoord1 = vec4(1.0 / u_tex_size0.xy, 0.0, 0.0); // F H
v_color0 = a_color0;
}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/fs_custom-jinc2-sharper.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/fs_custom-jinc2-sharper.sc
index fdf14bd393b..fd9a2d72f94 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/fs_custom-jinc2-sharper.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/fs_custom-jinc2-sharper.sc
@@ -18,11 +18,11 @@ uniform vec4 u_tex_size0;
SAMPLER2D(s_p, 0);
- /*
- This is an approximation of Jinc(x)*Jinc(x*r1/r2) for x < 2.5,
- where r1 and r2 are the first two zeros of jinc function.
- For a jinc 2-lobe best approximation, use A=0.5 and B=0.825.
- */
+/*
+ This is an approximation of Jinc(x)*Jinc(x*r1/r2) for x < 2.5,
+ where r1 and r2 are the first two zeros of jinc function.
+ For a jinc 2-lobe best approximation, use A=0.5 and B=0.825.
+*/
// A=0.5, B=0.825 is the best jinc approximation for x<2.5. if B=1.0, it's a lanczos filter.
// Increase A to get more blur. Decrease it to get a sharper picture.
@@ -47,12 +47,12 @@ float d(vec2 pt1, vec2 pt2)
vec4 min4(vec4 a, vec4 b, vec4 c, vec4 d)
{
- return min(a, min(b, min(c, d)));
+ return min(a, min(b, min(c, d)));
}
vec4 max4(vec4 a, vec4 b, vec4 c, vec4 d)
{
- return max(a, max(b, max(c, d)));
+ return max(a, max(b, max(c, d)));
}
vec4 resampler(vec4 x)
diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/fs_super-2xbr-3d-pass0.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/fs_super-2xbr-3d-pass0.sc
index 9e5520740c2..fdb38420261 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/fs_super-2xbr-3d-pass0.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/fs_super-2xbr-3d-pass0.sc
@@ -95,23 +95,23 @@ float hv_wd(float i1, float i2, float i3, float i4, float e1, float e2, float e3
vec4 min4(vec4 a, vec4 b, vec4 c, vec4 d)
{
- return min(a, min(b, min(c, d)));
+ return min(a, min(b, min(c, d)));
}
vec4 max4(vec4 a, vec4 b, vec4 c, vec4 d)
{
- return max(a, max(b, max(c, d)));
+ return max(a, max(b, max(c, d)));
}
void main()
{
//Skip pixels on wrong grid
vec2 fraction = fract(v_texcoord0 * u_tex_size0.xy / XBR_RES);
- if (fraction.x < 0.5 || fraction.y < 0.5)
- {
- gl_FragColor = texture2D(s0, v_texcoord0);
- return;
- }
+ if (fraction.x < 0.5 || fraction.y < 0.5)
+ {
+ gl_FragColor = texture2D(s0, v_texcoord0);
+ return;
+ }
vec2 tex = (floor(v_texcoord0 * u_tex_size0.xy / XBR_RES) + vec2(0.5, 0.5)) * XBR_RES / u_tex_size0.xy;
diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_custom-jinc2-sharper.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_custom-jinc2-sharper.sc
index 405ef8feb3b..df2b37f203c 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_custom-jinc2-sharper.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_custom-jinc2-sharper.sc
@@ -6,9 +6,14 @@ $output v_texcoord0, v_color0
#include "common.sh"
+uniform vec4 u_inv_view_dims;
+
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
v_color0 = a_color0;
}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-2xbr-3d-pass0.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-2xbr-3d-pass0.sc
index 405ef8feb3b..df2b37f203c 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-2xbr-3d-pass0.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-2xbr-3d-pass0.sc
@@ -6,9 +6,14 @@ $output v_texcoord0, v_color0
#include "common.sh"
+uniform vec4 u_inv_view_dims;
+
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
v_color0 = a_color0;
}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-2xbr-3d-pass1.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-2xbr-3d-pass1.sc
index 405ef8feb3b..df2b37f203c 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-2xbr-3d-pass1.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-2xbr-3d-pass1.sc
@@ -6,9 +6,14 @@ $output v_texcoord0, v_color0
#include "common.sh"
+uniform vec4 u_inv_view_dims;
+
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
v_color0 = a_color0;
}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-2xbr-3d-pass2.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-2xbr-3d-pass2.sc
index 1c3ee6a8f23..335c9ef8b4c 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-2xbr-3d-pass2.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-2xbr-3d-pass2.sc
@@ -33,10 +33,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_texcoord4, v_color
#include "common.sh"
uniform vec4 u_tex_size0;
+uniform vec4 u_inv_view_dims;
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
vec2 ps = 1.0 / u_tex_size0.xy;
diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-4xbr-3d-pass0.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-4xbr-3d-pass0.sc
index 405ef8feb3b..df2b37f203c 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-4xbr-3d-pass0.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-4xbr-3d-pass0.sc
@@ -6,9 +6,14 @@ $output v_texcoord0, v_color0
#include "common.sh"
+uniform vec4 u_inv_view_dims;
+
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
v_color0 = a_color0;
}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-4xbr-3d-pass1.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-4xbr-3d-pass1.sc
index 405ef8feb3b..df2b37f203c 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-4xbr-3d-pass1.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-4xbr-3d-pass1.sc
@@ -6,9 +6,14 @@ $output v_texcoord0, v_color0
#include "common.sh"
+uniform vec4 u_inv_view_dims;
+
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
v_color0 = a_color0;
}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-4xbr-3d-pass1f.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-4xbr-3d-pass1f.sc
index c5bd41ee120..338cadbe4b7 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-4xbr-3d-pass1f.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-4xbr-3d-pass1f.sc
@@ -7,10 +7,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_texcoord4, v_color
#include "common.sh"
uniform vec4 u_tex_size0;
+uniform vec4 u_inv_view_dims;
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
vec2 ps = 1.0 / u_tex_size0.xy;
diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-4xbr-3d-pass2.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-4xbr-3d-pass2.sc
index 405ef8feb3b..df2b37f203c 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-4xbr-3d-pass2.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-4xbr-3d-pass2.sc
@@ -6,9 +6,14 @@ $output v_texcoord0, v_color0
#include "common.sh"
+uniform vec4 u_inv_view_dims;
+
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
v_color0 = a_color0;
}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-4xbr-3d-pass3.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-4xbr-3d-pass3.sc
index 405ef8feb3b..df2b37f203c 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-4xbr-3d-pass3.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-4xbr-3d-pass3.sc
@@ -6,9 +6,14 @@ $output v_texcoord0, v_color0
#include "common.sh"
+uniform vec4 u_inv_view_dims;
+
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
v_color0 = a_color0;
}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-4xbr-3d-pass3f.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-4xbr-3d-pass3f.sc
index c5bd41ee120..338cadbe4b7 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-4xbr-3d-pass3f.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-4xbr-3d-pass3f.sc
@@ -7,10 +7,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_texcoord4, v_color
#include "common.sh"
uniform vec4 u_tex_size0;
+uniform vec4 u_inv_view_dims;
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
vec2 ps = 1.0 / u_tex_size0.xy;
diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-fast-pass0.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-fast-pass0.sc
index 5827f1999b8..21e16b595e4 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-fast-pass0.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-fast-pass0.sc
@@ -32,9 +32,14 @@ $output v_texcoord0, v_color0
#include "common.sh"
+uniform vec4 u_inv_view_dims;
+
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
v_color0 = a_color0;
}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-fast-pass1.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-fast-pass1.sc
index 60637684154..fc33723ec9d 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-fast-pass1.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-fast-pass1.sc
@@ -32,9 +32,14 @@ $output v_texcoord0, v_color0
#include "common.sh"
+uniform vec4 u_inv_view_dims;
+
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
v_color0 = a_color0;
}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-fast-pass2.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-fast-pass2.sc
index 2cfe541e2b8..a8ec5539c0b 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-fast-pass2.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-fast-pass2.sc
@@ -32,9 +32,14 @@ $output v_texcoord0, v_color0
#include "common.sh"
+uniform vec4 u_inv_view_dims;
+
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
v_color0 = a_color0;
}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-pass0.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-pass0.sc
index d10c9c24665..8352137204e 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-pass0.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-pass0.sc
@@ -33,10 +33,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_texcoord4, v_color
#include "common.sh"
uniform vec4 u_tex_size0;
+uniform vec4 u_inv_view_dims;
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
vec2 ps = 1.0 / u_tex_size0.xy;
diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-pass1.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-pass1.sc
index 5827f1999b8..21e16b595e4 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-pass1.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-pass1.sc
@@ -32,9 +32,14 @@ $output v_texcoord0, v_color0
#include "common.sh"
+uniform vec4 u_inv_view_dims;
+
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
v_color0 = a_color0;
}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-pass2.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-pass2.sc
index 9ae87c8a7ea..8f2d3277665 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-pass2.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-pass2.sc
@@ -33,10 +33,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_texcoord4, v_color
#include "common.sh"
uniform vec4 u_tex_size0;
+uniform vec4 u_inv_view_dims;
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
vec2 ps = 1.0 / u_tex_size0.xy;
diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-pass3.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-pass3.sc
index 9ae87c8a7ea..8f2d3277665 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-pass3.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-pass3.sc
@@ -33,10 +33,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_texcoord4, v_color
#include "common.sh"
uniform vec4 u_tex_size0;
+uniform vec4 u_inv_view_dims;
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
vec2 ps = 1.0 / u_tex_size0.xy;
diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv1-noblend.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv1-noblend.sc
index 3e97446a880..de23993d020 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv1-noblend.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv1-noblend.sc
@@ -7,10 +7,14 @@ $output v_texcoord0, v_texcoord1, v_color0
#include "common.sh"
uniform vec4 u_tex_size0;
+uniform vec4 u_inv_view_dims;
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
vec2 ps = 1.0 / u_tex_size0.xy;
diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv2-3d.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv2-3d.sc
index a3bb4330f45..7992b9eee51 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv2-3d.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv2-3d.sc
@@ -9,10 +9,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_texcoord4, v_texco
uniform vec4 XBR_RES;
uniform vec4 u_tex_size0;
+uniform vec4 u_inv_view_dims;
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
vec2 ps = XBR_RES.xx / u_tex_size0.xy;
diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv2-fast.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv2-fast.sc
index 38e92865308..48e9664b766 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv2-fast.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv2-fast.sc
@@ -7,10 +7,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_color0
#include "common.sh"
uniform vec4 u_tex_size0;
+uniform vec4 u_inv_view_dims;
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
// A1 B1 C1
diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv2-noblend.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv2-noblend.sc
index cfc1a7cfc47..5bcf3e31f5a 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv2-noblend.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv2-noblend.sc
@@ -33,10 +33,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_texcoord4, v_texco
#include "common.sh"
uniform vec4 u_tex_size0;
+uniform vec4 u_inv_view_dims;
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
// A1 B1 C1
diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv2.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv2.sc
index ce6e411b75d..22e993426ed 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv2.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv2.sc
@@ -7,10 +7,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_texcoord4, v_texco
#include "common.sh"
uniform vec4 u_tex_size0;
+uniform vec4 u_inv_view_dims;
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
vec2 ps = 1.0 / u_tex_size0.xy;
diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv3-noblend.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv3-noblend.sc
index 114f1669ad1..5957004443c 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv3-noblend.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv3-noblend.sc
@@ -33,10 +33,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_texcoord4, v_texco
#include "common.sh"
uniform vec4 u_tex_size0;
+uniform vec4 u_inv_view_dims;
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
// A1 B1 C1
diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv3.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv3.sc
index 3d72da14478..a5ee8cee547 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv3.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv3.sc
@@ -33,10 +33,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_texcoord4, v_texco
#include "common.sh"
uniform vec4 u_tex_size0;
+uniform vec4 u_inv_view_dims;
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
// A1 B1 C1
diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-sharp.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-sharp.sc
index c09b7b66d1c..35cc742cff1 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-sharp.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-sharp.sc
@@ -43,10 +43,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_texcoord4, v_texco
#include "common.sh"
uniform vec4 u_tex_size0;
+uniform vec4 u_inv_view_dims;
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
vec2 ps = 1.0 / u_tex_size0.xy;
diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-v2-gamma.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-v2-gamma.sc
index 2be09e52908..3a9b0e56b1c 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-v2-gamma.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-v2-gamma.sc
@@ -43,10 +43,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_texcoord4, v_texco
#include "common.sh"
uniform vec4 u_tex_size0;
+uniform vec4 u_inv_view_dims;
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
vec2 ps = 1.0 / u_tex_size0.xy;
diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-v2.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-v2.sc
index 2ec42c6585d..c08e3988e24 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-v2.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-v2.sc
@@ -43,10 +43,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_texcoord4, v_texco
#include "common.sh"
uniform vec4 u_tex_size0;
+uniform vec4 u_inv_view_dims;
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
vec2 ps = 1.0 / u_tex_size0.xy;
diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-v4-gamma.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-v4-gamma.sc
index f40310aa1b9..8c2b0aec4cd 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-v4-gamma.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-v4-gamma.sc
@@ -43,10 +43,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_texcoord4, v_texco
#include "common.sh"
uniform vec4 u_tex_size0;
+uniform vec4 u_inv_view_dims;
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
vec2 ps = 1.0 / u_tex_size0.xy;
diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-v4.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-v4.sc
index e363aba2eb4..d7328857ffd 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-v4.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-v4.sc
@@ -43,10 +43,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_texcoord4, v_texco
#include "common.sh"
uniform vec4 u_tex_size0;
+uniform vec4 u_inv_view_dims;
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
vec2 ps = 1.0 / u_tex_size0.xy;
diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-v4b.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-v4b.sc
index 8f9c58be4c1..48ebe4f0a54 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-v4b.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-v4b.sc
@@ -43,10 +43,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_texcoord4, v_texco
#include "common.sh"
uniform vec4 u_tex_size0;
+uniform vec4 u_inv_view_dims;
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
vec2 ps = 1.0 / u_tex_size0.xy;
diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-v5-gamma.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-v5-gamma.sc
index f40310aa1b9..8c2b0aec4cd 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-v5-gamma.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-v5-gamma.sc
@@ -43,10 +43,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_texcoord4, v_texco
#include "common.sh"
uniform vec4 u_tex_size0;
+uniform vec4 u_inv_view_dims;
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
vec2 ps = 1.0 / u_tex_size0.xy;
diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid.sc
index c09b7b66d1c..35cc742cff1 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid.sc
@@ -43,10 +43,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_texcoord4, v_texco
#include "common.sh"
uniform vec4 u_tex_size0;
+uniform vec4 u_inv_view_dims;
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
vec2 ps = 1.0 / u_tex_size0.xy;
diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-a-pass0.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-a-pass0.sc
index 59ffb0a026a..15490257390 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-a-pass0.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-a-pass0.sc
@@ -34,10 +34,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_texcoord4, v_texco
#include "common.sh"
uniform vec4 u_tex_size0;
+uniform vec4 u_inv_view_dims;
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
// A1 B1 C1
diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-accuracy-pass0.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-accuracy-pass0.sc
index 5c20062823a..f63eb7b2391 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-accuracy-pass0.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-accuracy-pass0.sc
@@ -33,10 +33,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_texcoord4, v_texco
#include "common.sh"
uniform vec4 u_tex_size0;
+uniform vec4 u_inv_view_dims;
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
// A1 B1 C1
diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-accuracy-pass1.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-accuracy-pass1.sc
index fbb10ec9ea5..db8c513319b 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-accuracy-pass1.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-accuracy-pass1.sc
@@ -33,10 +33,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_color0
#include "common.sh"
uniform vec4 u_tex_size1;
+uniform vec4 u_inv_view_dims;
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
// A1 B1 C1
diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-b-pass0.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-b-pass0.sc
index afdcf872331..0c317f16cc7 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-b-pass0.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-b-pass0.sc
@@ -34,10 +34,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_texcoord4, v_texco
#include "common.sh"
uniform vec4 u_tex_size0;
+uniform vec4 u_inv_view_dims;
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
// A1 B1 C1
diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-c-pass0.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-c-pass0.sc
index ba0da15a70d..fbcf72fd706 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-c-pass0.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-c-pass0.sc
@@ -34,10 +34,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_texcoord4, v_texco
#include "common.sh"
uniform vec4 u_tex_size0;
+uniform vec4 u_inv_view_dims;
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
// A1 B1 C1
diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-d-pass0.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-d-pass0.sc
index bfd5e4a6414..e75cc78ac8c 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-d-pass0.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-d-pass0.sc
@@ -34,10 +34,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_texcoord4, v_texco
#include "common.sh"
uniform vec4 u_tex_size0;
+uniform vec4 u_inv_view_dims;
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
// A1 B1 C1
diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-noblend-pass1.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-noblend-pass1.sc
index b85cca1828d..56cebbd6540 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-noblend-pass1.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-noblend-pass1.sc
@@ -32,10 +32,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_color0
#include "common.sh"
uniform vec4 u_tex_size1;
+uniform vec4 u_inv_view_dims;
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
// A1 B1 C1
diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-pass1.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-pass1.sc
index 11042eab09a..c35e62e81ac 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-pass1.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-pass1.sc
@@ -34,10 +34,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_color0
#include "common.sh"
uniform vec4 u_tex_size1;
+uniform vec4 u_inv_view_dims;
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
// A1 B1 C1
diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv3-multipass/fs_xbr-lv3-pass0.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv3-multipass/fs_xbr-lv3-pass0.sc
index 4331c2353f6..229f2f93936 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv3-multipass/fs_xbr-lv3-pass0.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv3-multipass/fs_xbr-lv3-pass0.sc
@@ -120,7 +120,7 @@ vec4 weighted_distance(vec4 a, vec4 b, vec4 c, vec4 d, vec4 e, vec4 f, vec4 g, v
LEFT = UP = LEFT3 = UP3 = 0.0; \
PX0 = vec2(0.0, PX); \
LIN0 = vec4(0.0, 0.0, 0.0, 0.0); \
- } \
+ }
diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv3-multipass/vs_xbr-lv3-pass0.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv3-multipass/vs_xbr-lv3-pass0.sc
index 80dd11d7ad9..8ae8f8df41c 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv3-multipass/vs_xbr-lv3-pass0.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv3-multipass/vs_xbr-lv3-pass0.sc
@@ -34,10 +34,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_texcoord4, v_texco
#include "common.sh"
uniform vec4 u_tex_size0;
+uniform vec4 u_inv_view_dims;
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
// A1 B1 C1
diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv3-multipass/vs_xbr-lv3-pass1.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv3-multipass/vs_xbr-lv3-pass1.sc
index 7932ba25f15..439005d2941 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv3-multipass/vs_xbr-lv3-pass1.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv3-multipass/vs_xbr-lv3-pass1.sc
@@ -32,10 +32,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_color0
uniform vec4 u_tex_size1;
uniform vec4 u_target_dims;
+uniform vec4 u_inv_view_dims;
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
// A3 B3 C3
diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-mlv4-multipass/fs_xbr-mlv4-pass4.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-mlv4-multipass/fs_xbr-mlv4-pass4.sc
index c37c512a7f6..bdd9f5b31db 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-mlv4-multipass/fs_xbr-mlv4-pass4.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-mlv4-multipass/fs_xbr-mlv4-pass4.sc
@@ -110,7 +110,7 @@ vec3 color_mix(vec3 c, vec3 color, vec3 E)
ax.x = round(info); \
iq.x = dot(ax, bin) - 2.0; \
iq.y = dot(ay, bin) - 2.0; \
- PIXEL = texture2D(ORIG_texture, v_texcoord0 + iq.x * v_texcoord1.xy + iq.y * v_texcoord1.zw).xyz; \
+ PIXEL = texture2D(ORIG_texture, v_texcoord0 + iq.x * v_texcoord1.xy + iq.y * v_texcoord1.zw).xyz;
void main()
diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-mlv4-multipass/vs_xbr-mlv4-pass1.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-mlv4-multipass/vs_xbr-mlv4-pass1.sc
index 1edfd8632ad..24f3b396cc2 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-mlv4-multipass/vs_xbr-mlv4-pass1.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-mlv4-multipass/vs_xbr-mlv4-pass1.sc
@@ -33,10 +33,14 @@ $output v_texcoord0, v_texcoord1, v_color0
#include "common.sh"
uniform vec4 u_tex_size0;
+uniform vec4 u_inv_view_dims;
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
// A3 B3 C3
diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-mlv4-multipass/vs_xbr-mlv4-pass2.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-mlv4-multipass/vs_xbr-mlv4-pass2.sc
index 92cf6b60b87..1d67bb87ebe 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-mlv4-multipass/vs_xbr-mlv4-pass2.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-mlv4-multipass/vs_xbr-mlv4-pass2.sc
@@ -33,10 +33,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_texcoord4, v_texco
#include "common.sh"
uniform vec4 u_tex_size0;
+uniform vec4 u_inv_view_dims;
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
// A1 B1 C1
diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-mlv4-multipass/vs_xbr-mlv4-pass3.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-mlv4-multipass/vs_xbr-mlv4-pass3.sc
index a6926a41f8b..2c85859340b 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-mlv4-multipass/vs_xbr-mlv4-pass3.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-mlv4-multipass/vs_xbr-mlv4-pass3.sc
@@ -33,10 +33,14 @@ $output v_texcoord0, v_texcoord1, v_color0
#include "common.sh"
uniform vec4 u_tex_size1;
+uniform vec4 u_inv_view_dims;
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
// A3 B3 C3
diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-mlv4-multipass/vs_xbr-mlv4-pass4.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-mlv4-multipass/vs_xbr-mlv4-pass4.sc
index 29fec2f1759..5e62a75a12e 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-mlv4-multipass/vs_xbr-mlv4-pass4.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-mlv4-multipass/vs_xbr-mlv4-pass4.sc
@@ -33,10 +33,14 @@ $output v_texcoord0, v_texcoord1, v_color0
#include "common.sh"
uniform vec4 u_tex_size1;
+uniform vec4 u_inv_view_dims;
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
// A3 B3 C3
diff --git a/src/osd/modules/render/bgfx/shaders/vs_gui.sc b/src/osd/modules/render/bgfx/shaders/vs_gui.sc
index 405ef8feb3b..df2b37f203c 100644
--- a/src/osd/modules/render/bgfx/shaders/vs_gui.sc
+++ b/src/osd/modules/render/bgfx/shaders/vs_gui.sc
@@ -6,9 +6,14 @@ $output v_texcoord0, v_color0
#include "common.sh"
+uniform vec4 u_inv_view_dims;
+
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
v_color0 = a_color0;
}
diff --git a/src/osd/modules/render/bgfx/shaders/vs_screen.sc b/src/osd/modules/render/bgfx/shaders/vs_screen.sc
index 405ef8feb3b..df2b37f203c 100644
--- a/src/osd/modules/render/bgfx/shaders/vs_screen.sc
+++ b/src/osd/modules/render/bgfx/shaders/vs_screen.sc
@@ -6,9 +6,14 @@ $output v_texcoord0, v_color0
#include "common.sh"
+uniform vec4 u_inv_view_dims;
+
void main()
{
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300
+ gl_Position.xy += u_inv_view_dims.xy * gl_Position.w;
+#endif
v_texcoord0 = a_texcoord0;
v_color0 = a_color0;
}
diff --git a/src/osd/modules/render/bgfx/slider.cpp b/src/osd/modules/render/bgfx/slider.cpp
index 452c934fd37..dcd64c0c865 100644
--- a/src/osd/modules/render/bgfx/slider.cpp
+++ b/src/osd/modules/render/bgfx/slider.cpp
@@ -11,8 +11,10 @@
#include "strformat.h"
-bgfx_slider::bgfx_slider(running_machine &machine, std::string name, float min, float def, float max, float step, slider_type type, screen_type screen, std::string format, std::string description, std::vector<std::string>& strings)
- : m_name(name)
+#include <utility>
+
+bgfx_slider::bgfx_slider(running_machine &machine, std::string &&name, float min, float def, float max, float step, slider_type type, screen_type screen, std::string format, std::string description, std::vector<std::string>& strings)
+ : m_name(std::move(name))
, m_step(step)
, m_type(type)
, m_screen_type(screen)
diff --git a/src/osd/modules/render/bgfx/slider.h b/src/osd/modules/render/bgfx/slider.h
index d7815765c34..89a713da4b3 100644
--- a/src/osd/modules/render/bgfx/slider.h
+++ b/src/osd/modules/render/bgfx/slider.h
@@ -6,14 +6,15 @@
//
//============================================================
-#pragma once
+#ifndef MAME_RENDER_BGFX_SLIDER_H
+#define MAME_RENDER_BGFX_SLIDER_H
-#ifndef __DRAWBGFX_SLIDER__
-#define __DRAWBGFX_SLIDER__
+#pragma once
#include <bgfx/bgfx.h>
#include <cmath>
+#include <cstdint>
#include <memory>
#include <string>
#include <vector>
@@ -46,16 +47,19 @@ public:
SLIDER_SCREEN_TYPE_ANY = SLIDER_SCREEN_TYPE_RASTER | SLIDER_SCREEN_TYPE_VECTOR | SLIDER_SCREEN_TYPE_LCD
};
- bgfx_slider(running_machine& machine, std::string name, float min, float def, float max, float step, slider_type type, screen_type screen, std::string format, std::string description, std::vector<std::string>& strings);
+ bgfx_slider(running_machine& machine, std::string &&name, float min, float def, float max, float step, slider_type type, screen_type screen, std::string format, std::string description, std::vector<std::string>& strings);
virtual ~bgfx_slider();
int32_t update(std::string *str, int32_t newval);
// Getters
- std::string name() const { return m_name; }
+ const std::string &name() const { return m_name; }
slider_type type() const { return m_type; }
float value() const { return m_value; }
float uniform_value() const { return float(m_value); }
+ float min_value() const { return m_min; }
+ float default_value() const { return m_default; }
+ float max_value() const { return m_max; }
slider_state *core_slider() const { return m_slider_state.get(); }
size_t size() const { return get_size_for_type(m_type); }
static size_t get_size_for_type(slider_type type);
@@ -82,4 +86,4 @@ protected:
running_machine&m_machine;
};
-#endif // __DRAWBGFX_SLIDER__
+#endif // MAME_RENDER_BGFX_SLIDER_H
diff --git a/src/osd/modules/render/bgfx/sliderreader.cpp b/src/osd/modules/render/bgfx/sliderreader.cpp
index 208bc241559..96ff2511c96 100644
--- a/src/osd/modules/render/bgfx/sliderreader.cpp
+++ b/src/osd/modules/render/bgfx/sliderreader.cpp
@@ -33,7 +33,7 @@ const slider_reader::string_to_enum slider_reader::SCREEN_NAMES[slider_reader::S
{ "all", uint64_t(bgfx_slider::screen_type::SLIDER_SCREEN_TYPE_ANY) }
};
-std::vector<bgfx_slider*> slider_reader::read_from_value(const Value& value, std::string prefix, chain_manager& chains, uint32_t screen_index)
+std::vector<bgfx_slider*> slider_reader::read_from_value(const Value& value, const std::string &prefix, chain_manager& chains, uint32_t screen_index)
{
std::vector<bgfx_slider*> sliders;
@@ -55,7 +55,7 @@ std::vector<bgfx_slider*> slider_reader::read_from_value(const Value& value, std
const Value& string_array = value["strings"];
for (uint32_t i = 0; i < string_array.Size(); i++)
{
- if (!READER_CHECK(string_array[i].IsString(), (prefix + "Slider '" + name + "': strings[" + std::to_string(i) + "]: must be a string\n").c_str()))
+ if (!READER_CHECK(string_array[i].IsString(), "%sSlider '%s': strings[%u]: must be a string\n", prefix, name, i))
{
return sliders;
}
@@ -82,18 +82,22 @@ std::vector<bgfx_slider*> slider_reader::read_from_value(const Value& value, std
break;
}
- std::string prefixed_desc = "Window " + std::to_string(chains.window_index()) + ", Screen " + std::to_string(screen_index) + ", " + description;
+ std::string prefixed_desc = util::string_format("Window %1$u, Screen %2$u, %3$s", chains.window_index(), screen_index, description);
if (slider_count > 1)
{
+ if (!READER_CHECK(value["min"].IsArray(), "%1$sSlider '%2$s': value 'min' must be an array", prefix, name))
+ return sliders;
+ if (!READER_CHECK(value["default"].IsArray(), "%1$sSlider '%2$s': value 'default' must be an array", prefix, name))
+ return sliders;
+ if (!READER_CHECK(value["max"].IsArray(), "%1$sSlider '%2$s': value 'max' must be an array", prefix, name))
+ return sliders;
+
float min[3];
float defaults[3];
float max[3];
- if (!READER_CHECK(value["min"].IsArray(), (prefix + "Slider '" + name + "': value 'min' must be an array\n").c_str())) return sliders;
- if (!READER_CHECK(value["default"].IsArray(), (prefix + "Slider '" + name + "': value 'default' must be an array\n").c_str())) return sliders;
- if (!READER_CHECK(value["max"].IsArray(), (prefix + "Slider '" + name + "': value 'max' must be an array\n").c_str())) return sliders;
- get_values(value, prefix + "Slider '" + name + "': 'min': ", "min", min, slider_count);
- get_values(value, prefix + "Slider '" + name + "': 'default': ", "default", defaults, slider_count);
- get_values(value, prefix + "Slider '" + name + "': 'max': ", "max", max, slider_count);
+ get_values(value, util::string_format("%1$sSlider '%2$s': 'min': ", prefix, name), "min", min, slider_count);
+ get_values(value, util::string_format("%1$sSlider '%2$s': 'default': ", prefix, name), "default", defaults, slider_count);
+ get_values(value, util::string_format("%1$sSlider '%2$s': 'max': ", prefix, name), "max", max, slider_count);
for (int index = 0; index < slider_count; index++)
{
std::string desc;
@@ -113,51 +117,50 @@ std::vector<bgfx_slider*> slider_reader::read_from_value(const Value& value, std
desc = prefixed_desc + "Invalid";
break;
}
- sliders.push_back(new bgfx_slider(chains.machine(), full_name, min[index], defaults[index], max[index], step, type, screen_type, format, desc, strings));
+ sliders.push_back(new bgfx_slider(chains.machine(), std::move(full_name), min[index], defaults[index], max[index], step, type, screen_type, format, desc, strings));
}
}
else
{
- float min = get_float(value, "min", 0.0f);
- float def = get_float(value, "default", 0.0f);
- float max = get_float(value, "max", 1.0f);
+ const float min = get_float(value, "min", 0.0f);
+ const float def = get_float(value, "default", 0.0f);
+ const float max = get_float(value, "max", 1.0f);
sliders.push_back(new bgfx_slider(chains.machine(), name + "0", min, def, max, step, type, screen_type, format, prefixed_desc, strings));
}
return sliders;
}
-bool slider_reader::get_values(const Value& value, std::string prefix, std::string name, float* values, const int count)
+bool slider_reader::get_values(const Value& value, const std::string &prefix, const std::string &name, float* values, const int count)
{
- const char* name_str = name.c_str();
- const Value& value_array = value[name_str];
+ const Value& value_array = value[name.c_str()];
for (uint32_t i = 0; i < value_array.Size() && i < count; i++)
{
- if (!READER_CHECK(value_array[i].IsNumber(), (prefix + "Entry " + std::to_string(i) + " must be a number\n").c_str())) return false;
+ if (!READER_CHECK(value_array[i].IsNumber(), "%sEntry %u must be a number\n", prefix, i)) return false;
values[i] = value_array[i].GetFloat();
}
return true;
}
-bool slider_reader::validate_parameters(const Value& value, std::string prefix)
+bool slider_reader::validate_parameters(const Value& value, const std::string &prefix)
{
- if (!READER_CHECK(value.HasMember("name"), (prefix + "Must have string value 'name'\n").c_str())) return false;
- if (!READER_CHECK(value["name"].IsString(), (prefix + "Value 'name' must be a string\n").c_str())) return false;
- if (!READER_CHECK(value.HasMember("min"), (prefix + "Must have a number or array value 'min'\n").c_str())) return false;
- if (!READER_CHECK(value["min"].IsNumber() || value["min"].IsArray(), (prefix + "Value 'min' must be a number or an array the size of the corresponding slider type\n").c_str())) return false;
- if (!READER_CHECK(value.HasMember("default"), (prefix + "Must have a number or array value 'default'\n").c_str())) return false;
- if (!READER_CHECK(value["default"].IsNumber() || value["default"].IsArray(), (prefix + "Value 'default' must be a number or an array the size of the corresponding slider type\n").c_str())) return false;
- if (!READER_CHECK(value.HasMember("max"), (prefix + "Must have a number or array value 'max'\n").c_str())) return false;
- if (!READER_CHECK(value["max"].IsNumber() || value["max"].IsArray(), (prefix + "Value 'max' must be a number or an array the size of the corresponding slider type\n").c_str())) return false;
- if (!READER_CHECK(value.HasMember("step"), (prefix + "Must have a number value 'step'\n").c_str())) return false;
- if (!READER_CHECK(value["step"].IsNumber(), (prefix + "Value 'step' must be a number (how much does this slider increment by internally?)\n").c_str())) return false;
- if (!READER_CHECK(value.HasMember("type"), (prefix + "Must have string value 'type'\n").c_str())) return false;
- if (!READER_CHECK(value["type"].IsString(), (prefix + "Value 'type' must be a string (what type of slider is this? [int_enum, int, float])\n").c_str())) return false;
- if (!READER_CHECK(value.HasMember("screen"), (prefix + "Must have string value 'screen'\n").c_str())) return false;
- if (!READER_CHECK(value["screen"].IsString(), (prefix + "Value 'screen' must be a string (what type of output device does this slider apply to? [none, raster, vector, crt, lcd, non_vector, any])\n").c_str())) return false;
- if (!READER_CHECK(value.HasMember("format"), (prefix + "Must have string value 'format'\n").c_str())) return false;
- if (!READER_CHECK(value["format"].IsString(), (prefix + "Value 'scale' must be a string (how would we display it in a printf?)").c_str())) return false;
- if (!READER_CHECK(value.HasMember("text"), (prefix + "Must have string value 'text'\n").c_str())) return false;
- if (!READER_CHECK(value["text"].IsString(), (prefix + "Value 'text' must be a string (how would you explain it?)").c_str())) return false;
- if (!READER_CHECK(!value.HasMember("strings") || value["strings"].IsArray(), (prefix + "Value 'strings' must be an array\n").c_str())) return false;
+ if (!READER_CHECK(value.HasMember("name"), "%1$sMust have string value 'name'", prefix)) return false;
+ if (!READER_CHECK(value["name"].IsString(), "%1$sValue 'name' must be a string", prefix)) return false;
+ if (!READER_CHECK(value.HasMember("min"), "%1$sMust have a number or array value 'min'", prefix)) return false;
+ if (!READER_CHECK(value["min"].IsNumber() || value["min"].IsArray(), "%1$sValue 'min' must be a number or an array the size of the corresponding slider type", prefix)) return false;
+ if (!READER_CHECK(value.HasMember("default"), "%1$sMust have a number or array value 'default'", prefix)) return false;
+ if (!READER_CHECK(value["default"].IsNumber() || value["default"].IsArray(), "%1$sValue 'default' must be a number or an array the size of the corresponding slider type", prefix)) return false;
+ if (!READER_CHECK(value.HasMember("max"), "%1$sMust have a number or array value 'max'", prefix)) return false;
+ if (!READER_CHECK(value["max"].IsNumber() || value["max"].IsArray(), "%1$sValue 'max' must be a number or an array the size of the corresponding slider type", prefix)) return false;
+ if (!READER_CHECK(value.HasMember("step"), "%1$sMust have a number value 'step'", prefix)) return false;
+ if (!READER_CHECK(value["step"].IsNumber(), "%1$sValue 'step' must be a number (how much does this slider increment by internally?)", prefix)) return false;
+ if (!READER_CHECK(value.HasMember("type"), "%1$sMust have string value 'type'", prefix)) return false;
+ if (!READER_CHECK(value["type"].IsString(), "%1$sValue 'type' must be a string (what type of slider is this? [int_enum, int, float])", prefix)) return false;
+ if (!READER_CHECK(value.HasMember("screen"), "%1$sMust have string value 'screen'", prefix)) return false;
+ if (!READER_CHECK(value["screen"].IsString(), "%1$sValue 'screen' must be a string (what type of output device does this slider apply to? [none, raster, vector, crt, lcd, non_vector, any])", prefix)) return false;
+ if (!READER_CHECK(value.HasMember("format"), "%1$sMust have string value 'format'", prefix)) return false;
+ if (!READER_CHECK(value["format"].IsString(), "%1$sValue 'scale' must be a string (how would we display it in a printf?)", prefix)) return false;
+ if (!READER_CHECK(value.HasMember("text"), "%1$sMust have string value 'text'", prefix)) return false;
+ if (!READER_CHECK(value["text"].IsString(), "%1$sValue 'text' must be a string (how would you explain it?)", prefix)) return false;
+ if (!READER_CHECK(!value.HasMember("strings") || value["strings"].IsArray(), "%1$sValue 'strings' must be an array", prefix)) return false;
return true;
}
diff --git a/src/osd/modules/render/bgfx/sliderreader.h b/src/osd/modules/render/bgfx/sliderreader.h
index 95c6872e171..dc905472cc8 100644
--- a/src/osd/modules/render/bgfx/sliderreader.h
+++ b/src/osd/modules/render/bgfx/sliderreader.h
@@ -6,26 +6,26 @@
//
//============================================================
+#ifndef MAME_RENDER_BGFX_SLIDERREADER_H
+#define MAME_RENDER_BGFX_SLIDERREADER_H
+
#pragma once
-#ifndef __DRAWBGFX_SLIDER_READER__
-#define __DRAWBGFX_SLIDER_READER__
+#include "statereader.h"
#include <vector>
-#include "statereader.h"
-
class bgfx_slider;
class chain_manager;
class slider_reader : public state_reader
{
public:
- static std::vector<bgfx_slider*> read_from_value(const Value& value, std::string prefix, chain_manager& chains, uint32_t screen_index);
+ static std::vector<bgfx_slider*> read_from_value(const Value& value, const std::string &prefix, chain_manager& chains, uint32_t screen_index);
private:
- static bool get_values(const Value& value, std::string prefix, std::string name, float* values, const int count);
- static bool validate_parameters(const Value& value, std::string prefix);
+ static bool get_values(const Value& value, const std::string &prefix, const std::string &name, float* values, const int count);
+ static bool validate_parameters(const Value& value, const std::string &prefix);
static const int TYPE_COUNT = 5;
static const string_to_enum TYPE_NAMES[TYPE_COUNT];
@@ -33,4 +33,4 @@ private:
static const string_to_enum SCREEN_NAMES[SCREEN_COUNT];
};
-#endif // __DRAWBGFX_SLIDER_READER__
+#endif // MAME_RENDER_BGFX_SLIDERREADER_H
diff --git a/src/osd/modules/render/bgfx/slideruniform.cpp b/src/osd/modules/render/bgfx/slideruniform.cpp
index 7a63b1e6901..bc116f51ff1 100644
--- a/src/osd/modules/render/bgfx/slideruniform.cpp
+++ b/src/osd/modules/render/bgfx/slideruniform.cpp
@@ -13,13 +13,12 @@
#include "slider.h"
-bgfx_slider_uniform::bgfx_slider_uniform(bgfx_uniform* uniform, std::vector<bgfx_slider*> sliders)
+#include <utility>
+
+bgfx_slider_uniform::bgfx_slider_uniform(bgfx_uniform* uniform, std::vector<bgfx_slider*> &&sliders)
: bgfx_entry_uniform(uniform)
+ , m_sliders(std::move(sliders))
{
- for (bgfx_slider* slider : sliders)
- {
- m_sliders.push_back(slider);
- }
}
void bgfx_slider_uniform::bind()
diff --git a/src/osd/modules/render/bgfx/slideruniform.h b/src/osd/modules/render/bgfx/slideruniform.h
index a2fa990dd1f..a08d2fb503d 100644
--- a/src/osd/modules/render/bgfx/slideruniform.h
+++ b/src/osd/modules/render/bgfx/slideruniform.h
@@ -9,10 +9,10 @@
//
//============================================================
-#pragma once
+#ifndef MAME_RENDER_BGFX_SLIDERUNIFORM_H
+#define MAME_RENDER_BGFX_SLIDERUNIFORM_H
-#ifndef __DRAWBGFX_SLIDER_UNIFORM__
-#define __DRAWBGFX_SLIDER_UNIFORM__
+#pragma once
#include "entryuniform.h"
@@ -23,7 +23,7 @@ class bgfx_slider;
class bgfx_slider_uniform : public bgfx_entry_uniform
{
public:
- bgfx_slider_uniform(bgfx_uniform* uniform, std::vector<bgfx_slider*> sliders);
+ bgfx_slider_uniform(bgfx_uniform* uniform, std::vector<bgfx_slider*> &&sliders);
virtual void bind() override;
@@ -31,4 +31,4 @@ private:
std::vector<bgfx_slider*> m_sliders;
};
-#endif // __DRAWBGFX_SLIDER_UNIFORM__
+#endif // MAME_RENDER_BGFX_SLIDERUNIFORM_H
diff --git a/src/osd/modules/render/bgfx/slideruniformreader.cpp b/src/osd/modules/render/bgfx/slideruniformreader.cpp
index 314cff0b78b..3fdeb0b21e6 100644
--- a/src/osd/modules/render/bgfx/slideruniformreader.cpp
+++ b/src/osd/modules/render/bgfx/slideruniformreader.cpp
@@ -8,13 +8,13 @@
#include "slideruniformreader.h"
-#include <vector>
-
-#include "slideruniform.h"
#include "entryuniform.h"
#include "slider.h"
+#include "slideruniform.h"
+
+#include <vector>
-bgfx_entry_uniform* slider_uniform_reader::read_from_value(const Value& value, std::string prefix, bgfx_uniform* uniform, std::map<std::string, bgfx_slider*>& sliders)
+bgfx_entry_uniform* slider_uniform_reader::read_from_value(const Value& value, const std::string &prefix, bgfx_uniform* uniform, std::map<std::string, bgfx_slider*>& sliders)
{
if (!validate_parameters(value, prefix))
{
@@ -35,12 +35,12 @@ bgfx_entry_uniform* slider_uniform_reader::read_from_value(const Value& value, s
slider_list.push_back(sliders[name + "2"]);
}
- return new bgfx_slider_uniform(uniform, slider_list);
+ return new bgfx_slider_uniform(uniform, std::move(slider_list));
}
-bool slider_uniform_reader::validate_parameters(const Value& value, std::string prefix)
+bool slider_uniform_reader::validate_parameters(const Value& value, const std::string &prefix)
{
- if (!READER_CHECK(value.HasMember("slider"), (prefix + "Must have string value 'slider' (what slider are we getting the value of?)\n").c_str())) return false;
- if (!READER_CHECK(value["slider"].IsString(), (prefix + "Value 'slider' must be a string\n").c_str())) return false;
+ if (!READER_CHECK(value.HasMember("slider"), "%sMust have string value 'slider' (what slider are we getting the value of?)\n", prefix)) return false;
+ if (!READER_CHECK(value["slider"].IsString(), "%sValue 'slider' must be a string\n", prefix)) return false;
return true;
}
diff --git a/src/osd/modules/render/bgfx/slideruniformreader.h b/src/osd/modules/render/bgfx/slideruniformreader.h
index 0db387270b0..f39e7fc2fd8 100644
--- a/src/osd/modules/render/bgfx/slideruniformreader.h
+++ b/src/osd/modules/render/bgfx/slideruniformreader.h
@@ -6,27 +6,27 @@
//
//================================================================
+#ifndef MAME_RENDER_BGFX_SLIDERUNIFORMREADER_H
+#define MAME_RENDER_BGFX_SLIDERUNIFORMREADER_H
+
#pragma once
-#ifndef __DRAWBGFX_SLIDER_UNIFORM_READER__
-#define __DRAWBGFX_SLIDER_UNIFORM_READER__
+#include "entryuniform.h"
+#include "statereader.h"
#include <string>
#include <map>
-#include "entryuniform.h"
-#include "statereader.h"
-
class bgfx_uniform;
class bgfx_slider;
class slider_uniform_reader : public state_reader
{
public:
- static bgfx_entry_uniform* read_from_value(const Value& value, std::string prefix, bgfx_uniform* uniform, std::map<std::string, bgfx_slider*>& sliders);
+ static bgfx_entry_uniform* read_from_value(const Value& value, const std::string &prefix, bgfx_uniform* uniform, std::map<std::string, bgfx_slider*>& sliders);
private:
- static bool validate_parameters(const Value& value, std::string prefix);
+ static bool validate_parameters(const Value& value, const std::string &prefix);
};
-#endif // __DRAWBGFX_SLIDER_UNIFORM_READER__
+#endif // MAME_RENDER_BGFX_SLIDERUNIFORMREADER_H
diff --git a/src/osd/modules/render/bgfx/statereader.cpp b/src/osd/modules/render/bgfx/statereader.cpp
index acaeddd35b5..277e6815185 100644
--- a/src/osd/modules/render/bgfx/statereader.cpp
+++ b/src/osd/modules/render/bgfx/statereader.cpp
@@ -13,17 +13,20 @@
#include <cmath>
-bool state_reader::READER_CHECK(bool condition, const char* format, ...)
+
+bool state_reader::V_READER_CHECK(bool condition, const util::format_argument_pack<char> &args)
{
if (!condition)
- {
- va_list ap;
- va_start(ap, format);
- char buf[2048];
- vsnprintf(buf, 2048, format, ap);
- osd_printf_error("Error: %s\n", buf);
- va_end(ap);
- }
+ osd_printf_error("Error: %s\n", util::string_format(args));
+
+ return condition;
+}
+
+bool state_reader::V_READER_WARN(bool condition, const util::format_argument_pack<char> &args)
+{
+ if (!condition)
+ osd_printf_warning("Warning: %s\n", util::string_format(args));
+
return condition;
}
@@ -117,7 +120,7 @@ float state_reader::get_float(const Value& value, const std::string name, const
{
if (value.HasMember(name.c_str()))
{
- return (float)value[name.c_str()].GetDouble();
+ return float(value[name.c_str()].GetDouble());
}
return default_value;
}
@@ -128,7 +131,7 @@ void state_reader::get_float(const Value& value, const std::string name, float*
{
if (count == 1)
{
- *out = (float) value[name.c_str()].GetDouble();
+ *out = float(value[name.c_str()].GetDouble());
return;
}
else
@@ -146,7 +149,7 @@ void state_reader::get_vec_values(const Value& value_array, float* data, const u
{
for (unsigned int i = 0; i < count && i < value_array.Size(); i++)
{
- data[i] = (float) value_array[i].GetDouble();
+ data[i] = float(value_array[i].GetDouble());
}
}
diff --git a/src/osd/modules/render/bgfx/statereader.h b/src/osd/modules/render/bgfx/statereader.h
index 43596bf4e94..69a795d9f04 100644
--- a/src/osd/modules/render/bgfx/statereader.h
+++ b/src/osd/modules/render/bgfx/statereader.h
@@ -7,16 +7,19 @@
//
//================================================================
+#ifndef MAME_RENDER_BGFX_STATEREADER_H
+#define MAME_RENDER_BGFX_STATEREADER_H
+
#pragma once
-#ifndef DRAWBGFX_STATE_READER
-#define DRAWBGFX_STATE_READER
+#include "util/strformat.h"
#include <rapidjson/document.h>
#include <cstdint>
#include <string>
+
using namespace rapidjson;
class state_reader
@@ -44,10 +47,22 @@ protected:
static uint64_t get_param_from_string(std::string value, const string_to_enum* enums, const int count);
protected:
- static bool READER_CHECK(bool condition, const char* format, ...);
+ template <typename Format, typename... Params>
+ static bool READER_CHECK(bool condition, Format &&fmt, Params &&... args)
+ {
+ return V_READER_CHECK(condition, util::make_format_argument_pack(std::forward<Format>(fmt), std::forward<Params>(args)...));
+ }
+
+ template <typename Format, typename... Params>
+ static bool READER_WARN(bool condition, Format &&fmt, Params &&... args)
+ {
+ return V_READER_WARN(condition, util::make_format_argument_pack(std::forward<Format>(fmt), std::forward<Params>(args)...));
+ }
private:
+ static bool V_READER_CHECK(bool condition, const util::format_argument_pack<char> &args);
+ static bool V_READER_WARN(bool condition, const util::format_argument_pack<char> &args);
static void get_vec_values(const Value& value_array, float* data, const unsigned int count);
};
-#endif // DRAWBGFX_STATE_READER
+#endif // MAME_RENDER_BGFX_STATEREADER_H
diff --git a/src/osd/modules/render/bgfx/suppressor.cpp b/src/osd/modules/render/bgfx/suppressor.cpp
index 83dd403adf7..8ffb4be6d66 100644
--- a/src/osd/modules/render/bgfx/suppressor.cpp
+++ b/src/osd/modules/render/bgfx/suppressor.cpp
@@ -13,13 +13,13 @@
#include <cstring>
-bgfx_suppressor::bgfx_suppressor(std::vector<bgfx_slider*> sliders, uint32_t condition, combine_mode combine, void* value)
- : m_sliders(sliders)
+bgfx_suppressor::bgfx_suppressor(std::vector<bgfx_slider*> &&sliders, uint32_t condition, combine_mode combine, void* value)
+ : m_sliders(std::move(sliders))
, m_condition(condition)
, m_combine(combine)
, m_value(nullptr)
{
- uint32_t size = sliders[0]->size();
+ uint32_t size = m_sliders[0]->size();
m_value = new uint8_t[size];
memcpy(m_value, value, size);
}
diff --git a/src/osd/modules/render/bgfx/suppressor.h b/src/osd/modules/render/bgfx/suppressor.h
index 343a621b72d..00276fbb398 100644
--- a/src/osd/modules/render/bgfx/suppressor.h
+++ b/src/osd/modules/render/bgfx/suppressor.h
@@ -7,10 +7,10 @@
//
//============================================================
-#pragma once
+#ifndef MAME_RENDER_BGFX_SUPPRESSOR_H
+#define MAME_RENDER_BGFX_SUPPRESSOR_H
-#ifndef __DRAWBGFX_SUPPRESSOR__
-#define __DRAWBGFX_SUPPRESSOR__
+#pragma once
#include <bgfx/bgfx.h>
@@ -34,7 +34,7 @@ public:
COMBINE_OR
};
- bgfx_suppressor(std::vector<bgfx_slider*> sliders, uint32_t condition, combine_mode combine, void* value);
+ bgfx_suppressor(std::vector<bgfx_slider*> &&sliders, uint32_t condition, combine_mode combine, void* value);
~bgfx_suppressor();
// Getters
@@ -48,4 +48,4 @@ private:
uint8_t* m_value;
};
-#endif // __DRAWBGFX_SUPPRESSOR__
+#endif // MAME_RENDER_BGFX_SUPPRESSOR_H
diff --git a/src/osd/modules/render/bgfx/suppressorreader.cpp b/src/osd/modules/render/bgfx/suppressorreader.cpp
index d7eb2b21fb8..353b79ad9bf 100644
--- a/src/osd/modules/render/bgfx/suppressorreader.cpp
+++ b/src/osd/modules/render/bgfx/suppressorreader.cpp
@@ -21,7 +21,7 @@ const suppressor_reader::string_to_enum suppressor_reader::COMBINE_NAMES[suppres
{ "or", bgfx_suppressor::combine_mode::COMBINE_OR }
};
-bgfx_suppressor* suppressor_reader::read_from_value(const Value& value, std::string prefix, std::map<std::string, bgfx_slider*>& sliders)
+bgfx_suppressor* suppressor_reader::read_from_value(const Value& value, const std::string &prefix, std::map<std::string, bgfx_slider*>& sliders)
{
if (!validate_parameters(value, prefix))
{
@@ -58,7 +58,7 @@ bgfx_suppressor* suppressor_reader::read_from_value(const Value& value, std::str
if (slider_count > 1)
{
get_values(value, prefix, "value", values, slider_count);
- if (!READER_CHECK(slider_count == value["value"].GetArray().Size(), (prefix + "Expected " + std::to_string(slider_count) + " values, got " + std::to_string(value["value"].GetArray().Size()) + "\n").c_str())) return nullptr;
+ if (!READER_CHECK(slider_count == value["value"].GetArray().Size(), "%sExpected %d values, got %u\n", prefix, slider_count, value["value"].GetArray().Size())) return nullptr;
for (int index = 1; index < slider_count; index++)
{
check_sliders.push_back(sliders[name + std::to_string(index)]);
@@ -69,26 +69,25 @@ bgfx_suppressor* suppressor_reader::read_from_value(const Value& value, std::str
values[0] = get_int(value, "value", 0);
}
- return new bgfx_suppressor(check_sliders, condition, mode, values);
+ return new bgfx_suppressor(std::move(check_sliders), condition, mode, values);
}
-bool suppressor_reader::validate_parameters(const Value& value, std::string prefix)
+bool suppressor_reader::validate_parameters(const Value& value, const std::string &prefix)
{
- if (!READER_CHECK(value["type"].IsString(), (prefix + "Value 'type' must be a string\n").c_str())) return false;
- if (!READER_CHECK(value.HasMember("name"), (prefix + "Must have string value 'name'\n").c_str())) return false;
- if (!READER_CHECK(value["name"].IsString(), (prefix + "Value 'name' must be a string\n").c_str())) return false;
- if (!READER_CHECK(value.HasMember("value"), (prefix + "Must have numeric or array value 'value'\n").c_str())) return false;
- if (!READER_CHECK(value["value"].IsNumber() || value["value"].IsArray(), (prefix + "Value 'value' must be a number or array the size of the corresponding slider type\n").c_str())) return false;
+ if (!READER_CHECK(value["type"].IsString(), "%sValue 'type' must be a string\n", prefix)) return false;
+ if (!READER_CHECK(value.HasMember("name"), "%sMust have string value 'name'\n", prefix)) return false;
+ if (!READER_CHECK(value["name"].IsString(), "%sValue 'name' must be a string\n", prefix)) return false;
+ if (!READER_CHECK(value.HasMember("value"), "%sMust have numeric or array value 'value'\n", prefix)) return false;
+ if (!READER_CHECK(value["value"].IsNumber() || value["value"].IsArray(), "%sValue 'value' must be a number or array the size of the corresponding slider type\n", prefix)) return false;
return true;
}
bool suppressor_reader::get_values(const Value& value, std::string prefix, std::string name, int* values, const int count)
{
- const char* name_str = name.c_str();
- const Value& value_array = value[name_str];
+ const Value& value_array = value[name.c_str()];
for (uint32_t i = 0; i < value_array.Size() && i < count; i++)
{
- if (!READER_CHECK(value_array[i].IsInt(), (prefix + "value[" + std::to_string(i) + "] must be an integer\n").c_str())) return false;
+ if (!READER_CHECK(value_array[i].IsInt(), "%svalue[%u] must be an integer\n", prefix, i)) return false;
values[i] = value_array[i].GetInt();
}
return true;
diff --git a/src/osd/modules/render/bgfx/suppressorreader.h b/src/osd/modules/render/bgfx/suppressorreader.h
index cf7d641997c..23855134c51 100644
--- a/src/osd/modules/render/bgfx/suppressorreader.h
+++ b/src/osd/modules/render/bgfx/suppressorreader.h
@@ -6,10 +6,10 @@
//
//============================================================
-#pragma once
+#ifndef MAME_RENDER_BGFX_SUPPRESSORREADER_H
+#define MAME_RENDER_BGFX_SUPPRESSORREADER_H
-#ifndef __DRAWBGFX_SUPPRESSOR_READER__
-#define __DRAWBGFX_SUPPRESSOR_READER__
+#pragma once
#include "statereader.h"
@@ -22,11 +22,11 @@ class bgfx_slider;
class suppressor_reader : public state_reader
{
public:
- static bgfx_suppressor* read_from_value(const Value& value, std::string prefix, std::map<std::string, bgfx_slider*>& sliders);
+ static bgfx_suppressor* read_from_value(const Value& value, const std::string &prefix, std::map<std::string, bgfx_slider*>& sliders);
private:
static bool get_values(const Value& value, std::string prefix, std::string name, int* values, const int count);
- static bool validate_parameters(const Value& value, std::string prefix);
+ static bool validate_parameters(const Value& value, const std::string &prefix);
static const int CONDITION_COUNT = 2;
static const string_to_enum CONDITION_NAMES[CONDITION_COUNT];
@@ -34,4 +34,4 @@ private:
static const string_to_enum COMBINE_NAMES[COMBINE_COUNT];
};
-#endif // __DRAWBGFX_SUPPRESSOR_READER__
+#endif // MAME_RENDER_BGFX_SUPPRESSORREADER_H
diff --git a/src/osd/modules/render/bgfx/target.cpp b/src/osd/modules/render/bgfx/target.cpp
index f900f4f99fb..dd9169cb6cd 100644
--- a/src/osd/modules/render/bgfx/target.cpp
+++ b/src/osd/modules/render/bgfx/target.cpp
@@ -10,13 +10,16 @@
#include "target.h"
-bgfx_target::bgfx_target(std::string name, bgfx::TextureFormat::Enum format, uint16_t width, uint16_t height, uint32_t style, bool double_buffer, bool filter, uint16_t scale, uint32_t screen)
+bgfx_target::bgfx_target(std::string name, bgfx::TextureFormat::Enum format, uint16_t width, uint16_t height, uint16_t xprescale, uint16_t yprescale,
+ uint32_t style, bool double_buffer, bool filter, uint16_t scale, uint32_t screen)
: m_name(name)
, m_format(format)
, m_targets(nullptr)
, m_textures(nullptr)
, m_width(width)
, m_height(height)
+ , m_xprescale(xprescale)
+ , m_yprescale(yprescale)
, m_double_buffer(double_buffer)
, m_style(style)
, m_filter(filter)
@@ -39,10 +42,10 @@ bgfx_target::bgfx_target(std::string name, bgfx::TextureFormat::Enum format, uin
m_targets = new bgfx::FrameBufferHandle[m_page_count];
for (int page = 0; page < m_page_count; page++)
{
- m_textures[page] = bgfx::createTexture2D(m_width, m_height, false, 1, format, wrap_mode | filter_mode | BGFX_TEXTURE_RT);
+ m_textures[page] = bgfx::createTexture2D(m_width * xprescale, m_height * yprescale, false, 1, format, wrap_mode | filter_mode | BGFX_TEXTURE_RT);
assert(m_textures[page].idx != 0xffff);
- m_textures[m_page_count + page] = bgfx::createTexture2D(m_width, m_height, false, 1, bgfx::TextureFormat::D32F, depth_flags | BGFX_TEXTURE_RT);
+ m_textures[m_page_count + page] = bgfx::createTexture2D(m_width * xprescale, m_height * yprescale, false, 1, bgfx::TextureFormat::D32F, depth_flags | BGFX_TEXTURE_RT);
assert(m_textures[m_page_count + page].idx != 0xffff);
bgfx::TextureHandle handles[2] = { m_textures[page], m_textures[m_page_count + page] };
@@ -62,6 +65,8 @@ bgfx_target::bgfx_target(void *handle, uint16_t width, uint16_t height)
, m_textures(nullptr)
, m_width(width)
, m_height(height)
+ , m_xprescale(1)
+ , m_yprescale(1)
, m_double_buffer(false)
, m_style(TARGET_STYLE_CUSTOM)
, m_filter(false)
diff --git a/src/osd/modules/render/bgfx/target.h b/src/osd/modules/render/bgfx/target.h
index c00fc669337..5b979373971 100644
--- a/src/osd/modules/render/bgfx/target.h
+++ b/src/osd/modules/render/bgfx/target.h
@@ -27,7 +27,8 @@ enum
class bgfx_target : public bgfx_texture_handle_provider
{
public:
- bgfx_target(std::string name, bgfx::TextureFormat::Enum format, uint16_t width, uint16_t height, uint32_t style, bool double_buffer, bool filter, uint16_t scale, uint32_t screen);
+ bgfx_target(std::string name, bgfx::TextureFormat::Enum format, uint16_t width, uint16_t height, uint16_t xprescale, uint16_t yprescale,
+ uint32_t style, bool double_buffer, bool filter, uint16_t scale, uint32_t screen);
bgfx_target(void *handle, uint16_t width, uint16_t height);
virtual ~bgfx_target();
@@ -42,13 +43,16 @@ public:
bool filter() const { return m_filter; }
uint16_t scale() const { return m_scale; }
uint32_t screen_index() const { return m_screen; }
+ uint16_t raw_width() const { return m_width; }
+ uint16_t raw_height() const { return m_height; }
// bgfx_texture_handle_provider
virtual bgfx::TextureHandle texture() const override;
virtual bool is_target() const override { return true; }
- virtual uint16_t width() const override { return m_width; }
- virtual uint16_t height() const override { return m_height; }
- virtual uint16_t rowpixels() const override { return m_width; }
+ virtual uint16_t width() const override { return m_width * m_xprescale; }
+ virtual uint16_t width_margin() const override { return 0; }
+ virtual uint16_t height() const override { return m_height * m_yprescale; }
+ virtual uint16_t rowpixels() const override { return m_width * m_xprescale; }
virtual int width_div_factor() const override { return 1; }
virtual int width_mul_factor() const override { return 1; }
@@ -62,6 +66,8 @@ private:
uint16_t m_width;
uint16_t m_height;
+ uint16_t m_xprescale;
+ uint16_t m_yprescale;
bool m_double_buffer;
uint32_t m_style;
diff --git a/src/osd/modules/render/bgfx/targetmanager.cpp b/src/osd/modules/render/bgfx/targetmanager.cpp
index dfd5b2adbd1..eae09c48008 100644
--- a/src/osd/modules/render/bgfx/targetmanager.cpp
+++ b/src/osd/modules/render/bgfx/targetmanager.cpp
@@ -9,15 +9,15 @@
//
//============================================================
-#include <bgfx/bgfx.h>
+#include "targetmanager.h"
-#include <vector>
+#include "bgfxutil.h"
+#include "target.h"
#include "modules/lib/osdobj_common.h"
-#include "targetmanager.h"
+#include <utility>
-#include "target.h"
const int32_t target_manager::MAX_SCREENS = 100;
@@ -29,100 +29,106 @@ target_manager::target_manager(texture_manager& textures)
target_manager::~target_manager()
{
- std::vector<bgfx_target*> to_delete;
- for (std::pair<std::string, bgfx_target*> target : m_targets)
- {
- if (target.second != nullptr)
- {
- to_delete.push_back(target.second);
- }
- }
- m_targets.clear();
-
- for (uint32_t i = 0; i < to_delete.size(); i++)
- {
- delete to_delete[i];
- }
+ for (auto iter = m_targets.begin(); iter != m_targets.end(); iter = m_targets.erase(iter))
+ m_textures.remove_provider(iter->first);
}
-bgfx_target* target_manager::create_target(std::string name, bgfx::TextureFormat::Enum format, uint16_t width, uint16_t height, uint32_t style, bool double_buffer, bool filter, uint16_t scale, uint32_t screen)
+bgfx_target* target_manager::create_target(
+ std::string &&name,
+ bgfx::TextureFormat::Enum format,
+ uint16_t width,
+ uint16_t height,
+ uint16_t xprescale,
+ uint16_t yprescale,
+ uint32_t style,
+ bool double_buffer,
+ bool filter,
+ uint16_t scale,
+ uint32_t screen)
{
- std::string full_name = name + std::to_string(screen);
+ const std::string full_name = name + std::to_string(screen);
auto iter = m_targets.find(full_name);
if (iter != m_targets.end())
- destroy_target(name, screen);
+ {
+ iter->second.reset();
+ m_textures.remove_provider(full_name);
+ }
- bgfx_target *target = new bgfx_target(name, format, width, height, style, double_buffer, filter, scale, screen);
- m_targets[full_name] = target;
- m_textures.add_provider(full_name, target);
+ auto target = std::make_unique<bgfx_target>(std::move(name), format, width, height, xprescale, yprescale, style, double_buffer, filter, scale, screen);
+ if (iter != m_targets.end())
+ iter->second = std::move(target);
+ else
+ iter = m_targets.emplace(full_name, std::move(target)).first;
+ m_textures.add_provider(full_name, *iter->second);
- return target;
+ return iter->second.get();
}
-void target_manager::destroy_target(std::string name, uint32_t screen)
+void target_manager::destroy_target(const std::string &name, uint32_t screen)
{
- std::string full_name = (screen < 0) ? name : (name + std::to_string(screen));
- if (m_targets.find(full_name) != m_targets.end())
+ const std::string full_name = (screen < 0) ? name : (name + std::to_string(screen));
+ const auto found = m_targets.find(full_name);
+ if (found != m_targets.end())
{
- delete m_targets[full_name];
- m_targets.erase(full_name);
+ m_targets.erase(found);
m_textures.remove_provider(full_name);
}
}
bgfx_target* target_manager::create_backbuffer(void *handle, uint16_t width, uint16_t height)
{
- auto* target = new bgfx_target(handle, width, height);
- m_targets["backbuffer"] = target;
- return target;
+ auto target = std::make_unique<bgfx_target>(handle, width, height);
+ return (m_targets["backbuffer"] = std::move(target)).get();
}
-bgfx_target* target_manager::target(uint32_t screen, std::string name)
+bgfx_target* target_manager::target(uint32_t screen, const std::string &name)
{
- std::string full_name = name + std::to_string(screen);
- if (m_targets.find(full_name) == m_targets.end())
+ const std::string full_name = name + std::to_string(screen);
+ const auto found = m_targets.find(full_name);
+ if (found != m_targets.end())
+ {
+ return found->second.get();
+ }
+ else
{
osd_printf_verbose("Warning: Attempting to retrieve a nonexistent target '%s' for screen %d\n", name, screen);
+ return nullptr;
}
- return m_targets[full_name];
}
-bool target_manager::update_target_sizes(uint32_t screen, uint16_t width, uint16_t height, uint32_t style)
+bool target_manager::update_target_sizes(uint32_t screen, uint16_t width, uint16_t height, uint32_t style, uint16_t user_prescale, uint16_t max_prescale_size)
{
- if (style == TARGET_STYLE_CUSTOM) return false;
+ if (style == TARGET_STYLE_CUSTOM)
+ return false;
- std::vector<osd_dim>& sizes = style == TARGET_STYLE_GUEST ? m_guest_dims : m_native_dims;
+ std::vector<osd_dim> &sizes = (style == TARGET_STYLE_GUEST) ? m_guest_dims : m_native_dims;
// Ensure that there's an entry to fill
while (sizes.size() <= screen)
{
- sizes.emplace_back(osd_dim(0, 0));
+ sizes.emplace_back(0, 0);
}
if (width != sizes[screen].width() || height != sizes[screen].height())
{
sizes[screen] = osd_dim(width, height);
- rebuild_targets(screen, style);
+ rebuild_targets(screen, style, user_prescale, max_prescale_size);
return true;
}
return false;
}
-void target_manager::rebuild_targets(uint32_t screen, uint32_t style)
+void target_manager::rebuild_targets(uint32_t screen, uint32_t style, uint16_t user_prescale, uint16_t max_prescale_size)
{
if (style == TARGET_STYLE_CUSTOM) return;
std::vector<bgfx_target*> to_resize;
- for (std::pair<std::string, bgfx_target*> target_pair : m_targets)
+ for (const auto &[name, target] : m_targets)
{
- bgfx_target* target = target_pair.second;
- if (target == nullptr || target->style() != style || target->screen_index() != screen)
- {
- continue;
- }
- to_resize.push_back(target);
+ if (target && (target->style() == style) && (target->screen_index() == screen))
+ to_resize.push_back(target.get());
}
std::vector<osd_dim>& sizes = style == TARGET_STYLE_GUEST ? m_guest_dims : m_native_dims;
@@ -135,13 +141,15 @@ void target_manager::rebuild_targets(uint32_t screen, uint32_t style)
const uint16_t scale = target->scale();
const uint16_t width(sizes[screen].width());
const uint16_t height(sizes[screen].height());
+ uint16_t xprescale = user_prescale;
+ uint16_t yprescale = user_prescale;
+ bgfx_util::find_prescale_factor(width, height, max_prescale_size, xprescale, yprescale);
- destroy_target(name, screen);
- create_target(name, format, width, height, style, double_buffered, filter, scale, screen);
+ create_target(std::move(name), format, width, height, xprescale, yprescale, style, double_buffered, filter, scale, screen);
}
}
-void target_manager::update_screen_count(uint32_t count)
+void target_manager::update_screen_count(uint32_t count, uint16_t user_prescale, uint16_t max_prescale_size)
{
// Ensure that there's an entry to fill
while (count > m_native_dims.size())
@@ -157,26 +165,26 @@ void target_manager::update_screen_count(uint32_t count)
{
for (uint32_t screen = old_count; screen < m_screen_count; screen++)
{
- create_target_if_nonexistent(screen, "output", false, false, TARGET_STYLE_NATIVE);
+ create_output_if_nonexistent(screen, user_prescale, max_prescale_size);
}
}
}
}
-void target_manager::create_target_if_nonexistent(uint32_t screen, std::string name, bool double_buffered, bool filter, uint32_t style)
+void target_manager::create_output_if_nonexistent(uint32_t screen, uint16_t user_prescale, uint16_t max_prescale_size)
{
- if (style == TARGET_STYLE_CUSTOM) return;
-
- if (m_targets.find(name + std::to_string(screen)) != m_targets.end())
+ if (m_targets.find("output" + std::to_string(screen)) != m_targets.end())
{
return;
}
- std::vector<osd_dim>& sizes = style == TARGET_STYLE_GUEST ? m_guest_dims : m_native_dims;
- uint16_t width(sizes[screen].width());
- uint16_t height(sizes[screen].height());
+ uint16_t width(m_native_dims[screen].width());
+ uint16_t height(m_native_dims[screen].height());
+ uint16_t xprescale = user_prescale;
+ uint16_t yprescale = user_prescale;
+ bgfx_util::find_prescale_factor(width, height, max_prescale_size, xprescale, yprescale);
- create_target(name, bgfx::TextureFormat::BGRA8, width, height, style, double_buffered, filter, 1, screen);
+ create_target("output", bgfx::TextureFormat::BGRA8, width, height, xprescale, yprescale, TARGET_STYLE_NATIVE, false, false, 1, screen);
}
uint16_t target_manager::width(uint32_t style, uint32_t screen)
diff --git a/src/osd/modules/render/bgfx/targetmanager.h b/src/osd/modules/render/bgfx/targetmanager.h
index fa44e2c1bd6..38bba4c5db5 100644
--- a/src/osd/modules/render/bgfx/targetmanager.h
+++ b/src/osd/modules/render/bgfx/targetmanager.h
@@ -9,44 +9,49 @@
//
//============================================================
+#ifndef MAME_RENDER_BGFX_TARGETMANAGER_H
+#define MAME_RENDER_BGFX_TARGETMANAGER_H
+
#pragma once
-#ifndef __DRAWBGFX_TARGET_MANAGER__
-#define __DRAWBGFX_TARGET_MANAGER__
+#include "texturemanager.h"
-#include <map>
-#include <string>
+#include "modules/osdhelper.h"
#include <bgfx/bgfx.h>
-#include "modules/osdhelper.h"
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
-#include "texturemanager.h"
class bgfx_target;
-class target_manager {
+class target_manager
+{
public:
target_manager(texture_manager& textures);
~target_manager();
- bgfx_target* create_target(std::string name, bgfx::TextureFormat::Enum format, uint16_t width, uint16_t height, uint32_t style, bool double_buffer, bool filter, uint16_t scale, uint32_t screen);
- void destroy_target(std::string name, uint32_t screen = -1);
+ bgfx_target* create_target(std::string &&name, bgfx::TextureFormat::Enum format, uint16_t width, uint16_t height, uint16_t xprescale, uint16_t yprescale,
+ uint32_t style, bool double_buffer, bool filter, uint16_t scale, uint32_t screen);
+ void destroy_target(const std::string &name, uint32_t screen = -1);
bgfx_target* create_backbuffer(void *handle, uint16_t width, uint16_t height);
- bool update_target_sizes(uint32_t screen, uint16_t width, uint16_t height, uint32_t style);
- void update_screen_count(uint32_t count);
+ bool update_target_sizes(uint32_t screen, uint16_t width, uint16_t height, uint32_t style, uint16_t user_prescale, uint16_t max_prescale_size);
+ void update_screen_count(uint32_t count, uint16_t user_prescale, uint16_t max_prescale_size);
// Getters
- bgfx_target* target(uint32_t screen, std::string name);
+ bgfx_target* target(uint32_t screen, const std::string &name);
uint16_t width(uint32_t style, uint32_t screen);
uint16_t height(uint32_t style, uint32_t screen);
private:
- void rebuild_targets(uint32_t screen, uint32_t style);
- void create_target_if_nonexistent(uint32_t screen, std::string name, bool double_buffered, bool filter, uint32_t style);
+ void rebuild_targets(uint32_t screen, uint32_t style, uint16_t user_prescale, uint16_t max_prescale_size);
+ void create_output_if_nonexistent(uint32_t screen, uint16_t user_prescale, uint16_t max_prescale_size);
- std::map<std::string, bgfx_target*> m_targets;
+ std::map<std::string, std::unique_ptr<bgfx_target> > m_targets;
texture_manager& m_textures;
std::vector<osd_dim> m_guest_dims;
@@ -56,4 +61,4 @@ private:
static const int32_t MAX_SCREENS;
};
-#endif // __DRAWBGFX_TARGET_MANAGER__
+#endif // MAME_RENDER_BGFX_TARGETMANAGER_H
diff --git a/src/osd/modules/render/bgfx/targetreader.cpp b/src/osd/modules/render/bgfx/targetreader.cpp
index e66a147d7ba..12386428822 100644
--- a/src/osd/modules/render/bgfx/targetreader.cpp
+++ b/src/osd/modules/render/bgfx/targetreader.cpp
@@ -8,11 +8,12 @@
#include "targetreader.h"
-#include <modules/lib/osdobj_common.h>
-
+#include "bgfxutil.h"
#include "chainmanager.h"
#include "target.h"
+#include "modules/lib/osdobj_common.h"
+
#include <cmath>
const target_reader::string_to_enum target_reader::STYLE_NAMES[target_reader::STYLE_COUNT] = {
@@ -21,7 +22,13 @@ const target_reader::string_to_enum target_reader::STYLE_NAMES[target_reader::ST
{ "custom", TARGET_STYLE_CUSTOM }
};
-bgfx_target* target_reader::read_from_value(const Value& value, std::string prefix, chain_manager& chains, uint32_t screen_index)
+bgfx_target* target_reader::read_from_value(
+ const Value& value,
+ const std::string &prefix,
+ chain_manager& chains,
+ uint32_t screen_index,
+ uint16_t user_prescale,
+ uint16_t max_prescale_size)
{
if (!validate_parameters(value, prefix))
{
@@ -37,40 +44,61 @@ bgfx_target* target_reader::read_from_value(const Value& value, std::string pref
{
scale = int(floor(value["scale"].GetDouble() + 0.5));
}
+ bool use_user_prescale = get_bool(value, "user_prescale", false);
uint16_t width = 0;
uint16_t height = 0;
+ uint16_t xprescale = 1;
+ uint16_t yprescale = 1;
switch (mode)
{
case TARGET_STYLE_GUEST:
+ {
width = chains.targets().width(TARGET_STYLE_GUEST, screen_index);
height = chains.targets().height(TARGET_STYLE_GUEST, screen_index);
+
+ if (use_user_prescale)
+ {
+ xprescale = user_prescale;
+ yprescale = user_prescale;
+ bgfx_util::find_prescale_factor(width, height, max_prescale_size, xprescale, yprescale);
+ }
break;
+ }
case TARGET_STYLE_NATIVE:
width = chains.targets().width(TARGET_STYLE_NATIVE, screen_index);
height = chains.targets().height(TARGET_STYLE_NATIVE, screen_index);
+
+ if (use_user_prescale)
+ {
+ xprescale = user_prescale;
+ yprescale = user_prescale;
+ bgfx_util::find_prescale_factor(width, height, max_prescale_size, xprescale, yprescale);
+ }
break;
case TARGET_STYLE_CUSTOM:
- if (!READER_CHECK(value.HasMember("width"), (prefix + "Target '" + target_name + "': Must have numeric value 'width'\n").c_str())) return nullptr;
- if (!READER_CHECK(value["width"].IsNumber(), (prefix + "Target '" + target_name + "': Value 'width' must be a number\n").c_str())) return nullptr;
- if (!READER_CHECK(value.HasMember("height"), (prefix + "Target '" + target_name + "': Must have numeric value 'height'\n").c_str())) return nullptr;
- if (!READER_CHECK(value["height"].IsNumber(), (prefix + "Target '" + target_name + "': Value 'height' must be a number\n").c_str())) return nullptr;
+ READER_WARN(!value.HasMember("user_prescale"), "%sTarget '%s': user_prescale parameter is not used for custom-type render targets.\n", prefix, target_name);
+ if (!READER_CHECK(value.HasMember("width"), "%sTarget '%s': Must have numeric value 'width'\n", prefix, target_name)) return nullptr;
+ if (!READER_CHECK(value["width"].IsNumber(), "%sTarget '%s': Value 'width' must be a number\n", prefix, target_name)) return nullptr;
+ if (!READER_CHECK(value.HasMember("height"), "%sTarget '%s': Must have numeric value 'height'\n", prefix, target_name)) return nullptr;
+ if (!READER_CHECK(value["height"].IsNumber(), "%sTarget '%s': Value 'height' must be a number\n", prefix, target_name)) return nullptr;
width = uint16_t(value["width"].GetDouble());
height = uint16_t(value["height"].GetDouble());
break;
}
- return chains.targets().create_target(target_name, bgfx::TextureFormat::BGRA8, width, height, mode, double_buffer, bilinear, scale, screen_index);
+ return chains.targets().create_target(std::move(target_name), bgfx::TextureFormat::BGRA8, width, height, xprescale, yprescale, mode, double_buffer, bilinear, scale, screen_index);
}
-bool target_reader::validate_parameters(const Value& value, std::string prefix)
+bool target_reader::validate_parameters(const Value& value, const std::string &prefix)
{
- if (!READER_CHECK(value.HasMember("name"), (prefix + "Must have string value 'name'\n").c_str())) return false;
- if (!READER_CHECK(value["name"].IsString(), (prefix + "Value 'name' must be a string\n").c_str())) return false;
- if (!READER_CHECK(value.HasMember("mode"), (prefix + "Must have string enum 'mode'\n").c_str())) return false;
- if (!READER_CHECK(value["mode"].IsString(), (prefix + "Value 'mode' must be a string (what screens does this apply to?)\n").c_str())) return false;
- if (!READER_CHECK(!value.HasMember("bilinear") || value["bilinear"].IsBool(), (prefix + "Value 'bilinear' must be a boolean\n").c_str())) return false;
- if (!READER_CHECK(!value.HasMember("doublebuffer") || value["doublebuffer"].IsBool(), (prefix + "Value 'doublebuffer' must be a boolean\n").c_str())) return false;
- if (!READER_CHECK(!value.HasMember("scale") || value["scale"].IsNumber(), (prefix + "Value 'scale' must be a numeric value\n").c_str())) return false;
+ if (!READER_CHECK(value.HasMember("name"), "%sMust have string value 'name'\n", prefix)) return false;
+ if (!READER_CHECK(value["name"].IsString(), "%sValue 'name' must be a string\n", prefix)) return false;
+ if (!READER_CHECK(value.HasMember("mode"), "%sMust have string enum 'mode'\n", prefix)) return false;
+ if (!READER_CHECK(value["mode"].IsString(), "%sValue 'mode' must be a string (what screens does this apply to?)\n", prefix)) return false;
+ if (!READER_CHECK(!value.HasMember("bilinear") || value["bilinear"].IsBool(), "%sValue 'bilinear' must be a boolean\n", prefix)) return false;
+ if (!READER_CHECK(!value.HasMember("doublebuffer") || value["doublebuffer"].IsBool(), "%sValue 'doublebuffer' must be a boolean\n", prefix)) return false;
+ if (!READER_CHECK(!value.HasMember("user_prescale") || value["user_prescale"].IsBool(), "%sValue 'user_prescale' must be a boolean\n", prefix)) return false;
+ if (!READER_CHECK(!value.HasMember("scale") || value["scale"].IsNumber(), "%sValue 'scale' must be a numeric value\n", prefix)) return false;
return true;
}
diff --git a/src/osd/modules/render/bgfx/targetreader.h b/src/osd/modules/render/bgfx/targetreader.h
index 7edf5e456fa..2db81311359 100644
--- a/src/osd/modules/render/bgfx/targetreader.h
+++ b/src/osd/modules/render/bgfx/targetreader.h
@@ -6,28 +6,28 @@
//
//============================================================
+#ifndef MAME_RENDER_BGFX_TARGETREADER_H
+#define MAME_RENDER_BGFX_TARGETREADER_H
+
#pragma once
-#ifndef __DRAWBGFX_TARGET_READER__
-#define __DRAWBGFX_TARGET_READER__
+#include "statereader.h"
#include <string>
-#include "statereader.h"
-
class bgfx_target;
class chain_manager;
class target_reader : public state_reader
{
public:
- static bgfx_target* read_from_value(const Value& value, std::string prefix, chain_manager& chains, uint32_t screen_index);
+ static bgfx_target* read_from_value(const Value& value, const std::string &prefix, chain_manager& chains, uint32_t screen_index, uint16_t user_prescale, uint16_t max_prescale_size);
private:
- static bool validate_parameters(const Value& value, std::string prefix);
+ static bool validate_parameters(const Value& value, const std::string &prefix);
static const int STYLE_COUNT = 3;
static const string_to_enum STYLE_NAMES[STYLE_COUNT];
};
-#endif // __DRAWBGFX_TARGET_READER__
+#endif // MAME_RENDER_BGFX_TARGETREADER_H
diff --git a/src/osd/modules/render/bgfx/texture.cpp b/src/osd/modules/render/bgfx/texture.cpp
index a504c625415..2ffa97c0b6f 100644
--- a/src/osd/modules/render/bgfx/texture.cpp
+++ b/src/osd/modules/render/bgfx/texture.cpp
@@ -10,10 +10,11 @@
#include "texture.h"
-bgfx_texture::bgfx_texture(std::string name, bgfx::TextureFormat::Enum format, uint16_t width, uint16_t height, uint32_t flags, void* data)
+bgfx_texture::bgfx_texture(std::string name, bgfx::TextureFormat::Enum format, uint16_t width, uint16_t width_margin, uint16_t height, uint32_t flags, void* data)
: m_name(name)
, m_format(format)
, m_width(width)
+ , m_width_margin(width_margin)
, m_height(height)
, m_rowpixels(width)
, m_width_div_factor(1)
@@ -35,10 +36,11 @@ bgfx_texture::bgfx_texture(std::string name, bgfx::TextureFormat::Enum format, u
}
}
-bgfx_texture::bgfx_texture(std::string name, bgfx::TextureFormat::Enum format, uint16_t width, uint16_t height, const bgfx::Memory* data, uint32_t flags, uint16_t pitch, uint16_t rowpixels, int width_div_factor, int width_mul_factor)
+bgfx_texture::bgfx_texture(std::string name, bgfx::TextureFormat::Enum format, uint16_t width, uint16_t width_margin, uint16_t height, const bgfx::Memory* data, uint32_t flags, uint16_t pitch, uint16_t rowpixels, int width_div_factor, int width_mul_factor)
: m_name(name)
, m_format(format)
, m_width(width)
+ , m_width_margin(width_margin)
, m_height(height)
, m_rowpixels(rowpixels ? rowpixels : width)
, m_width_div_factor(width_div_factor)
@@ -56,7 +58,8 @@ bgfx_texture::~bgfx_texture()
bgfx::destroy(m_texture);
}
-void bgfx_texture::update(const bgfx::Memory *data, uint16_t pitch)
+void bgfx_texture::update(const bgfx::Memory *data, uint16_t pitch, uint16_t width_margin)
{
+ m_width_margin = width_margin;
bgfx::updateTexture2D(m_texture, 0, 0, 0, 0, (m_rowpixels * m_width_mul_factor) / m_width_div_factor, m_height, data, pitch);
}
diff --git a/src/osd/modules/render/bgfx/texture.h b/src/osd/modules/render/bgfx/texture.h
index 75fedcd3129..ced0604dfcf 100644
--- a/src/osd/modules/render/bgfx/texture.h
+++ b/src/osd/modules/render/bgfx/texture.h
@@ -20,8 +20,8 @@
class bgfx_texture : public bgfx_texture_handle_provider
{
public:
- bgfx_texture(std::string name, bgfx::TextureFormat::Enum format, uint16_t width, uint16_t height, uint32_t flags, void* data);
- bgfx_texture(std::string name, bgfx::TextureFormat::Enum format, uint16_t width, uint16_t height, const bgfx::Memory* data, uint32_t flags = BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP, uint16_t pitch = UINT16_MAX, uint16_t rowpixels = 0, int width_div_factor = 1, int width_mul_factor = 1);
+ bgfx_texture(std::string name, bgfx::TextureFormat::Enum format, uint16_t width, uint16_t width_margin, uint16_t height, uint32_t flags, void* data);
+ bgfx_texture(std::string name, bgfx::TextureFormat::Enum format, uint16_t width, uint16_t width_margin, uint16_t height, const bgfx::Memory* data, uint32_t flags = BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP, uint16_t pitch = UINT16_MAX, uint16_t rowpixels = 0, int width_div_factor = 1, int width_mul_factor = 1);
virtual ~bgfx_texture();
// Getters
@@ -32,17 +32,19 @@ public:
virtual bgfx::TextureHandle texture() const override { return m_texture; }
virtual bool is_target() const override { return false; }
virtual uint16_t width() const override { return m_width; }
+ virtual uint16_t width_margin() const override { return m_width_margin; }
virtual uint16_t height() const override { return m_height; }
virtual uint16_t rowpixels() const override { return m_rowpixels; }
virtual int width_div_factor() const override { return m_width_div_factor; }
virtual int width_mul_factor() const override { return m_width_mul_factor; }
- void update(const bgfx::Memory *data, uint16_t pitch = UINT16_MAX);
+ void update(const bgfx::Memory *data, uint16_t pitch = UINT16_MAX, uint16_t width_margin = 0);
protected:
std::string m_name;
bgfx::TextureFormat::Enum m_format;
uint16_t m_width;
+ uint16_t m_width_margin;
uint16_t m_height;
uint16_t m_rowpixels;
int m_width_div_factor;
diff --git a/src/osd/modules/render/bgfx/texturehandleprovider.h b/src/osd/modules/render/bgfx/texturehandleprovider.h
index 14fb2fe892c..35e4e12dc43 100644
--- a/src/osd/modules/render/bgfx/texturehandleprovider.h
+++ b/src/osd/modules/render/bgfx/texturehandleprovider.h
@@ -7,26 +7,27 @@
//
//============================================================
-#pragma once
+#ifndef MAME_RENDER_BGFX_TEXTUREHANDLEPROVIDER_H
+#define MAME_RENDER_BGFX_TEXTUREHANDLEPROVIDER_H
-#ifndef __DRAWBGFX_TEXTURE_HANDLE_PROVIDER__
-#define __DRAWBGFX_TEXTURE_HANDLE_PROVIDER__
+#pragma once
#include <bgfx/bgfx.h>
class bgfx_texture_handle_provider
{
public:
- virtual ~bgfx_texture_handle_provider() { }
+ virtual ~bgfx_texture_handle_provider() = default;
// Getters
virtual bgfx::TextureHandle texture() const = 0;
virtual bool is_target() const = 0;
virtual uint16_t width() const = 0;
+ virtual uint16_t width_margin() const = 0;
virtual uint16_t height() const = 0;
virtual uint16_t rowpixels() const = 0;
virtual int width_div_factor() const = 0;
virtual int width_mul_factor() const = 0;
};
-#endif // __DRAWBGFX_TEXTURE_HANDLE_PROVIDER__
+#endif // MAME_RENDER_BGFX_TEXTUREHANDLEPROVIDER_H
diff --git a/src/osd/modules/render/bgfx/texturemanager.cpp b/src/osd/modules/render/bgfx/texturemanager.cpp
index 82225f87eb0..b9acd5748e8 100644
--- a/src/osd/modules/render/bgfx/texturemanager.cpp
+++ b/src/osd/modules/render/bgfx/texturemanager.cpp
@@ -11,23 +11,24 @@
#include "texturemanager.h"
-#include "texture.h"
#include "bgfxutil.h"
+#include "texture.h"
+
+#include "modules/render/copyutil.h"
+#include "osdcore.h"
+
#include "emucore.h"
#include "fileio.h"
#include "rendutil.h"
-#include "osdcore.h"
-#include "modules/render/copyutil.h"
+
+
+texture_manager::texture_manager()
+{
+ // out-of-line so header works with forward declarations
+}
texture_manager::~texture_manager()
{
- for (std::pair<std::string, bgfx_texture_handle_provider*> texture : m_textures)
- {
- if (texture.second != nullptr && !(texture.second)->is_target())
- {
- delete texture.second;
- }
- }
m_textures.clear();
for (std::pair<uint64_t, sequenced_handle> mame_texture : m_mame_textures)
@@ -37,27 +38,45 @@ texture_manager::~texture_manager()
m_mame_textures.clear();
}
-void texture_manager::add_provider(std::string name, bgfx_texture_handle_provider* provider)
+void texture_manager::add_provider(const std::string &name, std::unique_ptr<bgfx_texture_handle_provider> &&provider)
{
- auto iter = m_textures.find(name);
+ const auto iter = m_textures.find(name);
if (iter != m_textures.end())
- {
- iter->second = provider;
- }
+ iter->second = std::make_pair(provider.get(), std::move(provider));
else
- {
- m_textures[name] = provider;
- }
+ m_textures.emplace(name, std::make_pair(provider.get(), std::move(provider)));
}
-bgfx_texture* texture_manager::create_texture(std::string name, bgfx::TextureFormat::Enum format, uint32_t width, uint32_t height, void* data, uint32_t flags)
+void texture_manager::add_provider(const std::string &name, bgfx_texture_handle_provider &provider)
{
- auto* texture = new bgfx_texture(name, format, width, height, flags, data);
- m_textures[name] = texture;
- return texture;
+ const auto iter = m_textures.find(name);
+ if (iter != m_textures.end())
+ iter->second = std::make_pair(&provider, nullptr);
+ else
+ m_textures.emplace(name, std::make_pair(&provider, nullptr));
+}
+
+bgfx_texture* texture_manager::create_texture(
+ const std::string &name,
+ bgfx::TextureFormat::Enum format,
+ uint32_t width,
+ uint32_t width_margin,
+ uint32_t height,
+ void* data,
+ uint32_t flags)
+{
+ auto texture = std::make_unique<bgfx_texture>(name, format, width, width_margin, height, flags, data);
+ bgfx_texture &result = *texture;
+ m_textures[name] = std::make_pair(texture.get(), std::move(texture));
+ return &result;
}
-bgfx_texture* texture_manager::create_png_texture(std::string path, std::string file_name, std::string texture_name, uint32_t flags, uint32_t screen)
+bgfx_texture* texture_manager::create_png_texture(
+ const std::string &path,
+ const std::string &file_name,
+ std::string texture_name,
+ uint32_t flags,
+ uint32_t screen)
{
bitmap_argb32 bitmap;
emu_file file(path, OPEN_FLAG_READ);
@@ -69,40 +88,45 @@ bgfx_texture* texture_manager::create_png_texture(std::string path, std::string
if (bitmap.width() == 0 || bitmap.height() == 0)
{
- osd_printf_error("Unable to load PNG '%s' from path '%s'\n", file_name.c_str(), path.c_str());
+ osd_printf_error("Unable to load PNG '%s' from path '%s'\n", file_name, path);
return nullptr;
}
- auto *data = new uint8_t[bitmap.width() * bitmap.height() * 4];
- auto *data32 = reinterpret_cast<uint32_t *>(data);
-
const uint32_t width = bitmap.width();
const uint32_t height = bitmap.height();
+ auto data32 = std::make_unique<uint32_t []>(width * height);
+
const uint32_t rowpixels = bitmap.rowpixels();
auto* base = reinterpret_cast<uint32_t *>(bitmap.raw_pixptr(0));
for (int y = 0; y < height; y++)
{
- copy_util::copyline_argb32_to_bgra(data32 + y * width, base + y * rowpixels, width, nullptr);
+ copy_util::copyline_argb32_to_bgra(&data32[y * width], base + y * rowpixels, width, nullptr);
}
if (screen >= 0)
{
texture_name += std::to_string(screen);
}
- bgfx_texture* texture = create_texture(texture_name, bgfx::TextureFormat::BGRA8, width, height, data, flags);
-
- delete [] data;
-
- return texture;
+ return create_texture(texture_name, bgfx::TextureFormat::BGRA8, width, 0, height, data32.get(), flags);
}
-bgfx::TextureHandle texture_manager::create_or_update_mame_texture(uint32_t format, int width, int height
- , int rowpixels, const rgb_t *palette, void *base, uint32_t seqid, uint32_t flags, uint64_t key, uint64_t old_key)
+bgfx::TextureHandle texture_manager::create_or_update_mame_texture(
+ uint32_t format,
+ int width,
+ int width_margin,
+ int height,
+ int rowpixels,
+ const rgb_t *palette,
+ void *base,
+ uint32_t seqid,
+ uint32_t flags,
+ uint64_t key,
+ uint64_t old_key)
{
bgfx::TextureHandle handle = BGFX_INVALID_HANDLE;
if (old_key != ~0ULL)
{
- auto iter = m_mame_textures.find(old_key);
+ const auto iter = m_mame_textures.find(old_key);
if (iter != m_mame_textures.end())
{
handle = iter->second.handle;
@@ -126,8 +150,8 @@ bgfx::TextureHandle texture_manager::create_or_update_mame_texture(uint32_t form
uint16_t pitch = width;
int width_div_factor = 1;
int width_mul_factor = 1;
- const bgfx::Memory* mem = bgfx_util::mame_texture_data_to_bgfx_texture_data(dst_format, format, rowpixels, height, palette, base, pitch, width_div_factor, width_mul_factor);
- bgfx::updateTexture2D(handle, 0, 0, 0, 0, (uint16_t)((rowpixels * width_mul_factor) / width_div_factor), (uint16_t)height, mem, pitch);
+ const bgfx::Memory* mem = bgfx_util::mame_texture_data_to_bgfx_texture_data(dst_format, format, rowpixels, width_margin, height, palette, base, pitch, width_div_factor, width_mul_factor);
+ bgfx::updateTexture2D(handle, 0, 0, 0, 0, uint16_t((rowpixels * width_mul_factor) / width_div_factor), uint16_t(height), mem, pitch);
return handle;
}
}
@@ -156,8 +180,8 @@ bgfx::TextureHandle texture_manager::create_or_update_mame_texture(uint32_t form
uint16_t pitch = width;
int width_div_factor = 1;
int width_mul_factor = 1;
- const bgfx::Memory* mem = bgfx_util::mame_texture_data_to_bgfx_texture_data(dst_format, format, rowpixels, height, palette, base, pitch, width_div_factor, width_mul_factor);
- bgfx::updateTexture2D(handle, 0, 0, 0, 0, (uint16_t)((rowpixels * width_mul_factor) / width_div_factor), (uint16_t)height, mem, pitch);
+ const bgfx::Memory* mem = bgfx_util::mame_texture_data_to_bgfx_texture_data(dst_format, format, rowpixels, width_margin, height, palette, base, pitch, width_div_factor, width_mul_factor);
+ bgfx::updateTexture2D(handle, 0, 0, 0, 0, uint16_t((rowpixels * width_mul_factor) / width_div_factor), uint16_t(height), mem, pitch);
return handle;
}
}
@@ -169,47 +193,36 @@ bgfx::TextureHandle texture_manager::create_or_update_mame_texture(uint32_t form
uint16_t pitch = width;
int width_div_factor = 1;
int width_mul_factor = 1;
- const bgfx::Memory* mem = bgfx_util::mame_texture_data_to_bgfx_texture_data(dst_format, format, rowpixels, height, palette, base, pitch, width_div_factor, width_mul_factor);
- const uint16_t adjusted_width = (uint16_t)((rowpixels * width_mul_factor) / width_div_factor);
+ const bgfx::Memory* mem = bgfx_util::mame_texture_data_to_bgfx_texture_data(dst_format, format, rowpixels, width_margin, height, palette, base, pitch, width_div_factor, width_mul_factor);
+ const uint16_t adjusted_width = uint16_t((rowpixels * width_mul_factor) / width_div_factor);
handle = bgfx::createTexture2D(adjusted_width, height, false, 1, dst_format, flags, nullptr);
- bgfx::updateTexture2D(handle, 0, 0, 0, 0, adjusted_width, (uint16_t)height, mem, pitch);
+ bgfx::updateTexture2D(handle, 0, 0, 0, 0, adjusted_width, uint16_t(height), mem, pitch);
m_mame_textures[key] = { handle, seqid, width, height };
return handle;
}
-bgfx::TextureHandle texture_manager::handle(std::string name)
+bgfx::TextureHandle texture_manager::handle(const std::string &name)
{
bgfx::TextureHandle handle = BGFX_INVALID_HANDLE;
- auto iter = m_textures.find(name);
+ const auto iter = m_textures.find(name);
if (iter != m_textures.end())
- {
- handle = (iter->second)->texture();
- }
+ handle = iter->second.first->texture();
assert(handle.idx != bgfx::kInvalidHandle);
return handle;
}
-bgfx_texture_handle_provider* texture_manager::provider(std::string name)
+bgfx_texture_handle_provider* texture_manager::provider(const std::string &name)
{
- auto iter = m_textures.find(name);
+ const auto iter = m_textures.find(name);
if (iter != m_textures.end())
- {
- return iter->second;
- }
-
- return nullptr;
+ return iter->second.first;
+ else
+ return nullptr;
}
-void texture_manager::remove_provider(std::string name, bool delete_provider)
+void texture_manager::remove_provider(const std::string &name)
{
- if (provider(name) != nullptr)
- {
- if (delete_provider)
- {
- delete m_textures[name];
- }
- m_textures.erase(name);
- }
+ m_textures.erase(name);
}
diff --git a/src/osd/modules/render/bgfx/texturemanager.h b/src/osd/modules/render/bgfx/texturemanager.h
index db71f07c0fa..8ed5d410f75 100644
--- a/src/osd/modules/render/bgfx/texturemanager.h
+++ b/src/osd/modules/render/bgfx/texturemanager.h
@@ -9,40 +9,45 @@
//
//============================================================
-#pragma once
+#ifndef MAME_RENDER_BGFX_TEXTUREMANAGER_H
+#define MAME_RENDER_BGFX_TEXTUREMANAGER_H
-#ifndef DRAWBGFX_TEXTURE_MANAGER
-#define DRAWBGFX_TEXTURE_MANAGER
+#pragma once
#include "bitmap.h"
#include <cstdint>
#include <map>
+#include <memory>
#include <string>
+#include <utility>
#include <bgfx/bgfx.h>
+
class bgfx_texture_handle_provider;
class bgfx_texture;
-class texture_manager {
+class texture_manager
+{
public:
- texture_manager() { }
+ texture_manager();
~texture_manager();
- bgfx_texture* create_texture(std::string name, bgfx::TextureFormat::Enum format, uint32_t width, uint32_t height, void* data = nullptr, uint32_t flags = BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP);
- bgfx_texture* create_png_texture(std::string path, std::string file_name, std::string texture_name, uint32_t flags = BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP, uint32_t screen = -1);
- void add_provider(std::string name, bgfx_texture_handle_provider* texture);
- void remove_provider(std::string name, bool delete_provider = false);
- bgfx::TextureHandle create_or_update_mame_texture(uint32_t format, int width, int height
- , int rowpixels, const rgb_t *palette, void *base, uint32_t seqid, uint32_t flags, uint64_t key, uint64_t old_key);
+ bgfx_texture* create_texture(const std::string &name, bgfx::TextureFormat::Enum format, uint32_t width, uint32_t width_margin, uint32_t height, void* data = nullptr, uint32_t flags = BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP);
+ bgfx_texture* create_png_texture(const std::string &path, const std::string &file_name, std::string texture_name, uint32_t flags = BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP, uint32_t screen = -1);
+ void add_provider(const std::string &name, std::unique_ptr<bgfx_texture_handle_provider> &&texture);
+ void add_provider(const std::string &name, bgfx_texture_handle_provider &texture);
+ void remove_provider(const std::string &name);
+ bgfx::TextureHandle create_or_update_mame_texture(uint32_t format, int width, int width_margin, int height,
+ int rowpixels, const rgb_t *palette, void *base, uint32_t seqid, uint32_t flags, uint64_t key, uint64_t old_key);
// Getters
- bgfx::TextureHandle handle(std::string name);
- bgfx_texture_handle_provider* provider(std::string name);
+ bgfx::TextureHandle handle(const std::string &name);
+ bgfx_texture_handle_provider* provider(const std::string &name);
private:
- bgfx_texture* create_texture(std::string name);
+ bgfx_texture* create_texture(const std::string &name);
struct sequenced_handle
{
@@ -52,8 +57,8 @@ private:
int height;
};
- std::map<std::string, bgfx_texture_handle_provider*> m_textures;
+ std::map<std::string, std::pair<bgfx_texture_handle_provider *, std::unique_ptr<bgfx_texture_handle_provider> > > m_textures;
std::map<uint64_t, sequenced_handle> m_mame_textures;
};
-#endif // DRAWBGFX_TEXTURE_MANAGER
+#endif // MAME_RENDER_BGFX_TEXTUREMANAGER_H
diff --git a/src/osd/modules/render/bgfx/timeparameter.cpp b/src/osd/modules/render/bgfx/timeparameter.cpp
index cbcd56c8e6e..bc01bb33b61 100644
--- a/src/osd/modules/render/bgfx/timeparameter.cpp
+++ b/src/osd/modules/render/bgfx/timeparameter.cpp
@@ -8,8 +8,10 @@
#include "timeparameter.h"
-bgfx_time_parameter::bgfx_time_parameter(std::string name, parameter_type type, double limit)
- : bgfx_parameter(name, type)
+#include <utility>
+
+bgfx_time_parameter::bgfx_time_parameter(std::string &&name, parameter_type type, double limit)
+ : bgfx_parameter(std::move(name), type)
, m_current_time(0)
, m_limit(limit)
{
diff --git a/src/osd/modules/render/bgfx/timeparameter.h b/src/osd/modules/render/bgfx/timeparameter.h
index ad01f8f7e60..ff7005041ff 100644
--- a/src/osd/modules/render/bgfx/timeparameter.h
+++ b/src/osd/modules/render/bgfx/timeparameter.h
@@ -6,22 +6,19 @@
//
//============================================================
-#pragma once
+#ifndef MAME_RENDER_BGFX_TIMEPARAMETER_H
+#define MAME_RENDER_BGFX_TIMEPARAMETER_H
-#ifndef __DRAWBGFX_TIME_PARAMETER__
-#define __DRAWBGFX_TIME_PARAMETER__
+#pragma once
-#include <bgfx/bgfx.h>
+#include "parameter.h"
#include <string>
-#include "parameter.h"
-
class bgfx_time_parameter : public bgfx_parameter
{
public:
- bgfx_time_parameter(std::string name, parameter_type type, double limit);
- virtual ~bgfx_time_parameter() { }
+ bgfx_time_parameter(std::string &&name, parameter_type type, double limit);
virtual float value() override;
virtual void tick(double delta) override;
@@ -31,4 +28,4 @@ private:
double m_limit;
};
-#endif // __DRAWBGFX_TIME_PARAMETER__
+#endif // MAME_RENDER_BGFX_TIMEPARAMETER_H
diff --git a/src/osd/modules/render/bgfx/uniform.cpp b/src/osd/modules/render/bgfx/uniform.cpp
index 36f68b7a9c7..238a6a4315d 100644
--- a/src/osd/modules/render/bgfx/uniform.cpp
+++ b/src/osd/modules/render/bgfx/uniform.cpp
@@ -7,10 +7,12 @@
//============================================================
#include "uniform.h"
+
#include <cstring>
+#include <utility>
-bgfx_uniform::bgfx_uniform(std::string name, bgfx::UniformType::Enum type)
- : m_name(name)
+bgfx_uniform::bgfx_uniform(std::string &&name, bgfx::UniformType::Enum type)
+ : m_name(std::move(name))
, m_type(type)
{
m_handle = BGFX_INVALID_HANDLE;
diff --git a/src/osd/modules/render/bgfx/uniform.h b/src/osd/modules/render/bgfx/uniform.h
index f7873f400a9..6a9999ca19f 100644
--- a/src/osd/modules/render/bgfx/uniform.h
+++ b/src/osd/modules/render/bgfx/uniform.h
@@ -6,10 +6,10 @@
//
//============================================================
-#pragma once
+#ifndef MAME_RENDER_BGFX_UNIFORM_H
+#define MAME_RENDER_BGFX_UNIFORM_H
-#ifndef __DRAWBGFX_UNIFORM__
-#define __DRAWBGFX_UNIFORM__
+#pragma once
#include <bgfx/bgfx.h>
@@ -18,7 +18,7 @@
class bgfx_uniform
{
public:
- bgfx_uniform(std::string name, bgfx::UniformType::Enum type);
+ bgfx_uniform(std::string &&name, bgfx::UniformType::Enum type);
virtual ~bgfx_uniform();
virtual void upload();
@@ -26,7 +26,7 @@ public:
void create();
// Getters
- std::string name() { return m_name; }
+ const std::string &name() { return m_name; }
bgfx::UniformType::Enum type() const { return m_type; }
bgfx::UniformHandle handle() const { return m_handle; }
@@ -47,4 +47,4 @@ protected:
size_t m_data_size;
};
-#endif // __DRAWBGFX_UNIFORM__
+#endif // MAME_RENDER_BGFX_UNIFORM_H
diff --git a/src/osd/modules/render/bgfx/uniformreader.cpp b/src/osd/modules/render/bgfx/uniformreader.cpp
index f2bf1114ec6..d1eab8098c7 100644
--- a/src/osd/modules/render/bgfx/uniformreader.cpp
+++ b/src/osd/modules/render/bgfx/uniformreader.cpp
@@ -10,6 +10,9 @@
#include "uniform.h"
+#include <cstdlib>
+
+
const uniform_reader::string_to_enum uniform_reader::TYPE_NAMES[uniform_reader::TYPE_COUNT] = {
{ "int", bgfx::UniformType::Sampler },
{ "vec4", bgfx::UniformType::Vec4 },
@@ -17,7 +20,7 @@ const uniform_reader::string_to_enum uniform_reader::TYPE_NAMES[uniform_reader::
{ "mat4", bgfx::UniformType::Mat4 }
};
-bgfx_uniform* uniform_reader::read_from_value(const Value& value, std::string prefix)
+std::unique_ptr<bgfx_uniform> uniform_reader::read_from_value(const Value& value, const std::string &prefix)
{
if (!validate_parameters(value, prefix))
{
@@ -31,33 +34,28 @@ bgfx_uniform* uniform_reader::read_from_value(const Value& value, std::string pr
const Value& value_array = value["values"];
const size_t array_size = value_array.Size() * sizeof(float);
- const size_t alloc_size = (type_size > array_size) ? type_size : array_size;
- auto* data = reinterpret_cast<float*>(new char[alloc_size]);
+ auto* data = reinterpret_cast<float*>(std::malloc(std::max(type_size, array_size)));
unsigned int index = 0;
for (; index < type_size / 4 && index < value_array.Size(); index++)
- {
- data[index] = (float)value_array[index].GetDouble();
- }
+ data[index] = float(value_array[index].GetDouble());
for (; index < type_size / 4; index++)
- {
data[index] = 0.0f;
- }
- auto* uniform = new bgfx_uniform(name, type);
- uniform->set((void*)data, type_size);
- delete [] data;
+ auto uniform = std::make_unique<bgfx_uniform>(name, type);
+ uniform->set(data, type_size);
+ std::free(data);
return uniform;
}
-bool uniform_reader::validate_parameters(const Value& value, std::string prefix)
+bool uniform_reader::validate_parameters(const Value& value, const std::string &prefix)
{
- if (!READER_CHECK(value.HasMember("name"), (prefix + "Must have string value 'name' (what is this uniform called in the shader code?)\n").c_str())) return false;
- if (!READER_CHECK(value["name"].IsString(), (prefix + "Value 'name' must be a string\n").c_str())) return false;
- if (!READER_CHECK(value.HasMember("type"), (prefix + "Must have string value 'type' [int, vec4, mat3, mat4]\n").c_str())) return false;
- if (!READER_CHECK(value.HasMember("values"), (prefix + "Must have array value 'values' (what are the uniform's default values?)\n").c_str())) return false;
- if (!READER_CHECK(value["values"].IsArray(), (prefix + "Value 'values' must be an array\n").c_str())) return false;
+ if (!READER_CHECK(value.HasMember("name"), "%sMust have string value 'name' (what is this uniform called in the shader code?)\n", prefix)) return false;
+ if (!READER_CHECK(value["name"].IsString(), "%sValue 'name' must be a string\n", prefix)) return false;
+ if (!READER_CHECK(value.HasMember("type"), "%sMust have string value 'type' [int, vec4, mat3, mat4]\n", prefix)) return false;
+ if (!READER_CHECK(value.HasMember("values"), "%sMust have array value 'values' (what are the uniform's default values?)\n", prefix)) return false;
+ if (!READER_CHECK(value["values"].IsArray(), "%sValue 'values' must be an array\n", prefix)) return false;
return true;
}
diff --git a/src/osd/modules/render/bgfx/uniformreader.h b/src/osd/modules/render/bgfx/uniformreader.h
index ce1b1e9ccbe..ebb3a485d63 100644
--- a/src/osd/modules/render/bgfx/uniformreader.h
+++ b/src/osd/modules/render/bgfx/uniformreader.h
@@ -6,27 +6,29 @@
//
//============================================================
+#ifndef MAME_RENDER_BGFX_UNIFORMREADER_H
+#define MAME_RENDER_BGFX_UNIFORMREADER_H
+
#pragma once
-#ifndef __DRAWBGFX_UNIFORM_READER__
-#define __DRAWBGFX_UNIFORM_READER__
+#include "statereader.h"
-#include <bgfx/bgfx.h>
+#include <memory>
+#include <string>
-#include "statereader.h"
class bgfx_uniform;
class uniform_reader : public state_reader
{
public:
- static bgfx_uniform* read_from_value(const Value& value, std::string prefix);
+ static std::unique_ptr<bgfx_uniform> read_from_value(const Value& value, const std::string &prefix);
private:
- static bool validate_parameters(const Value& value, std::string prefix);
+ static bool validate_parameters(const Value& value, const std::string &prefix);
static const int TYPE_COUNT = 4;
static const string_to_enum TYPE_NAMES[TYPE_COUNT];
};
-#endif // __DRAWBGFX_UNIFORM_READER__
+#endif // MAME_RENDER_BGFX_UNIFORMREADER_H
diff --git a/src/osd/modules/render/bgfx/valueuniform.cpp b/src/osd/modules/render/bgfx/valueuniform.cpp
index 8a018ac492a..e36ee3cbca8 100644
--- a/src/osd/modules/render/bgfx/valueuniform.cpp
+++ b/src/osd/modules/render/bgfx/valueuniform.cpp
@@ -10,13 +10,17 @@
//============================================================
#include "valueuniform.h"
-#include <cstring>
-bgfx_value_uniform::bgfx_value_uniform(bgfx_uniform* uniform, float* values, const int count)
+#include <algorithm>
+#include <cassert>
+
+
+bgfx_value_uniform::bgfx_value_uniform(bgfx_uniform* uniform, const float* values, const int count)
: bgfx_entry_uniform(uniform)
, m_count(count)
{
- memcpy(m_values, values, sizeof(float) * count);
+ assert(count <= std::size(m_values));
+ std::copy_n(values, count, m_values);
}
void bgfx_value_uniform::bind()
diff --git a/src/osd/modules/render/bgfx/valueuniform.h b/src/osd/modules/render/bgfx/valueuniform.h
index 40d207aa0bb..aa8139650a3 100644
--- a/src/osd/modules/render/bgfx/valueuniform.h
+++ b/src/osd/modules/render/bgfx/valueuniform.h
@@ -9,17 +9,17 @@
//
//============================================================
-#pragma once
+#ifndef MAME_RENDER_BGFX_VALUEUNIFORM_H
+#define MAME_RENDER_BGFX_VALUEUNIFORM_H
-#ifndef __DRAWBGFX_VALUE_UNIFORM__
-#define __DRAWBGFX_VALUE_UNIFORM__
+#pragma once
#include "entryuniform.h"
class bgfx_value_uniform : public bgfx_entry_uniform
{
public:
- bgfx_value_uniform(bgfx_uniform* uniform, float* values, const int count);
+ bgfx_value_uniform(bgfx_uniform* uniform, const float* values, const int count);
virtual void bind() override;
@@ -28,4 +28,4 @@ private:
const int m_count;
};
-#endif // __DRAWBGFX_VALUE_UNIFORM__
+#endif // MAME_RENDER_BGFX_VALUEUNIFORM_H
diff --git a/src/osd/modules/render/bgfx/valueuniformreader.cpp b/src/osd/modules/render/bgfx/valueuniformreader.cpp
index e71f1c86329..137a6d24719 100644
--- a/src/osd/modules/render/bgfx/valueuniformreader.cpp
+++ b/src/osd/modules/render/bgfx/valueuniformreader.cpp
@@ -11,7 +11,7 @@
#include "entryuniform.h"
#include "valueuniform.h"
-bgfx_entry_uniform* value_uniform_reader::read_from_value(const Value& value, std::string prefix, bgfx_uniform* uniform)
+bgfx_entry_uniform* value_uniform_reader::read_from_value(const Value& value, const std::string &prefix, bgfx_uniform* uniform)
{
if (!validate_parameters(value, prefix))
{
@@ -36,9 +36,9 @@ bgfx_entry_uniform* value_uniform_reader::read_from_value(const Value& value, st
return new bgfx_value_uniform(uniform, values, count);
}
-bool value_uniform_reader::validate_parameters(const Value& value, std::string prefix)
+bool value_uniform_reader::validate_parameters(const Value& value, const std::string &prefix)
{
- if (!READER_CHECK(value.HasMember("value"), (prefix + "Must have string value 'value' (what value is being assigned?)\n").c_str())) return false;
- if (!READER_CHECK(value["value"].IsArray() || value["value"].IsNumber(), (prefix + "Value 'value' must be numeric or an array\n").c_str())) return false;
+ if (!READER_CHECK(value.HasMember("value"), "%sMust have string value 'value' (what value is being assigned?)\n", prefix)) return false;
+ if (!READER_CHECK(value["value"].IsArray() || value["value"].IsNumber(), "%sValue 'value' must be numeric or an array\n", prefix)) return false;
return true;
}
diff --git a/src/osd/modules/render/bgfx/valueuniformreader.h b/src/osd/modules/render/bgfx/valueuniformreader.h
index 0b6fead1cca..ea544266a84 100644
--- a/src/osd/modules/render/bgfx/valueuniformreader.h
+++ b/src/osd/modules/render/bgfx/valueuniformreader.h
@@ -6,15 +6,14 @@
//
//================================================================
+#ifndef MAME_RENDER_BGFX_VALUEUNIFORMREADER_H
+#define MAME_RENDER_BGFX_VALUEUNIFORMREADER_H
+
#pragma once
-#ifndef __DRAWBGFX_VALUE_UNIFORM_READER__
-#define __DRAWBGFX_VALUE_UNIFORM_READER__
+#include "statereader.h"
#include <string>
-#include <map>
-
-#include "statereader.h"
class bgfx_entry_uniform;
class bgfx_uniform;
@@ -22,10 +21,10 @@ class bgfx_uniform;
class value_uniform_reader : public state_reader
{
public:
- static bgfx_entry_uniform* read_from_value(const Value& value, std::string prefix, bgfx_uniform* uniform);
+ static bgfx_entry_uniform* read_from_value(const Value& value, const std::string &prefix, bgfx_uniform* uniform);
private:
- static bool validate_parameters(const Value& value, std::string prefix);
+ static bool validate_parameters(const Value& value, const std::string &prefix);
};
-#endif // __DRAWBGFX_VALUE_UNIFORM_READER__
+#endif // MAME_RENDER_BGFX_VALUEUNIFORMREADER_H
diff --git a/src/osd/modules/render/bgfx/view.cpp b/src/osd/modules/render/bgfx/view.cpp
index 6935e19bca7..3a731fc71f8 100644
--- a/src/osd/modules/render/bgfx/view.cpp
+++ b/src/osd/modules/render/bgfx/view.cpp
@@ -13,9 +13,7 @@
#include "target.h"
void bgfx_view::update() {
- std::shared_ptr<osd_window> win = m_renderer->assert_window();
-
- const uint32_t window_index = win->index();
+ const uint32_t window_index = m_renderer->window().index();
const uint32_t width = m_renderer->get_window_width(window_index);
const uint32_t height = m_renderer->get_window_height(window_index);
diff --git a/src/osd/modules/render/bgfx/view.h b/src/osd/modules/render/bgfx/view.h
index a1793f89d0b..b257eb12ea4 100644
--- a/src/osd/modules/render/bgfx/view.h
+++ b/src/osd/modules/render/bgfx/view.h
@@ -4,12 +4,14 @@
#pragma once
#include "window.h"
+
#include <climits>
class renderer_bgfx;
class bgfx_target;
-class bgfx_view {
+class bgfx_view
+{
public:
bgfx_view(renderer_bgfx *renderer, uint32_t index, bgfx_target *backbuffer, std::vector<uint32_t> &seen_views)
: m_renderer(renderer)
@@ -21,7 +23,7 @@ public:
, m_view_height(0)
, m_z_near(0.0f)
, m_z_far(100.0f)
- , m_clear_color(0)
+ , m_clear_color(0x000000ff)
, m_clear_depth(1.0f)
, m_clear_stencil(0)
, m_do_clear_color(true)
diff --git a/src/osd/modules/render/bgfx/windowparameter.h b/src/osd/modules/render/bgfx/windowparameter.h
index 0ba4224de40..45df9060c71 100644
--- a/src/osd/modules/render/bgfx/windowparameter.h
+++ b/src/osd/modules/render/bgfx/windowparameter.h
@@ -6,22 +6,20 @@
//
//============================================================
-#pragma once
+#ifndef MAME_RENDER_BGFX_WINDOWPARAMETER_H
+#define MAME_RENDER_BGFX_WINDOWPARAMETER_H
-#ifndef __DRAWBGFX_WINDOW_PARAMETER__
-#define __DRAWBGFX_WINDOW_PARAMETER__
+#pragma once
-#include <bgfx/bgfx.h>
+#include "parameter.h"
#include <string>
-
-#include "parameter.h"
+#include <utility>
class bgfx_window_parameter : public bgfx_parameter
{
public:
- bgfx_window_parameter(std::string name, parameter_type type, uint32_t index) : bgfx_parameter(name, type), m_index(index) { }
- virtual ~bgfx_window_parameter() { }
+ bgfx_window_parameter(std::string &&name, parameter_type type, uint32_t index) : bgfx_parameter(std::move(name), type), m_index(index) { }
virtual float value() override { return float(m_index); }
virtual void tick(double delta) override { }
@@ -30,4 +28,4 @@ private:
uint32_t m_index;
};
-#endif // __DRAWBGFX_WINDOW_PARAMETER__
+#endif // MAME_RENDER_BGFX_WINDOWPARAMETER_H
diff --git a/src/osd/modules/render/bgfxutil.cpp b/src/osd/modules/render/bgfxutil.cpp
index e864cb98fb4..3d555bb60ad 100644
--- a/src/osd/modules/render/bgfxutil.cpp
+++ b/src/osd/modules/render/bgfxutil.cpp
@@ -14,10 +14,11 @@
#include "render.h"
-const bgfx::Memory* bgfx_util::mame_texture_data_to_bgfx_texture_data(bgfx::TextureFormat::Enum &dst_format, uint32_t src_format, int rowpixels, int height, const rgb_t *palette, void *base, uint16_t &out_pitch, int &width_div_factor, int &width_mul_factor)
+const bgfx::Memory* bgfx_util::mame_texture_data_to_bgfx_texture_data(bgfx::TextureFormat::Enum &dst_format, uint32_t src_format, int rowpixels, int width_margin, int height, const rgb_t *palette, void *base, uint16_t &out_pitch, int &width_div_factor, int &width_mul_factor)
{
bgfx::TextureInfo info;
const bgfx::Memory *data = nullptr;
+ uint8_t *adjusted_base = (uint8_t *)base;
switch (src_format)
{
@@ -28,7 +29,11 @@ const bgfx::Memory* bgfx_util::mame_texture_data_to_bgfx_texture_data(bgfx::Text
out_pitch = rowpixels * 2;
bgfx::calcTextureSize(info, rowpixels / width_div_factor, height, 1, false, false, 1, dst_format);
- data = bgfx::copy(base, info.storageSize);
+ if (width_margin)
+ {
+ adjusted_base -= width_margin * 2;
+ }
+ data = bgfx::copy(adjusted_base, info.storageSize);
break;
case PRIMFLAG_TEXFORMAT(TEXFORMAT_PALETTE16):
dst_format = bgfx::TextureFormat::R8;
@@ -37,7 +42,11 @@ const bgfx::Memory* bgfx_util::mame_texture_data_to_bgfx_texture_data(bgfx::Text
out_pitch = rowpixels * 2;
bgfx::calcTextureSize(info, rowpixels * width_mul_factor, height, 1, false, false, 1, dst_format);
- data = bgfx::copy(base, info.storageSize);
+ if (width_margin)
+ {
+ adjusted_base -= width_margin * 2;
+ }
+ data = bgfx::copy(adjusted_base, info.storageSize);
break;
case PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32):
case PRIMFLAG_TEXFORMAT(TEXFORMAT_RGB32):
@@ -47,7 +56,11 @@ const bgfx::Memory* bgfx_util::mame_texture_data_to_bgfx_texture_data(bgfx::Text
out_pitch = rowpixels * 4;
bgfx::calcTextureSize(info, rowpixels, height, 1, false, false, 1, dst_format);
- data = bgfx::copy(base, info.storageSize);
+ if (width_margin)
+ {
+ adjusted_base -= width_margin * 4;
+ }
+ data = bgfx::copy(adjusted_base, info.storageSize);
break;
}
@@ -96,6 +109,7 @@ uint64_t bgfx_util::get_blend_state(uint32_t blend)
case BLENDMODE_ALPHA:
return BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA);
case BLENDMODE_RGB_MULTIPLY:
+ //return BGFX_STATE_BLEND_FUNC_SEPARATE(BGFX_STATE_BLEND_DST_COLOR, BGFX_STATE_BLEND_INV_SRC_COLOR, BGFX_STATE_BLEND_ONE, BGFX_STATE_BLEND_ZERO);
return BGFX_STATE_BLEND_FUNC_SEPARATE(BGFX_STATE_BLEND_DST_COLOR, BGFX_STATE_BLEND_ZERO, BGFX_STATE_BLEND_DST_ALPHA, BGFX_STATE_BLEND_ZERO);
case BLENDMODE_ADD:
return BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_ONE);
@@ -104,3 +118,15 @@ uint64_t bgfx_util::get_blend_state(uint32_t blend)
}
return 0L;
}
+
+void bgfx_util::find_prescale_factor(uint16_t width, uint16_t height, uint16_t max_prescale_size, uint16_t &xprescale, uint16_t &yprescale)
+{
+ while (xprescale > 1 && width * xprescale > max_prescale_size)
+ {
+ xprescale--;
+ }
+ while (yprescale > 1 && height * yprescale > max_prescale_size)
+ {
+ yprescale--;
+ }
+}
diff --git a/src/osd/modules/render/bgfxutil.h b/src/osd/modules/render/bgfxutil.h
index db07e7fba77..aa108a6fb3b 100644
--- a/src/osd/modules/render/bgfxutil.h
+++ b/src/osd/modules/render/bgfxutil.h
@@ -15,9 +15,10 @@
class bgfx_util
{
public:
- static const bgfx::Memory* mame_texture_data_to_bgfx_texture_data(bgfx::TextureFormat::Enum &dst_format, uint32_t format, int rowpixels, int height, const rgb_t *palette, void *base, uint16_t &out_pitch, int &width_div_factor, int &width_mul_factor);
+ static const bgfx::Memory* mame_texture_data_to_bgfx_texture_data(bgfx::TextureFormat::Enum &dst_format, uint32_t format, int rowpixels, int width_margin, int height, const rgb_t *palette, void *base, uint16_t &out_pitch, int &width_div_factor, int &width_mul_factor);
static const bgfx::Memory* mame_texture_data_to_bgra32(uint32_t src_format, int width, int height, int rowpixels, const rgb_t *palette, void *base);
static uint64_t get_blend_state(uint32_t blend);
+ static void find_prescale_factor(uint16_t width, uint16_t height, uint16_t max_prescale_size, uint16_t &xprescale, uint16_t &yprescale);
};
#endif // RENDER_BGFX_UTIL
diff --git a/src/osd/modules/render/binpacker.h b/src/osd/modules/render/binpacker.h
index 1fb84596eec..52efe4abb85 100644
--- a/src/osd/modules/render/binpacker.h
+++ b/src/osd/modules/render/binpacker.h
@@ -29,7 +29,7 @@ public:
class packable_rectangle
{
public:
- packable_rectangle() : m_hash(0), m_width(-1), m_height(-1) { }
+ packable_rectangle() = default;
packable_rectangle(uint32_t hash, uint32_t format, int width, int height, int rowpixels, const rgb_t *palette, void *base)
: m_hash(hash)
, m_format(format)
@@ -50,19 +50,19 @@ public:
void* base() const { return m_base; }
private:
- uint32_t m_hash;
- uint32_t m_format;
- int m_width;
- int m_height;
- int m_rowpixels;
- const rgb_t* m_palette;
- void* m_base;
+ uint32_t m_hash = 0;
+ uint32_t m_format = 0;
+ int m_width = -1;
+ int m_height = -1;
+ int m_rowpixels = 0;
+ const rgb_t* m_palette = nullptr;
+ void* m_base = nullptr;
};
class packed_rectangle
{
public:
- packed_rectangle() : m_hash(0), m_format(0), m_width(-1), m_height(-1), m_x(-1), m_y(-1), m_rowpixels(0), m_palette(nullptr), m_base(nullptr) { }
+ packed_rectangle() = default;
packed_rectangle(const packed_rectangle& rect)
: m_hash(rect.m_hash)
, m_format(rect.m_format)
@@ -99,15 +99,15 @@ public:
void* base() const { return m_base; }
private:
- uint32_t m_hash;
- uint32_t m_format;
- int m_width;
- int m_height;
- int m_x;
- int m_y;
- int m_rowpixels;
- const rgb_t* m_palette;
- void* m_base;
+ uint32_t m_hash = 0;
+ uint32_t m_format = 0;
+ int m_width = -1;
+ int m_height = -1;
+ int m_x = -1;
+ int m_y = -1;
+ int m_rowpixels = 0;
+ const rgb_t* m_palette = nullptr;
+ void* m_base = nullptr;
};
bool pack(const std::vector<packable_rectangle>& rects, std::vector<std::vector<packed_rectangle>>& packs, int pack_size);
diff --git a/src/osd/modules/render/blit13.h b/src/osd/modules/render/blit13.ipp
index 1ac485bab8d..1ac485bab8d 100644
--- a/src/osd/modules/render/blit13.h
+++ b/src/osd/modules/render/blit13.ipp
diff --git a/src/osd/modules/render/d3d/d3dcomm.h b/src/osd/modules/render/d3d/d3dcomm.h
index c7dc58c6340..846d9dac791 100644
--- a/src/osd/modules/render/d3d/d3dcomm.h
+++ b/src/osd/modules/render/d3d/d3dcomm.h
@@ -6,8 +6,22 @@
//
//============================================================
-#ifndef __WIN_D3DCOMM__
-#define __WIN_D3DCOMM__
+#ifndef MAME_RENDER_D3D_D3DCOMM_H
+#define MAME_RENDER_D3D_D3DCOMM_H
+
+#pragma once
+
+// lib/util
+#include "bitmap.h"
+
+#include <windows.h>
+#include <d3d9.h>
+#include <wrl/client.h>
+
+#include <cstring>
+#include <memory>
+#include <vector>
+
//============================================================
// CONSTANTS
@@ -60,10 +74,7 @@ public:
class d3d_texture_manager
{
public:
- d3d_texture_manager(): m_renderer(nullptr), m_yuv_format(), m_texture_caps(0), m_texture_max_aspect(0), m_texture_max_width(0), m_texture_max_height(0), m_default_texture(nullptr)
- { }
-
- d3d_texture_manager(renderer_d3d9 *d3d);
+ d3d_texture_manager(renderer_d3d9 &d3d, IDirect3D9 *d3dobj);
void update_textures();
@@ -82,12 +93,12 @@ public:
texture_info * get_default_texture() const { return m_default_texture; }
- renderer_d3d9 * get_d3d() const { return m_renderer; }
+ renderer_d3d9 & get_d3d() const { return m_renderer; }
- std::vector<std::unique_ptr<texture_info>> m_texture_list; // list of active textures
+ std::vector<std::unique_ptr<texture_info> > m_texture_list; // list of active textures
private:
- renderer_d3d9 * m_renderer;
+ renderer_d3d9 & m_renderer;
D3DFORMAT m_yuv_format; // format to use for YUV textures
DWORD m_texture_caps; // textureCaps field
@@ -104,7 +115,7 @@ private:
class texture_info
{
public:
- texture_info(d3d_texture_manager *manager, const render_texinfo *texsource, int prescale, uint32_t flags);
+ texture_info(d3d_texture_manager &manager, const render_texinfo *texsource, int prescale, uint32_t flags);
~texture_info();
render_texinfo & get_texinfo() { return m_texinfo; }
@@ -125,15 +136,16 @@ public:
int get_cur_frame() const { return m_cur_frame; }
- IDirect3DTexture9 * get_tex() const { return m_d3dtex; }
- IDirect3DSurface9 * get_surface() const { return m_d3dsurface; }
- IDirect3DTexture9 * get_finaltex() const { return m_d3dfinaltex; }
+ IDirect3DTexture9 * get_finaltex() const { return m_d3dfinaltex.Get(); }
vec2f & get_uvstart() { return m_start; }
vec2f & get_uvstop() { return m_stop; }
vec2f & get_rawdims() { return m_rawdims; }
private:
+ using IDirect3DTexture9Ptr = Microsoft::WRL::ComPtr<IDirect3DTexture9>;
+ using IDirect3DSurface9Ptr = Microsoft::WRL::ComPtr<IDirect3DSurface9>;
+
void prescale();
void compute_size(int texwidth, int texheight);
void compute_size_subroutine(int texwidth, int texheight, int* p_width, int* p_height);
@@ -145,23 +157,23 @@ private:
inline void copyline_yuy16_to_uyvy(uint16_t *dst, const uint16_t *src, int width, const rgb_t *palette);
inline void copyline_yuy16_to_argb(uint32_t *dst, const uint16_t *src, int width, const rgb_t *palette);
- d3d_texture_manager * m_texture_manager; // texture manager pointer
+ d3d_texture_manager & m_texture_manager; // texture manager pointer
- renderer_d3d9 * m_renderer; // renderer pointer
+ renderer_d3d9 & m_renderer; // renderer pointer
- uint32_t m_hash; // hash value for the texture
- uint32_t m_flags; // rendering flags
+ const uint32_t m_hash; // hash value for the texture
+ const uint32_t m_flags; // rendering flags
render_texinfo m_texinfo; // copy of the texture info
+ const int m_type; // what type of texture are we?
vec2f m_start; // beggining UV coordinates
vec2f m_stop; // ending UV coordinates
vec2f m_rawdims; // raw dims of the texture
- int m_type; // what type of texture are we?
int m_xprescale, m_yprescale; // X/Y prescale factor
int m_xborderpix, m_yborderpix; // X/Y border pixels
int m_cur_frame; // what is our current frame?
- IDirect3DTexture9 * m_d3dtex; // Direct3D texture pointer
- IDirect3DSurface9 * m_d3dsurface; // Direct3D offscreen plain surface pointer
- IDirect3DTexture9 * m_d3dfinaltex; // Direct3D final (post-scaled) texture
+ IDirect3DTexture9Ptr m_d3dtex; // Direct3D texture pointer
+ IDirect3DSurface9Ptr m_d3dsurface; // Direct3D offscreen plain surface pointer
+ IDirect3DTexture9Ptr m_d3dfinaltex; // Direct3D final (post-scaled) texture
};
/* poly_info holds information about a single polygon/d3d primitive */
@@ -170,7 +182,7 @@ class poly_info
public:
void init(D3DPRIMITIVETYPE type, uint32_t count, uint32_t numverts,
uint32_t flags, texture_info *texture, uint32_t modmode,
- float prim_width, float prim_height)
+ float prim_width, float prim_height, uint32_t tint)
{
m_type = type;
m_count = count;
@@ -180,6 +192,7 @@ public:
m_modmode = modmode;
m_prim_width = prim_width;
m_prim_height = prim_height;
+ m_tint = tint;
}
D3DPRIMITIVETYPE type() const { return m_type; }
@@ -193,6 +206,8 @@ public:
float prim_width() const { return m_prim_width; }
float prim_height() const { return m_prim_height; }
+ DWORD tint() const { return m_tint; }
+
private:
D3DPRIMITIVETYPE m_type; // type of primitive
uint32_t m_count; // total number of primitives
@@ -204,6 +219,8 @@ private:
float m_prim_width; // used by quads
float m_prim_height; // used by quads
+
+ uint32_t m_tint; // color tint for primitive
};
/* vertex describes a single vertex */
@@ -222,24 +239,14 @@ class d3d_render_target
{
public:
// construction/destruction
- d3d_render_target(): target_width(0), target_height(0), width(0), height(0), screen_index(0), bloom_count(0)
+ d3d_render_target()
+ : target_width(0)
+ , target_height(0)
+ , width(0)
+ , height(0)
+ , screen_index(0)
+ , bloom_count(0)
{
- for (int index = 0; index < MAX_BLOOM_COUNT; index++)
- {
- bloom_texture[index] = nullptr;
- bloom_surface[index] = nullptr;
- }
-
- for (int index = 0; index < 2; index++)
- {
- source_texture[index] = nullptr;
- source_surface[index] = nullptr;
- target_texture[index] = nullptr;
- target_surface[index] = nullptr;
- }
-
- cache_texture = nullptr;
- cache_surface = nullptr;
}
~d3d_render_target();
@@ -257,20 +264,20 @@ public:
int screen_index;
- IDirect3DSurface9 *target_surface[2];
- IDirect3DTexture9 *target_texture[2];
- IDirect3DSurface9 *source_surface[2];
- IDirect3DTexture9 *source_texture[2];
+ Microsoft::WRL::ComPtr<IDirect3DSurface9> target_surface[2];
+ Microsoft::WRL::ComPtr<IDirect3DTexture9> target_texture[2];
+ Microsoft::WRL::ComPtr<IDirect3DSurface9> source_surface[2];
+ Microsoft::WRL::ComPtr<IDirect3DTexture9> source_texture[2];
- IDirect3DSurface9 *cache_surface;
- IDirect3DTexture9 *cache_texture;
+ Microsoft::WRL::ComPtr<IDirect3DSurface9> cache_surface;
+ Microsoft::WRL::ComPtr<IDirect3DTexture9> cache_texture;
- IDirect3DSurface9 *bloom_surface[MAX_BLOOM_COUNT];
- IDirect3DTexture9 *bloom_texture[MAX_BLOOM_COUNT];
+ Microsoft::WRL::ComPtr<IDirect3DSurface9> bloom_surface[MAX_BLOOM_COUNT];
+ Microsoft::WRL::ComPtr<IDirect3DTexture9> bloom_texture[MAX_BLOOM_COUNT];
float bloom_dims[MAX_BLOOM_COUNT][2];
int bloom_count;
};
-#endif
+#endif // MAME_RENDER_D3D_D3DCOMM_H
diff --git a/src/osd/modules/render/d3d/d3dhlsl.cpp b/src/osd/modules/render/d3d/d3dhlsl.cpp
index 22a6b5af508..52bec85f06f 100644
--- a/src/osd/modules/render/d3d/d3dhlsl.cpp
+++ b/src/osd/modules/render/d3d/d3dhlsl.cpp
@@ -8,15 +8,18 @@
// MAME headers
#include "emu.h"
+
#include "drivenum.h"
+#include "emuopts.h"
+#include "fileio.h"
+#include "main.h"
#include "render.h"
#include "rendlay.h"
#include "rendutil.h"
-#include "emuopts.h"
-#include "fileio.h"
+#include "screen.h"
+
#include "aviio.h"
#include "png.h"
-#include "screen.h"
// MAMEOS headers
#include "winmain.h"
@@ -50,8 +53,6 @@ class movie_recorder
public:
movie_recorder(running_machine& machine, renderer_d3d9 *d3d, int width, int height)
: m_initialized(false), m_d3d(d3d), m_width(width), m_height(height)
- , m_sys_texture(nullptr), m_sys_surface(nullptr)
- , m_vid_texture(nullptr), m_vid_surface(nullptr)
{
HRESULT result;
@@ -82,17 +83,6 @@ public:
~movie_recorder()
{
- if (m_sys_texture != nullptr)
- m_sys_texture->Release();
-
- if (m_sys_surface != nullptr)
- m_sys_surface->Release();
-
- if (m_vid_texture != nullptr)
- m_vid_texture->Release();
-
- if (m_vid_surface != nullptr)
- m_vid_surface->Release();
}
void record(const char *name)
@@ -109,7 +99,7 @@ public:
return;
// copy the frame from video memory, where it is not accessible, to system memory
- HRESULT result = m_d3d->get_device()->GetRenderTargetData(m_vid_surface, m_sys_surface);
+ HRESULT result = m_d3d->get_device()->GetRenderTargetData(m_vid_surface.Get(), m_sys_surface.Get());
if (FAILED(result))
return;
@@ -144,7 +134,7 @@ public:
m_avi_writer->audio_frame(buffer, samples_this_frame);
}
- IDirect3DSurface9 * target_surface() { return m_vid_surface; }
+ IDirect3DSurface9 * target_surface() { return m_vid_surface.Get(); }
private:
bool m_initialized;
@@ -156,10 +146,10 @@ private:
bitmap_rgb32 m_frame;
int m_width;
int m_height;
- IDirect3DTexture9 * m_sys_texture; // texture in system memory
- IDirect3DSurface9 * m_sys_surface; // surface in system memory
- IDirect3DTexture9 * m_vid_texture; // texture in video memory
- IDirect3DSurface9 * m_vid_surface; // surface in video memory
+ Microsoft::WRL::ComPtr<IDirect3DTexture9> m_sys_texture; // texture in system memory
+ Microsoft::WRL::ComPtr<IDirect3DSurface9> m_sys_surface; // surface in system memory
+ Microsoft::WRL::ComPtr<IDirect3DTexture9> m_vid_texture; // texture in video memory
+ Microsoft::WRL::ComPtr<IDirect3DSurface9> m_vid_surface; // surface in video memory
};
@@ -168,51 +158,32 @@ private:
//============================================================
shaders::shaders() :
- d3dintf(nullptr),
machine(nullptr),
d3d(nullptr),
post_fx_enable(false),
oversampling_enable(false),
num_screens(0),
- curr_screen(0),
+ num_targets(0),
+ curr_target(0),
acc_t(0),
delta_t(0),
shadow_texture(nullptr),
lut_texture(nullptr),
ui_lut_texture(nullptr),
options(nullptr),
- black_surface(nullptr),
- black_texture(nullptr),
recording_movie(false),
render_snap(false),
- snap_copy_target(nullptr),
- snap_copy_texture(nullptr),
- snap_target(nullptr),
- snap_texture(nullptr),
snap_width(0),
snap_height(0),
initialized(false),
- backbuffer(nullptr),
curr_effect(nullptr),
- default_effect(nullptr),
- prescale_effect(nullptr),
- post_effect(nullptr),
- distortion_effect(nullptr),
- scanline_effect(nullptr),
- focus_effect(nullptr),
- phosphor_effect(nullptr),
- deconverge_effect(nullptr),
- color_effect(nullptr),
- ntsc_effect(nullptr),
- bloom_effect(nullptr),
- downsample_effect(nullptr),
- vector_effect(nullptr),
- chroma_effect(nullptr),
+ diffuse_texture(nullptr),
curr_texture(nullptr),
curr_render_target(nullptr),
curr_poly(nullptr),
d3dx_create_effect_from_file_ptr(nullptr)
{
+ std::fill(std::begin(target_to_screen), std::end(target_to_screen), 0);
}
@@ -222,12 +193,7 @@ shaders::shaders() :
shaders::~shaders()
{
- for (slider* slider : internal_sliders)
- {
- delete slider;
- }
-
- if (options != nullptr)
+ if (options && (&last_options != options))
{
delete options;
options = nullptr;
@@ -244,11 +210,9 @@ void shaders::save_snapshot()
if (!enabled())
return;
- auto win = d3d->assert_window();
-
int width = snap_width;
int height = snap_height;
- if (win->swap_xy())
+ if (d3d->window().swap_xy())
{
std::swap(width, height);
}
@@ -289,8 +253,7 @@ void shaders::record_movie()
return;
}
- auto win = d3d->assert_window();
- osd_dim wdim = win->get_size();
+ osd_dim wdim = d3d->window().get_size();
recorder = std::make_unique<movie_recorder>(*machine, d3d, wdim.width(), wdim.height());
recorder->record(downcast<windows_options &>(machine->options()).d3d_hlsl_write());
@@ -323,11 +286,9 @@ void shaders::render_snapshot(IDirect3DSurface9 *surface)
if (!enabled())
return;
- auto win = d3d->assert_window();
-
int width = snap_width;
int height = snap_height;
- if (win->swap_xy())
+ if (d3d->window().swap_xy())
{
std::swap(width, height);
}
@@ -337,7 +298,7 @@ void shaders::render_snapshot(IDirect3DSurface9 *surface)
return;
// copy the texture
- HRESULT result = d3d->get_device()->GetRenderTargetData(surface, snap_copy_target);
+ HRESULT result = d3d->get_device()->GetRenderTargetData(surface, snap_copy_target.Get());
if (FAILED(result))
return;
@@ -378,29 +339,10 @@ void shaders::render_snapshot(IDirect3DSurface9 *surface)
if (FAILED(result))
osd_printf_verbose("Direct3D: Error %08lX during texture UnlockRect call\n", result);
- if (snap_texture != nullptr)
- {
- snap_texture->Release();
- snap_texture = nullptr;
- }
-
- if (snap_target != nullptr)
- {
- snap_target->Release();
- snap_target = nullptr;
- }
-
- if (snap_copy_texture != nullptr)
- {
- snap_copy_texture->Release();
- snap_copy_texture = nullptr;
- }
-
- if (snap_copy_target != nullptr)
- {
- snap_copy_target->Release();
- snap_copy_target = nullptr;
- }
+ snap_texture.Reset();
+ snap_target.Reset();
+ snap_copy_texture.Reset();
+ snap_copy_target.Reset();
}
@@ -440,25 +382,33 @@ void shaders::set_texture(texture_info *texture)
return;
}
- // set initial texture to use
- texture_info *default_texture = d3d->get_default_texture();
- default_effect->set_texture("Diffuse", (texture == nullptr) ? default_texture->get_finaltex() : texture->get_finaltex());
- if (options->yiq_enable)
+ if (texture)
{
- ntsc_effect->set_texture("Diffuse", (texture == nullptr) ? default_texture->get_finaltex() : texture->get_finaltex());
+ diffuse_texture = texture;
}
else
{
- color_effect->set_texture("Diffuse", (texture == nullptr) ? default_texture->get_finaltex() : texture->get_finaltex());
+ diffuse_texture = d3d->get_default_texture();
}
}
//============================================================
+// shaders::set_filter - indicates if screens should be
+// filtered on upscaling
+//============================================================
+
+void shaders::set_filter(bool filter_screens)
+{
+ this->filter_screens = filter_screens;
+}
+
+
+//============================================================
// shaders::init
//============================================================
-bool shaders::init(d3d_base *d3dintf, running_machine *machine, renderer_d3d9 *renderer)
+bool shaders::init(IDirect3D9 *d3dobj, running_machine *machine, renderer_d3d9 *renderer)
{
osd_printf_verbose("Direct3D: Initialize HLSL\n");
@@ -490,14 +440,10 @@ bool shaders::init(d3d_base *d3dintf, running_machine *machine, renderer_d3d9 *r
return false;
}
- d3dintf->post_fx_available = true;
-
- this->d3dintf = d3dintf;
+ this->d3dobj = d3dobj;
this->machine = machine;
this->d3d = renderer;
- enumerate_screens();
-
auto &winoptions = downcast<windows_options &>(machine->options());
post_fx_enable = winoptions.d3d_hlsl_enable();
@@ -505,19 +451,18 @@ bool shaders::init(d3d_base *d3dintf, running_machine *machine, renderer_d3d9 *r
snap_width = winoptions.d3d_snap_width();
snap_height = winoptions.d3d_snap_height();
- this->options = new hlsl_options;
- this->options->params_init = false;
-
- // copy last options if initialized
if (last_options.params_init)
{
+ // copy last options if initialized
osd_printf_verbose("Direct3D: First restore options\n");
options = &last_options;
}
-
- // read options if not initialized
- if (!options->params_init)
+ else
{
+ // read options if not initialized
+ options = new hlsl_options;
+ options->params_init = false;
+
strncpy(options->shadow_mask_texture, winoptions.screen_shadow_mask_texture(), sizeof(options->shadow_mask_texture));
options->shadow_mask_tile_mode = winoptions.screen_shadow_mask_tile_mode();
options->shadow_mask_alpha = winoptions.screen_shadow_mask_alpha();
@@ -599,6 +544,7 @@ bool shaders::init(d3d_base *d3dintf, running_machine *machine, renderer_d3d9 *r
osd_printf_verbose("Direct3D: First store options\n");
last_options = *options;
+ delete options;
options = &last_options;
}
@@ -613,11 +559,70 @@ bool shaders::init(d3d_base *d3dintf, running_machine *machine, renderer_d3d9 *r
//============================================================
+// shaders::begin_frame
+//
+// Enumerates the total number of screen textures present.
+//
+// Additionally, ensures the presence of necessary post-
+// processing geometry.
+//
+//============================================================
+
+void shaders::begin_frame(render_primitive_list *primlist)
+{
+ init_fsfx_quad();
+
+ std::fill(std::begin(target_to_screen), std::end(target_to_screen), 0);
+ std::fill(std::begin(targets_per_screen), std::end(targets_per_screen), 0);
+ EQUIVALENT_ARRAY(target_to_screen, render_container *) containers;
+
+ // Maximum potential runtime O(max_num_targets^2)
+ num_targets = 0;
+ num_screens = 0;
+ curr_target = 0;
+ for (render_primitive &prim : *primlist)
+ {
+ if (PRIMFLAG_GET_SCREENTEX(prim.flags))
+ {
+ int screen_index = 0;
+ for (; screen_index < num_screens && containers[screen_index] != prim.container; screen_index++);
+ containers[screen_index] = prim.container;
+ target_to_screen[num_targets] = screen_index;
+ targets_per_screen[screen_index]++;
+ if (screen_index >= num_screens)
+ num_screens++;
+ num_targets++;
+ }
+ }
+
+ diffuse_texture = d3d->get_default_texture();
+}
+
+
+//============================================================
+// shaders::end_frame
+//
+// Closes out any still-active effects at the end of
+// rendering.
+//
+//============================================================
+
+void shaders::end_frame()
+{
+ if (curr_effect->is_active())
+ {
+ curr_effect->end();
+ }
+}
+
+
+//============================================================
// shaders::init_fsfx_quad
//
// Called always at the start of each frame so that the two
// triangles used for the post-processing effects are always
-// at the beginning of the vertex buffer
+// at the beginning of the vertex buffer.
+//
//============================================================
void shaders::init_fsfx_quad()
@@ -714,7 +719,7 @@ int shaders::create_resources()
return 1;
}
black_texture->GetSurfaceLevel(0, &black_surface);
- result = d3d->get_device()->SetRenderTarget(0, black_surface);
+ result = d3d->get_device()->SetRenderTarget(0, black_surface.Get());
if (FAILED(result))
osd_printf_verbose("Direct3D: Error %08lX during device SetRenderTarget call\n", result);
@@ -722,7 +727,7 @@ int shaders::create_resources()
if (FAILED(result))
osd_printf_verbose("Direct3D: Error %08lX during device clear call\n", result);
- result = d3d->get_device()->SetRenderTarget(0, backbuffer);
+ result = d3d->get_device()->SetRenderTarget(0, backbuffer.Get());
if (FAILED(result))
osd_printf_verbose("Direct3D: Error %08lX during device SetRenderTarget call\n", result);
@@ -747,7 +752,7 @@ int shaders::create_resources()
texture.seqid = 0;
// now create it (no prescale, no wrap)
- auto tex = std::make_unique<texture_info>(d3d->get_texture_manager(), &texture, 1, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32));
+ auto tex = std::make_unique<texture_info>(*d3d->get_texture_manager(), &texture, 1, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32));
shadow_texture = tex.get();
d3d->get_texture_manager()->m_texture_list.push_back(std::move(tex));
}
@@ -770,7 +775,7 @@ int shaders::create_resources()
texture.seqid = 0;
// now create it (no prescale, no wrap)
- auto tex = std::make_unique<texture_info>(d3d->get_texture_manager(), &texture, 1, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32));
+ auto tex = std::make_unique<texture_info>(*d3d->get_texture_manager(), &texture, 1, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32));
lut_texture = tex.get();
d3d->get_texture_manager()->m_texture_list.push_back(std::move(tex));
}
@@ -793,74 +798,66 @@ int shaders::create_resources()
texture.seqid = 0;
// now create it (no prescale, no wrap)
- auto tex = std::make_unique<texture_info>(d3d->get_texture_manager(), &texture, 1, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32));
+ auto tex = std::make_unique<texture_info>(*d3d->get_texture_manager(), &texture, 1, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32));
ui_lut_texture = tex.get();
d3d->get_texture_manager()->m_texture_list.push_back(std::move(tex));
}
const char *fx_dir = downcast<windows_options &>(machine->options()).screen_post_fx_dir();
- default_effect = new effect(this, d3d->get_device(), "primary.fx", fx_dir);
- post_effect = new effect(this, d3d->get_device(), "post.fx", fx_dir);
- distortion_effect = new effect(this, d3d->get_device(), "distortion.fx", fx_dir);
- prescale_effect = new effect(this, d3d->get_device(), "prescale.fx", fx_dir);
- phosphor_effect = new effect(this, d3d->get_device(), "phosphor.fx", fx_dir);
- focus_effect = new effect(this, d3d->get_device(), "focus.fx", fx_dir);
- scanline_effect = new effect(this, d3d->get_device(), "scanline.fx", fx_dir);
- deconverge_effect = new effect(this, d3d->get_device(), "deconverge.fx", fx_dir);
- color_effect = new effect(this, d3d->get_device(), "color.fx", fx_dir);
- ntsc_effect = new effect(this, d3d->get_device(), "ntsc.fx", fx_dir);
- bloom_effect = new effect(this, d3d->get_device(), "bloom.fx", fx_dir);
- downsample_effect = new effect(this, d3d->get_device(), "downsample.fx", fx_dir);
- vector_effect = new effect(this, d3d->get_device(), "vector.fx", fx_dir);
- chroma_effect = new effect(this, d3d->get_device(), "chroma.fx", fx_dir);
-
- if (!default_effect->is_valid() ||
- !post_effect->is_valid() ||
- !distortion_effect->is_valid() ||
- !prescale_effect->is_valid() ||
- !phosphor_effect->is_valid() ||
- !focus_effect->is_valid() ||
- !scanline_effect->is_valid() ||
- !deconverge_effect->is_valid() ||
- !color_effect->is_valid() ||
- !ntsc_effect->is_valid() ||
- !bloom_effect->is_valid() ||
- !downsample_effect->is_valid() ||
- !vector_effect->is_valid() ||
- !chroma_effect->is_valid())
- {
- return 1;
- }
-
- std::array<effect*, 15> effects = {
- default_effect,
- post_effect,
- distortion_effect,
- prescale_effect,
- phosphor_effect,
- focus_effect,
- scanline_effect,
- deconverge_effect,
- color_effect,
- ntsc_effect,
- color_effect,
- bloom_effect,
- downsample_effect,
- vector_effect,
- chroma_effect
- };
-
- for (int i = 0; i < effects.size(); i++)
- {
- effects[i]->add_uniform("SourceDims", uniform::UT_VEC2, uniform::CU_SOURCE_DIMS);
- effects[i]->add_uniform("TargetDims", uniform::UT_VEC2, uniform::CU_TARGET_DIMS);
- effects[i]->add_uniform("TargetScale", uniform::UT_FLOAT, uniform::CU_TARGET_SCALE);
- effects[i]->add_uniform("ScreenDims", uniform::UT_VEC2, uniform::CU_SCREEN_DIMS);
- effects[i]->add_uniform("ScreenCount", uniform::UT_INT, uniform::CU_SCREEN_COUNT);
- effects[i]->add_uniform("QuadDims", uniform::UT_VEC2, uniform::CU_QUAD_DIMS);
- effects[i]->add_uniform("SwapXY", uniform::UT_BOOL, uniform::CU_SWAP_XY);
- effects[i]->add_uniform("VectorScreen", uniform::UT_BOOL, uniform::CU_VECTOR_SCREEN);
+ default_effect = std::make_unique<effect>(this, d3d->get_device(), "primary.fx", fx_dir);
+ ui_effect = std::make_unique<effect>(this, d3d->get_device(), "primary.fx", fx_dir);
+ ui_wrap_effect = std::make_unique<effect>(this, d3d->get_device(), "primary.fx", fx_dir);
+ vector_buffer_effect = std::make_unique<effect>(this, d3d->get_device(), "primary.fx", fx_dir);
+ post_effect = std::make_unique<effect>(this, d3d->get_device(), "post.fx", fx_dir);
+ distortion_effect = std::make_unique<effect>(this, d3d->get_device(), "distortion.fx", fx_dir);
+ prescale_effect = std::make_unique<effect>(this, d3d->get_device(), "prescale.fx", fx_dir);
+ prescale_point_effect = std::make_unique<effect>(this, d3d->get_device(), "prescale.fx", fx_dir);
+ phosphor_effect = std::make_unique<effect>(this, d3d->get_device(), "phosphor.fx", fx_dir);
+ focus_effect = std::make_unique<effect>(this, d3d->get_device(), "focus.fx", fx_dir);
+ scanline_effect = std::make_unique<effect>(this, d3d->get_device(), "scanline.fx", fx_dir);
+ deconverge_effect = std::make_unique<effect>(this, d3d->get_device(), "deconverge.fx", fx_dir);
+ color_effect = std::make_unique<effect>(this, d3d->get_device(), "color.fx", fx_dir);
+ ntsc_effect = std::make_unique<effect>(this, d3d->get_device(), "ntsc.fx", fx_dir);
+ bloom_effect = std::make_unique<effect>(this, d3d->get_device(), "bloom.fx", fx_dir);
+ downsample_effect = std::make_unique<effect>(this, d3d->get_device(), "downsample.fx", fx_dir);
+ vector_effect = std::make_unique<effect>(this, d3d->get_device(), "vector.fx", fx_dir);
+ chroma_effect = std::make_unique<effect>(this, d3d->get_device(), "chroma.fx", fx_dir);
+
+ std::array<effect*, 18> effects = {
+ default_effect.get(),
+ ui_effect.get(),
+ ui_wrap_effect.get(),
+ vector_buffer_effect.get(),
+ post_effect.get(),
+ distortion_effect.get(),
+ prescale_effect.get(),
+ prescale_point_effect.get(),
+ phosphor_effect.get(),
+ focus_effect.get(),
+ scanline_effect.get(),
+ deconverge_effect.get(),
+ color_effect.get(),
+ ntsc_effect.get(),
+ bloom_effect.get(),
+ downsample_effect.get(),
+ vector_effect.get(),
+ chroma_effect.get() };
+
+ for (effect *eff : effects)
+ {
+ if (!eff->is_valid())
+ return 1;
+ }
+
+ for (effect *eff : effects)
+ {
+ eff->add_uniform("TargetDims", uniform::UT_VEC2, uniform::CU_TARGET_DIMS);
+ eff->add_uniform("TargetScale", uniform::UT_FLOAT, uniform::CU_TARGET_SCALE);
+ eff->add_uniform("ScreenDims", uniform::UT_VEC2, uniform::CU_SCREEN_DIMS);
+ eff->add_uniform("ScreenCount", uniform::UT_INT, uniform::CU_SCREEN_COUNT);
+ eff->add_uniform("SwapXY", uniform::UT_BOOL, uniform::CU_SWAP_XY);
+ eff->add_uniform("VectorScreen", uniform::UT_BOOL, uniform::CU_VECTOR_SCREEN);
}
ntsc_effect->add_uniform("CCValue", uniform::UT_FLOAT, uniform::CU_NTSC_CCFREQ);
@@ -873,6 +870,7 @@ int shaders::create_resources()
ntsc_effect->add_uniform("IFreqResponse", uniform::UT_FLOAT, uniform::CU_NTSC_IFREQ);
ntsc_effect->add_uniform("QFreqResponse", uniform::UT_FLOAT, uniform::CU_NTSC_QFREQ);
ntsc_effect->add_uniform("ScanTime", uniform::UT_FLOAT, uniform::CU_NTSC_HTIME);
+ ntsc_effect->add_uniform("SourceDims", uniform::UT_VEC2, uniform::CU_SOURCE_DIMS);
color_effect->add_uniform("RedRatios", uniform::UT_VEC3, uniform::CU_COLOR_RED_RATIOS);
color_effect->add_uniform("GrnRatios", uniform::UT_VEC3, uniform::CU_COLOR_GRN_RATIOS);
@@ -880,6 +878,8 @@ int shaders::create_resources()
color_effect->add_uniform("Offset", uniform::UT_VEC3, uniform::CU_COLOR_OFFSET);
color_effect->add_uniform("Scale", uniform::UT_VEC3, uniform::CU_COLOR_SCALE);
color_effect->add_uniform("Saturation", uniform::UT_FLOAT, uniform::CU_COLOR_SATURATION);
+ color_effect->add_uniform("SourceDims", uniform::UT_VEC2, uniform::CU_SOURCE_DIMS);
+ color_effect->add_uniform("LutEnable", uniform::UT_BOOL, uniform::CU_LUT_ENABLE);
deconverge_effect->add_uniform("ConvergeX", uniform::UT_VEC3, uniform::CU_CONVERGE_LINEAR_X);
deconverge_effect->add_uniform("ConvergeY", uniform::UT_VEC3, uniform::CU_CONVERGE_LINEAR_Y);
@@ -892,6 +892,8 @@ int shaders::create_resources()
scanline_effect->add_uniform("ScanlineVariation", uniform::UT_FLOAT, uniform::CU_POST_SCANLINE_VARIATION);
scanline_effect->add_uniform("ScanlineBrightScale", uniform::UT_FLOAT, uniform::CU_POST_SCANLINE_BRIGHT_SCALE);
scanline_effect->add_uniform("ScanlineBrightOffset", uniform::UT_FLOAT, uniform::CU_POST_SCANLINE_BRIGHT_OFFSET);
+ scanline_effect->add_uniform("QuadDims", uniform::UT_VEC2, uniform::CU_QUAD_DIMS);
+ scanline_effect->add_uniform("SourceDims", uniform::UT_VEC2, uniform::CU_SOURCE_DIMS);
focus_effect->add_uniform("Defocus", uniform::UT_VEC2, uniform::CU_FOCUS_SIZE);
@@ -904,9 +906,15 @@ int shaders::create_resources()
post_effect->add_uniform("Floor", uniform::UT_VEC3, uniform::CU_POST_FLOOR);
post_effect->add_uniform("ChomaMode", uniform::UT_INT, uniform::CU_CHROMA_MODE);
post_effect->add_uniform("ConversionGain", uniform::UT_VEC3, uniform::CU_CHROMA_CONVERSION_GAIN);
+ post_effect->add_uniform("QuadDims", uniform::UT_VEC2, uniform::CU_QUAD_DIMS);
+ post_effect->add_uniform("SourceDims", uniform::UT_VEC2, uniform::CU_SOURCE_DIMS);
phosphor_effect->add_uniform("Phosphor", uniform::UT_VEC3, uniform::CU_PHOSPHOR_LIFE);
+ bloom_effect->add_uniform("SourceDims", uniform::UT_VEC2, uniform::CU_SOURCE_DIMS);
+
+ downsample_effect->add_uniform("QuadDims", uniform::UT_VEC2, uniform::CU_QUAD_DIMS);
+
chroma_effect->add_uniform("YGain", uniform::UT_VEC3, uniform::CU_CHROMA_Y_GAIN);
chroma_effect->add_uniform("ChromaA", uniform::UT_VEC2, uniform::CU_CHROMA_A);
chroma_effect->add_uniform("ChromaB", uniform::UT_VEC2, uniform::CU_CHROMA_B);
@@ -919,9 +927,19 @@ int shaders::create_resources()
distortion_effect->add_uniform("RoundCornerAmount", uniform::UT_FLOAT, uniform::CU_POST_ROUND_CORNER);
distortion_effect->add_uniform("SmoothBorderAmount", uniform::UT_FLOAT, uniform::CU_POST_SMOOTH_BORDER);
distortion_effect->add_uniform("ReflectionAmount", uniform::UT_FLOAT, uniform::CU_POST_REFLECTION);
+ distortion_effect->add_uniform("QuadDims", uniform::UT_VEC2, uniform::CU_QUAD_DIMS);
+
+ prescale_effect->add_uniform("SourceDims", uniform::UT_VEC2, uniform::CU_SOURCE_DIMS);
+
+ prescale_point_effect->add_uniform("SourceDims", uniform::UT_VEC2, uniform::CU_SOURCE_DIMS);
- default_effect->add_uniform("LutEnable", uniform::UT_BOOL, uniform::CU_LUT_ENABLE);
- default_effect->add_uniform("UiLutEnable", uniform::UT_BOOL, uniform::CU_UI_LUT_ENABLE);
+ ui_effect->add_uniform("LutEnable", uniform::UT_BOOL, uniform::CU_LUT_ENABLE);
+ ui_effect->add_uniform("UiLutEnable", uniform::UT_BOOL, uniform::CU_UI_LUT_ENABLE);
+
+ ui_wrap_effect->add_uniform("LutEnable", uniform::UT_BOOL, uniform::CU_LUT_ENABLE);
+ ui_wrap_effect->add_uniform("UiLutEnable", uniform::UT_BOOL, uniform::CU_UI_LUT_ENABLE);
+
+ vector_buffer_effect->add_uniform("LutEnable", uniform::UT_BOOL, uniform::CU_LUT_ENABLE);
return 0;
}
@@ -933,24 +951,24 @@ int shaders::create_resources()
void shaders::begin_draw()
{
- double t;
-
if (!enabled())
- {
return;
- }
- curr_screen = 0;
- curr_effect = default_effect;
+ curr_target = 0;
+
// Update for delta_time
- t = machine->time().as_double();
+ const double t = machine->time().as_double();
delta_t = t - acc_t;
acc_t = t;
default_effect->set_technique("ScreenTechnique");
+ ui_effect->set_technique("UiTechnique");
+ ui_wrap_effect->set_technique("UiWrapTechnique");
+ vector_buffer_effect->set_technique("VectorBufferTechnique");
post_effect->set_technique("DefaultTechnique");
distortion_effect->set_technique("DefaultTechnique");
prescale_effect->set_technique("DefaultTechnique");
+ prescale_point_effect->set_technique("PointTechnique");
phosphor_effect->set_technique("DefaultTechnique");
focus_effect->set_technique("DefaultTechnique");
scanline_effect->set_technique("DefaultTechnique");
@@ -963,11 +981,31 @@ void shaders::begin_draw()
vector_effect->set_technique("DefaultTechnique");
chroma_effect->set_technique("DefaultTechnique");
- HRESULT result = d3d->get_device()->SetRenderTarget(0, backbuffer);
+ HRESULT result = d3d->get_device()->SetRenderTarget(0, backbuffer.Get());
if (FAILED(result))
{
osd_printf_verbose("Direct3D: Error %08lX during device SetRenderTarget call\n", result);
}
+
+ set_curr_effect(default_effect.get());
+}
+
+
+//============================================================
+// shaders::set_curr_effect
+//============================================================
+
+void shaders::set_curr_effect(effect *curr_effect)
+{
+ if (this->curr_effect == curr_effect)
+ {
+ return;
+ }
+ if (this->curr_effect && this->curr_effect->is_active())
+ {
+ this->curr_effect->end();
+ }
+ this->curr_effect = curr_effect;
}
@@ -994,7 +1032,7 @@ void shaders::blit(
if (clear_dst)
{
- result = d3d->get_device()->Clear(0, nullptr, D3DCLEAR_TARGET, D3DCOLOR_ARGB(1,0,0,0), 0, 0);
+ result = d3d->get_device()->Clear(0, nullptr, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0xff,0,0,0), 0, 0);
if (FAILED(result))
{
osd_printf_verbose("Direct3D: Error %08lX during device clear call\n", result);
@@ -1002,24 +1040,17 @@ void shaders::blit(
}
}
- UINT num_passes = 0;
- curr_effect->begin(&num_passes, 0);
-
- for (UINT pass = 0; pass < num_passes; pass++)
+ if (!curr_effect->is_active())
{
- curr_effect->begin_pass(pass);
-
- // add the primitives
- result = d3d->get_device()->DrawPrimitive(prim_type, prim_index, prim_count);
- if (FAILED(result))
- {
- osd_printf_verbose("Direct3D: Error %08lX during device DrawPrimitive call\n", result);
- }
-
- curr_effect->end_pass();
+ curr_effect->begin(0);
}
- curr_effect->end();
+ // add the primitives
+ result = d3d->get_device()->DrawPrimitive(prim_type, prim_index, prim_count);
+ if (FAILED(result))
+ {
+ osd_printf_verbose("Direct3D: Error %08lX during device DrawPrimitive call\n", result);
+ }
}
//============================================================
@@ -1056,14 +1087,15 @@ int shaders::ntsc_pass(d3d_render_target *rt, int source_index, poly_info *poly,
// initial "Diffuse" texture is set in shaders::set_texture()
- curr_effect = ntsc_effect;
+ set_curr_effect(ntsc_effect.get());
+ curr_effect->set_texture("Diffuse", diffuse_texture->get_finaltex());
curr_effect->update_uniforms();
curr_effect->set_float("SignalOffset", signal_offset);
next_index = rt->next_index(next_index);
- blit(rt->source_surface[next_index], false, D3DPT_TRIANGLELIST, 0, 2);
+ blit(rt->source_surface[next_index].Get(), false, D3DPT_TRIANGLELIST, 0, 2);
- color_effect->set_texture("Diffuse", rt->source_texture[next_index]);
+ color_effect->set_texture("Diffuse", rt->source_texture[next_index].Get());
return next_index;
}
@@ -1112,13 +1144,23 @@ int shaders::color_convolution_pass(d3d_render_target *rt, int source_index, pol
{
int next_index = source_index;
- curr_effect = color_effect;
- curr_effect->update_uniforms();
+ set_curr_effect(color_effect.get());
- // initial "Diffuse" texture is set in shaders::set_texture() or the result of shaders::ntsc_pass()
+ // initial "Diffuse" texture is set in shaders::ntsc_pass() if NTSC processing is enabled
+ if (!options->yiq_enable)
+ {
+ curr_effect->set_texture("Diffuse", diffuse_texture->get_finaltex());
+ }
+
+ curr_effect->update_uniforms();
+ uint32_t tint = (uint32_t)poly->tint();
+ float prim_tint[3] = { ((tint >> 16) & 0xff) / 255.0f, ((tint >> 8) & 0xff) / 255.0f, (tint & 0xff) / 255.0f };
+ curr_effect->set_vector("PrimTint", 3, prim_tint);
+ curr_effect->set_texture("LutTexture", !lut_texture ? nullptr : lut_texture->get_finaltex());
+ curr_effect->set_bool("UiLutEnable", false);
next_index = rt->next_index(next_index);
- blit(rt->source_surface[next_index], false, D3DPT_TRIANGLELIST, 0, 2);
+ blit(rt->source_surface[next_index].Get(), false, D3DPT_TRIANGLELIST, 0, 2);
return next_index;
}
@@ -1127,12 +1169,12 @@ int shaders::prescale_pass(d3d_render_target *rt, int source_index, poly_info *p
{
int next_index = source_index;
- curr_effect = prescale_effect;
+ set_curr_effect(filter_screens ? prescale_effect.get() : prescale_point_effect.get());
curr_effect->update_uniforms();
- curr_effect->set_texture("Diffuse", rt->source_texture[next_index]);
+ curr_effect->set_texture("Diffuse", rt->source_texture[next_index].Get());
next_index = rt->next_index(next_index);
- blit(rt->target_surface[next_index], false, D3DPT_TRIANGLELIST, 0, 2);
+ blit(rt->target_surface[next_index].Get(), false, D3DPT_TRIANGLELIST, 0, 2);
return next_index;
}
@@ -1150,12 +1192,12 @@ int shaders::deconverge_pass(d3d_render_target *rt, int source_index, poly_info
return next_index;
}
- curr_effect = deconverge_effect;
+ set_curr_effect(deconverge_effect.get());
curr_effect->update_uniforms();
- curr_effect->set_texture("Diffuse", rt->target_texture[next_index]);
+ curr_effect->set_texture("Diffuse", rt->target_texture[next_index].Get());
next_index = rt->next_index(next_index);
- blit(rt->target_surface[next_index], false, D3DPT_TRIANGLELIST, 0, 2);
+ blit(rt->target_surface[next_index].Get(), false, D3DPT_TRIANGLELIST, 0, 2);
return next_index;
}
@@ -1165,12 +1207,11 @@ int shaders::scanline_pass(d3d_render_target *rt, int source_index, poly_info *p
int next_index = source_index;
// skip scanline if alpha is 0
- if (options->scanline_alpha == 0.0f)
- return next_index;
+ //if (options->scanline_alpha == 0.0f)
+ //return next_index;
- auto win = d3d->assert_window();
screen_device_enumerator screen_iterator(machine->root_device());
- screen_device *screen = screen_iterator.byindex(curr_screen);
+ screen_device *screen = screen_iterator.byindex(target_to_screen[curr_target]);
render_container &screen_container = screen->container();
float xscale = 1.0f / screen_container.xscale();
float yscale = 1.0f / screen_container.yscale();
@@ -1179,16 +1220,16 @@ int shaders::scanline_pass(d3d_render_target *rt, int source_index, poly_info *p
float screen_scale[] = { xscale, yscale };
float screen_offset[] = { xoffset, yoffset };
- curr_effect = scanline_effect;
+ set_curr_effect(scanline_effect.get());
curr_effect->update_uniforms();
- curr_effect->set_texture("Diffuse", rt->target_texture[next_index]);
+ curr_effect->set_texture("Diffuse", rt->target_texture[next_index].Get());
curr_effect->set_vector("ScreenScale", 2, screen_scale);
curr_effect->set_vector("ScreenOffset", 2, screen_offset);
curr_effect->set_float("ScanlineOffset",
curr_texture->get_cur_frame() == 0 ?
0.0f : options->scanline_jitter);
next_index = rt->next_index(next_index);
- blit(rt->target_surface[next_index], false, D3DPT_TRIANGLELIST, 0, 2);
+ blit(rt->target_surface[next_index].Get(), false, D3DPT_TRIANGLELIST, 0, 2);
return next_index;
}
@@ -1202,12 +1243,12 @@ int shaders::defocus_pass(d3d_render_target *rt, int source_index, poly_info *po
return next_index;
}
- curr_effect = focus_effect;
+ set_curr_effect(focus_effect.get());
curr_effect->update_uniforms();
- curr_effect->set_texture("Diffuse", rt->target_texture[next_index]);
+ curr_effect->set_texture("Diffuse", rt->target_texture[next_index].Get());
next_index = rt->next_index(next_index);
- blit(rt->target_surface[next_index], false, D3DPT_TRIANGLELIST, 0, 2);
+ blit(rt->target_surface[next_index].Get(), false, D3DPT_TRIANGLELIST, 0, 2);
return next_index;
}
@@ -1223,23 +1264,23 @@ int shaders::phosphor_pass(d3d_render_target *rt, int source_index, poly_info *p
}
// Shader needs time between last update
- curr_effect = phosphor_effect;
+ set_curr_effect(phosphor_effect.get());
curr_effect->update_uniforms();
- curr_effect->set_texture("Diffuse", rt->target_texture[next_index]);
- curr_effect->set_texture("LastPass", rt->cache_texture);
+ curr_effect->set_texture("Diffuse", rt->target_texture[next_index].Get());
+ curr_effect->set_texture("LastPass", rt->cache_texture.Get());
curr_effect->set_bool("Passthrough", false);
curr_effect->set_float("DeltaTime", delta_time());
next_index = rt->next_index(next_index);
- blit(rt->target_surface[next_index], false, D3DPT_TRIANGLELIST, 0, 2);
+ blit(rt->target_surface[next_index].Get(), false, D3DPT_TRIANGLELIST, 0, 2);
// Pass along our phosphor'd screen
curr_effect->update_uniforms();
- curr_effect->set_texture("Diffuse", rt->target_texture[next_index]);
- curr_effect->set_texture("LastPass", rt->target_texture[next_index]);
+ curr_effect->set_texture("Diffuse", rt->target_texture[next_index].Get());
+ curr_effect->set_texture("LastPass", rt->target_texture[next_index].Get());
curr_effect->set_bool("Passthrough", true);
- blit(rt->cache_surface, false, D3DPT_TRIANGLELIST, 0, 2);
+ blit(rt->cache_surface.Get(), false, D3DPT_TRIANGLELIST, 0, 2);
return next_index;
}
@@ -1248,10 +1289,8 @@ int shaders::post_pass(d3d_render_target *rt, int source_index, poly_info *poly,
{
int next_index = source_index;
- auto win = d3d->assert_window();
-
screen_device_enumerator screen_iterator(machine->root_device());
- screen_device *screen = screen_iterator.byindex(curr_screen);
+ screen_device *screen = screen_iterator.byindex(target_to_screen[curr_target]);
render_container &screen_container = screen->container();
float xscale = 1.0f / screen_container.xscale();
@@ -1270,11 +1309,11 @@ int shaders::post_pass(d3d_render_target *rt, int source_index, poly_info *poly,
float(back_color_rgb.g()) / 255.0f,
float(back_color_rgb.b()) / 255.0f };
- curr_effect = post_effect;
+ set_curr_effect(post_effect.get());
curr_effect->update_uniforms();
- curr_effect->set_texture("ShadowTexture", shadow_texture == nullptr ? nullptr : shadow_texture->get_finaltex());
+ curr_effect->set_texture("ShadowTexture", !shadow_texture ? nullptr : shadow_texture->get_finaltex());
curr_effect->set_int("ShadowTileMode", options->shadow_mask_tile_mode);
- curr_effect->set_texture("DiffuseTexture", rt->target_texture[next_index]);
+ curr_effect->set_texture("DiffuseTexture", rt->target_texture[next_index].Get());
curr_effect->set_vector("BackColor", 3, back_color);
curr_effect->set_vector("ScreenScale", 2, screen_scale);
curr_effect->set_vector("ScreenOffset", 2, screen_offset);
@@ -1283,7 +1322,7 @@ int shaders::post_pass(d3d_render_target *rt, int source_index, poly_info *poly,
curr_effect->set_bool("PrepareBloom", prepare_bloom);
next_index = rt->next_index(next_index);
- blit(prepare_bloom ? rt->source_surface[next_index] : rt->target_surface[next_index], false, D3DPT_TRIANGLELIST, 0, 2);
+ blit(prepare_bloom ? rt->source_surface[next_index].Get() : rt->target_surface[next_index].Get(), false, D3DPT_TRIANGLELIST, 0, 2);
return next_index;
}
@@ -1292,11 +1331,11 @@ int shaders::chroma_pass(d3d_render_target *rt, int source_index, poly_info *pol
{
int next_index = source_index;
- curr_effect = chroma_effect;
+ set_curr_effect(chroma_effect.get());
curr_effect->update_uniforms();
- curr_effect->set_texture("Diffuse", rt->target_texture[next_index]);
+ curr_effect->set_texture("Diffuse", rt->target_texture[next_index].Get());
next_index = rt->next_index(next_index);
- blit(rt->target_surface[next_index], false, D3DPT_TRIANGLELIST, 0, 2);
+ blit(rt->target_surface[next_index].Get(), false, D3DPT_TRIANGLELIST, 0, 2);
return next_index;
}
@@ -1310,18 +1349,19 @@ int shaders::downsample_pass(d3d_render_target *rt, int source_index, poly_info
return next_index;
}
- curr_effect = downsample_effect;
- curr_effect->update_uniforms();
+ set_curr_effect(downsample_effect.get());
for (int bloom_index = 0; bloom_index < rt->bloom_count; bloom_index++)
{
+ curr_effect->update_uniforms();
curr_effect->set_vector("TargetDims", 2, rt->bloom_dims[bloom_index]);
curr_effect->set_texture("DiffuseTexture",
bloom_index == 0
- ? rt->source_texture[next_index]
- : rt->bloom_texture[bloom_index - 1]);
+ ? rt->source_texture[next_index].Get()
+ : rt->bloom_texture[bloom_index - 1].Get());
- blit(rt->bloom_surface[bloom_index], false, D3DPT_TRIANGLELIST, 0, 2);
+ blit(rt->bloom_surface[bloom_index].Get(), false, D3DPT_TRIANGLELIST, 0, 2);
+ downsample_effect->end();
}
return next_index;
@@ -1337,7 +1377,7 @@ int shaders::bloom_pass(d3d_render_target *rt, int source_index, poly_info *poly
return next_index;
}
- curr_effect = bloom_effect;
+ set_curr_effect(bloom_effect.get());
curr_effect->update_uniforms();
curr_effect->set_float("Level0Weight", options->bloom_level0_weight);
@@ -1354,22 +1394,22 @@ int shaders::bloom_pass(d3d_render_target *rt, int source_index, poly_info *poly
curr_effect->set_float("BloomScale", options->bloom_scale);
curr_effect->set_vector("BloomOverdrive", 3, options->bloom_overdrive);
- curr_effect->set_texture("DiffuseTexture", rt->target_texture[next_index]);
+ curr_effect->set_texture("DiffuseTexture", rt->target_texture[next_index].Get());
char name[14] = "BloomTexture*";
for (int index = 1; index < rt->bloom_count; index++)
{
name[12] = 'A' + index - 1;
- curr_effect->set_texture(name, rt->bloom_texture[index - 1]);
+ curr_effect->set_texture(name, rt->bloom_texture[index - 1].Get());
}
for (int index = rt->bloom_count; index < MAX_BLOOM_COUNT; index++)
{
name[12] = 'A' + index - 1;
- curr_effect->set_texture(name, black_texture);
+ curr_effect->set_texture(name, black_texture.Get());
}
next_index = rt->next_index(next_index);
- blit(rt->target_surface[next_index], false, D3DPT_TRIANGLELIST, 0, 2);
+ blit(rt->target_surface[next_index].Get(), false, D3DPT_TRIANGLELIST, 0, 2);
return next_index;
}
@@ -1390,12 +1430,12 @@ int shaders::distortion_pass(d3d_render_target *rt, int source_index, poly_info
return next_index;
}
- curr_effect = distortion_effect;
+ set_curr_effect(distortion_effect.get());
curr_effect->update_uniforms();
- curr_effect->set_texture("DiffuseTexture", rt->target_texture[next_index]);
+ curr_effect->set_texture("DiffuseTexture", rt->target_texture[next_index].Get());
next_index = rt->next_index(next_index);
- blit(rt->target_surface[next_index], false, D3DPT_TRIANGLELIST, 0, 2);
+ blit(rt->target_surface[next_index].Get(), false, D3DPT_TRIANGLELIST, 0, 2);
return next_index;
}
@@ -1404,14 +1444,14 @@ int shaders::vector_pass(d3d_render_target *rt, int source_index, poly_info *pol
{
int next_index = source_index;
- curr_effect = vector_effect;
+ set_curr_effect(vector_effect.get());
curr_effect->update_uniforms();
curr_effect->set_float("LengthRatio", options->vector_length_ratio);
curr_effect->set_float("LengthScale", options->vector_length_scale);
curr_effect->set_float("BeamSmooth", options->vector_beam_smooth);
// we need to clear the vector render target here
- blit(rt->target_surface[next_index], true, poly->type(), vertnum, poly->count());
+ blit(rt->target_surface[next_index].Get(), true, poly->type(), vertnum, poly->count());
return next_index;
}
@@ -1420,17 +1460,17 @@ int shaders::vector_buffer_pass(d3d_render_target *rt, int source_index, poly_in
{
int next_index = source_index;
- curr_effect = default_effect;
+ set_curr_effect(vector_buffer_effect.get());
+ curr_effect->set_texture("Diffuse", diffuse_texture->get_finaltex());
curr_effect->update_uniforms();
- curr_effect->set_technique("VectorBufferTechnique");
-
- curr_effect->set_texture("Diffuse", rt->target_texture[next_index]);
- curr_effect->set_texture("LutTexture", lut_texture == nullptr ? nullptr : lut_texture->get_finaltex());
+ curr_effect->set_texture("Diffuse", rt->target_texture[next_index].Get());
+ curr_effect->set_texture("LutTexture", !lut_texture ? nullptr : lut_texture->get_finaltex());
+ curr_effect->set_bool("UiLutEnable", false);
// we need to clear the vector render target here
next_index = rt->next_index(next_index);
- blit(rt->target_surface[next_index], true, D3DPT_TRIANGLELIST, 0, 2);
+ blit(rt->target_surface[next_index].Get(), true, D3DPT_TRIANGLELIST, 0, 2);
return next_index;
}
@@ -1441,14 +1481,16 @@ int shaders::screen_pass(d3d_render_target *rt, int source_index, poly_info *pol
d3d->set_blendmode(PRIMFLAG_GET_BLENDMODE(poly->flags()));
- curr_effect = default_effect;
+ set_curr_effect(default_effect.get());
+ curr_effect->set_texture("Diffuse", diffuse_texture->get_finaltex());
curr_effect->update_uniforms();
- curr_effect->set_technique("ScreenTechnique");
- curr_effect->set_texture("Diffuse", rt->target_texture[next_index]);
- curr_effect->set_texture("LutTexture", lut_texture == nullptr ? nullptr : lut_texture->get_finaltex());
+ curr_effect->set_texture("Diffuse", rt->target_texture[next_index].Get());
+ curr_effect->set_texture("LutTexture", nullptr);
+ curr_effect->set_bool("LutEnable", false);
+ curr_effect->set_bool("UiLutEnable", false);
- blit(backbuffer, false, poly->type(), vertnum, poly->count());
+ blit(backbuffer.Get(), false, poly->type(), vertnum, poly->count());
if (recording_movie)
{
@@ -1460,9 +1502,9 @@ int shaders::screen_pass(d3d_render_target *rt, int source_index, poly_info *pol
if (render_snap)
{
// we need to clear the snap render target here
- blit(snap_target, true, poly->type(), vertnum, poly->count());
+ blit(snap_target.Get(), true, poly->type(), vertnum, poly->count());
- render_snapshot(snap_target);
+ render_snapshot(snap_target.Get());
render_snap = false;
}
@@ -1474,11 +1516,11 @@ void shaders::ui_pass(poly_info *poly, int vertnum)
{
d3d->set_blendmode(PRIMFLAG_GET_BLENDMODE(poly->flags()));
- curr_effect = default_effect;
+ set_curr_effect(PRIMFLAG_GET_TEXWRAP(poly->flags()) ? ui_wrap_effect.get() : ui_effect.get());
+ curr_effect->set_texture("Diffuse", diffuse_texture->get_finaltex());
curr_effect->update_uniforms();
- curr_effect->set_technique("UiTechnique");
- curr_effect->set_texture("LutTexture", lut_texture == nullptr ? nullptr : ui_lut_texture->get_finaltex());
+ curr_effect->set_texture("LutTexture", !lut_texture ? nullptr : ui_lut_texture->get_finaltex());
blit(nullptr, false, poly->type(), vertnum, poly->count());
}
@@ -1498,8 +1540,6 @@ void shaders::render_quad(poly_info *poly, int vertnum)
curr_texture = poly->texture();
curr_poly = poly;
- auto win = d3d->assert_window();
-
if (PRIMFLAG_GET_SCREENTEX(poly->flags()))
{
if (curr_texture == nullptr)
@@ -1508,9 +1548,9 @@ void shaders::render_quad(poly_info *poly, int vertnum)
return;
}
- curr_screen = curr_screen < num_screens ? curr_screen : 0;
+ curr_target = curr_target < num_targets ? curr_target : 0;
- curr_render_target = find_render_target(curr_texture->get_width(), curr_texture->get_height(), curr_screen);
+ curr_render_target = find_render_target(curr_texture->get_width(), curr_texture->get_height(), curr_target);
d3d_render_target *rt = curr_render_target;
if (rt == nullptr)
@@ -1530,12 +1570,16 @@ void shaders::render_quad(poly_info *poly, int vertnum)
//next_index = phosphor_pass(rt, next_index, poly, vertnum);
// create bloom textures
- int old_index = next_index;
- next_index = post_pass(rt, next_index, poly, vertnum, true);
- next_index = downsample_pass(rt, next_index, poly, vertnum);
+ bool bloom_enabled = (options->bloom_scale > 0.0f);
+ if (bloom_enabled)
+ {
+ int old_index = next_index;
+ next_index = post_pass(rt, next_index, poly, vertnum, true);
+ next_index = downsample_pass(rt, next_index, poly, vertnum);
+ next_index = old_index;
+ }
- // apply bloom textures
- next_index = old_index;
+ // apply bloom textures (if enabled) and other post effects
next_index = post_pass(rt, next_index, poly, vertnum, false);
next_index = bloom_pass(rt, next_index, poly, vertnum);
next_index = phosphor_pass(rt, next_index, poly, vertnum);
@@ -1551,19 +1595,19 @@ void shaders::render_quad(poly_info *poly, int vertnum)
curr_texture->increment_frame_count();
curr_texture->mask_frame_count(options->yiq_phase_count);
- curr_screen++;
+ curr_target++;
}
else if (PRIMFLAG_GET_VECTOR(poly->flags()))
{
- curr_screen = curr_screen < num_screens ? curr_screen : 0;
+ curr_target = curr_target < num_targets ? curr_target : 0;
int source_width = int(poly->prim_width() + 0.5f);
int source_height = int(poly->prim_height() + 0.5f);
- if (win->swap_xy())
+ if (d3d->window().swap_xy())
{
std::swap(source_width, source_height);
}
- curr_render_target = find_render_target(source_width, source_height, curr_screen);
+ curr_render_target = find_render_target(source_width, source_height, curr_target);
d3d_render_target *rt = curr_render_target;
if (rt == nullptr)
@@ -1576,25 +1620,25 @@ void shaders::render_quad(poly_info *poly, int vertnum)
next_index = vector_pass(rt, next_index, poly, vertnum);
- HRESULT result = d3d->get_device()->SetRenderTarget(0, backbuffer);
+ HRESULT result = d3d->get_device()->SetRenderTarget(0, backbuffer.Get());
if (FAILED(result))
{
osd_printf_verbose("Direct3D: Error %08lX during device SetRenderTarget call\n", result);
}
- curr_screen++;
+ curr_target++;
}
else if (PRIMFLAG_GET_VECTORBUF(poly->flags()))
{
- curr_screen = curr_screen < num_screens ? curr_screen : 0;
+ curr_target = curr_target < num_targets ? curr_target : 0;
int source_width = int(poly->prim_width() + 0.5f);
int source_height = int(poly->prim_height() + 0.5f);
- if (win->swap_xy())
+ if (d3d->window().swap_xy())
{
std::swap(source_width, source_height);
}
- curr_render_target = find_render_target(source_width, source_height, curr_screen);
+ curr_render_target = find_render_target(source_width, source_height, curr_target);
d3d_render_target *rt = curr_render_target;
if (rt == nullptr)
@@ -1629,7 +1673,7 @@ void shaders::render_quad(poly_info *poly, int vertnum)
next_index = screen_pass(rt, next_index, poly, vertnum);
d3d->set_wrap(PRIMFLAG_GET_TEXWRAP(curr_texture->get_flags()) ? D3DTADDRESS_WRAP : D3DTADDRESS_CLAMP);
- curr_screen++;
+ curr_target++;
}
else
{
@@ -1655,7 +1699,7 @@ void shaders::end_draw()
return;
}
- backbuffer->Release();
+ backbuffer->Release(); // TODO: where's the matching AddRef that requires this explicit Release?
}
@@ -1670,8 +1714,6 @@ d3d_render_target* shaders::get_texture_target(render_primitive *prim, int width
return nullptr;
}
- auto win = d3d->assert_window();
-
int source_width = width;
int source_height = height;
int source_screen = screen;
@@ -1679,7 +1721,7 @@ d3d_render_target* shaders::get_texture_target(render_primitive *prim, int width
int target_height = int(prim->get_full_quad_height() + 0.5f);
target_width *= oversampling_enable ? 2 : 1;
target_height *= oversampling_enable ? 2 : 1;
- if (win->swap_xy())
+ if (d3d->window().swap_xy())
{
std::swap(target_width, target_height);
}
@@ -1710,8 +1752,6 @@ d3d_render_target* shaders::get_vector_target(render_primitive *prim, int screen
return nullptr;
}
- auto win = d3d->assert_window();
-
int source_width = int(prim->get_quad_width() + 0.5f);
int source_height = int(prim->get_quad_height() + 0.5f);
int source_screen = screen;
@@ -1719,7 +1759,7 @@ d3d_render_target* shaders::get_vector_target(render_primitive *prim, int screen
int target_height = int(prim->get_full_quad_height() + 0.5f);
target_width *= oversampling_enable ? 2 : 1;
target_height *= oversampling_enable ? 2 : 1;
- if (win->swap_xy())
+ if (d3d->window().swap_xy())
{
std::swap(source_width, source_height);
std::swap(target_width, target_height);
@@ -1751,8 +1791,6 @@ bool shaders::create_vector_target(render_primitive *prim, int screen)
return false;
}
- auto win = d3d->assert_window();
-
int source_width = int(prim->get_quad_width() + 0.5f);
int source_height = int(prim->get_quad_height() + 0.5f);
int source_screen = screen;
@@ -1760,7 +1798,7 @@ bool shaders::create_vector_target(render_primitive *prim, int screen)
int target_height = int(prim->get_full_quad_height() + 0.5f);
target_width *= oversampling_enable ? 2 : 1;
target_height *= oversampling_enable ? 2 : 1;
- if (win->swap_xy())
+ if (d3d->window().swap_xy())
{
std::swap(source_width, source_height);
std::swap(target_width, target_height);
@@ -1796,16 +1834,6 @@ bool shaders::add_render_target(renderer_d3d9* d3d, render_primitive *prim, int
//============================================================
-// shaders::enumerate_screens
-//============================================================
-void shaders::enumerate_screens()
-{
- screen_device_enumerator iter(machine->root_device());
- num_screens = iter.count();
-}
-
-
-//============================================================
// shaders::create_texture_target
//============================================================
@@ -1816,8 +1844,6 @@ bool shaders::create_texture_target(render_primitive *prim, int width, int heigh
return false;
}
- auto win = d3d->assert_window();
-
int source_width = width;
int source_height = height;
int source_screen = screen;
@@ -1825,7 +1851,7 @@ bool shaders::create_texture_target(render_primitive *prim, int width, int heigh
int target_height = int(prim->get_full_quad_height() + 0.5f);
target_width *= oversampling_enable ? 2 : 1;
target_height *= oversampling_enable ? 2 : 1;
- if (win->swap_xy())
+ if (d3d->window().swap_xy())
{
// source texture is already swapped
std::swap(target_width, target_height);
@@ -1863,93 +1889,29 @@ void shaders::delete_resources()
m_render_target_list.clear();
- if (downsample_effect != nullptr)
- {
- delete downsample_effect;
- downsample_effect = nullptr;
- }
- if (bloom_effect != nullptr)
- {
- delete bloom_effect;
- bloom_effect = nullptr;
- }
- if (vector_effect != nullptr)
- {
- delete vector_effect;
- vector_effect = nullptr;
- }
- if (default_effect != nullptr)
- {
- delete default_effect;
- default_effect = nullptr;
- }
- if (post_effect != nullptr)
- {
- delete post_effect;
- post_effect = nullptr;
- }
- if (distortion_effect != nullptr)
- {
- delete distortion_effect;
- distortion_effect = nullptr;
- }
- if (prescale_effect != nullptr)
- {
- delete prescale_effect;
- prescale_effect = nullptr;
- }
- if (phosphor_effect != nullptr)
- {
- delete phosphor_effect;
- phosphor_effect = nullptr;
- }
- if (focus_effect != nullptr)
- {
- delete focus_effect;
- focus_effect = nullptr;
- }
- if (scanline_effect != nullptr)
- {
- delete scanline_effect;
- scanline_effect = nullptr;
- }
- if (deconverge_effect != nullptr)
- {
- delete deconverge_effect;
- deconverge_effect = nullptr;
- }
- if (color_effect != nullptr)
- {
- delete color_effect;
- color_effect = nullptr;
- }
- if (ntsc_effect != nullptr)
- {
- delete ntsc_effect;
- ntsc_effect = nullptr;
- }
- if (chroma_effect != nullptr)
- {
- delete chroma_effect;
- chroma_effect = nullptr;
- }
-
- if (backbuffer != nullptr)
- {
- backbuffer->Release();
- backbuffer = nullptr;
- }
-
- if (black_surface != nullptr)
- {
- black_surface->Release();
- black_surface = nullptr;
- }
- if (black_texture != nullptr)
- {
- black_texture->Release();
- black_texture = nullptr;
- }
+ downsample_effect.reset();
+ bloom_effect.reset();
+ vector_effect.reset();
+ default_effect.reset();
+ ui_effect.reset();
+ ui_wrap_effect.reset();
+ vector_buffer_effect.reset();
+ post_effect.reset();
+ distortion_effect.reset();
+ prescale_effect.reset();
+ prescale_point_effect.reset();
+ phosphor_effect.reset();
+ focus_effect.reset();
+ scanline_effect.reset();
+ deconverge_effect.reset();
+ color_effect.reset();
+ ntsc_effect.reset();
+ chroma_effect.reset();
+
+ backbuffer.Reset();
+
+ black_surface.Reset();
+ black_texture.Reset();
shadow_bitmap.reset();
lut_bitmap.reset();
@@ -2215,13 +2177,13 @@ slider_desc shaders::s_sliders[] =
{ "NTSC Frame Jitter Offset", 0, 0, 100, 1, SLIDER_FLOAT, SLIDER_SCREEN_TYPE_LCD_OR_RASTER, SLIDER_NTSC_JITTER, 0.01f, "%1.2f", {} },
{ "NTSC A Value", -100, 50, 100, 1, SLIDER_FLOAT, SLIDER_SCREEN_TYPE_LCD_OR_RASTER, SLIDER_NTSC_A_VALUE, 0.01f, "%1.2f", {} },
{ "NTSC B Value", -100, 50, 100, 1, SLIDER_FLOAT, SLIDER_SCREEN_TYPE_LCD_OR_RASTER, SLIDER_NTSC_B_VALUE, 0.01f, "%1.2f", {} },
- { "NTSC Incoming Phase Pixel Clock Scale",-300, 100, 300, 1, SLIDER_FLOAT, SLIDER_SCREEN_TYPE_LCD_OR_RASTER, SLIDER_NTSC_P_VALUE, 0.01f, "%1.2f", {} },
- { "NTSC Outgoing Phase Offset", -300, 0, 300, 1, SLIDER_FLOAT, SLIDER_SCREEN_TYPE_LCD_OR_RASTER, SLIDER_NTSC_O_VALUE, 0.01f, "%1.2f", {} },
- { "NTSC Color Carrier (Hz)", 0, 35795, 60000, 5, SLIDER_FLOAT, SLIDER_SCREEN_TYPE_LCD_OR_RASTER, SLIDER_NTSC_CC_VALUE, 0.001f, "%1.4f", {} },
- { "NTSC Color Notch Filter Width", 0, 100, 600, 5, SLIDER_FLOAT, SLIDER_SCREEN_TYPE_LCD_OR_RASTER, SLIDER_NTSC_N_VALUE, 0.01f, "%1.4f", {} },
- { "NTSC Y Signal Bandwidth (Hz)", 0, 600, 600, 5, SLIDER_FLOAT, SLIDER_SCREEN_TYPE_LCD_OR_RASTER, SLIDER_NTSC_Y_VALUE, 0.01f, "%1.4f", {} },
- { "NTSC I Signal Bandwidth (Hz)", 0, 120, 600, 5, SLIDER_FLOAT, SLIDER_SCREEN_TYPE_LCD_OR_RASTER, SLIDER_NTSC_I_VALUE, 0.01f, "%1.4f", {} },
- { "NTSC Q Signal Bandwidth (Hz)", 0, 60, 600, 5, SLIDER_FLOAT, SLIDER_SCREEN_TYPE_LCD_OR_RASTER, SLIDER_NTSC_Q_VALUE, 0.01f, "%1.4f", {} },
+ { "NTSC Incoming Phase Pixel Clock Scale",-300,100, 300, 1, SLIDER_FLOAT, SLIDER_SCREEN_TYPE_LCD_OR_RASTER, SLIDER_NTSC_P_VALUE, 0.01f, "%1.2f", {} },
+ { "NTSC Outgoing Phase Offset (radians)",-314, 0, 314, 1, SLIDER_FLOAT, SLIDER_SCREEN_TYPE_LCD_OR_RASTER, SLIDER_NTSC_O_VALUE, 0.01f, "%1.2f", {} },
+ { "NTSC Color Carrier (MHz)", 0, 31500,6*8800, 1, SLIDER_FLOAT, SLIDER_SCREEN_TYPE_LCD_OR_RASTER, SLIDER_NTSC_CC_VALUE, 1/8800.f, "%1.5f", {} },
+ { "NTSC Color Notch Filter Width (MHz)",0, 100, 600, 5, SLIDER_FLOAT, SLIDER_SCREEN_TYPE_LCD_OR_RASTER, SLIDER_NTSC_N_VALUE, 0.01f, "%1.2f", {} },
+ { "NTSC Y Signal Bandwidth (MHz)", 0, 600, 2100, 5, SLIDER_FLOAT, SLIDER_SCREEN_TYPE_LCD_OR_RASTER, SLIDER_NTSC_Y_VALUE, 0.01f, "%1.2f", {} },
+ { "NTSC I Signal Bandwidth (MHz)", 0, 120, 2100, 5, SLIDER_FLOAT, SLIDER_SCREEN_TYPE_LCD_OR_RASTER, SLIDER_NTSC_I_VALUE, 0.01f, "%1.2f", {} },
+ { "NTSC Q Signal Bandwidth (MHz)", 0, 60, 2100, 5, SLIDER_FLOAT, SLIDER_SCREEN_TYPE_LCD_OR_RASTER, SLIDER_NTSC_Q_VALUE, 0.01f, "%1.2f", {} },
{ "NTSC Scanline Duration (uSec)", 0, 5260, 10000, 1, SLIDER_FLOAT, SLIDER_SCREEN_TYPE_LCD_OR_RASTER, SLIDER_NTSC_SCAN_TIME, 0.01f, "%1.2f", {} },
{ "3D LUT (Screen)", 0, 0, 1, 1, SLIDER_INT_ENUM, SLIDER_SCREEN_TYPE_ANY, SLIDER_LUT_ENABLE, 0, "%s", { "Off", "On" } },
{ nullptr, 0, 0, 0, 0, 0, 0, -1, 0, nullptr, {} }
@@ -2313,10 +2275,6 @@ void shaders::init_slider_list()
m_sliders.clear();
m_core_sliders.clear();
- for (slider* slider : internal_sliders)
- {
- delete slider;
- }
internal_sliders.clear();
const screen_device *first_screen = screen_device_enumerator(machine->root_device()).first();
@@ -2349,28 +2307,27 @@ void shaders::init_slider_list()
for (int j = 0; j < count; j++)
{
- auto* slider_arg = new slider(desc, get_slider_option(desc->id, j), &options->params_dirty);
- internal_sliders.push_back(slider_arg);
+ slider &slider_arg = *internal_sliders.emplace_back(std::make_unique<slider>(desc, get_slider_option(desc->id, j), &options->params_dirty));
std::string name = desc->name;
switch (desc->slider_type)
{
case SLIDER_VEC2:
{
- std::string names[2] = { " X", " Y" };
- name = name + names[j];
+ char const *const names[2] = { " X", " Y" };
+ name += names[j];
break;
}
case SLIDER_COLOR:
{
- std::string names[3] = { " Red", " Green", " Blue" };
- name = name + names[j];
+ char const *const names[3] = { " Red", " Green", " Blue" };
+ name += names[j];
break;
}
default:
break;
}
- std::unique_ptr<slider_state> core_slider = slider_alloc(std::move(name), desc->minval, desc->defval, desc->maxval, desc->step, slider_arg);
+ std::unique_ptr<slider_state> core_slider = slider_alloc(std::move(name), desc->minval, desc->defval, desc->maxval, desc->step, &slider_arg);
ui::menu_item item(ui::menu_item_type::SLIDER, core_slider.get());
item.set_text(core_slider->description);
@@ -2405,8 +2362,7 @@ void uniform::update()
hlsl_options *options = shadersys->options;
renderer_d3d9 *d3d = shadersys->d3d;
- auto win = d3d->assert_window();
- const screen_device *first_screen = screen_device_enumerator(win->machine().root_device()).first();
+ const screen_device *first_screen = screen_device_enumerator(d3d->window().machine().root_device()).first();
bool vector_screen =
first_screen != nullptr &&
@@ -2422,7 +2378,7 @@ void uniform::update()
}
case CU_SCREEN_COUNT:
{
- int screen_count = win->target()->current_view().visible_screen_count();
+ int screen_count = d3d->window().target()->current_view().visible_screen_count();
m_shader->set_int("ScreenCount", screen_count);
break;
}
@@ -2485,7 +2441,7 @@ void uniform::update()
case CU_SWAP_XY:
{
- m_shader->set_bool("SwapXY", win->swap_xy());
+ m_shader->set_bool("SwapXY", d3d->window().swap_xy());
break;
}
case CU_VECTOR_SCREEN:
@@ -2609,7 +2565,7 @@ void uniform::update()
m_shader->set_float("SmoothBorderAmount", options->smooth_border);
break;
case CU_POST_SHADOW_ALPHA:
- m_shader->set_float("ShadowAlpha", shadersys->shadow_texture == nullptr ? 0.0f : options->shadow_mask_alpha);
+ m_shader->set_float("ShadowAlpha", !shadersys->shadow_texture ? 0.0f : options->shadow_mask_alpha);
break;
case CU_POST_SHADOW_COUNT:
{
@@ -2684,12 +2640,14 @@ void uniform::update()
//============================================================
effect::effect(shaders *shadersys, IDirect3DDevice9 *dev, const char *name, const char *path)
+ : m_effect(nullptr)
+ , m_shaders(shadersys)
+ , m_num_passes(0)
+ , m_valid(false)
+ , m_active(false)
{
LPD3DXBUFFER buffer_errors = nullptr;
- m_shaders = shadersys;
- m_valid = false;
-
char name_cstr[1024];
sprintf(name_cstr, "%s\\%s", path, name);
auto effect_name = osd::text::to_tstring(name_cstr);
@@ -2716,6 +2674,12 @@ effect::effect(shaders *shadersys, IDirect3DDevice9 *dev, const char *name, cons
effect::~effect()
{
m_effect->Release();
+
+ m_vecs.clear();
+ m_floats.clear();
+ m_ints.clear();
+ m_bools.clear();
+ m_textures.clear();
}
void effect::add_uniform(const char *name, uniform::uniform_type type, int id)
@@ -2729,24 +2693,19 @@ void effect::update_uniforms()
(*uniform).update();
}
-void effect::begin(UINT *passes, DWORD flags)
+void effect::begin(DWORD flags)
{
- m_effect->Begin(passes, flags);
+ m_active = true;
+ m_num_passes = 0;
+ m_effect->Begin(&m_num_passes, flags);
+ m_effect->BeginPass(0);
}
void effect::end()
{
- m_effect->End();
-}
-
-void effect::begin_pass(UINT pass)
-{
- m_effect->BeginPass(pass);
-}
-
-void effect::end_pass()
-{
+ m_active = false;
m_effect->EndPass();
+ m_effect->End();
}
void effect::set_technique(const char *name)
@@ -2756,48 +2715,97 @@ void effect::set_technique(const char *name)
void effect::set_vector(D3DXHANDLE param, int count, float *vector)
{
- static D3DXVECTOR4 out_vector;
- if (count > 0)
- {
- out_vector.x = vector[0];
- }
- if (count > 1)
- {
- out_vector.y = vector[1];
- }
- if (count > 2)
+ count = std::min(count, 4);
+
+ auto iter = m_vecs.find(param);
+ if (iter != m_vecs.end())
{
- out_vector.z = vector[2];
+ D3DXVECTOR4 &data = iter->second;
+ if (!memcmp((float *)data, vector, sizeof(float) * count))
+ {
+ return;
+ }
+ memcpy(data, vector, sizeof(float) * count);
+ m_effect->SetVector(param, &iter->second);
}
- if (count > 3)
+ else
{
- out_vector.w = vector[3];
+ D3DXVECTOR4 vec;
+ memcpy((float *)vec, vector, sizeof(float) * count);
+ m_effect->SetVector(param, &vec);
+ m_vecs[param] = vec;
}
- m_effect->SetVector(param, &out_vector);
}
void effect::set_float(D3DXHANDLE param, float value)
{
+ auto iter = m_floats.find(param);
+ if (iter != m_floats.end())
+ {
+ if (iter->second == value)
+ {
+ return;
+ }
+ iter->second = value;
+ }
+ else
+ {
+ m_floats[param] = value;
+ }
m_effect->SetFloat(param, value);
}
void effect::set_int(D3DXHANDLE param, int value)
{
+ auto iter = m_ints.find(param);
+ if (iter != m_ints.end())
+ {
+ if (iter->second == value)
+ {
+ return;
+ }
+ iter->second = value;
+ }
+ else
+ {
+ m_ints[param] = value;
+ }
m_effect->SetInt(param, value);
}
void effect::set_bool(D3DXHANDLE param, bool value)
{
+ auto iter = m_bools.find(param);
+ if (iter != m_bools.end())
+ {
+ if (iter->second == value)
+ {
+ return;
+ }
+ iter->second = value;
+ }
+ else
+ {
+ m_bools[param] = value;
+ }
m_effect->SetBool(param, value);
}
-void effect::set_matrix(D3DXHANDLE param, D3DXMATRIX *matrix)
-{
- m_effect->SetMatrix(param, matrix);
-}
-
void effect::set_texture(D3DXHANDLE param, IDirect3DTexture9 *tex)
{
+ auto iter = m_textures.find(param);
+ if (iter != m_textures.end())
+ {
+ if (iter->second == (void *)tex)
+ {
+ return;
+ }
+ iter->second = (void *)tex;
+ }
+ else
+ {
+ m_textures[param] = (void *)tex;
+ }
m_effect->SetTexture(param, tex);
}
diff --git a/src/osd/modules/render/d3d/d3dhlsl.h b/src/osd/modules/render/d3d/d3dhlsl.h
index f72197cb7b1..f06deca2a57 100644
--- a/src/osd/modules/render/d3d/d3dhlsl.h
+++ b/src/osd/modules/render/d3d/d3dhlsl.h
@@ -9,11 +9,16 @@
#ifndef __WIN_D3DHLSL__
#define __WIN_D3DHLSL__
-#include <vector>
#include "../frontend/mame/ui/menuitem.h"
#include "../frontend/mame/ui/slider.h"
#include "modules/lib/osdlib.h"
+#include <wrl/client.h>
+
+#include <map>
+#include <memory>
+#include <vector>
+
//============================================================
// TYPE DEFINITIONS
//============================================================
@@ -133,11 +138,8 @@ public:
effect(shaders *shadersys, IDirect3DDevice9 *dev, const char *name, const char *path);
~effect();
- void begin(UINT *passes, DWORD flags);
- void begin_pass(UINT pass);
-
+ void begin(DWORD flags);
void end();
- void end_pass();
void set_technique(const char *name);
@@ -145,7 +147,6 @@ public:
void set_float(D3DXHANDLE param, float value);
void set_int(D3DXHANDLE param, int value);
void set_bool(D3DXHANDLE param, bool value);
- void set_matrix(D3DXHANDLE param, D3DXMATRIX *matrix);
void set_texture(D3DXHANDLE param, IDirect3DTexture9 *tex);
void add_uniform(const char *name, uniform::uniform_type type, int id);
@@ -154,16 +155,26 @@ public:
D3DXHANDLE get_parameter(D3DXHANDLE param, const char *name);
shaders* get_shaders() { return m_shaders; }
+ uint32_t num_passes() { return m_num_passes; }
bool is_valid() { return m_valid; }
+ bool is_active() { return m_active; }
private:
std::vector<std::unique_ptr<uniform>> m_uniform_list;
ID3DXEffect *m_effect;
shaders *m_shaders;
+ uint32_t m_num_passes;
+
+ std::map<D3DXHANDLE, D3DXVECTOR4> m_vecs;
+ std::map<D3DXHANDLE, float> m_floats;
+ std::map<D3DXHANDLE, int> m_ints;
+ std::map<D3DXHANDLE, bool> m_bools;
+ std::map<D3DXHANDLE, void*> m_textures;
bool m_valid;
+ bool m_active;
};
class d3d_render_target;
@@ -300,11 +311,14 @@ public:
shaders();
~shaders();
- bool init(d3d_base *d3dintf, running_machine *machine, renderer_d3d9 *renderer);
+ bool init(IDirect3D9 *d3dobj, running_machine *machine, renderer_d3d9 *renderer);
- bool enabled() { return post_fx_enable && d3dintf->post_fx_available; }
+ bool enabled() { return post_fx_enable && d3d->post_fx_available(); }
void toggle() { post_fx_enable = initialized && !post_fx_enable; }
+ void begin_frame(render_primitive_list *primlist);
+ void end_frame();
+
void begin_draw();
void end_draw();
@@ -323,6 +337,7 @@ public:
void init_fsfx_quad();
void set_texture(texture_info *info);
+ void set_filter(bool filter_screens);
void remove_render_target(int source_width, int source_height, uint32_t screen_index);
void remove_render_target(d3d_render_target *rt);
@@ -336,8 +351,12 @@ public:
void *get_slider_option(int id, int index = 0);
private:
+ using IDirect3D9Ptr = Microsoft::WRL::ComPtr<IDirect3D9>;
+ using IDirect3DTexture9Ptr = Microsoft::WRL::ComPtr<IDirect3DTexture9>;
+ using IDirect3DSurface9Ptr = Microsoft::WRL::ComPtr<IDirect3DSurface9>;
+
+ void set_curr_effect(effect *curr_effect);
void blit(IDirect3DSurface9 *dst, bool clear_dst, D3DPRIMITIVETYPE prim_type, uint32_t prim_index, uint32_t prim_count);
- void enumerate_screens();
void render_snapshot(IDirect3DSurface9 *surface);
// Time since last call, only updates once per render of all screens
@@ -364,7 +383,7 @@ private:
int screen_pass(d3d_render_target *rt, int source_index, poly_info *poly, int vertnum);
void ui_pass(poly_info *poly, int vertnum);
- d3d_base * d3dintf; // D3D interface
+ IDirect3D9Ptr d3dobj; // D3D interface
running_machine * machine;
renderer_d3d9 * d3d; // D3D renderer
@@ -372,7 +391,10 @@ private:
bool post_fx_enable; // overall enable flag
bool oversampling_enable; // oversampling enable flag
int num_screens; // number of emulated physical screens
- int curr_screen; // current screen for render target operations
+ int num_targets; // number of emulated screen targets (can be different from above; cf. artwork and Laserdisc games)
+ int curr_target; // current target index for render target operations
+ int targets_per_screen[256]; // screen target count per screen device/container index; estimated maximum count for array size
+ int target_to_screen[256]; // lookup from target index to screen device/container index; estimated maximum count for array size
double acc_t; // accumulated machine time
double delta_t; // data for delta_time
bitmap_argb32 shadow_bitmap; // shadow mask bitmap for post-processing shader
@@ -383,49 +405,55 @@ private:
texture_info * ui_lut_texture;
hlsl_options * options; // current options
- IDirect3DSurface9 * black_surface; // black dummy surface
- IDirect3DTexture9 * black_texture; // black dummy texture
+ IDirect3DSurface9Ptr black_surface; // black dummy surface
+ IDirect3DTexture9Ptr black_texture; // black dummy texture
bool recording_movie; // ongoing movie recording
std::unique_ptr<movie_recorder> recorder; // HLSL post-render movie recorder
bool render_snap; // whether or not to take HLSL post-render snapshot
- IDirect3DSurface9 * snap_copy_target; // snapshot destination surface in system memory
- IDirect3DTexture9 * snap_copy_texture; // snapshot destination surface in system memory
- IDirect3DSurface9 * snap_target; // snapshot upscaled surface
- IDirect3DTexture9 * snap_texture; // snapshot upscaled texture
+ IDirect3DSurface9Ptr snap_copy_target; // snapshot destination surface in system memory
+ IDirect3DTexture9Ptr snap_copy_texture; // snapshot destination surface in system memory
+ IDirect3DSurface9Ptr snap_target; // snapshot upscaled surface
+ IDirect3DTexture9Ptr snap_texture; // snapshot upscaled texture
int snap_width; // snapshot width
int snap_height; // snapshot height
bool initialized; // whether or not we're initialized
// HLSL effects
- IDirect3DSurface9 * backbuffer; // pointer to our device's backbuffer
+ IDirect3DSurface9Ptr backbuffer; // pointer to our device's backbuffer
effect * curr_effect; // pointer to the currently active effect object
- effect * default_effect; // pointer to the primary-effect object
- effect * prescale_effect; // pointer to the prescale-effect object
- effect * post_effect; // pointer to the post-effect object
- effect * distortion_effect; // pointer to the distortion-effect object
- effect * scanline_effect;
- effect * focus_effect; // pointer to the focus-effect object
- effect * phosphor_effect; // pointer to the phosphor-effect object
- effect * deconverge_effect; // pointer to the deconvergence-effect object
- effect * color_effect; // pointer to the color-effect object
- effect * ntsc_effect; // pointer to the NTSC effect object
- effect * bloom_effect; // pointer to the bloom composite effect
- effect * downsample_effect; // pointer to the bloom downsample effect
- effect * vector_effect; // pointer to the vector-effect object
- effect * chroma_effect;
-
+ std::unique_ptr<effect> default_effect; // pointer to the primary-effect object
+ std::unique_ptr<effect> ui_effect; // pointer to the UI-element effect object
+ std::unique_ptr<effect> ui_wrap_effect; // pointer to the UI-element effect object with texture wrapping
+ std::unique_ptr<effect> vector_buffer_effect; // pointer to the vector-buffering effect object
+ std::unique_ptr<effect> prescale_effect; // pointer to the prescale-effect object
+ std::unique_ptr<effect> prescale_point_effect; // pointer to the prescale-effect object with point filtering
+ std::unique_ptr<effect> post_effect; // pointer to the post-effect object
+ std::unique_ptr<effect> distortion_effect; // pointer to the distortion-effect object
+ std::unique_ptr<effect> scanline_effect;
+ std::unique_ptr<effect> focus_effect; // pointer to the focus-effect object
+ std::unique_ptr<effect> phosphor_effect; // pointer to the phosphor-effect object
+ std::unique_ptr<effect> deconverge_effect; // pointer to the deconvergence-effect object
+ std::unique_ptr<effect> color_effect; // pointer to the color-effect object
+ std::unique_ptr<effect> ntsc_effect; // pointer to the NTSC effect object
+ std::unique_ptr<effect> bloom_effect; // pointer to the bloom composite effect
+ std::unique_ptr<effect> downsample_effect; // pointer to the bloom downsample effect
+ std::unique_ptr<effect> vector_effect; // pointer to the vector-effect object
+ std::unique_ptr<effect> chroma_effect;
+
+ texture_info * diffuse_texture;
+ bool filter_screens;
texture_info * curr_texture;
d3d_render_target * curr_render_target;
poly_info * curr_poly;
std::vector<std::unique_ptr<d3d_render_target>> m_render_target_list;
- std::vector<slider*> internal_sliders;
+ std::vector<std::unique_ptr<slider> > internal_sliders;
std::vector<ui::menu_item> m_sliders;
- std::vector<std::unique_ptr<slider_state>> m_core_sliders;
+ std::vector<std::unique_ptr<slider_state> > m_core_sliders;
static slider_desc s_sliders[];
static hlsl_options last_options; // last used options
diff --git a/src/osd/modules/render/draw13.cpp b/src/osd/modules/render/draw13.cpp
index af7c8559ca0..a36ee8a8f52 100644
--- a/src/osd/modules/render/draw13.cpp
+++ b/src/osd/modules/render/draw13.cpp
@@ -2,7 +2,7 @@
// copyright-holders: Couriersud, Olivier Galibert, R. Belmont
//============================================================
//
-// draw13.c - SDL 2.0 drawing implementation
+// draw13.cpp - SDL 2.0 drawing implementation
//
// SDLMAME by Olivier Galibert and R. Belmont
//
@@ -10,24 +10,202 @@
//
//============================================================
+#include "render_module.h"
+
+#include "modules/osdmodule.h"
+
+#if defined(OSD_SDL)
+
+// OSD headers
+#include "sdlopts.h"
+#include "window.h"
+
+// lib/util
+#include "options.h"
+
+// emu
+#include "emucore.h"
+#include "render.h"
+
+// standard SDL headers
+#include <SDL2/SDL.h>
+
// standard C headers
+#include <algorithm>
#include <cmath>
#include <cstdio>
+#include <iterator>
+#include <list>
-// MAME headers
-#include "emu.h"
-#include "options.h"
-// OSD headers
-#include "osdsdl.h"
-#include "window.h"
+namespace osd {
+
+namespace {
+
+struct quad_setup_data
+{
+ quad_setup_data() = default;
+
+ void compute(const render_primitive &prim, const int prescale);
+
+ int32_t dudx = 0, dvdx = 0, dudy = 0, dvdy = 0;
+ int32_t startu = 0, startv = 0;
+ int32_t rotwidth = 0, rotheight = 0;
+};
+
+//============================================================
+// Textures
+//============================================================
+
+class renderer_sdl2;
+struct copy_info_t;
+
+/* texture_info holds information about a texture */
+class texture_info
+{
+public:
+ texture_info(renderer_sdl2 *renderer, const render_texinfo &texsource, const quad_setup_data &setup, const uint32_t flags);
+ ~texture_info();
+
+ void set_data(const render_texinfo &texsource, const uint32_t flags);
+ void render_quad(const render_primitive &prim, const int x, const int y);
+ bool matches(const render_primitive &prim, const quad_setup_data &setup);
+
+ copy_info_t const *compute_size_type();
+
+ void *m_pixels; // pixels for the texture
+ int m_pitch;
+
+ copy_info_t const *m_copyinfo;
+ quad_setup_data m_setup;
+
+ osd_ticks_t m_last_access;
+
+ int raw_width() const { return m_texinfo.width; }
+ int raw_height() const { return m_texinfo.height; }
+
+ const render_texinfo &texinfo() const { return m_texinfo; }
+ render_texinfo &texinfo() { return m_texinfo; }
+
+ HashT hash() const { return m_hash; }
+ uint32_t flags() const { return m_flags; }
+
+private:
+ bool is_pixels_owned() const;
+
+ void set_coloralphamode(SDL_Texture *texture_id, const render_color *color);
+
+ Uint32 m_sdl_access;
+ renderer_sdl2 * m_renderer;
+ render_texinfo m_texinfo; // copy of the texture info
+ HashT m_hash; // hash value for the texture (must be >= pointer size)
+ uint32_t m_flags; // rendering flags
-#include "draw13.h"
+ SDL_Texture * m_texture_id;
+ bool m_is_rotated;
+
+ int m_format; // texture format
+ SDL_BlendMode m_sdl_blendmode;
+};
+
+// inline functions and macros
+#include "blit13.ipp"
//============================================================
-// DEBUGGING
+// TEXCOPY FUNCS
//============================================================
+enum SDL_TEXFORMAT_E
+{
+ SDL_TEXFORMAT_ARGB32 = 0,
+ SDL_TEXFORMAT_RGB32,
+ SDL_TEXFORMAT_RGB32_PALETTED,
+ SDL_TEXFORMAT_YUY16,
+ SDL_TEXFORMAT_YUY16_PALETTED,
+ SDL_TEXFORMAT_PALETTE16,
+ SDL_TEXFORMAT_RGB15,
+ SDL_TEXFORMAT_RGB15_PALETTED,
+ SDL_TEXFORMAT_PALETTE16A,
+ SDL_TEXFORMAT_PALETTE16_ARGB1555,
+ SDL_TEXFORMAT_RGB15_ARGB1555,
+ SDL_TEXFORMAT_RGB15_PALETTED_ARGB1555,
+ SDL_TEXFORMAT_LAST = SDL_TEXFORMAT_RGB15_PALETTED_ARGB1555
+};
+
+struct copy_info_t
+{
+ int src_fmt;
+ Uint32 dst_fmt;
+ const blit_base *blitter;
+ Uint32 bm_mask;
+ const char *srcname;
+ const char *dstname;
+ /* Statistics */
+ mutable uint64_t pixel_count;
+ mutable int64_t time;
+ mutable int samples;
+ mutable int perf;
+ /* list */
+ copy_info_t const *next;
+};
+
+/* renderer_sdl2 is the information about SDL for the current screen */
+class renderer_sdl2 : public osd_renderer
+{
+public:
+ renderer_sdl2(
+ osd_window &window,
+ copy_info_t const *const (&blit_info)[SDL_TEXFORMAT_LAST + 1]);
+
+ virtual ~renderer_sdl2()
+ {
+ destroy_all_textures();
+ SDL_DestroyRenderer(m_sdl_renderer);
+ m_sdl_renderer = nullptr;
+ }
+
+ virtual int create() override;
+ virtual int draw(const int update) override;
+ virtual int xy_to_render_target(const int x, const int y, int *xt, int *yt) override;
+ virtual render_primitive_list *get_primitives() override;
+
+ int RendererSupportsFormat(Uint32 format, Uint32 access, const char *sformat);
+
+ SDL_Renderer *m_sdl_renderer;
+ copy_info_t const *const (&m_blit_info)[SDL_TEXFORMAT_LAST + 1];
+
+private:
+ void render_quad(texture_info *texture, const render_primitive &prim, const int x, const int y);
+
+ texture_info *texture_find(const render_primitive &prim, const quad_setup_data &setup);
+ texture_info *texture_update(const render_primitive &prim);
+
+ void destroy_all_textures();
+
+ int32_t m_blittimer;
+
+ std::list<texture_info> m_texlist; // list of active textures
+
+ float m_last_hofs;
+ float m_last_vofs;
+
+ int m_width;
+ int m_height;
+
+ osd_dim m_blit_dim;
+
+ struct
+ {
+ Uint32 format;
+ int status;
+ } fmt_support[30];
+
+ // Stats
+ int64_t m_last_blit_time;
+ int64_t m_last_blit_pixels;
+};
+
+
//============================================================
// CONSTANTS
//============================================================
@@ -60,9 +238,12 @@ static inline bool is_transparent(const float &a)
// CONSTRUCTOR & DESTRUCTOR
//============================================================
-renderer_sdl2::renderer_sdl2(std::shared_ptr<osd_window> window, int extra_flags)
- : osd_renderer(window, FLAG_NEEDS_OPENGL | extra_flags)
+renderer_sdl2::renderer_sdl2(
+ osd_window &window,
+ copy_info_t const *const (&blit_info)[SDL_TEXFORMAT_LAST + 1])
+ : osd_renderer(window)
, m_sdl_renderer(nullptr)
+ , m_blit_info(blit_info)
, m_blittimer(0)
, m_last_hofs(0)
, m_last_vofs(0)
@@ -77,112 +258,8 @@ renderer_sdl2::renderer_sdl2(std::shared_ptr<osd_window> window, int extra_flags
fmt_support[i].format = 0;
fmt_support[i].status = 0;
}
-
- if (!s_blit_info_initialized)
- {
- /* On OSX, calling this from drawsdl2_init will
- * prohibit fullscreen toggling. It is than not possible
- * to toggle from fullscreen to window mode.
- */
- expand_copy_info(s_blit_info_default);
- s_blit_info_initialized = true;
- }
}
-
-//============================================================
-// STATIC VARIABLES
-//============================================================
-
-#define BM_ALL (UINT32_MAX)
-//( SDL_BLENDMODE_MASK | SDL_BLENDMODE_BLEND | SDL_BLENDMODE_ADD | SDL_BLENDMODE_MOD)
-
-#define ENTRY(a,b,f) { SDL_TEXFORMAT_ ## a, SDL_PIXELFORMAT_ ## b, &texcopy_ ## f, BM_ALL, #a, #b, 0, 0, 0, 0}
-#define ENTRY_BM(a,b,f,bm) { SDL_TEXFORMAT_ ## a, SDL_PIXELFORMAT_ ## b, &texcopy_ ## f, bm, #a, #b, 0, 0, 0, 0}
-#define ENTRY_LR(a,b,f) { SDL_TEXFORMAT_ ## a, SDL_PIXELFORMAT_ ## b, &texcopy_ ## f, BM_ALL, #a, #b, 0, 0, 0, -1}
-
-const copy_info_t renderer_sdl2::s_blit_info_default[] =
-{
- /* no rotation */
- ENTRY(ARGB32, ARGB8888, argb32_argb32),
- ENTRY_LR(ARGB32, RGB888, argb32_rgb32),
- /* Entry primarily for directfb */
- ENTRY_BM(ARGB32, RGB888, argb32_rgb32, SDL_BLENDMODE_ADD),
- ENTRY_BM(ARGB32, RGB888, argb32_rgb32, SDL_BLENDMODE_MOD),
- ENTRY_BM(ARGB32, RGB888, argb32_rgb32, SDL_BLENDMODE_NONE),
-
- ENTRY(RGB32, ARGB8888, rgb32_argb32),
- ENTRY(RGB32, RGB888, rgb32_rgb32),
-
- ENTRY(RGB32_PALETTED, ARGB8888, rgb32pal_argb32),
- ENTRY(RGB32_PALETTED, RGB888, rgb32pal_argb32),
-
- ENTRY(YUY16, UYVY, yuv16_uyvy),
- ENTRY(YUY16, YUY2, yuv16_yuy2),
- ENTRY(YUY16, YVYU, yuv16_yvyu),
- ENTRY(YUY16, ARGB8888, yuv16_argb32),
- ENTRY(YUY16, RGB888, yuv16_argb32),
-
- ENTRY(YUY16_PALETTED, UYVY, yuv16pal_uyvy),
- ENTRY(YUY16_PALETTED, YUY2, yuv16pal_yuy2),
- ENTRY(YUY16_PALETTED, YVYU, yuv16pal_yvyu),
- ENTRY(YUY16_PALETTED, ARGB8888, yuv16pal_argb32),
- ENTRY(YUY16_PALETTED, RGB888, yuv16pal_argb32),
-
- ENTRY(PALETTE16, ARGB8888, pal16_argb32),
- ENTRY(PALETTE16, RGB888, pal16_argb32),
-
- ENTRY(RGB15, RGB555, rgb15_rgb555),
- ENTRY(RGB15, ARGB1555, rgb15_argb1555),
- ENTRY(RGB15, ARGB8888, rgb15_argb32),
- ENTRY(RGB15, RGB888, rgb15_argb32),
-
- ENTRY(RGB15_PALETTED, ARGB8888, rgb15pal_argb32),
- ENTRY(RGB15_PALETTED, RGB888, rgb15pal_argb32),
-
- ENTRY(PALETTE16A, ARGB8888, pal16a_argb32),
- ENTRY(PALETTE16A, RGB888, pal16a_rgb32),
-
- /* rotation */
- ENTRY(ARGB32, ARGB8888, rot_argb32_argb32),
- ENTRY_LR(ARGB32, RGB888, rot_argb32_rgb32),
- /* Entry primarily for directfb */
- ENTRY_BM(ARGB32, RGB888, rot_argb32_rgb32, SDL_BLENDMODE_ADD),
- ENTRY_BM(ARGB32, RGB888, rot_argb32_rgb32, SDL_BLENDMODE_MOD),
- ENTRY_BM(ARGB32, RGB888, rot_argb32_rgb32, SDL_BLENDMODE_NONE),
-
- ENTRY(RGB32, ARGB8888, rot_rgb32_argb32),
- ENTRY(RGB32, RGB888, rot_argb32_argb32),
-
- ENTRY(RGB32_PALETTED, ARGB8888, rot_rgb32pal_argb32),
- ENTRY(RGB32_PALETTED, RGB888, rot_rgb32pal_argb32),
-
- ENTRY(YUY16, ARGB8888, rot_yuv16_argb32rot),
- ENTRY(YUY16, RGB888, rot_yuv16_argb32rot),
-
- ENTRY(YUY16_PALETTED, ARGB8888, rot_yuv16pal_argb32rot),
- ENTRY(YUY16_PALETTED, RGB888, rot_yuv16pal_argb32rot),
-
- ENTRY(PALETTE16, ARGB8888, rot_pal16_argb32),
- ENTRY(PALETTE16, RGB888, rot_pal16_argb32),
-
- ENTRY(RGB15, RGB555, rot_rgb15_argb1555),
- ENTRY(RGB15, ARGB1555, rot_rgb15_argb1555),
- ENTRY(RGB15, ARGB8888, rot_rgb15_argb32),
- ENTRY(RGB15, RGB888, rot_rgb15_argb32),
-
- ENTRY(RGB15_PALETTED, ARGB8888, rot_rgb15pal_argb32),
- ENTRY(RGB15_PALETTED, RGB888, rot_rgb15pal_argb32),
-
- ENTRY(PALETTE16A, ARGB8888, rot_pal16a_argb32),
- ENTRY(PALETTE16A, RGB888, rot_pal16a_rgb32),
-
-{ -1 },
-};
-
-copy_info_t* renderer_sdl2::s_blit_info[SDL_TEXFORMAT_LAST+1] = { nullptr };
-bool renderer_sdl2::s_blit_info_initialized = false;
-
//============================================================
// INLINES
//============================================================
@@ -277,7 +354,7 @@ void renderer_sdl2::render_quad(texture_info *texture, const render_primitive &p
if (texture)
{
- copy_info_t *copyinfo = texture->m_copyinfo;
+ copy_info_t const *copyinfo = texture->m_copyinfo;
copyinfo->time -= osd_ticks();
texture->render_quad(prim, x, y);
copyinfo->time += osd_ticks();
@@ -288,7 +365,7 @@ void renderer_sdl2::render_quad(texture_info *texture, const render_primitive &p
copyinfo->time += (m_last_blit_time * (int64_t) (texture->raw_width() * texture->raw_height())) / (int64_t) m_last_blit_pixels;
}
copyinfo->samples++;
- copyinfo->perf = ( texture->m_copyinfo->pixel_count * (osd_ticks_per_second()/1000)) / texture->m_copyinfo->time;
+ copyinfo->perf = (texture->m_copyinfo->pixel_count * (osd_ticks_per_second()/1000)) / std::max<int64_t>(texture->m_copyinfo->time, 1);
}
else
{
@@ -329,59 +406,6 @@ int renderer_sdl2::RendererSupportsFormat(Uint32 format, Uint32 access, const ch
return 0;
}
-//============================================================
-// drawsdl_init
-//============================================================
-
-void renderer_sdl2::add_list(copy_info_t **head, const copy_info_t *element, Uint32 bm)
-{
- copy_info_t *newci = new copy_info_t;
- *newci = *element;
-
- newci->bm_mask = bm;
- newci->next = *head;
- *head = newci;
-}
-
-void renderer_sdl2::expand_copy_info(const copy_info_t *list)
-{
- for (const copy_info_t *bi = list; bi->src_fmt != -1; bi++)
- {
- if (bi->bm_mask == BM_ALL)
- {
- add_list(&s_blit_info[bi->src_fmt], bi, SDL_BLENDMODE_NONE);
- add_list(&s_blit_info[bi->src_fmt], bi, SDL_BLENDMODE_ADD);
- add_list(&s_blit_info[bi->src_fmt], bi, SDL_BLENDMODE_MOD);
- add_list(&s_blit_info[bi->src_fmt], bi, SDL_BLENDMODE_BLEND);
- }
- else
- {
- add_list(&s_blit_info[bi->src_fmt], bi, bi->bm_mask);
- }
- }
-}
-
-// FIXME: machine only used to access options.
-void renderer_sdl2::init(running_machine &machine)
-{
- osd_printf_verbose("Using SDL native texturing driver (SDL 2.0+)\n");
-
-#if USE_OPENGL
- // Load the GL library now - else MT will fail
- const char *stemp = downcast<sdl_options &>(machine.options()).gl_lib();
-#else
- const char *stemp = nullptr;
-#endif
- if (stemp != nullptr && strcmp(stemp, OSDOPTVAL_AUTO) == 0)
- stemp = nullptr;
-
- // No fatalerror here since not all video drivers support GL !
- if (SDL_GL_LoadLibrary(stemp) != 0) // Load library (default for e==nullptr
- osd_printf_warning("Warning: Unable to load opengl library: %s\n", stemp ? stemp : "<default>");
- else
- osd_printf_verbose("Loaded opengl shared library: %s\n", stemp ? stemp : "<default>");
-}
-
//============================================================
// sdl_info::create
@@ -434,12 +458,10 @@ int renderer_sdl2::create()
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "0");
}
- auto win = assert_window();
-
if (video_config.waitvsync)
- m_sdl_renderer = SDL_CreateRenderer(std::dynamic_pointer_cast<sdl_window_info>(win)->platform_window(), -1, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED);
+ m_sdl_renderer = SDL_CreateRenderer(dynamic_cast<sdl_window_info &>(window()).platform_window(), -1, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED);
else
- m_sdl_renderer = SDL_CreateRenderer(std::dynamic_pointer_cast<sdl_window_info>(win)->platform_window(), -1, SDL_RENDERER_ACCELERATED);
+ m_sdl_renderer = SDL_CreateRenderer(dynamic_cast<sdl_window_info &>(window()).platform_window(), -1, SDL_RENDERER_ACCELERATED);
if (!m_sdl_renderer)
{
@@ -483,18 +505,14 @@ int renderer_sdl2::xy_to_render_target(int x, int y, int *xt, int *yt)
void renderer_sdl2::destroy_all_textures()
{
- auto win = assert_window();
- if (win == nullptr)
- return;
-
- if(win->m_primlist)
+ if (window().m_primlist)
{
- win->m_primlist->acquire_lock();
- m_texlist.reset();
- win->m_primlist->release_lock();
+ window().m_primlist->acquire_lock();
+ m_texlist.clear();
+ window().m_primlist->release_lock();
}
else
- m_texlist.reset();
+ m_texlist.clear();
}
//============================================================
@@ -507,13 +525,7 @@ int renderer_sdl2::draw(int update)
float vofs, hofs;
int blit_pixels = 0;
- if (video_config.novideo)
- {
- return 0;
- }
-
- auto win = assert_window();
- osd_dim wdim = win->get_size();
+ osd_dim wdim = window().get_size();
if (has_flags(FI_CHANGED) || (wdim.width() != m_width) || (wdim.height() != m_height))
{
@@ -560,10 +572,10 @@ int renderer_sdl2::draw(int update)
m_last_hofs = hofs;
m_last_vofs = vofs;
- win->m_primlist->acquire_lock();
+ window().m_primlist->acquire_lock();
// now draw
- for (render_primitive &prim : *win->m_primlist)
+ for (render_primitive &prim : *window().m_primlist)
{
Uint8 sr, sg, sb, sa;
@@ -593,7 +605,7 @@ int renderer_sdl2::draw(int update)
}
}
- win->m_primlist->release_lock();
+ window().m_primlist->release_lock();
m_last_blit_pixels = blit_pixels;
m_last_blit_time = -osd_ticks();
@@ -612,22 +624,23 @@ int renderer_sdl2::draw(int update)
// texture_compute_size and type
//============================================================
-copy_info_t *texture_info::compute_size_type()
+copy_info_t const *texture_info::compute_size_type()
{
- copy_info_t *result = nullptr;
+ copy_info_t const *result = nullptr;
int maxperf = 0;
- for (copy_info_t *bi = renderer_sdl2::s_blit_info[m_format]; bi != nullptr; bi = bi->next)
+ for (copy_info_t const *bi = m_renderer->m_blit_info[m_format]; bi != nullptr; bi = bi->next)
{
- if ((m_is_rotated == bi->blitter->m_is_rot)
- && (m_sdl_blendmode == bi->bm_mask))
+ if ((m_is_rotated == bi->blitter->m_is_rot) && (m_sdl_blendmode == bi->bm_mask))
{
if (m_renderer->RendererSupportsFormat(bi->dst_fmt, m_sdl_access, bi->dstname))
{
- int perf = bi->perf;
+ int const perf = bi->perf;
if (perf == 0)
+ {
return bi;
- else if (perf > (maxperf * 102) / 100)
+ }
+ else if (perf > ((maxperf * 102) / 100))
{
result = bi;
maxperf = perf;
@@ -639,23 +652,21 @@ copy_info_t *texture_info::compute_size_type()
if (result)
return result;
- /* try last resort handlers */
- for (copy_info_t *bi = renderer_sdl2::s_blit_info[m_format]; bi != nullptr; bi = bi->next)
+ // try last resort handlers
+ for (copy_info_t const *bi = m_renderer->m_blit_info[m_format]; bi != nullptr; bi = bi->next)
{
- if ((m_is_rotated == bi->blitter->m_is_rot)
- && (m_sdl_blendmode == bi->bm_mask))
+ if ((m_is_rotated == bi->blitter->m_is_rot) && (m_sdl_blendmode == bi->bm_mask))
if (m_renderer->RendererSupportsFormat(bi->dst_fmt, m_sdl_access, bi->dstname))
return bi;
}
- //FIXME: crash implement a -do nothing handler */
+ //FIXME: crash implement a -do nothing handler
return nullptr;
}
-// FIXME:
bool texture_info::is_pixels_owned() const
-{ // do we own / allocated it ?
- return ((m_sdl_access == SDL_TEXTUREACCESS_STATIC)
- && (m_copyinfo->blitter->m_is_passthrough));
+{
+ // do we own / allocated it ?
+ return (m_sdl_access == SDL_TEXTUREACCESS_STATIC) && !m_copyinfo->blitter->m_is_passthrough;
}
//============================================================
@@ -745,12 +756,11 @@ texture_info::texture_info(renderer_sdl2 *renderer, const render_texinfo &texsou
m_pixels = malloc(m_setup.rotwidth * m_setup.rotheight * m_copyinfo->blitter->m_dest_bpp);
}
m_last_access = osd_ticks();
-
}
texture_info::~texture_info()
{
- if ( is_pixels_owned() && (m_pixels != nullptr) )
+ if (is_pixels_owned() && m_pixels)
free(m_pixels);
SDL_DestroyTexture(m_texture_id);
}
@@ -764,7 +774,7 @@ void texture_info::set_data(const render_texinfo &texsource, const uint32_t flag
m_copyinfo->time -= osd_ticks();
if (m_sdl_access == SDL_TEXTUREACCESS_STATIC)
{
- if ( m_copyinfo->blitter->m_is_passthrough )
+ if (m_copyinfo->blitter->m_is_passthrough)
{
m_pixels = texsource.base;
m_pitch = m_texinfo.rowpixels * m_copyinfo->blitter->m_dest_bpp;
@@ -778,11 +788,11 @@ void texture_info::set_data(const render_texinfo &texsource, const uint32_t flag
}
else
{
- SDL_LockTexture(m_texture_id, nullptr, (void **) &m_pixels, &m_pitch);
+ SDL_LockTexture(m_texture_id, nullptr, (void **)&m_pixels, &m_pitch);
if ( m_copyinfo->blitter->m_is_passthrough )
{
- uint8_t *src = (uint8_t *) texsource.base;
- uint8_t *dst = (uint8_t *) m_pixels;
+ const uint8_t *src = (uint8_t *)texsource.base;
+ uint8_t *dst = (uint8_t *)m_pixels;
int spitch = texsource.rowpixels * m_copyinfo->blitter->m_dest_bpp;
int num = texsource.width * m_copyinfo->blitter->m_dest_bpp;
int h = texsource.height;
@@ -868,64 +878,38 @@ void quad_setup_data::compute(const render_primitive &prim, const int prescale)
texture_info *renderer_sdl2::texture_find(const render_primitive &prim, const quad_setup_data &setup)
{
- HashT texhash = texture_compute_hash(prim.texture, prim.flags);
- texture_info *texture;
- osd_ticks_t now = osd_ticks();
+ const HashT texhash = texture_compute_hash(prim.texture, prim.flags);
+ const osd_ticks_t now = osd_ticks();
// find a match
- for (texture = m_texlist.first(); texture != nullptr; )
- if (texture->hash() == texhash &&
- texture->matches(prim, setup))
+ for (auto texture = m_texlist.begin(); texture != m_texlist.end(); )
+ {
+ if ((texture->hash() == texhash) && texture->matches(prim, setup))
{
- /* would we choose another blitter based on performance ? */
+ // would we choose another blitter based on performance?
if ((texture->m_copyinfo->samples & 0x7f) == 0x7f)
{
if (texture->m_copyinfo != texture->compute_size_type())
return nullptr;
}
texture->m_last_access = now;
- return texture;
+ return &*texture;
}
else
{
- /* free resources not needed any longer? */
- texture_info *expire = texture;
- texture = texture->next();
- if (now - expire->m_last_access > osd_ticks_per_second())
- m_texlist.remove(*expire);
+ // free resources not needed any longer?
+ if ((now - texture->m_last_access) > osd_ticks_per_second())
+ texture = m_texlist.erase(texture);
+ else
+ ++texture;
}
+ }
// nothing found
return nullptr;
}
//============================================================
-// exit
-//============================================================
-
-void renderer_sdl2::exit()
-{
- if (s_blit_info_initialized)
- {
- for (int i = 0; i <= SDL_TEXFORMAT_LAST; i++)
- {
- for (copy_info_t *bi = s_blit_info[i]; bi != nullptr; )
- {
- if (bi->pixel_count)
- osd_printf_verbose("%s -> %s %s blendmode 0x%02x, %d samples: %d KPixel/sec\n", bi->srcname, bi->dstname,
- bi->blitter->m_is_rot ? "rot" : "norot", bi->bm_mask, bi->samples,
- (int) bi->perf);
- copy_info_t *freeme = bi;
- bi = bi->next;
- delete freeme;
- }
- s_blit_info[i] = nullptr;
- }
- s_blit_info_initialized = false;
- }
-}
-
-//============================================================
// texture_update
//============================================================
@@ -934,22 +918,20 @@ texture_info * renderer_sdl2::texture_update(const render_primitive &prim)
quad_setup_data setup;
texture_info *texture;
- auto win = assert_window();
- setup.compute(prim, win->prescale());
+ setup.compute(prim, window().prescale());
texture = texture_find(prim, setup);
// if we didn't find one, create a new texture
- if (texture == nullptr && prim.texture.base != nullptr)
+ if (!texture && prim.texture.base)
{
- texture = new texture_info(this, prim.texture, setup, prim.flags);
- /* add us to the texture list */
- m_texlist.prepend(*texture);
+ // add us to the texture list
+ texture = &m_texlist.emplace_front(this, prim.texture, setup, prim.flags);
}
- if (texture != nullptr)
+ if (texture)
{
- if (prim.texture.base != nullptr && texture->texinfo().seqid != prim.texture.seqid)
+ if (prim.texture.base && (texture->texinfo().seqid != prim.texture.seqid))
{
texture->texinfo().seqid = prim.texture.seqid;
// if we found it, but with a different seqid, copy the data
@@ -962,16 +944,249 @@ texture_info * renderer_sdl2::texture_update(const render_primitive &prim)
render_primitive_list *renderer_sdl2::get_primitives()
{
- auto win = assert_window();
- if (win == nullptr)
- return nullptr;
-
- osd_dim nd = win->get_size();
+ osd_dim nd = window().get_size();
if (nd != m_blit_dim)
{
m_blit_dim = nd;
notify_changed();
}
- win->target()->set_bounds(m_blit_dim.width(), m_blit_dim.height(), win->pixel_aspect());
- return &win->target()->get_primitives();
+ window().target()->set_bounds(m_blit_dim.width(), m_blit_dim.height(), window().pixel_aspect());
+ return &window().target()->get_primitives();
+}
+
+
+class video_sdl2 : public osd_module, public render_module
+{
+public:
+ video_sdl2()
+ : osd_module(OSD_RENDERER_PROVIDER, "accel")
+ , m_blit_info_initialized(false)
+ , m_gllib_loaded(false)
+ {
+ std::fill(std::begin(m_blit_info), std::end(m_blit_info), nullptr);
+ }
+ ~video_sdl2()
+ {
+ free_copy_info();
+ }
+
+ virtual int init(osd_interface &osd, osd_options const &options) override;
+ virtual void exit() override { free_copy_info(); }
+
+ virtual std::unique_ptr<osd_renderer> create(osd_window &window) override;
+
+protected:
+ virtual unsigned flags() const override { return FLAG_INTERACTIVE | FLAG_SDL_NEEDS_OPENGL; }
+
+private:
+ static inline constexpr Uint32 BM_ALL = UINT32_MAX; // SDL_BLENDMODE_MASK | SDL_BLENDMODE_BLEND | SDL_BLENDMODE_ADD | SDL_BLENDMODE_MOD
+
+ void expand_copy_info();
+ void free_copy_info();
+
+ static void add_list(copy_info_t const *&head, copy_info_t const &element, Uint32 bm);
+
+ copy_info_t const *m_blit_info[SDL_TEXFORMAT_LAST + 1];
+ bool m_blit_info_initialized;
+ bool m_gllib_loaded;
+
+ static copy_info_t const s_blit_info_default[];
+};
+
+int video_sdl2::init(osd_interface &osd, osd_options const &options)
+{
+ osd_printf_verbose("Using SDL native texturing driver (SDL 2.0+)\n");
+
+ // Load the GL library now - else MT will fail
+ char const *libname = nullptr;
+#if USE_OPENGL
+ libname = dynamic_cast<sdl_options const &>(options).gl_lib();
+ if (libname && (!*libname || !std::strcmp(libname, OSDOPTVAL_AUTO)))
+ libname = nullptr;
+#endif
+
+ if (!m_gllib_loaded)
+ {
+ // No fatalerror here since not all video drivers support GL!
+ if (SDL_GL_LoadLibrary(libname) != 0)
+ {
+ osd_printf_error("Unable to load OpenGL shared library: %s\n", libname ? libname : "<default>");
+ m_gllib_loaded = true;
+ }
+ else
+ {
+ osd_printf_verbose("Loaded OpenGL shared library: %s\n", libname ? libname : "<default>");
+ }
+ }
+
+ return 0;
+}
+
+std::unique_ptr<osd_renderer> video_sdl2::create(osd_window &window)
+{
+ if (!m_blit_info_initialized)
+ {
+ // On macOS, calling this from drawsdl2_init will prohibit fullscreen toggling.
+ // It is than not possible to toggle from fullscreen to window mode.
+ expand_copy_info();
+ m_blit_info_initialized = true;
+ }
+
+ return std::make_unique<renderer_sdl2>(window, m_blit_info);
+}
+
+void video_sdl2::expand_copy_info()
+{
+ for (const copy_info_t *bi = s_blit_info_default; bi->src_fmt != -1; bi++)
+ {
+ if (bi->bm_mask == BM_ALL)
+ {
+ add_list(m_blit_info[bi->src_fmt], *bi, SDL_BLENDMODE_NONE);
+ add_list(m_blit_info[bi->src_fmt], *bi, SDL_BLENDMODE_ADD);
+ add_list(m_blit_info[bi->src_fmt], *bi, SDL_BLENDMODE_MOD);
+ add_list(m_blit_info[bi->src_fmt], *bi, SDL_BLENDMODE_BLEND);
+ }
+ else
+ {
+ add_list(m_blit_info[bi->src_fmt], *bi, bi->bm_mask);
+ }
+ }
+}
+
+void video_sdl2::free_copy_info()
+{
+ if (m_blit_info_initialized)
+ {
+ for (int i = 0; i <= SDL_TEXFORMAT_LAST; i++)
+ {
+ for (copy_info_t const *bi = m_blit_info[i]; bi != nullptr; )
+ {
+ if (bi->pixel_count)
+ {
+ osd_printf_verbose(
+ "%s -> %s %s blendmode 0x%02x, %d samples: %d KPixel/sec\n",
+ bi->srcname,
+ bi->dstname,
+ bi->blitter->m_is_rot ? "rot" : "norot",
+ bi->bm_mask,
+ bi->samples,
+ bi->perf);
+ }
+ delete std::exchange(bi, bi->next);
+ }
+ m_blit_info[i] = nullptr;
+ }
+ m_blit_info_initialized = false;
+ }
+}
+
+void video_sdl2::add_list(copy_info_t const *&head, copy_info_t const &element, Uint32 bm)
+{
+ copy_info_t *const newci = new copy_info_t(element);
+
+ newci->bm_mask = bm;
+ newci->next = head;
+ head = newci;
}
+
+
+//============================================================
+// STATIC VARIABLES
+//============================================================
+
+#define ENTRY(a,b,f) { SDL_TEXFORMAT_ ## a, SDL_PIXELFORMAT_ ## b, &texcopy_ ## f, BM_ALL, #a, #b, 0, 0, 0, 0}
+#define ENTRY_BM(a,b,f,bm) { SDL_TEXFORMAT_ ## a, SDL_PIXELFORMAT_ ## b, &texcopy_ ## f, bm, #a, #b, 0, 0, 0, 0}
+#define ENTRY_LR(a,b,f) { SDL_TEXFORMAT_ ## a, SDL_PIXELFORMAT_ ## b, &texcopy_ ## f, BM_ALL, #a, #b, 0, 0, 0, -1}
+
+copy_info_t const video_sdl2::s_blit_info_default[] =
+{
+ /* no rotation */
+ ENTRY(ARGB32, ARGB8888, argb32_argb32),
+ ENTRY_LR(ARGB32, RGB888, argb32_rgb32),
+ /* Entry primarily for directfb */
+ ENTRY_BM(ARGB32, RGB888, argb32_rgb32, SDL_BLENDMODE_ADD),
+ ENTRY_BM(ARGB32, RGB888, argb32_rgb32, SDL_BLENDMODE_MOD),
+ ENTRY_BM(ARGB32, RGB888, argb32_rgb32, SDL_BLENDMODE_NONE),
+
+ ENTRY(RGB32, ARGB8888, rgb32_argb32),
+ ENTRY(RGB32, RGB888, rgb32_rgb32),
+
+ ENTRY(RGB32_PALETTED, ARGB8888, rgb32pal_argb32),
+ ENTRY(RGB32_PALETTED, RGB888, rgb32pal_argb32),
+
+ ENTRY(YUY16, UYVY, yuv16_uyvy),
+ ENTRY(YUY16, YUY2, yuv16_yuy2),
+ ENTRY(YUY16, YVYU, yuv16_yvyu),
+ ENTRY(YUY16, ARGB8888, yuv16_argb32),
+ ENTRY(YUY16, RGB888, yuv16_argb32),
+
+ ENTRY(YUY16_PALETTED, UYVY, yuv16pal_uyvy),
+ ENTRY(YUY16_PALETTED, YUY2, yuv16pal_yuy2),
+ ENTRY(YUY16_PALETTED, YVYU, yuv16pal_yvyu),
+ ENTRY(YUY16_PALETTED, ARGB8888, yuv16pal_argb32),
+ ENTRY(YUY16_PALETTED, RGB888, yuv16pal_argb32),
+
+ ENTRY(PALETTE16, ARGB8888, pal16_argb32),
+ ENTRY(PALETTE16, RGB888, pal16_argb32),
+
+ ENTRY(RGB15, RGB555, rgb15_rgb555),
+ ENTRY(RGB15, ARGB1555, rgb15_argb1555),
+ ENTRY(RGB15, ARGB8888, rgb15_argb32),
+ ENTRY(RGB15, RGB888, rgb15_argb32),
+
+ ENTRY(RGB15_PALETTED, ARGB8888, rgb15pal_argb32),
+ ENTRY(RGB15_PALETTED, RGB888, rgb15pal_argb32),
+
+ ENTRY(PALETTE16A, ARGB8888, pal16a_argb32),
+ ENTRY(PALETTE16A, RGB888, pal16a_rgb32),
+
+ /* rotation */
+ ENTRY(ARGB32, ARGB8888, rot_argb32_argb32),
+ ENTRY_LR(ARGB32, RGB888, rot_argb32_rgb32),
+ /* Entry primarily for directfb */
+ ENTRY_BM(ARGB32, RGB888, rot_argb32_rgb32, SDL_BLENDMODE_ADD),
+ ENTRY_BM(ARGB32, RGB888, rot_argb32_rgb32, SDL_BLENDMODE_MOD),
+ ENTRY_BM(ARGB32, RGB888, rot_argb32_rgb32, SDL_BLENDMODE_NONE),
+
+ ENTRY(RGB32, ARGB8888, rot_rgb32_argb32),
+ ENTRY(RGB32, RGB888, rot_argb32_argb32),
+
+ ENTRY(RGB32_PALETTED, ARGB8888, rot_rgb32pal_argb32),
+ ENTRY(RGB32_PALETTED, RGB888, rot_rgb32pal_argb32),
+
+ ENTRY(YUY16, ARGB8888, rot_yuv16_argb32rot),
+ ENTRY(YUY16, RGB888, rot_yuv16_argb32rot),
+
+ ENTRY(YUY16_PALETTED, ARGB8888, rot_yuv16pal_argb32rot),
+ ENTRY(YUY16_PALETTED, RGB888, rot_yuv16pal_argb32rot),
+
+ ENTRY(PALETTE16, ARGB8888, rot_pal16_argb32),
+ ENTRY(PALETTE16, RGB888, rot_pal16_argb32),
+
+ ENTRY(RGB15, RGB555, rot_rgb15_argb1555),
+ ENTRY(RGB15, ARGB1555, rot_rgb15_argb1555),
+ ENTRY(RGB15, ARGB8888, rot_rgb15_argb32),
+ ENTRY(RGB15, RGB888, rot_rgb15_argb32),
+
+ ENTRY(RGB15_PALETTED, ARGB8888, rot_rgb15pal_argb32),
+ ENTRY(RGB15_PALETTED, RGB888, rot_rgb15pal_argb32),
+
+ ENTRY(PALETTE16A, ARGB8888, rot_pal16a_argb32),
+ ENTRY(PALETTE16A, RGB888, rot_pal16a_rgb32),
+
+ { -1 },
+};
+
+} // anonymous namespace
+
+} // namespace osd
+
+
+#else // defined(OSD_SDL)
+
+namespace osd { namespace { MODULE_NOT_SUPPORTED(video_sdl2, OSD_RENDERER_PROVIDER, "accel") } }
+
+#endif // defined(OSD_SDL)
+
+
+MODULE_DEFINITION(RENDERER_SDL2, osd::video_sdl2)
diff --git a/src/osd/modules/render/draw13.h b/src/osd/modules/render/draw13.h
deleted file mode 100644
index d69c84c1c9d..00000000000
--- a/src/osd/modules/render/draw13.h
+++ /dev/null
@@ -1,216 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Couriersud, Olivier Galibert, R. Belmont
-//============================================================
-//
-// draw13.h - SDL 2.0 drawing implementation
-//
-// SDLMAME by Olivier Galibert and R. Belmont
-//
-//============================================================
-
-#ifndef MAME_OSD_MODULES_RENDER_DRAW13_H
-#define MAME_OSD_MODULES_RENDER_DRAW13_H
-
-#pragma once
-
-// OSD headers
-#ifndef OSD_WINDOWS
-#include "osdsdl.h"
-#include "window.h"
-#else
-#include "../windows/window.h"
-typedef uint64_t HashT;
-#endif
-
-// standard SDL headers
-#include <SDL2/SDL.h>
-
-#include "emucore.h"
-#include "render.h"
-
-struct quad_setup_data
-{
- quad_setup_data()
- : dudx(0)
- , dvdx(0)
- , dudy(0)
- , dvdy(0)
- , startu(0)
- , startv(0)
- , rotwidth(0)
- , rotheight(0)
- {
- }
-
- void compute(const render_primitive &prim, const int prescale);
-
- int32_t dudx, dvdx, dudy, dvdy;
- int32_t startu, startv;
- int32_t rotwidth, rotheight;
-};
-
-//============================================================
-// Textures
-//============================================================
-
-class renderer_sdl2;
-struct copy_info_t;
-
-/* texture_info holds information about a texture */
-class texture_info
-{
- friend class simple_list<texture_info>;
-public:
- texture_info(renderer_sdl2 *renderer, const render_texinfo &texsource, const quad_setup_data &setup, const uint32_t flags);
- ~texture_info();
-
- void set_data(const render_texinfo &texsource, const uint32_t flags);
- void render_quad(const render_primitive &prim, const int x, const int y);
- bool matches(const render_primitive &prim, const quad_setup_data &setup);
-
- copy_info_t *compute_size_type();
-
- void *m_pixels; // pixels for the texture
- int m_pitch;
-
- copy_info_t *m_copyinfo;
- quad_setup_data m_setup;
-
- osd_ticks_t m_last_access;
-
- int raw_width() const { return m_texinfo.width; }
- int raw_height() const { return m_texinfo.height; }
-
- texture_info *next() { return m_next; }
- const render_texinfo &texinfo() const { return m_texinfo; }
- render_texinfo &texinfo() { return m_texinfo; }
-
- HashT hash() const { return m_hash; }
- uint32_t flags() const { return m_flags; }
- // FIXME:
- bool is_pixels_owned() const;
-
-private:
- void set_coloralphamode(SDL_Texture *texture_id, const render_color *color);
-
- Uint32 m_sdl_access;
- renderer_sdl2 * m_renderer;
- render_texinfo m_texinfo; // copy of the texture info
- HashT m_hash; // hash value for the texture (must be >= pointer size)
- uint32_t m_flags; // rendering flags
-
- SDL_Texture * m_texture_id;
- bool m_is_rotated;
-
- int m_format; // texture format
- SDL_BlendMode m_sdl_blendmode;
-
- texture_info * m_next; // next texture in the list
-};
-
-//============================================================
-// TEXCOPY FUNCS
-//============================================================
-
-enum SDL_TEXFORMAT_E
-{
- SDL_TEXFORMAT_ARGB32 = 0,
- SDL_TEXFORMAT_RGB32,
- SDL_TEXFORMAT_RGB32_PALETTED,
- SDL_TEXFORMAT_YUY16,
- SDL_TEXFORMAT_YUY16_PALETTED,
- SDL_TEXFORMAT_PALETTE16,
- SDL_TEXFORMAT_RGB15,
- SDL_TEXFORMAT_RGB15_PALETTED,
- SDL_TEXFORMAT_PALETTE16A,
- SDL_TEXFORMAT_PALETTE16_ARGB1555,
- SDL_TEXFORMAT_RGB15_ARGB1555,
- SDL_TEXFORMAT_RGB15_PALETTED_ARGB1555,
- SDL_TEXFORMAT_LAST = SDL_TEXFORMAT_RGB15_PALETTED_ARGB1555
-};
-
-#include "blit13.h"
-
-struct copy_info_t
-{
- int src_fmt;
- Uint32 dst_fmt;
- const blit_base *blitter;
- Uint32 bm_mask;
- const char *srcname;
- const char *dstname;
- /* Statistics */
- uint64_t pixel_count;
- int64_t time;
- int samples;
- int perf;
- /* list */
- copy_info_t *next;
-};
-
-/* renderer_sdl2 is the information about SDL for the current screen */
-class renderer_sdl2 : public osd_renderer
-{
-public:
- renderer_sdl2(std::shared_ptr<osd_window> window, int extra_flags);
-
- virtual ~renderer_sdl2()
- {
- destroy_all_textures();
- SDL_DestroyRenderer(m_sdl_renderer);
- m_sdl_renderer = nullptr;
- }
-
- static void init(running_machine &machine);
- static void exit();
-
- virtual int create() override;
- virtual int draw(const int update) override;
- virtual int xy_to_render_target(const int x, const int y, int *xt, int *yt) override;
- virtual render_primitive_list *get_primitives() override;
-
- int RendererSupportsFormat(Uint32 format, Uint32 access, const char *sformat);
-
- SDL_Renderer * m_sdl_renderer;
-
- static copy_info_t* s_blit_info[SDL_TEXFORMAT_LAST+1];
-
-private:
- void expand_copy_info(const copy_info_t *list);
- void add_list(copy_info_t **head, const copy_info_t *element, Uint32 bm);
-
- void render_quad(texture_info *texture, const render_primitive &prim, const int x, const int y);
-
- texture_info *texture_find(const render_primitive &prim, const quad_setup_data &setup);
- texture_info *texture_update(const render_primitive &prim);
-
- void destroy_all_textures();
-
- int32_t m_blittimer;
-
-
- simple_list<texture_info> m_texlist; // list of active textures
-
- float m_last_hofs;
- float m_last_vofs;
-
- int m_width;
- int m_height;
-
- osd_dim m_blit_dim;
-
- struct
- {
- Uint32 format;
- int status;
- } fmt_support[30];
-
- // Stats
- int64_t m_last_blit_time;
- int64_t m_last_blit_pixels;
-
- static bool s_blit_info_initialized;
- static const copy_info_t s_blit_info_default[];
-};
-
-#endif // MAME_OSD_MODULES_RENDER_DRAW13_H
diff --git a/src/osd/modules/render/drawbgfx.cpp b/src/osd/modules/render/drawbgfx.cpp
index fc9214fe446..36758914961 100644
--- a/src/osd/modules/render/drawbgfx.cpp
+++ b/src/osd/modules/render/drawbgfx.cpp
@@ -5,6 +5,40 @@
// drawbgfx.cpp - BGFX renderer
//
//============================================================
+
+#include "drawbgfx.h"
+
+// render/bgfx
+#include "bgfx/effect.h"
+#include "bgfx/effectmanager.h"
+#include "bgfx/shadermanager.h"
+#include "bgfx/slider.h"
+#include "bgfx/target.h"
+#include "bgfx/target.h"
+#include "bgfx/targetmanager.h"
+#include "bgfx/texture.h"
+#include "bgfx/texturemanager.h"
+#include "bgfx/uniform.h"
+#include "bgfx/view.h"
+
+// render
+#include "aviwrite.h"
+#include "bgfxutil.h"
+#include "render_module.h"
+
+// emu
+#include "emu.h"
+#include "config.h"
+#include "render.h"
+#include "rendutil.h"
+
+// util
+#include "util/xmlfile.h"
+
+// OSD
+#include "modules/lib/osdobj_common.h"
+#include "window.h"
+
#include <bx/math.h>
#include <bx/readerwriter.h>
@@ -22,334 +56,658 @@ extern void *GetOSWindow(void *wincontroller);
#endif
#endif
-// MAMEOS headers
-#include "emu.h"
-#include "window.h"
-#include "render.h"
-#include "rendutil.h"
-#include "aviwrite.h"
+#if defined(SDLMAME_USE_WAYLAND)
+#include <wayland-egl.h>
+#endif
#include <bgfx/bgfx.h>
#include <bgfx/platform.h>
-#include <algorithm>
-#include "drawbgfx.h"
-#include "bgfxutil.h"
-#include "bgfx/texturemanager.h"
-#include "bgfx/targetmanager.h"
-#include "bgfx/shadermanager.h"
-#include "bgfx/effectmanager.h"
-#include "bgfx/chainmanager.h"
-#include "bgfx/effect.h"
-#include "bgfx/texture.h"
-#include "bgfx/target.h"
-#include "bgfx/chain.h"
-#include "bgfx/vertex.h"
-#include "bgfx/uniform.h"
-#include "bgfx/slider.h"
-#include "bgfx/target.h"
-#include "bgfx/view.h"
+#include "imgui/imgui.h"
-#include "modules/lib/osdobj_common.h"
+#include <algorithm>
-#include "imgui/imgui.h"
//============================================================
-// DEBUGGING
+// Renderer interface to parent module
//============================================================
-//============================================================
-// CONSTANTS
-//============================================================
+class renderer_bgfx::parent_module
+{
+public:
+ util::xml::data_node &persistent_settings() { return *m_persistent_settings; }
+ osd_options const &options() const { return *m_options; }
+ uint32_t max_texture_size() const { return m_max_texture_size; }
+
+ template <typename T>
+ util::notifier_subscription subscribe_load(void (T::*func)(util::xml::data_node const &), T *obj)
+ {
+ return m_load_notifier.subscribe(delegate<void (util::xml::data_node const &)>(func, obj));
+ }
+
+ template <typename T>
+ util::notifier_subscription subscribe_save(void (T::*func)(util::xml::data_node &), T *obj)
+ {
+ return m_save_notifier.subscribe(delegate<void (util::xml::data_node &)>(func, obj));
+ }
+
+protected:
+ parent_module()
+ : m_options(nullptr)
+ , m_max_texture_size(0)
+ , m_renderer_count(0)
+ {
+ }
+ virtual ~parent_module()
+ {
+ assert(!m_renderer_count);
+ }
+
+ bool has_active_renderers() const
+ {
+ return 0 < m_renderer_count;
+ }
+
+ util::notifier<util::xml::data_node const &> m_load_notifier;
+ util::notifier<util::xml::data_node &> m_save_notifier;
+ util::xml::file::ptr m_persistent_settings;
+ osd_options const *m_options;
+ uint32_t m_max_texture_size;
+
+private:
+ friend class parent_module_holder;
+
+ virtual void last_renderer_destroyed() = 0;
+
+ void renderer_created()
+ {
+ ++m_renderer_count;
+ }
+
+ void renderer_destroyed()
+ {
+ assert(m_renderer_count);
+ if (!--m_renderer_count)
+ last_renderer_destroyed();
+ }
+
+ unsigned m_renderer_count;
+};
+
+
+inline renderer_bgfx::parent_module_holder::parent_module_holder(parent_module &parent)
+ : m_parent(parent)
+{
+ m_parent.renderer_created();
+}
+
+
+inline renderer_bgfx::parent_module_holder::~parent_module_holder()
+{
+ m_parent.renderer_destroyed();
+}
+
-uint16_t const renderer_bgfx::CACHE_SIZE = 1024;
-uint32_t const renderer_bgfx::PACKABLE_SIZE = 128;
-uint32_t const renderer_bgfx::WHITE_HASH = 0x87654321;
-char const *const renderer_bgfx::WINDOW_PREFIX = "Window 0, ";
//============================================================
-// MACROS
+// OSD MODULE
//============================================================
-#define GIBBERISH (0)
-#define SCENE_VIEW (0)
+namespace osd {
+
+namespace {
+
+class video_bgfx : public osd_module, public render_module, protected renderer_bgfx::parent_module
+{
+public:
+ video_bgfx()
+ : osd_module(OSD_RENDERER_PROVIDER, "bgfx")
+ , m_bgfx_library_initialized(false)
+ {
+ }
+ ~video_bgfx() { exit(); }
+
+ virtual int init(osd_interface &osd, osd_options const &options) override;
+ virtual void exit() override;
+
+ virtual std::unique_ptr<osd_renderer> create(osd_window &window) override;
+
+protected:
+ virtual unsigned flags() const override { return FLAG_INTERACTIVE; }
+
+private:
+ virtual void last_renderer_destroyed() override;
+
+ void load_config(config_type cfg_type, config_level cfg_level, util::xml::data_node const *parentnode);
+ void save_config(config_type cfg_type, util::xml::data_node *parentnode);
+
+ bool init_bgfx_library(osd_window &window);
+
+ static bool set_platform_data(bgfx::PlatformData &platform_data, osd_window const &window);
+
+ bool m_bgfx_library_initialized;
+};
+
//============================================================
-// STATICS
+// video_bgfx::init
//============================================================
-uint32_t renderer_bgfx::s_current_view = 0;
-bool renderer_bgfx::s_bgfx_library_initialized = false;
-uint32_t renderer_bgfx::s_width[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-uint32_t renderer_bgfx::s_height[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+int video_bgfx::init(osd_interface &osd, osd_options const &options)
+{
+ m_options = &options;
+ m_persistent_settings = util::xml::file::create();
+
+ // Check that BGFX directory exists
+ char const *const bgfx_path = options.bgfx_path();
+ osd::directory::ptr directory = osd::directory::open(bgfx_path);
+ if (!directory)
+ {
+ osd_printf_error("Unable to find the BGFX path %s, please install it or fix the bgfx_path setting to use the BGFX renderer.\n", bgfx_path);
+ return -1;
+ }
+ directory.reset();
+
+ // Verify baseline shaders
+ const bool gui_opaque_valid = effect_manager::validate_effect(options, "gui_opaque");
+ const bool gui_blend_valid = effect_manager::validate_effect(options, "gui_blend");
+ const bool gui_multiply_valid = effect_manager::validate_effect(options, "gui_multiply");
+ const bool gui_add_valid = effect_manager::validate_effect(options, "gui_add");
+ const bool all_gui_valid = gui_opaque_valid && gui_blend_valid && gui_multiply_valid && gui_add_valid;
+
+ const bool screen_opaque_valid = effect_manager::validate_effect(options, "screen_opaque");
+ const bool screen_blend_valid = effect_manager::validate_effect(options, "screen_blend");
+ const bool screen_multiply_valid = effect_manager::validate_effect(options, "screen_multiply");
+ const bool screen_add_valid = effect_manager::validate_effect(options, "screen_add");
+ const bool all_screen_valid = screen_opaque_valid && screen_blend_valid && screen_multiply_valid && screen_add_valid;
+
+ if (!all_gui_valid || !all_screen_valid)
+ {
+ osd_printf_error("BGFX: Unable to load required shaders. Please update the %s folder or adjust your bgfx_path setting.\n", options.bgfx_path());
+ return -1;
+ }
+
+ m_max_texture_size = 16384; // Relatively safe default on modern GPUs
+
+ // Register configuration handlers - do this last because it can't be undone
+ downcast<osd_common_t &>(osd).machine().configuration().config_register(
+ "bgfx",
+ configuration_manager::load_delegate(&video_bgfx::load_config, this),
+ configuration_manager::save_delegate(&video_bgfx::save_config, this));
+
+ return 0;
+}
+
//============================================================
-// renderer_bgfx - constructor
+// video_bgfx::exit
//============================================================
-renderer_bgfx::renderer_bgfx(std::shared_ptr<osd_window> w)
- : osd_renderer(w, FLAG_NONE)
- , m_options(downcast<osd_options &>(w->machine().options()))
- , m_framebuffer(nullptr)
- , m_texture_cache(nullptr)
- , m_dimensions(0, 0)
- , m_textures(nullptr)
- , m_targets(nullptr)
- , m_shaders(nullptr)
- , m_effects(nullptr)
- , m_chains(nullptr)
- , m_ortho_view(nullptr)
- , m_max_view(0)
- , m_avi_view(nullptr)
- , m_avi_writer(nullptr)
- , m_avi_target(nullptr)
+void video_bgfx::exit()
{
+ assert(!has_active_renderers());
+
+ if (m_bgfx_library_initialized)
+ {
+ osd_printf_verbose("Shutting down BGFX library\n");
+ imguiDestroy();
+ bgfx::shutdown();
+ m_bgfx_library_initialized = false;
+ }
+ m_max_texture_size = 0;
+ m_persistent_settings.reset();
+ m_options = nullptr;
}
+
//============================================================
-// renderer_bgfx - destructor
+// video_bgfx::create
//============================================================
-renderer_bgfx::~renderer_bgfx()
+std::unique_ptr<osd_renderer> video_bgfx::create(osd_window &window)
{
- bgfx::reset(0, 0, BGFX_RESET_NONE);
-
- if (m_avi_writer != nullptr && m_avi_writer->recording())
+ // start BGFX if this is the first window
+ if (!m_bgfx_library_initialized)
{
- m_avi_writer->stop();
+ assert(window.index() == 0); // bad things will happen otherwise
+ assert(!has_active_renderers());
- m_targets->destroy_target("avibuffer0");
- m_avi_target = nullptr;
+ osd_printf_verbose("Initializing BGFX library\n");
+ if (!init_bgfx_library(window))
+ {
+ osd_printf_error("BGFX library initialization failed\n");
+ return nullptr;
+ }
+ m_bgfx_library_initialized = true;
+ }
- bgfx::destroy(m_avi_texture);
+ return std::make_unique<renderer_bgfx>(window, static_cast<renderer_bgfx::parent_module &>(*this));
+}
- delete m_avi_writer;
- delete [] m_avi_data;
- delete m_avi_view;
+
+//============================================================
+// video_bgfx::last_renderer_destroyed
+//============================================================
+
+void video_bgfx::last_renderer_destroyed()
+{
+ if (m_bgfx_library_initialized)
+ {
+ osd_printf_verbose("No more renderers - shutting down BGFX library\n");
+ imguiDestroy();
+ bgfx::shutdown();
+ m_bgfx_library_initialized = false;
+ m_max_texture_size = 0;
}
+}
- // Cleanup.
- if (m_ortho_view)
- delete m_ortho_view;
- delete m_chains;
- delete m_effects;
- delete m_shaders;
- delete m_textures;
- delete m_targets;
+//============================================================
+// video_bgfx::load_config
+//============================================================
+
+void video_bgfx::load_config(config_type cfg_type, config_level cfg_level, util::xml::data_node const *parentnode)
+{
+ if ((cfg_type == config_type::SYSTEM) && parentnode)
+ m_load_notifier(*parentnode);
}
+//============================================================
+// video_bgfx::save_config
+//============================================================
+
+void video_bgfx::save_config(config_type cfg_type, util::xml::data_node *parentnode)
+{
+ if (cfg_type == config_type::SYSTEM)
+ m_save_notifier(*parentnode);
+}
+
//============================================================
-// renderer_bgfx::init_bgfx_library
+// video_bgfx::init_bgfx_library
//============================================================
-void renderer_bgfx::init_bgfx_library()
+bool video_bgfx::init_bgfx_library(osd_window &window)
{
- std::string backend(m_options.bgfx_backend());
+ osd_dim const wdim = window.get_size();
bgfx::Init init;
init.type = bgfx::RendererType::Count;
init.vendorId = BGFX_PCI_ID_NONE;
- init.resolution.width = s_width[0];
- init.resolution.height = s_height[0];
+ init.resolution.width = wdim.width();
+ init.resolution.height = wdim.height();
init.resolution.numBackBuffers = 1;
- init.resolution.reset = BGFX_RESET_NONE;
- init.platformData = m_platform_data;
- if (backend == "auto")
+ init.resolution.reset = video_config.waitvsync ? BGFX_RESET_VSYNC : BGFX_RESET_NONE;
+ if (!set_platform_data(init.platformData, window))
{
+ osd_printf_error("Setting BGFX platform data failed\n");
+ return false;
}
+
+ std::string_view const backend(m_options->bgfx_backend());
+ if (backend == "auto")
+ ; // do nothing
else if (backend == "dx9" || backend == "d3d9")
- {
init.type = bgfx::RendererType::Direct3D9;
- }
else if (backend == "dx11" || backend == "d3d11")
- {
init.type = bgfx::RendererType::Direct3D11;
- }
else if (backend == "dx12" || backend == "d3d12")
- {
init.type = bgfx::RendererType::Direct3D12;
- }
else if (backend == "gles")
- {
init.type = bgfx::RendererType::OpenGLES;
- }
else if (backend == "glsl" || backend == "opengl")
- {
init.type = bgfx::RendererType::OpenGL;
- }
else if (backend == "vulkan")
- {
init.type = bgfx::RendererType::Vulkan;
- }
else if (backend == "metal")
- {
init.type = bgfx::RendererType::Metal;
- }
else
- {
- osd_printf_verbose("Unknown backend type '%s', going with auto-detection.\n", backend.c_str());
- }
+ osd_printf_warning("Unknown BGFX backend type '%s', going with auto-detection.\n", backend);
- bgfx::init(init);
- bgfx::reset(s_width[0], s_height[0], video_config.waitvsync ? BGFX_RESET_VSYNC : BGFX_RESET_NONE);
- // Enable debug text if requested.
- bool bgfx_debug = m_options.bgfx_debug();
+ if (!bgfx::init(init))
+ return false;
+
+ bgfx::reset(wdim.width(), wdim.height(), video_config.waitvsync ? BGFX_RESET_VSYNC : BGFX_RESET_NONE);
+
+ // Enable debug text if requested
+ bool bgfx_debug = m_options->bgfx_debug();
bgfx::setDebug(bgfx_debug ? BGFX_DEBUG_STATS : BGFX_DEBUG_TEXT);
+ // Get actual maximum texture size
+ bgfx::Caps const *const caps = bgfx::getCaps();
+ m_max_texture_size = caps->limits.maxTextureSize;
+
ScreenVertex::init();
imguiCreate();
-}
+ return true;
+}
//============================================================
-// Utilities for setting up window handles
+// Helper for creating a wayland window
//============================================================
-#ifdef OSD_WINDOWS
-inline void winSetHwnd(bgfx::PlatformData &platform_data, ::HWND _window)
-{
- platform_data.ndt = NULL;
- platform_data.nwh = _window;
- platform_data.context = NULL;
- platform_data.backBuffer = NULL;
- platform_data.backBufferDS = NULL;
- bgfx::setPlatformData(platform_data);
-}
-#elif defined(OSD_MAC)
-inline void macSetWindow(bgfx::PlatformData &platform_data, void *_window)
-{
- platform_data.ndt = NULL;
- platform_data.nwh = GetOSWindow(_window);
- platform_data.context = NULL;
- platform_data.backBuffer = NULL;
- platform_data.backBufferDS = NULL;
- bgfx::setPlatformData(platform_data);
-}
-#elif defined(OSD_SDL)
-static void* sdlNativeWindowHandle(SDL_Window* _window)
+#if defined(SDLMAME_USE_WAYLAND)
+wl_egl_window *create_wl_egl_window(SDL_Window *window, struct wl_surface *surface)
{
- SDL_SysWMinfo wmi;
- SDL_VERSION(&wmi.version);
- if (!SDL_GetWindowWMInfo(_window, &wmi))
+ if (!surface)
{
+ osd_printf_error("Wayland surface missing, aborting\n");
return nullptr;
}
-
-# if BX_PLATFORM_LINUX || BX_PLATFORM_BSD || BX_PLATFORM_RPI
- return (void*)wmi.info.x11.window;
-# elif BX_PLATFORM_OSX
- return wmi.info.cocoa.window;
-# elif BX_PLATFORM_WINDOWS
- return wmi.info.win.window;
-# elif BX_PLATFORM_EMSCRIPTEN || BX_PLATFORM_ANDROID
- return nullptr;
-# endif // BX_PLATFORM_
+ wl_egl_window *win_impl = (wl_egl_window *)SDL_GetWindowData(window, "wl_egl_window");
+ if (!win_impl)
+ {
+ int width, height;
+ SDL_GetWindowSize(window, &width, &height);
+ win_impl = wl_egl_window_create(surface, width, height);
+ if (!win_impl)
+ {
+ osd_printf_error("Creating wayland window failed\n");
+ return nullptr;
+ }
+ SDL_SetWindowData(window, "wl_egl_window", win_impl);
+ }
+ return win_impl;
}
+#endif
-inline bool sdlSetWindow(bgfx::PlatformData &platform_data, SDL_Window* _window)
+
+//============================================================
+// Utility for setting up window handle
+//============================================================
+
+bool video_bgfx::set_platform_data(bgfx::PlatformData &platform_data, osd_window const &window)
{
+#if defined(OSD_WINDOWS)
+ platform_data.ndt = nullptr;
+ platform_data.nwh = dynamic_cast<win_window_info const &>(window).platform_window();
+#elif defined(OSD_MAC)
+ platform_data.ndt = nullptr;
+ platform_data.nwh = GetOSWindow(dynamic_cast<mac_window_info const &>(window).platform_window());
+#else // defined(OSD_*)
SDL_SysWMinfo wmi;
SDL_VERSION(&wmi.version);
- if (!SDL_GetWindowWMInfo(_window, &wmi) )
+ if (!SDL_GetWindowWMInfo(dynamic_cast<sdl_window_info const &>(window).platform_window(), &wmi))
{
+ osd_printf_error("BGFX: Error getting SDL window info: %s\n", SDL_GetError());
return false;
}
-# if BX_PLATFORM_LINUX || BX_PLATFORM_BSD
- platform_data.ndt = wmi.info.x11.display;
- platform_data.nwh = (void*)(uintptr_t)wmi.info.x11.window;
-# elif BX_PLATFORM_OSX
- platform_data.ndt = NULL;
- platform_data.nwh = wmi.info.cocoa.window;
-# elif BX_PLATFORM_WINDOWS
- platform_data.ndt = NULL;
- platform_data.nwh = wmi.info.win.window;
-# endif // BX_PLATFORM_
- platform_data.context = NULL;
- platform_data.backBuffer = NULL;
- platform_data.backBufferDS = NULL;
+ switch (wmi.subsystem)
+ {
+#if defined(SDL_VIDEO_DRIVER_WINDOWS)
+ case SDL_SYSWM_WINDOWS:
+ platform_data.ndt = nullptr;
+ platform_data.nwh = wmi.info.win.window;
+ break;
+#endif
+#if defined(SDL_VIDEO_DRIVER_X11)
+ case SDL_SYSWM_X11:
+ platform_data.ndt = wmi.info.x11.display;
+ platform_data.nwh = (void *)uintptr_t(wmi.info.x11.window);
+ break;
+#endif
+#if defined(SDL_VIDEO_DRIVER_COCOA)
+ case SDL_SYSWM_COCOA:
+ platform_data.ndt = nullptr;
+ platform_data.nwh = wmi.info.cocoa.window;
+ break;
+#endif
+#if defined(SDL_VIDEO_DRIVER_WAYLAND) && SDL_VERSION_ATLEAST(2, 0, 16) && defined(SDLMAME_USE_WAYLAND)
+ case SDL_SYSWM_WAYLAND:
+ platform_data.ndt = wmi.info.wl.display;
+ platform_data.nwh = create_wl_egl_window(dynamic_cast<sdl_window_info const &>(window).platform_window(), wmi.info.wl.surface);
+ if (!platform_data.nwh)
+ {
+ osd_printf_error("BGFX: Error creating a Wayland window\n");
+ return false;
+ }
+ platform_data.type = bgfx::NativeWindowHandleType::Wayland;
+ break;
+#endif
+#if defined(SDL_VIDEO_DRIVER_ANDROID)
+ case SDL_SYSWM_ANDROID:
+ platform_data.ndt = nullptr;
+ platform_data.nwh = wmi.info.android.window;
+ break;
+#endif
+ default:
+ osd_printf_error("BGFX: Unsupported SDL window manager type %u\n", wmi.subsystem);
+ return false;
+ }
+#endif // defined(OSD_*)
+
+ platform_data.context = nullptr;
+ platform_data.backBuffer = nullptr;
+ platform_data.backBufferDS = nullptr;
bgfx::setPlatformData(platform_data);
return true;
}
-#endif
+
+} // anonymous namespace
+
+} // namespace osd
+
+MODULE_DEFINITION(RENDERER_BGFX, osd::video_bgfx)
//============================================================
-// renderer_bgfx::create
+// CONSTANTS
//============================================================
-int renderer_bgfx::create()
+uint16_t const renderer_bgfx::CACHE_SIZE = 1024;
+uint32_t const renderer_bgfx::PACKABLE_SIZE = 128;
+uint32_t const renderer_bgfx::WHITE_HASH = 0x87654321;
+char const *const renderer_bgfx::WINDOW_PREFIX = "Window 0, ";
+
+
+
+//============================================================
+// MACROS
+//============================================================
+
+#define GIBBERISH (0)
+#define SCENE_VIEW (0)
+
+
+
+//============================================================
+// STATICS
+//============================================================
+
+uint32_t renderer_bgfx::s_current_view = 0;
+uint32_t renderer_bgfx::s_width[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+uint32_t renderer_bgfx::s_height[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+
+
+
+//============================================================
+// helper for getting native platform window
+//============================================================
+
+#ifdef OSD_SDL
+static std::pair<void *, bool> sdlNativeWindowHandle(SDL_Window *window)
{
- std::shared_ptr<osd_window> win = assert_window();
- osd_dim wdim = win->get_size();
- s_width[win->index()] = wdim.width();
- s_height[win->index()] = wdim.height();
- m_dimensions = wdim;
+ SDL_SysWMinfo wmi;
+ SDL_VERSION(&wmi.version);
+ if (!SDL_GetWindowWMInfo(window, &wmi))
+ return std::make_pair(nullptr, false);
- if (s_bgfx_library_initialized)
+ switch (wmi.subsystem)
{
- exit();
+#if defined(SDL_VIDEO_DRIVER_WINDOWS)
+ case SDL_SYSWM_WINDOWS:
+ return std::make_pair(wmi.info.win.window, true);
+#endif
+#if defined(SDL_VIDEO_DRIVER_X11)
+ case SDL_SYSWM_X11:
+ return std::make_pair((void *)uintptr_t(wmi.info.x11.window), true);
+#endif
+#if defined(SDL_VIDEO_DRIVER_COCOA)
+ case SDL_SYSWM_COCOA:
+ return std::make_pair(wmi.info.cocoa.window, true);
+#endif
+#if defined(SDL_VIDEO_DRIVER_WAYLAND) && SDL_VERSION_ATLEAST(2, 0, 16) && defined(SDLMAME_USE_WAYLAND)
+ case SDL_SYSWM_WAYLAND:
+ {
+ void *const platform_window = osd::create_wl_egl_window(window, wmi.info.wl.surface);
+ return std::make_pair(platform_window, platform_window != nullptr);
+ }
+#endif
+#if defined(SDL_VIDEO_DRIVER_ANDROID)
+ case SDL_SYSWM_ANDROID:
+ return std::make_pair(wmi.info.android.window, true);
+#endif
+ default:
+ return std::make_pair(nullptr, false);
}
+}
+#endif // OSD_SDL
+
+
+
+//============================================================
+// renderer_bgfx - constructor
+//============================================================
- if (win->index() == 0)
+renderer_bgfx::renderer_bgfx(osd_window &window, parent_module &parent)
+ : osd_renderer(window)
+ , m_module(parent)
+ , m_framebuffer(nullptr)
+ , m_texture_cache(nullptr)
+ , m_dimensions(0, 0)
+ , m_max_view(0)
+ , m_avi_view(nullptr)
+ , m_avi_writer(nullptr)
+ , m_avi_target(nullptr)
+ , m_load_sub(parent.subscribe_load(&renderer_bgfx::load_config, this))
+ , m_save_sub(parent.subscribe_save(&renderer_bgfx::save_config, this))
+{
+ // load settings if recreated after fullscreen toggle
+ util::xml::data_node *windownode = m_module().persistent_settings().get_child("window");
+ while (windownode)
{
-#ifdef OSD_WINDOWS
- winSetHwnd(m_platform_data, std::static_pointer_cast<win_window_info>(win)->platform_window());
-#elif defined(OSD_MAC)
- macSetWindow(m_platform_data, std::static_pointer_cast<mac_window_info>(win)->platform_window());
-#else
- sdlSetWindow(m_platform_data, std::dynamic_pointer_cast<sdl_window_info>(win)->platform_window());
-#endif
+ if (windownode->get_attribute_int("index", -1) != window.index())
+ {
+ windownode = windownode->get_next_sibling("window");
+ }
+ else
+ {
+ if (!m_config)
+ {
+ m_config = util::xml::file::create();
+ windownode->copy_into(*m_config);
+ }
+ std::exchange(windownode, windownode->get_next_sibling("window"))->delete_node();
+ }
+ }
+}
+
- init_bgfx_library();
+
+//============================================================
+// renderer_bgfx - destructor
+//============================================================
+
+renderer_bgfx::~renderer_bgfx()
+{
+ // persist settings across fullscreen toggle
+ if (m_config)
+ m_config->get_first_child()->copy_into(m_module().persistent_settings());
+ else if (m_chains)
+ m_chains->save_config(m_module().persistent_settings());
+
+ bgfx::reset(0, 0, BGFX_RESET_NONE);
+
+ if (m_avi_writer != nullptr && m_avi_writer->recording())
+ {
+ m_avi_writer->stop();
+
+ m_targets->destroy_target("avibuffer0");
+ m_avi_target = nullptr;
+
+ bgfx::destroy(m_avi_texture);
+
+ delete m_avi_writer;
+ delete [] m_avi_data;
+ delete m_avi_view;
}
+}
- // finish creating the renderer
- m_textures = new texture_manager();
- m_targets = new target_manager(*m_textures);
- m_shaders = new shader_manager();
- m_effects = new effect_manager(*m_shaders);
- // Create program from shaders.
- m_gui_effect[0] = m_effects->get_or_load_effect(m_options, "gui_opaque");
- m_gui_effect[1] = m_effects->get_or_load_effect(m_options, "gui_blend");
- m_gui_effect[2] = m_effects->get_or_load_effect(m_options, "gui_multiply");
- m_gui_effect[3] = m_effects->get_or_load_effect(m_options, "gui_add");
+//============================================================
+// renderer_bgfx::create
+//============================================================
+
+int renderer_bgfx::create()
+{
+ const osd_dim wdim = window().get_size();
+ s_width[window().index()] = wdim.width();
+ s_height[window().index()] = wdim.height();
+ m_dimensions = wdim;
- m_screen_effect[0] = m_effects->get_or_load_effect(m_options, "screen_opaque");
- m_screen_effect[1] = m_effects->get_or_load_effect(m_options, "screen_blend");
- m_screen_effect[2] = m_effects->get_or_load_effect(m_options, "screen_multiply");
- m_screen_effect[3] = m_effects->get_or_load_effect(m_options, "screen_add");
+ // finish creating the renderer
+ m_textures = std::make_unique<texture_manager>();
+ m_targets = std::make_unique<target_manager>(*m_textures);
- if (win->index() != 0)
+ if (window().index() != 0)
{
#ifdef OSD_WINDOWS
- m_framebuffer = m_targets->create_backbuffer(std::static_pointer_cast<win_window_info>(win)->platform_window(), s_width[win->index()], s_height[win->index()]);
+ m_framebuffer = m_targets->create_backbuffer(dynamic_cast<win_window_info &>(window()).platform_window(), s_width[window().index()], s_height[window().index()]);
#elif defined(OSD_MAC)
- m_framebuffer = m_targets->create_backbuffer(GetOSWindow(std::static_pointer_cast<mac_window_info>(win)->platform_window()), s_width[win->index()], s_height[win->index()]);
+ m_framebuffer = m_targets->create_backbuffer(GetOSWindow(dynamic_cast<mac_window_info &>(window()).platform_window()), s_width[window().index()], s_height[window().index()]);
#else
- m_framebuffer = m_targets->create_backbuffer(sdlNativeWindowHandle(std::dynamic_pointer_cast<sdl_window_info>(win)->platform_window()), s_width[win->index()], s_height[win->index()]);
+ auto const [winhdl, success] = sdlNativeWindowHandle(dynamic_cast<sdl_window_info &>(window()).platform_window());
+ if (!success)
+ {
+ m_targets.reset();
+ m_textures.reset();
+ return -1;
+ }
+ m_framebuffer = m_targets->create_backbuffer(winhdl, s_width[window().index()], s_height[window().index()]);
#endif
- bgfx::touch(win->index());
+ bgfx::touch(window().index());
- if (m_ortho_view) {
+ if (m_ortho_view)
m_ortho_view->set_backbuffer(m_framebuffer);
- }
}
- m_chains = new chain_manager(win->machine(), m_options, *m_textures, *m_targets, *m_effects, win->index(), *this);
+ m_shaders = std::make_unique<shader_manager>();
+ m_effects = std::make_unique<effect_manager>(*m_shaders);
+
+ // Create program from shaders.
+ m_gui_effect[0] = m_effects->get_or_load_effect(m_module().options(), "gui_opaque");
+ m_gui_effect[1] = m_effects->get_or_load_effect(m_module().options(), "gui_blend");
+ m_gui_effect[2] = m_effects->get_or_load_effect(m_module().options(), "gui_multiply");
+ m_gui_effect[3] = m_effects->get_or_load_effect(m_module().options(), "gui_add");
+
+ m_screen_effect[0] = m_effects->get_or_load_effect(m_module().options(), "screen_opaque");
+ m_screen_effect[1] = m_effects->get_or_load_effect(m_module().options(), "screen_blend");
+ m_screen_effect[2] = m_effects->get_or_load_effect(m_module().options(), "screen_multiply");
+ m_screen_effect[3] = m_effects->get_or_load_effect(m_module().options(), "screen_add");
+
+ const uint32_t max_prescale_size = std::min(2u * std::max(wdim.width(), wdim.height()), m_module().max_texture_size());
+ m_chains = std::make_unique<chain_manager>(
+ window().machine(),
+ m_module().options(),
+ *m_textures,
+ *m_targets,
+ *m_effects,
+ window().index(),
+ *this,
+ window().prescale(),
+ max_prescale_size);
m_sliders_dirty = true;
uint32_t flags = BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP | BGFX_SAMPLER_MIN_POINT | BGFX_SAMPLER_MAG_POINT | BGFX_SAMPLER_MIP_POINT;
- m_texture_cache = m_textures->create_texture("#cache", bgfx::TextureFormat::BGRA8, CACHE_SIZE, CACHE_SIZE, nullptr, flags);
+ m_texture_cache = m_textures->create_texture("#cache", bgfx::TextureFormat::BGRA8, CACHE_SIZE, 0, CACHE_SIZE, nullptr, flags);
memset(m_white, 0xff, sizeof(uint32_t) * 16 * 16);
m_texinfo.push_back(rectangle_packer::packable_rectangle(WHITE_HASH, PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32), 16, 16, 16, nullptr, m_white));
@@ -365,16 +723,12 @@ int renderer_bgfx::create()
void renderer_bgfx::record()
{
- std::shared_ptr<osd_window> win = assert_window();
-
- if (win->index() > 0)
- {
+ if (window().index() > 0)
return;
- }
if (m_avi_writer == nullptr)
{
- m_avi_writer = new avi_write(win->machine(), s_width[0], s_height[0]);
+ m_avi_writer = new avi_write(window().machine(), s_width[0], s_height[0]);
m_avi_data = new uint8_t[s_width[0] * s_height[0] * 4];
m_avi_bitmap.allocate(s_width[0], s_height[0]);
}
@@ -390,8 +744,8 @@ void renderer_bgfx::record()
}
else
{
- m_avi_writer->record(m_options.bgfx_avi_name());
- m_avi_target = m_targets->create_target("avibuffer", bgfx::TextureFormat::BGRA8, s_width[0], s_height[0], TARGET_STYLE_CUSTOM, false, true, 1, 0);
+ m_avi_writer->record(m_module().options().bgfx_avi_name());
+ m_avi_target = m_targets->create_target("avibuffer", bgfx::TextureFormat::BGRA8, s_width[0], s_height[0], 1, 1, TARGET_STYLE_CUSTOM, false, true, 1, 0);
m_avi_texture = bgfx::createTexture2D(s_width[0], s_height[0], false, 1, bgfx::TextureFormat::BGRA8, BGFX_TEXTURE_BLIT_DST | BGFX_TEXTURE_READ_BACK);
if (m_avi_view == nullptr)
@@ -401,47 +755,6 @@ void renderer_bgfx::record()
}
}
-bool renderer_bgfx::init(running_machine &machine)
-{
- osd_options &options = downcast<osd_options &>(machine.options());
- const char *bgfx_path = options.bgfx_path();
-
- osd::directory::ptr directory = osd::directory::open(bgfx_path);
- if (directory == nullptr)
- {
- osd_printf_error("Unable to find the BGFX path %s, please install it or fix the bgfx_path setting to use the BGFX renderer.\n", bgfx_path);
- return true;
- }
-
- // Verify baseline shaders.
- const bool gui_opaque_valid = effect_manager::validate_effect(options, "gui_opaque");
- const bool gui_blend_valid = effect_manager::validate_effect(options, "gui_blend");
- const bool gui_multiply_valid = effect_manager::validate_effect(options, "gui_multiply");
- const bool gui_add_valid = effect_manager::validate_effect(options, "gui_add");
- const bool all_gui_valid = gui_opaque_valid && gui_blend_valid && gui_multiply_valid && gui_add_valid;
-
- const bool screen_opaque_valid = effect_manager::validate_effect(options, "screen_opaque");
- const bool screen_blend_valid = effect_manager::validate_effect(options, "screen_blend");
- const bool screen_multiply_valid = effect_manager::validate_effect(options, "screen_multiply");
- const bool screen_add_valid = effect_manager::validate_effect(options, "screen_add");
- const bool all_screen_valid = screen_opaque_valid && screen_blend_valid && screen_multiply_valid && screen_add_valid;
-
- if (!all_gui_valid || !all_screen_valid)
- {
- osd_printf_error("BGFX: Unable to load required shaders. Please update the %s folder or adjust your bgfx_path setting.\n", options.bgfx_path());
- return true;
- }
-
- return false;
-}
-
-void renderer_bgfx::exit()
-{
- imguiDestroy();
- bgfx::shutdown();
- s_bgfx_library_initialized = false;
-}
-
//============================================================
// drawsdl_xy_to_render_target
//============================================================
@@ -480,15 +793,6 @@ void renderer_bgfx::put_packed_quad(render_primitive *prim, uint32_t hash, Scree
float u[4] = { u0, u1, u0, u1 };
float v[4] = { v0, v0, v1, v1 };
- if (bgfx::getRendererType() == bgfx::RendererType::Direct3D9)
- {
- for (int i = 0; i < 4; i++)
- {
- u[i] += 0.5f / size;
- v[i] += 0.5f / size;
- }
- }
-
if (PRIMFLAG_GET_TEXORIENT(prim->flags) & ORIENTATION_SWAP_XY)
{
std::swap(u[1], u[2]);
@@ -529,7 +833,7 @@ void renderer_bgfx::vertex(ScreenVertex* vertex, float x, float y, float z, uint
vertex->m_v = v;
}
-void renderer_bgfx::render_post_screen_quad(int view, render_primitive* prim, bgfx::TransientVertexBuffer* buffer, int32_t screen)
+void renderer_bgfx::render_post_screen_quad(int view, render_primitive* prim, bgfx::TransientVertexBuffer* buffer, int32_t screen, int window_index)
{
auto* vertices = reinterpret_cast<ScreenVertex*>(buffer->data);
@@ -554,6 +858,15 @@ void renderer_bgfx::render_post_screen_quad(int view, render_primitive* prim, bg
uint32_t blend = PRIMFLAG_GET_BLENDMODE(prim->flags);
bgfx::setVertexBuffer(0,buffer);
bgfx::setTexture(0, m_screen_effect[blend]->uniform("s_tex")->handle(), m_targets->target(screen, "output")->texture(), texture_flags);
+
+ bgfx_uniform* inv_view_dims = m_screen_effect[blend]->uniform("u_inv_view_dims");
+ if (inv_view_dims)
+ {
+ float values[2] = { -1.0f / s_width[window_index], 1.0f / s_height[window_index] };
+ inv_view_dims->set(values, sizeof(float) * 2);
+ inv_view_dims->upload();
+ }
+
m_screen_effect[blend]->submit(m_ortho_view->get_index());
}
@@ -563,7 +876,7 @@ void renderer_bgfx::render_avi_quad()
m_avi_view->setup();
bgfx::setViewRect(s_current_view, 0, 0, s_width[0], s_height[0]);
- bgfx::setViewClear(s_current_view, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH, 0x00000000, 1.0f, 0);
+ bgfx::setViewClear(s_current_view, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH, 0x000000ff, 1.0f, 0);
bgfx::TransientVertexBuffer buffer;
bgfx::allocTransientVertexBuffer(&buffer, 6, ScreenVertex::ms_decl);
@@ -584,11 +897,21 @@ void renderer_bgfx::render_avi_quad()
bgfx::setVertexBuffer(0,&buffer);
bgfx::setTexture(0, m_gui_effect[PRIMFLAG_GET_BLENDMODE(BLENDMODE_NONE)]->uniform("s_tex")->handle(), m_avi_target->texture());
- m_gui_effect[PRIMFLAG_GET_BLENDMODE(BLENDMODE_NONE)]->submit(s_current_view);
+
+ bgfx_effect* effect = m_gui_effect[PRIMFLAG_GET_BLENDMODE(BLENDMODE_NONE)];
+ bgfx_uniform* inv_view_dims = effect->uniform("u_inv_view_dims");
+ if (inv_view_dims)
+ {
+ float values[2] = { -1.0f / s_width[0], 1.0f / s_height[0] };
+ inv_view_dims->set(values, sizeof(float) * 2);
+ inv_view_dims->upload();
+ }
+
+ effect->submit(s_current_view);
s_current_view++;
}
-void renderer_bgfx::render_textured_quad(render_primitive* prim, bgfx::TransientVertexBuffer* buffer)
+void renderer_bgfx::render_textured_quad(render_primitive* prim, bgfx::TransientVertexBuffer* buffer, int window_index)
{
auto* vertices = reinterpret_cast<ScreenVertex*>(buffer->data);
uint32_t rgba = u32Color(prim->color.r * 255, prim->color.g * 255, prim->color.b * 255, prim->color.a * 255);
@@ -625,7 +948,7 @@ void renderer_bgfx::render_textured_quad(render_primitive* prim, bgfx::Transient
else
{
texture = m_textures->create_or_update_mame_texture(prim->flags & PRIMFLAG_TEXFORMAT_MASK
- , tex_width, tex_height, prim->texture.rowpixels, prim->texture.palette, prim->texture.base, prim->texture.seqid
+ , tex_width, prim->texture.width_margin, tex_height, prim->texture.rowpixels, prim->texture.palette, prim->texture.base, prim->texture.seqid
, texture_flags, prim->texture.unique_id, prim->texture.old_id);
}
@@ -634,6 +957,15 @@ void renderer_bgfx::render_textured_quad(render_primitive* prim, bgfx::Transient
uint32_t blend = PRIMFLAG_GET_BLENDMODE(prim->flags);
bgfx::setVertexBuffer(0,buffer);
bgfx::setTexture(0, effects[blend]->uniform("s_tex")->handle(), texture);
+
+ bgfx_uniform* inv_view_dims = effects[blend]->uniform("u_inv_view_dims");
+ if (inv_view_dims)
+ {
+ float values[2] = { -1.0f / s_width[window_index], 1.0f / s_height[window_index] };
+ inv_view_dims->set(values, sizeof(float) * 2);
+ inv_view_dims->upload();
+ }
+
effects[blend]->submit(m_ortho_view->get_index());
if (is_screen)
@@ -852,16 +1184,13 @@ uint32_t renderer_bgfx::u32Color(uint32_t r, uint32_t g, uint32_t b, uint32_t a
int renderer_bgfx::draw(int update)
{
- std::shared_ptr<osd_window> win = assert_window();
-
- int window_index = win->index();
+ int window_index = window().index();
m_seen_views.clear();
- if (m_ortho_view) {
+ if (m_ortho_view)
m_ortho_view->set_index(UINT_MAX);
- }
- osd_dim wdim = win->get_size();
+ osd_dim wdim = window().get_size();
s_width[window_index] = wdim.width();
s_height[window_index] = wdim.height();
@@ -871,9 +1200,9 @@ int renderer_bgfx::draw(int update)
s_current_view = 0;
}
- win->m_primlist->acquire_lock();
- uint32_t num_screens = m_chains->update_screen_textures(s_current_view, win->m_primlist->first(), *win.get());
- win->m_primlist->release_lock();
+ window().m_primlist->acquire_lock();
+ uint32_t num_screens = m_chains->update_screen_textures(s_current_view, window().m_primlist->first(), window());
+ window().m_primlist->release_lock();
bool skip_frame = update_dimensions();
if (skip_frame)
@@ -883,7 +1212,21 @@ int renderer_bgfx::draw(int update)
if (num_screens)
{
- uint32_t chain_view_count = m_chains->process_screen_chains(s_current_view, *win.get());
+ // Restore config after counting screens the first time
+ // Doing this here is hacky - it means config is restored at the wrong
+ // time if the initial view has no screens and the user switches to a
+ // view with screens. The trouble is there's no real interface between
+ // the render targets and the renderer so we don't actually know when
+ // we're first called on to render a live view (as opposed to an info
+ // screen).
+ if (m_config)
+ {
+ osd_printf_verbose("BGFX: Applying configuration for window %d\n", window().index());
+ m_chains->load_config(*m_config->get_first_child());
+ m_config.reset();
+ }
+
+ uint32_t chain_view_count = m_chains->process_screen_chains(s_current_view, window());
s_current_view += chain_view_count;
}
@@ -896,12 +1239,12 @@ int renderer_bgfx::draw(int update)
s_current_view = m_max_view;
}
- win->m_primlist->acquire_lock();
+ window().m_primlist->acquire_lock();
// Mark our texture atlas as dirty if we need to do so
bool atlas_valid = update_atlas();
- render_primitive *prim = win->m_primlist->first();
+ render_primitive *prim = window().m_primlist->first();
std::vector<void*> sources;
while (prim != nullptr)
{
@@ -926,12 +1269,21 @@ int renderer_bgfx::draw(int update)
}
}
- buffer_status status = buffer_primitives(atlas_valid, &prim, &buffer, screen);
+ buffer_status status = buffer_primitives(atlas_valid, &prim, &buffer, screen, window_index);
if (status != BUFFER_EMPTY && status != BUFFER_SCREEN)
{
- bgfx::setVertexBuffer(0,&buffer);
+ bgfx::setVertexBuffer(0, &buffer);
bgfx::setTexture(0, m_gui_effect[blend]->uniform("s_tex")->handle(), m_texture_cache->texture());
+
+ bgfx_uniform* inv_view_dims = m_gui_effect[blend]->uniform("u_inv_view_dims");
+ if (inv_view_dims)
+ {
+ float values[2] = { -1.0f / s_width[window_index], 1.0f / s_height[window_index] };
+ inv_view_dims->set(values, sizeof(float) * 2);
+ inv_view_dims->upload();
+ }
+
m_gui_effect[blend]->submit(m_ortho_view->get_index());
}
@@ -941,7 +1293,7 @@ int renderer_bgfx::draw(int update)
}
}
- win->m_primlist->release_lock();
+ window().m_primlist->release_lock();
// This dummy draw call is here to make sure that view 0 is cleared
// if no other draw calls are submitted to view 0.
@@ -959,7 +1311,7 @@ int renderer_bgfx::draw(int update)
}
}
- if (win->index() == osd_common_t::s_window_list.size() - 1)
+ if (window().index() == osd_common_t::window_list().size() - 1)
{
bgfx::frame();
}
@@ -989,8 +1341,7 @@ void renderer_bgfx::update_recording()
void renderer_bgfx::add_audio_to_recording(const int16_t *buffer, int samples_this_frame)
{
- std::shared_ptr<osd_window> win = assert_window();
- if (m_avi_writer != nullptr && m_avi_writer->recording() && win->index() == 0)
+ if (m_avi_writer != nullptr && m_avi_writer->recording() && window().index() == 0)
{
m_avi_writer->audio_frame(buffer, samples_this_frame);
}
@@ -998,9 +1349,7 @@ void renderer_bgfx::add_audio_to_recording(const int16_t *buffer, int samples_th
bool renderer_bgfx::update_dimensions()
{
- std::shared_ptr<osd_window> win = assert_window();
-
- const uint32_t window_index = win->index();
+ const uint32_t window_index = window().index();
const uint32_t width = s_width[window_index];
const uint32_t height = s_height[window_index];
@@ -1009,15 +1358,14 @@ bool renderer_bgfx::update_dimensions()
bgfx::reset(width, height, video_config.waitvsync ? BGFX_RESET_VSYNC : BGFX_RESET_NONE);
m_dimensions = osd_dim(width, height);
- if (win->index() != 0)
+ if (window().index() != 0)
{
- delete m_framebuffer;
#ifdef OSD_WINDOWS
- m_framebuffer = m_targets->create_backbuffer(std::static_pointer_cast<win_window_info>(win)->platform_window(), width, height);
+ m_framebuffer = m_targets->create_backbuffer(dynamic_cast<win_window_info &>(window()).platform_window(), width, height);
#elif defined(OSD_MAC)
- m_framebuffer = m_targets->create_backbuffer(GetOSWindow(std::static_pointer_cast<mac_window_info>(win)->platform_window()), width, height);
+ m_framebuffer = m_targets->create_backbuffer(GetOSWindow(dynamic_cast<mac_window_info &>(window()).platform_window()), width, height);
#else
- m_framebuffer = m_targets->create_backbuffer(sdlNativeWindowHandle(std::dynamic_pointer_cast<sdl_window_info>(win)->platform_window()), width, height);
+ m_framebuffer = m_targets->create_backbuffer(sdlNativeWindowHandle(dynamic_cast<sdl_window_info &>(window()).platform_window()).first, width, height);
#endif
if (m_ortho_view)
{
@@ -1026,7 +1374,7 @@ bool renderer_bgfx::update_dimensions()
bgfx::setViewFrameBuffer(s_current_view, m_framebuffer->target());
}
- bgfx::setViewClear(s_current_view, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH, 0x00000000, 1.0f, 0);
+ bgfx::setViewClear(s_current_view, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH, 0x000000ff, 1.0f, 0);
bgfx::setViewMode(s_current_view, bgfx::ViewMode::Sequential);
bgfx::touch(s_current_view);
bgfx::frame();
@@ -1039,7 +1387,7 @@ void renderer_bgfx::setup_ortho_view()
{
if (!m_ortho_view)
{
- m_ortho_view = new bgfx_ortho_view(this, 0, m_framebuffer, m_seen_views);
+ m_ortho_view = std::make_unique<bgfx_ortho_view>(this, 0, m_framebuffer, m_seen_views);
}
if (m_ortho_view->get_index() == UINT_MAX)
{
@@ -1052,10 +1400,6 @@ void renderer_bgfx::setup_ortho_view()
render_primitive_list *renderer_bgfx::get_primitives()
{
- auto win = try_getwindow();
- if (win == nullptr)
- return nullptr;
-
// determines whether the screen container is transformed by the chain's shaders
bool chain_transform = false;
@@ -1066,15 +1410,15 @@ render_primitive_list *renderer_bgfx::get_primitives()
chain_transform = chain->transform();
}
- osd_dim wdim = win->get_size();
+ osd_dim wdim = window().get_size();
if (wdim.width() > 0 && wdim.height() > 0)
- win->target()->set_bounds(wdim.width(), wdim.height(), win->pixel_aspect());
+ window().target()->set_bounds(wdim.width(), wdim.height(), window().pixel_aspect());
- win->target()->set_transform_container(!chain_transform);
- return &win->target()->get_primitives();
+ window().target()->set_transform_container(!chain_transform);
+ return &window().target()->get_primitives();
}
-renderer_bgfx::buffer_status renderer_bgfx::buffer_primitives(bool atlas_valid, render_primitive** prim, bgfx::TransientVertexBuffer* buffer, int32_t screen)
+renderer_bgfx::buffer_status renderer_bgfx::buffer_primitives(bool atlas_valid, render_primitive** prim, bgfx::TransientVertexBuffer* buffer, int32_t screen, int window_index)
{
int vertices = 0;
@@ -1116,18 +1460,18 @@ renderer_bgfx::buffer_status renderer_bgfx::buffer_primitives(bool atlas_valid,
{
#if SCENE_VIEW
setup_view(s_current_view, true);
- render_post_screen_quad(s_current_view, *prim, buffer, screen);
+ render_post_screen_quad(s_current_view, *prim, buffer, screen, window_index);
s_current_view++;
#else
setup_ortho_view();
- render_post_screen_quad(m_ortho_view->get_index(), *prim, buffer, screen);
+ render_post_screen_quad(m_ortho_view->get_index(), *prim, buffer, screen, window_index);
#endif
return BUFFER_SCREEN;
}
else
{
setup_ortho_view();
- render_textured_quad(*prim, buffer);
+ render_textured_quad(*prim, buffer, window_index);
return BUFFER_EMPTY;
}
}
@@ -1208,7 +1552,7 @@ void renderer_bgfx::process_atlas_packs(std::vector<std::vector<rectangle_packer
uint16_t pitch = rect.width();
int width_div_factor = 1;
int width_mul_factor = 1;
- const bgfx::Memory* mem = bgfx_util::mame_texture_data_to_bgfx_texture_data(dst_format, rect.format(), rect.rowpixels(), rect.height(), rect.palette(), rect.base(), pitch, width_div_factor, width_mul_factor);
+ const bgfx::Memory* mem = bgfx_util::mame_texture_data_to_bgfx_texture_data(dst_format, rect.format(), rect.rowpixels(), 0, rect.height(), rect.palette(), rect.base(), pitch, width_div_factor, width_mul_factor);
bgfx::updateTexture2D(m_texture_cache->texture(), 0, 0, rect.x(), rect.y(), (rect.width() * width_mul_factor) / width_div_factor, rect.height(), mem, pitch);
}
}
@@ -1246,9 +1590,8 @@ bool renderer_bgfx::check_for_dirty_atlas()
{
bool atlas_dirty = false;
- std::shared_ptr<osd_window> win = assert_window();
std::map<uint32_t, rectangle_packer::packable_rectangle> acquired_infos;
- for (render_primitive &prim : *win->m_primlist)
+ for (render_primitive &prim : *window().m_primlist)
{
bool pack = prim.packable(PACKABLE_SIZE);
if (prim.type == render_primitive::QUAD && prim.texture.base != nullptr && pack)
@@ -1261,8 +1604,7 @@ bool renderer_bgfx::check_for_dirty_atlas()
atlas_dirty = true;
m_texinfo.push_back(rectangle_packer::packable_rectangle(hash, prim.flags & PRIMFLAG_TEXFORMAT_MASK,
- prim.texture.width, prim.texture.height,
- prim.texture.rowpixels, prim.texture.palette, prim.texture.base));
+ prim.texture.width, prim.texture.height, prim.texture.rowpixels, prim.texture.palette, prim.texture.base));
acquired_infos[hash] = m_texinfo[m_texinfo.size() - 1];
}
}
@@ -1339,11 +1681,44 @@ void renderer_bgfx::set_sliders_dirty()
m_sliders_dirty = true;
}
-uint32_t renderer_bgfx::get_window_width(uint32_t index) const {
+uint32_t renderer_bgfx::get_window_width(uint32_t index) const
+{
return s_width[index];
}
-uint32_t renderer_bgfx::get_window_height(uint32_t index) const {
+uint32_t renderer_bgfx::get_window_height(uint32_t index) const
+{
return s_height[index];
}
+
+void renderer_bgfx::load_config(util::xml::data_node const &parentnode)
+{
+ util::xml::data_node const *windownode = parentnode.get_child("window");
+ while (windownode)
+ {
+ if (windownode->get_attribute_int("index", -1) != window().index())
+ {
+ windownode = windownode->get_next_sibling("window");
+ continue;
+ }
+
+ if (!m_config)
+ m_config = util::xml::file::create();
+ else
+ m_config->get_first_child()->delete_node();
+ windownode->copy_into(*m_config);
+ m_config->get_first_child()->set_attribute("persist", "0");
+ osd_printf_verbose("BGFX: Found configuration for window %d\n", window().index());
+ break;
+ }
+}
+
+
+void renderer_bgfx::save_config(util::xml::data_node &parentnode)
+{
+ if (m_config)
+ m_config->get_first_child()->copy_into(parentnode);
+ else
+ m_chains->save_config(parentnode);
+}
diff --git a/src/osd/modules/render/drawbgfx.h b/src/osd/modules/render/drawbgfx.h
index fc728e41d67..bb9f538aafa 100644
--- a/src/osd/modules/render/drawbgfx.h
+++ b/src/osd/modules/render/drawbgfx.h
@@ -1,30 +1,34 @@
// license:BSD-3-Clause
// copyright-holders:Ryan Holtz
+#ifndef MAME_RENDER_DRAWBGFX_H
+#define MAME_RENDER_DRAWBGFX_H
+
#pragma once
-#ifndef RENDER_BGFX
-#define RENDER_BGFX
+#include "binpacker.h"
+#include "bgfx/chain.h"
+#include "bgfx/chainmanager.h"
+#include "bgfx/vertex.h"
+#include "sliderdirtynotifier.h"
+
+#include "modules/osdwindow.h"
+
+#include "notifier.h"
#include <bgfx/bgfx.h>
#include <map>
+#include <memory>
#include <vector>
-#include "binpacker.h"
-#include "bgfx/vertex.h"
-#include "bgfx/chain.h"
-#include "bgfx/chainmanager.h"
-#include "sliderdirtynotifier.h"
class texture_manager;
class target_manager;
class shader_manager;
class effect_manager;
-class chain_manager;
class bgfx_texture;
class bgfx_effect;
class bgfx_target;
-class bgfx_chain;
class bgfx_view;
class osd_options;
class avi_write;
@@ -33,11 +37,10 @@ class avi_write;
class renderer_bgfx : public osd_renderer, public slider_dirty_notifier
{
public:
- renderer_bgfx(std::shared_ptr<osd_window> w);
- virtual ~renderer_bgfx();
+ class parent_module;
- static bool init(running_machine &machine);
- static void exit();
+ renderer_bgfx(osd_window &window, parent_module &parent_module);
+ virtual ~renderer_bgfx();
virtual int create() override;
virtual int draw(const int update) override;
@@ -62,7 +65,24 @@ public:
static char const *const WINDOW_PREFIX;
private:
- void init_bgfx_library();
+ enum buffer_status
+ {
+ BUFFER_PRE_FLUSH,
+ BUFFER_FLUSH,
+ BUFFER_SCREEN,
+ BUFFER_EMPTY,
+ BUFFER_DONE
+ };
+
+ class parent_module_holder
+ {
+ public:
+ parent_module_holder(parent_module &parent);
+ ~parent_module_holder();
+ parent_module &operator()() const { return m_parent; }
+ private:
+ parent_module &m_parent;
+ };
void vertex(ScreenVertex* vertex, float x, float y, float z, uint32_t rgba, float u, float v);
void render_avi_quad();
@@ -73,18 +93,10 @@ private:
void setup_ortho_view();
void allocate_buffer(render_primitive *prim, uint32_t blend, bgfx::TransientVertexBuffer *buffer);
- enum buffer_status
- {
- BUFFER_PRE_FLUSH,
- BUFFER_FLUSH,
- BUFFER_SCREEN,
- BUFFER_EMPTY,
- BUFFER_DONE
- };
- buffer_status buffer_primitives(bool atlas_valid, render_primitive** prim, bgfx::TransientVertexBuffer* buffer, int32_t screen);
+ buffer_status buffer_primitives(bool atlas_valid, render_primitive** prim, bgfx::TransientVertexBuffer* buffer, int32_t screen, int window_index);
- void render_textured_quad(render_primitive* prim, bgfx::TransientVertexBuffer* buffer);
- void render_post_screen_quad(int view, render_primitive* prim, bgfx::TransientVertexBuffer* buffer, int32_t screen);
+ void render_textured_quad(render_primitive* prim, bgfx::TransientVertexBuffer* buffer, int window_index);
+ void render_post_screen_quad(int view, render_primitive* prim, bgfx::TransientVertexBuffer* buffer, int32_t screen, int window_index);
void put_packed_quad(render_primitive *prim, uint32_t hash, ScreenVertex* vertex);
void put_packed_line(render_primitive *prim, ScreenVertex* vertex);
@@ -100,8 +112,10 @@ private:
void process_atlas_packs(std::vector<std::vector<rectangle_packer::packed_rectangle>>& packed);
uint32_t get_texture_hash(render_primitive *prim);
- osd_options& m_options;
- bgfx::PlatformData m_platform_data;
+ void load_config(util::xml::data_node const &parentnode);
+ void save_config(util::xml::data_node &parentnode);
+
+ parent_module_holder m_module; // keep this where it will be destructed last
bgfx_target *m_framebuffer;
bgfx_texture *m_texture_cache;
@@ -109,11 +123,11 @@ private:
// Original display_mode
osd_dim m_dimensions;
- texture_manager *m_textures;
- target_manager *m_targets;
- shader_manager *m_shaders;
- effect_manager *m_effects;
- chain_manager *m_chains;
+ std::unique_ptr<texture_manager> m_textures;
+ std::unique_ptr<target_manager> m_targets;
+ std::unique_ptr<shader_manager> m_shaders;
+ std::unique_ptr<effect_manager> m_effects;
+ std::unique_ptr<chain_manager> m_chains;
bgfx_effect *m_gui_effect[4];
bgfx_effect *m_screen_effect[4];
@@ -124,7 +138,7 @@ private:
rectangle_packer m_packer;
uint32_t m_white[16*16];
- bgfx_view *m_ortho_view;
+ std::unique_ptr<bgfx_view> m_ortho_view;
uint32_t m_max_view;
bgfx_view *m_avi_view;
@@ -134,14 +148,17 @@ private:
bitmap_rgb32 m_avi_bitmap;
uint8_t *m_avi_data;
+ std::unique_ptr<util::xml::file> m_config;
+ const util::notifier_subscription m_load_sub;
+ const util::notifier_subscription m_save_sub;
+
static const uint16_t CACHE_SIZE;
static const uint32_t PACKABLE_SIZE;
static const uint32_t WHITE_HASH;
static uint32_t s_current_view;
- static bool s_bgfx_library_initialized;
static uint32_t s_width[16];
static uint32_t s_height[16];
};
-#endif // RENDER_BGFX
+#endif // MAME_RENDER_DRAWBGFX_H
diff --git a/src/osd/modules/render/drawd3d.cpp b/src/osd/modules/render/drawd3d.cpp
index cfc494a2be9..542e2f8955d 100644
--- a/src/osd/modules/render/drawd3d.cpp
+++ b/src/osd/modules/render/drawd3d.cpp
@@ -13,21 +13,132 @@
#include "rendutil.h"
#include "screen.h"
-#include "aviio.h"
-
// MAMEOS headers
-#include "winmain.h"
-#include "window.h"
#include "drawd3d.h"
-#include "modules/render/d3d/d3dhlsl.h"
+
+#include "d3d/d3dhlsl.h"
+
+#include "render_module.h"
+
+// from OSD implementation
+#include "window.h"
+#include "winmain.h"
+
+// general OSD headers
#include "modules/monitor/monitor_module.h"
+
+// lib/util
+#include "aviio.h"
+
#include <utility>
+
+//============================================================
+// OSD MODULE
+//============================================================
+
+namespace osd {
+
+namespace {
+
+class video_d3d : public osd_module, public render_module
+{
+public:
+ video_d3d()
+ : osd_module(OSD_RENDERER_PROVIDER, "d3d")
+ , m_options(nullptr)
+ {
+ }
+
+ virtual bool probe() override;
+ virtual int init(osd_interface &osd, osd_options const &options) override;
+ virtual void exit() override;
+
+ virtual std::unique_ptr<osd_renderer> create(osd_window &window) override;
+
+protected:
+ virtual unsigned flags() const override { return FLAG_INTERACTIVE; }
+
+private:
+ using d3d9_create_fn = IDirect3D9 *(WINAPI *)(UINT);
+
+ dynamic_module::ptr m_d3d9_dll;
+ Microsoft::WRL::ComPtr<IDirect3D9> m_d3dobj;
+ osd_options const *m_options;
+};
+
+
+//============================================================
+// video_d3d::probe
+//============================================================
+
+bool video_d3d::probe()
+{
+ // do a dry run of loading the Direct3D 9 DLL
+ return dynamic_module::open({ "d3d9.dll" })->bind<d3d9_create_fn>("Direct3DCreate9") != nullptr;
+}
+
+
+//============================================================
+// video_d3d::init
+//============================================================
+
+int video_d3d::init(osd_interface &osd, osd_options const &options)
+{
+ m_options = &options;
+
+ m_d3d9_dll = dynamic_module::open({ "d3d9.dll" });
+ auto const d3d9_create_ptr = m_d3d9_dll->bind<d3d9_create_fn>("Direct3DCreate9");
+ if (!d3d9_create_ptr)
+ {
+ osd_printf_warning("Direct3D: Could not find Direct3DCreate9 function in d3d9.dll\n");
+ m_d3d9_dll.reset();
+ m_options = nullptr;
+ return -1;
+ }
+
+ m_d3dobj.Attach((d3d9_create_ptr)(D3D_SDK_VERSION));
+ if (!m_d3dobj)
+ {
+ osd_printf_warning("Direct3D: Unable to initialize Direct3D 9\n");
+ m_d3d9_dll.reset();
+ m_options = nullptr;
+ return -1;
+ }
+
+ osd_printf_verbose("Direct3D: Using Direct3D 9\n");
+
+ return 0;
+}
+
+
+//============================================================
+// video_d3d::exit
+//============================================================
+
+void video_d3d::exit()
+{
+ m_d3dobj.Reset();
+ m_d3d9_dll.reset();
+ m_options = nullptr;
+}
+
+
//============================================================
-// TYPE DEFINITIONS
+// video_d3d::create
//============================================================
-typedef IDirect3D9* (WINAPI *d3d9_create_fn)(UINT);
+std::unique_ptr<osd_renderer> video_d3d::create(osd_window &window)
+{
+ return std::make_unique<renderer_d3d9>(window, m_d3dobj);
+}
+
+} // anonymous namespace
+
+} // namespace osd
+
+MODULE_DEFINITION(RENDERER_D3D, osd::video_d3d)
+
//============================================================
@@ -116,13 +227,6 @@ static inline uint32_t ycc_to_rgb(uint8_t y, uint8_t cb, uint8_t cr)
//============================================================
-// drawd3d_init
-//============================================================
-
-static d3d_base *d3dintf = nullptr; // FIX ME
-
-
-//============================================================
// drawd3d_window_init
//============================================================
@@ -174,60 +278,22 @@ void renderer_d3d9::save()
render_primitive_list *renderer_d3d9::get_primitives()
{
RECT client;
- auto win = try_getwindow();
- if (win == nullptr)
- return nullptr;
-
- HWND hWnd = std::static_pointer_cast<win_window_info>(win)->platform_window();
+ HWND hWnd = dynamic_cast<win_window_info &>(window()).platform_window();
if (IsIconic(hWnd))
return nullptr;
- GetClientRectExceptMenu(hWnd, &client, win->fullscreen());
+ GetClientRectExceptMenu(hWnd, &client, window().fullscreen());
if (rect_width(&client) > 0 && rect_height(&client) > 0)
{
- win->target()->set_bounds(rect_width(&client), rect_height(&client), win->pixel_aspect());
- win->target()->set_max_update_rate((get_refresh() == 0) ? get_origmode().RefreshRate : get_refresh());
+ window().target()->set_bounds(rect_width(&client), rect_height(&client), window().pixel_aspect());
+ window().target()->set_max_update_rate((get_refresh() == 0) ? get_origmode().RefreshRate : get_refresh());
}
if (m_shaders != nullptr)
{
// do not transform primitives (scale, offset) if shaders are enabled, the shaders will handle the transformation
- win->target()->set_transform_container(!m_shaders->enabled());
+ window().target()->set_transform_container(!m_shaders->enabled());
}
- return &win->target()->get_primitives();
-}
-
-
-//============================================================
-// renderer_d3d9::init
-//============================================================
-
-bool renderer_d3d9::init(running_machine &machine)
-{
- d3dintf = new d3d_base;
-
- d3dintf->d3d9_dll = osd::dynamic_module::open({ "d3d9.dll" });
-
- d3d9_create_fn d3d9_create_ptr = d3dintf->d3d9_dll->bind<d3d9_create_fn>("Direct3DCreate9");
- if (d3d9_create_ptr == nullptr)
- {
- delete d3dintf;
- d3dintf = nullptr;
- osd_printf_verbose("Direct3D: Unable to find Direct3D 9 runtime library\n");
- return true;
- }
-
- d3dintf->d3dobj = (*d3d9_create_ptr)(D3D_SDK_VERSION);
- if (d3dintf->d3dobj == nullptr)
- {
- delete d3dintf;
- d3dintf = nullptr;
- osd_printf_verbose("Direct3D: Unable to initialize Direct3D 9\n");
- return true;
- }
-
- osd_printf_verbose("Direct3D: Using Direct3D 9\n");
-
- return false;
+ return &window().target()->get_primitives();
}
@@ -242,7 +308,12 @@ int renderer_d3d9::draw(const int update)
return check;
begin_frame();
+
+ // reset blend mode
+ set_blendmode(BLENDMODE_NONE);
+
process_primitives();
+
end_frame();
return 0;
@@ -254,8 +325,12 @@ void renderer_d3d9::set_texture(texture_info *texture)
{
m_last_texture = texture;
m_last_texture_flags = (texture == nullptr ? 0 : texture->get_flags());
+ if (m_shaders->enabled())
+ {
+ m_shaders->set_texture(texture);
+ }
+
HRESULT result = m_device->SetTexture(0, (texture == nullptr) ? get_default_texture()->get_finaltex() : texture->get_finaltex());
- m_shaders->set_texture(texture);
if (FAILED(result))
osd_printf_verbose("Direct3D: Error %08lX during device set_texture call\n", result);
}
@@ -353,15 +428,20 @@ void renderer_d3d9::set_blendmode(int blendmode)
}
// adjust the bits that changed
+ bool new_blend_enable = false;
if (blendenable != m_last_blendenable)
{
m_last_blendenable = blendenable;
+ if (blendenable)
+ {
+ new_blend_enable = true;
+ }
HRESULT result = m_device->SetRenderState(D3DRS_ALPHABLENDENABLE, blendenable);
if (FAILED(result))
osd_printf_verbose("Direct3D: Error %08lX during device SetRenderState call\n", result);
}
- if (blendop != m_last_blendop)
+ if (blendop != m_last_blendop || new_blend_enable)
{
m_last_blendop = blendop;
HRESULT result = m_device->SetRenderState(D3DRS_BLENDOP, blendop);
@@ -369,7 +449,7 @@ void renderer_d3d9::set_blendmode(int blendmode)
osd_printf_verbose("Direct3D: Error %08lX during device SetRenderState call\n", result);
}
- if (blendsrc != m_last_blendsrc)
+ if (blendsrc != m_last_blendsrc || new_blend_enable)
{
m_last_blendsrc = blendsrc;
HRESULT result = m_device->SetRenderState(D3DRS_SRCBLEND, blendsrc);
@@ -377,7 +457,7 @@ void renderer_d3d9::set_blendmode(int blendmode)
osd_printf_verbose("Direct3D: Error %08lX during device SetRenderState call\n", result);
}
- if (blenddst != m_last_blenddst)
+ if (blenddst != m_last_blenddst || new_blend_enable)
{
m_last_blenddst = blenddst;
HRESULT result = m_device->SetRenderState(D3DRS_DESTBLEND, blenddst);
@@ -398,14 +478,12 @@ void renderer_d3d9::reset_render_states()
m_last_wrap = (D3DTEXTUREADDRESS)-1;
}
-d3d_texture_manager::d3d_texture_manager(renderer_d3d9 *d3d)
+d3d_texture_manager::d3d_texture_manager(renderer_d3d9 &d3d, IDirect3D9 *d3dobj)
+ : m_renderer(d3d)
+ , m_default_texture(nullptr)
{
- m_renderer = d3d;
-
- m_default_texture = nullptr;
-
D3DCAPS9 caps;
- HRESULT result = d3dintf->d3dobj->GetDeviceCaps(d3d->get_adapter(), D3DDEVTYPE_HAL, &caps);
+ HRESULT result = d3dobj->GetDeviceCaps(d3d.get_adapter(), D3DDEVTYPE_HAL, &caps);
if (FAILED(result))
osd_printf_verbose("Direct3D: Error %08lX during GetDeviceCaps call\n", result);
@@ -417,35 +495,30 @@ d3d_texture_manager::d3d_texture_manager(renderer_d3d9 *d3d)
// pick a YUV texture format
m_yuv_format = D3DFMT_UYVY;
- result = d3dintf->d3dobj->CheckDeviceFormat(d3d->get_adapter(), D3DDEVTYPE_HAL, d3d->get_pixel_format(), 0, D3DRTYPE_TEXTURE, D3DFMT_UYVY);
+ result = d3dobj->CheckDeviceFormat(d3d.get_adapter(), D3DDEVTYPE_HAL, d3d.get_pixel_format(), 0, D3DRTYPE_TEXTURE, D3DFMT_UYVY);
if (FAILED(result))
{
m_yuv_format = D3DFMT_YUY2;
- result = d3dintf->d3dobj->CheckDeviceFormat(d3d->get_adapter(), D3DDEVTYPE_HAL, d3d->get_pixel_format(), 0, D3DRTYPE_TEXTURE, D3DFMT_YUY2);
+ result = d3dobj->CheckDeviceFormat(d3d.get_adapter(), D3DDEVTYPE_HAL, d3d.get_pixel_format(), 0, D3DRTYPE_TEXTURE, D3DFMT_YUY2);
if (FAILED(result))
m_yuv_format = D3DFMT_A8R8G8B8;
}
osd_printf_verbose("Direct3D: YUV format = %s\n", (m_yuv_format == D3DFMT_YUY2) ? "YUY2" : (m_yuv_format == D3DFMT_UYVY) ? "UYVY" : "RGB");
- auto win = d3d->assert_window();
-
// set the max texture size
- win->target()->set_max_texture_size(m_texture_max_width, m_texture_max_height);
- osd_printf_verbose("Direct3D: Max texture size = %dx%d\n", (int)m_texture_max_width, (int)m_texture_max_height);
+ d3d.window().target()->set_max_texture_size(m_texture_max_width, m_texture_max_height);
+ osd_printf_verbose("Direct3D: Max texture size = %dx%d\n", m_texture_max_width, m_texture_max_height);
}
void d3d_texture_manager::create_resources()
{
- auto win = m_renderer->assert_window();
-
m_default_bitmap.allocate(8, 8);
- m_default_bitmap.fill(rgb_t(0xff,0xff,0xff,0xff));
-
if (m_default_bitmap.valid())
{
- render_texinfo texture;
+ m_default_bitmap.fill(rgb_t(0xff,0xff,0xff,0xff));
// fake in the basic data so it looks like it came from render.c
+ render_texinfo texture;
texture.base = m_default_bitmap.raw_pixptr(0);
texture.rowpixels = m_default_bitmap.rowpixels();
texture.width = m_default_bitmap.width();
@@ -456,7 +529,7 @@ void d3d_texture_manager::create_resources()
texture.old_id = ~0ULL;
// now create it
- auto tex = std::make_unique<texture_info>(this, &texture, win->prescale(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32));
+ auto tex = std::make_unique<texture_info>(*this, &texture, m_renderer.window().prescale(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32));
m_default_texture = tex.get();
m_texture_list.push_back(std::move(tex));
}
@@ -465,7 +538,6 @@ void d3d_texture_manager::create_resources()
void d3d_texture_manager::delete_resources()
{
// is part of m_texlist and will be free'd there
- //delete m_default_texture;
m_default_texture = nullptr;
// free all textures
@@ -479,16 +551,16 @@ uint32_t d3d_texture_manager::texture_compute_hash(const render_texinfo *texture
texture_info *d3d_texture_manager::find_texinfo(const render_texinfo *texinfo, uint32_t flags)
{
- uint32_t hash = texture_compute_hash(texinfo, flags);
+ const uint32_t hash = texture_compute_hash(texinfo, flags);
// find a match
for (auto it = m_texture_list.begin(); it != m_texture_list.end(); it++)
{
- auto test_screen = (uint32_t)((*it)->get_texinfo().unique_id >> 57);
- uint32_t test_page = (uint32_t)((*it)->get_texinfo().unique_id >> 56) & 1;
- auto prim_screen = (uint32_t)(texinfo->unique_id >> 57);
- uint32_t prim_page = (uint32_t)(texinfo->unique_id >> 56) & 1;
- if (test_screen != prim_screen || test_page != prim_page)
+ const uint32_t test_screen = uint32_t((*it)->get_texinfo().unique_id >> 57);
+ const uint32_t test_page = uint32_t((*it)->get_texinfo().unique_id >> 56) & 1;
+ const uint32_t prim_screen = uint32_t(texinfo->unique_id >> 57);
+ const uint32_t prim_page = uint32_t(texinfo->unique_id >> 56) & 1;
+ if ((test_screen != prim_screen) || (test_page != prim_page))
continue;
if ((*it)->get_hash() == hash &&
@@ -504,11 +576,35 @@ texture_info *d3d_texture_manager::find_texinfo(const render_texinfo *texinfo, u
return nullptr;
}
-renderer_d3d9::renderer_d3d9(std::shared_ptr<osd_window> window)
- : osd_renderer(window, FLAG_NONE), m_adapter(0), m_width(0), m_height(0), m_refresh(0), m_create_error_count(0), m_device(nullptr), m_gamma_supported(0), m_pixformat(),
- m_vertexbuf(nullptr), m_lockedbuf(nullptr), m_numverts(0), m_vectorbatch(nullptr), m_batchindex(0), m_numpolys(0), m_toggle(false),
- m_screen_format(), m_last_texture(nullptr), m_last_texture_flags(0), m_last_blendenable(0), m_last_blendop(0), m_last_blendsrc(0), m_last_blenddst(0), m_last_filter(0),
- m_last_wrap(), m_last_modmode(0), m_shaders(nullptr), m_texture_manager()
+renderer_d3d9::renderer_d3d9(osd_window &window, const IDirect3D9Ptr &d3dobj)
+ : osd_renderer(window)
+ , m_d3dobj(d3dobj)
+ , m_adapter(0)
+ , m_width(0)
+ , m_height(0)
+ , m_refresh(0)
+ , m_create_error_count(0)
+ , m_post_fx_available(true)
+ , m_gamma_supported(0)
+ , m_pixformat()
+ , m_lockedbuf(nullptr)
+ , m_numverts(0)
+ , m_vectorbatch(nullptr)
+ , m_batchindex(0)
+ , m_numpolys(0)
+ , m_toggle(false)
+ , m_screen_format()
+ , m_last_texture(nullptr)
+ , m_last_texture_flags(0)
+ , m_last_blendenable(0)
+ , m_last_blendop(0)
+ , m_last_blendsrc(0)
+ , m_last_blenddst(0)
+ , m_last_filter(0)
+ , m_last_wrap()
+ , m_last_modmode(0)
+ , m_shaders(nullptr)
+ , m_texture_manager()
{
}
@@ -523,8 +619,7 @@ int renderer_d3d9::initialize()
}
// create the device immediately for the full screen case (defer for window mode in update_window_size())
- auto win = assert_window();
- if (win->fullscreen() && device_create(std::static_pointer_cast<win_window_info>(win->main_window())->platform_window()))
+ if (window().fullscreen() && device_create(dynamic_cast<win_window_info &>(window()).main_window()->platform_window()))
{
return false;
}
@@ -534,10 +629,8 @@ int renderer_d3d9::initialize()
int renderer_d3d9::pre_window_draw_check()
{
- auto win = assert_window();
-
// if we're in the middle of resizing, leave things alone
- if (win->m_resize_state == RESIZE_STATE_RESIZING)
+ if (dynamic_cast<win_window_info &>(window()).m_resize_state == win_window_info::RESIZE_STATE_RESIZING)
return 0;
// check if shaders should be toggled
@@ -561,7 +654,7 @@ int renderer_d3d9::pre_window_draw_check()
}
// if we have a device, check the cooperative level
- if (m_device != nullptr)
+ if (m_device)
{
if (device_test_cooperative())
{
@@ -570,14 +663,14 @@ int renderer_d3d9::pre_window_draw_check()
}
// in window mode, we need to track the window size
- if (!win->fullscreen() || m_device == nullptr)
+ if (!window().fullscreen() || !m_device)
{
// if the size changes, skip this update since the render target will be out of date
if (update_window_size())
return 0;
// if we have no device, after updating the size, return an error so GDI can try
- if (m_device == nullptr)
+ if (!m_device)
return 1;
}
@@ -586,18 +679,16 @@ int renderer_d3d9::pre_window_draw_check()
void d3d_texture_manager::update_textures()
{
- auto win = m_renderer->assert_window();
-
- for (render_primitive &prim : *win->m_primlist)
+ for (render_primitive &prim : *m_renderer.window().m_primlist)
{
if (prim.texture.base != nullptr)
{
texture_info *texture = find_texinfo(&prim.texture, prim.flags);
if (texture == nullptr)
{
- int prescale = m_renderer->get_shaders()->enabled() ? 1 : win->prescale();
+ const int prescale = m_renderer.get_shaders()->enabled() ? 1 : m_renderer.window().prescale();
- auto tex = std::make_unique<texture_info>(this, &prim.texture, prescale, prim.flags);
+ auto tex = std::make_unique<texture_info>(*this, &prim.texture, prescale, prim.flags);
texture = tex.get();
m_texture_list.push_back(std::move(tex));
}
@@ -613,21 +704,19 @@ void d3d_texture_manager::update_textures()
}
}
- if (!m_renderer->get_shaders()->enabled())
- {
+ if (!m_renderer.get_shaders()->enabled())
return;
- }
int screen_index = 0;
- for (render_primitive &prim : *win->m_primlist)
+ for (render_primitive &prim : *m_renderer.window().m_primlist)
{
if (PRIMFLAG_GET_SCREENTEX(prim.flags))
{
- if (!m_renderer->get_shaders()->get_texture_target(&prim, prim.texture.width, prim.texture.height, screen_index))
+ if (!m_renderer.get_shaders()->get_texture_target(&prim, prim.texture.width, prim.texture.height, screen_index))
{
- if (!m_renderer->get_shaders()->create_texture_target(&prim, prim.texture.width, prim.texture.height, screen_index))
+ if (!m_renderer.get_shaders()->create_texture_target(&prim, prim.texture.width, prim.texture.height, screen_index))
{
- d3dintf->post_fx_available = false;
+ m_renderer.set_post_fx_unavailable();
break;
}
}
@@ -635,11 +724,11 @@ void d3d_texture_manager::update_textures()
}
else if (PRIMFLAG_GET_VECTORBUF(prim.flags))
{
- if (!m_renderer->get_shaders()->get_vector_target(&prim, screen_index))
+ if (!m_renderer.get_shaders()->get_vector_target(&prim, screen_index))
{
- if (!m_renderer->get_shaders()->create_vector_target(&prim, screen_index))
+ if (!m_renderer.get_shaders()->create_vector_target(&prim, screen_index))
{
- d3dintf->post_fx_available = false;
+ m_renderer.set_post_fx_unavailable();
break;
}
}
@@ -650,13 +739,11 @@ void d3d_texture_manager::update_textures()
void renderer_d3d9::begin_frame()
{
- auto win = assert_window();
-
- HRESULT result = m_device->Clear(0, nullptr, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0);
+ HRESULT result = m_device->Clear(0, nullptr, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0xff,0,0,0), 0, 0);
if (FAILED(result))
osd_printf_verbose("Direct3D: Error %08lX during device clear call\n", result);
- win->m_primlist->acquire_lock();
+ window().m_primlist->acquire_lock();
// first update any textures
m_texture_manager->update_textures();
@@ -667,16 +754,17 @@ void renderer_d3d9::begin_frame()
osd_printf_verbose("Direct3D: Error %08lX during device BeginScene call\n", result);
if (m_shaders->enabled())
- m_shaders->init_fsfx_quad();
+ m_shaders->begin_frame(window().m_primlist);
+
+ // set an initial default texture
+ set_texture(nullptr);
}
void renderer_d3d9::process_primitives()
{
- auto win = assert_window();
-
// loop over line primitives
int vector_count = 0;
- for (render_primitive &prim : *win->m_primlist)
+ for (render_primitive &prim : *window().m_primlist)
{
if (prim.type == render_primitive::LINE && PRIMFLAG_GET_VECTOR(prim.flags))
{
@@ -685,7 +773,7 @@ void renderer_d3d9::process_primitives()
}
// Rotating index for vector time offsets
- for (render_primitive &prim : *win->m_primlist)
+ for (render_primitive &prim : *window().m_primlist)
{
switch (prim.type)
{
@@ -716,13 +804,14 @@ void renderer_d3d9::process_primitives()
void renderer_d3d9::end_frame()
{
- auto win = assert_window();
-
- win->m_primlist->release_lock();
+ window().m_primlist->release_lock();
// flush any pending polygons
primitive_flush_pending();
+ if (m_shaders->enabled())
+ m_shaders->end_frame();
+
// finish the scene
HRESULT result = m_device->EndScene();
if (FAILED(result))
@@ -736,8 +825,6 @@ void renderer_d3d9::end_frame()
void renderer_d3d9::update_presentation_parameters()
{
- auto win = assert_window();
-
memset(&m_presentation, 0, sizeof(m_presentation));
m_presentation.BackBufferWidth = m_width;
m_presentation.BackBufferHeight = m_height;
@@ -745,14 +832,14 @@ void renderer_d3d9::update_presentation_parameters()
m_presentation.BackBufferCount = video_config.triplebuf ? 2 : 1;
m_presentation.MultiSampleType = D3DMULTISAMPLE_NONE;
m_presentation.SwapEffect = D3DSWAPEFFECT_DISCARD;
- m_presentation.hDeviceWindow = std::static_pointer_cast<win_window_info>(win)->platform_window();
- m_presentation.Windowed = !win->fullscreen() || win->win_has_menu();
+ m_presentation.hDeviceWindow = dynamic_cast<win_window_info &>(window()).platform_window();
+ m_presentation.Windowed = !window().fullscreen();
m_presentation.EnableAutoDepthStencil = FALSE;
m_presentation.AutoDepthStencilFormat = D3DFMT_D16;
m_presentation.Flags = 0;
m_presentation.FullScreen_RefreshRateInHz = m_refresh;
m_presentation.PresentationInterval = (
- (video_config.triplebuf && win->fullscreen())
+ (video_config.triplebuf && window().fullscreen())
|| video_config.waitvsync
|| video_config.syncrefresh)
? D3DPRESENT_INTERVAL_ONE
@@ -767,13 +854,11 @@ void renderer_d3d9::update_gamma_ramp()
return;
}
- auto win = assert_window();
-
// set the gamma if we need to
- if (win->fullscreen())
+ if (window().fullscreen())
{
// only set the gamma if it's not 1.0
- auto &options = downcast<windows_options &>(win->machine().options());
+ auto &options = downcast<windows_options &>(window().machine().options());
float brightness = options.full_screen_brightness();
float contrast = options.full_screen_contrast();
float gamma = options.full_screen_gamma();
@@ -803,27 +888,23 @@ int renderer_d3d9::device_create(HWND hwnd)
HWND device_hwnd = GetAncestor(hwnd, GA_ROOT);
// if a device exists, free it
- if (m_device != nullptr)
- {
+ if (m_device)
device_delete();
- }
// verify the caps
if (!device_verify_caps())
- {
return 1;
- }
- m_texture_manager = std::make_unique<d3d_texture_manager>(this);
+ m_texture_manager = std::make_unique<d3d_texture_manager>(*this, m_d3dobj.Get());
// try for XRGB first
m_screen_format = D3DFMT_X8R8G8B8;
- HRESULT result = d3dintf->d3dobj->CheckDeviceFormat(m_adapter, D3DDEVTYPE_HAL, m_pixformat, D3DUSAGE_DYNAMIC, D3DRTYPE_TEXTURE, m_screen_format);
+ HRESULT result = m_d3dobj->CheckDeviceFormat(m_adapter, D3DDEVTYPE_HAL, m_pixformat, D3DUSAGE_DYNAMIC, D3DRTYPE_TEXTURE, m_screen_format);
if (FAILED(result))
{
// if not, try for ARGB
m_screen_format = D3DFMT_A8R8G8B8;
- result = d3dintf->d3dobj->CheckDeviceFormat(m_adapter, D3DDEVTYPE_HAL, m_pixformat, D3DUSAGE_DYNAMIC, D3DRTYPE_TEXTURE, m_screen_format);
+ result = m_d3dobj->CheckDeviceFormat(m_adapter, D3DDEVTYPE_HAL, m_pixformat, D3DUSAGE_DYNAMIC, D3DRTYPE_TEXTURE, m_screen_format);
if (FAILED(result))
{
osd_printf_error("Error: unable to configure a screen texture format\n");
@@ -835,8 +916,13 @@ int renderer_d3d9::device_create(HWND hwnd)
update_presentation_parameters();
// create the D3D device
- result = d3dintf->d3dobj->CreateDevice(
- m_adapter, D3DDEVTYPE_HAL, device_hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE, &m_presentation, &m_device);
+ result = m_d3dobj->CreateDevice(
+ m_adapter,
+ D3DDEVTYPE_HAL,
+ device_hwnd,
+ D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE,
+ &m_presentation,
+ &m_device);
if (FAILED(result))
{
// if we got a "DEVICELOST" error, it may be transitory; count it and only fail if
@@ -869,16 +955,13 @@ int renderer_d3d9::device_create(HWND hwnd)
int renderer_d3d9::device_create_resources()
{
- auto win = assert_window();
-
// create shaders only once
- if (m_shaders == nullptr)
- {
- m_shaders = new shaders;
- }
+ if (!m_shaders)
+ m_shaders = std::make_unique<shaders>();
- if (m_shaders->init(d3dintf, &win->machine(), this))
+ if (m_shaders->init(m_d3dobj.Get(), &window().machine(), this))
{
+ m_post_fx_available = true;
m_shaders->init_slider_list();
m_sliders_dirty = true;
}
@@ -892,12 +975,12 @@ int renderer_d3d9::device_create_resources()
// allocate a vertex buffer to use
HRESULT result = m_device->CreateVertexBuffer(
- sizeof(vertex) * VERTEX_BUFFER_SIZE,
- D3DUSAGE_DYNAMIC | D3DUSAGE_SOFTWAREPROCESSING | D3DUSAGE_WRITEONLY,
- VERTEX_BASE_FORMAT | ((m_shaders->enabled())
- ? D3DFVF_XYZW
- : D3DFVF_XYZRHW),
- D3DPOOL_DEFAULT, &m_vertexbuf, nullptr);
+ sizeof(vertex) * VERTEX_BUFFER_SIZE,
+ D3DUSAGE_DYNAMIC | D3DUSAGE_SOFTWAREPROCESSING | D3DUSAGE_WRITEONLY,
+ VERTEX_BASE_FORMAT | (m_shaders->enabled() ? D3DFVF_XYZW : D3DFVF_XYZRHW),
+ D3DPOOL_DEFAULT,
+ &m_vertexbuf,
+ nullptr);
if (FAILED(result))
{
osd_printf_error("Error creating vertex buffer (%08X)\n", (uint32_t)result);
@@ -906,9 +989,7 @@ int renderer_d3d9::device_create_resources()
// set the vertex format
result = m_device->SetFVF(
- (D3DFORMAT)(VERTEX_BASE_FORMAT | ((m_shaders->enabled())
- ? D3DFVF_XYZW
- : D3DFVF_XYZRHW)));
+ D3DFORMAT(VERTEX_BASE_FORMAT | (m_shaders->enabled() ? D3DFVF_XYZW : D3DFVF_XYZRHW)));
if (FAILED(result))
{
osd_printf_error("Error setting vertex format (%08X)\n", (uint32_t)result);
@@ -960,24 +1041,6 @@ int renderer_d3d9::device_create_resources()
renderer_d3d9::~renderer_d3d9()
{
device_delete();
-
- // todo: throws error when switching from full screen to window mode
- //if (m_shaders != nullptr)
- //{
- // // delete the HLSL interface
- // delete m_shaders;
- // m_shaders = nullptr;
- //}
-}
-
-void renderer_d3d9::exit()
-{
- if (d3dintf != nullptr)
- {
- d3dintf->d3dobj->Release();
- delete d3dintf;
- d3dintf = nullptr;
- }
}
void renderer_d3d9::device_delete()
@@ -990,11 +1053,7 @@ void renderer_d3d9::device_delete()
m_texture_manager.reset();
// free the device itself
- if (m_device != nullptr)
- {
- m_device->Release();
- m_device = nullptr;
- }
+ m_device.Reset();
}
@@ -1004,22 +1063,14 @@ void renderer_d3d9::device_delete()
void renderer_d3d9::device_delete_resources()
{
- if (m_shaders != nullptr)
- {
+ if (m_shaders)
m_shaders->delete_resources();
- }
- if (m_texture_manager != nullptr)
- {
+ if (m_texture_manager)
m_texture_manager->delete_resources();
- }
// free the vertex buffer
- if (m_vertexbuf != nullptr)
- {
- m_vertexbuf->Release();
- m_vertexbuf = nullptr;
- }
+ m_vertexbuf.Reset();
}
@@ -1032,7 +1083,7 @@ bool renderer_d3d9::device_verify_caps()
bool success = true;
D3DCAPS9 caps;
- HRESULT result = d3dintf->d3dobj->GetDeviceCaps(m_adapter, D3DDEVTYPE_HAL, &caps);
+ HRESULT result = m_d3dobj->GetDeviceCaps(m_adapter, D3DDEVTYPE_HAL, &caps);
if (FAILED(result))
{
osd_printf_verbose("Direct3D: Error %08lX during GetDeviceCaps call\n", result);
@@ -1042,7 +1093,7 @@ bool renderer_d3d9::device_verify_caps()
if (caps.MaxPixelShader30InstructionSlots < 512)
{
osd_printf_verbose("Direct3D: Warning - Device does not support Pixel Shader 3.0, falling back to non-PS rendering\n");
- d3dintf->post_fx_available = false;
+ set_post_fx_unavailable();
}
// verify presentation capabilities
@@ -1097,7 +1148,7 @@ bool renderer_d3d9::device_verify_caps()
}
// verify texture formats
- result = d3dintf->d3dobj->CheckDeviceFormat(m_adapter, D3DDEVTYPE_HAL, m_pixformat, 0, D3DRTYPE_TEXTURE, D3DFMT_A8R8G8B8);
+ result = m_d3dobj->CheckDeviceFormat(m_adapter, D3DDEVTYPE_HAL, m_pixformat, 0, D3DRTYPE_TEXTURE, D3DFMT_A8R8G8B8);
if (FAILED(result))
{
osd_printf_error("Direct3D Error: Your graphics card does not support the A8R8G8B8 texture format.\n");
@@ -1173,7 +1224,7 @@ int renderer_d3d9::config_adapter_mode()
// get the identifier
D3DADAPTER_IDENTIFIER9 id;
- HRESULT result = d3dintf->d3dobj->GetAdapterIdentifier(m_adapter, 0, &id);
+ HRESULT result = m_d3dobj->GetAdapterIdentifier(m_adapter, 0, &id);
if (FAILED(result))
{
osd_printf_error("Error getting identifier for adapter #%d\n", m_adapter);
@@ -1183,22 +1234,20 @@ int renderer_d3d9::config_adapter_mode()
osd_printf_verbose("Direct3D: Configuring adapter #%d = %s\n", m_adapter, id.Description);
// get the current display mode
- result = d3dintf->d3dobj->GetAdapterDisplayMode(m_adapter, &m_origmode);
+ result = m_d3dobj->GetAdapterDisplayMode(m_adapter, &m_origmode);
if (FAILED(result))
{
osd_printf_error("Error getting mode for adapter #%d\n", m_adapter);
return 1;
}
- auto win = assert_window();
-
- // choose a resolution: window mode case
- if (!win->fullscreen() || !video_config.switchres || win->win_has_menu())
+ if (!window().fullscreen() || !video_config.switchres)
{
- RECT client;
+ // choose a resolution: window mode case
// bounds are from the window client rect
- GetClientRectExceptMenu(std::static_pointer_cast<win_window_info>(win)->platform_window(), &client, win->fullscreen());
+ RECT client;
+ GetClientRectExceptMenu(dynamic_cast<win_window_info &>(window()).platform_window(), &client, window().fullscreen());
m_width = client.right - client.left;
m_height = client.bottom - client.top;
@@ -1209,14 +1258,14 @@ int renderer_d3d9::config_adapter_mode()
// make sure it's a pixel format we can get behind
if (m_pixformat != D3DFMT_X1R5G5B5 && m_pixformat != D3DFMT_R5G6B5 && m_pixformat != D3DFMT_X8R8G8B8)
{
- osd_printf_error("Device %s currently in an unsupported mode\n", win->monitor()->devicename());
+ osd_printf_error("Device %s currently in an unsupported mode\n", window().monitor()->devicename());
return 1;
}
}
-
- // choose a resolution: full screen mode case
else
{
+ // choose a resolution: full screen mode case
+
// default to the current mode exactly
m_width = m_origmode.Width;
m_height = m_origmode.Height;
@@ -1229,10 +1278,10 @@ int renderer_d3d9::config_adapter_mode()
}
// see if we can handle the device type
- result = d3dintf->d3dobj->CheckDeviceType(m_adapter, D3DDEVTYPE_HAL, m_pixformat, m_pixformat, !win->fullscreen());
+ result = m_d3dobj->CheckDeviceType(m_adapter, D3DDEVTYPE_HAL, m_pixformat, m_pixformat, !window().fullscreen());
if (FAILED(result))
{
- osd_printf_error("Proposed video mode not supported on device %s\n", win->monitor()->devicename());
+ osd_printf_error("Proposed video mode not supported on device %s\n", window().monitor()->devicename());
return 1;
}
@@ -1246,18 +1295,16 @@ int renderer_d3d9::config_adapter_mode()
int renderer_d3d9::get_adapter_for_monitor()
{
- int maxadapter = d3dintf->d3dobj->GetAdapterCount();
-
- auto win = assert_window();
+ int maxadapter = m_d3dobj->GetAdapterCount();
// iterate over adapters until we error or find a match
for (int adapternum = 0; adapternum < maxadapter; adapternum++)
{
// get the monitor for this adapter
- HMONITOR curmonitor = d3dintf->d3dobj->GetAdapterMonitor(adapternum);
+ HMONITOR curmonitor = m_d3dobj->GetAdapterMonitor(adapternum);
// if we match the proposed monitor, this is it
- if (curmonitor == reinterpret_cast<HMONITOR>(win->monitor()->oshandle()))
+ if (curmonitor == reinterpret_cast<HMONITOR>(window().monitor()->oshandle()))
{
return adapternum;
}
@@ -1278,10 +1325,8 @@ void renderer_d3d9::pick_best_mode()
int32_t minwidth, minheight;
float best_score = 0.0f;
- auto win = assert_window();
-
// determine the refresh rate of the primary screen
- const screen_device *primary_screen = screen_device_enumerator(win->machine().root_device()).first();
+ const screen_device *primary_screen = screen_device_enumerator(window().machine().root_device()).first();
if (primary_screen != nullptr)
{
target_refresh = ATTOSECONDS_TO_HZ(primary_screen->refresh_attoseconds());
@@ -1291,14 +1336,14 @@ void renderer_d3d9::pick_best_mode()
// note: technically we should not be calling this from an alternate window
// thread; however, it is only done during init time, and the init code on
// the main thread is waiting for us to finish, so it is safe to do so here
- win->target()->compute_minimum_size(minwidth, minheight);
+ window().target()->compute_minimum_size(minwidth, minheight);
// use those as the target for now
int32_t target_width = minwidth;
int32_t target_height = minheight;
// determine the maximum number of modes
- int maxmodes = d3dintf->d3dobj->GetAdapterModeCount(m_adapter, D3DFMT_X8R8G8B8);
+ int maxmodes = m_d3dobj->GetAdapterModeCount(m_adapter, D3DFMT_X8R8G8B8);
// enumerate all the video modes and find the best match
osd_printf_verbose("Direct3D: Selecting video mode...\n");
@@ -1306,7 +1351,7 @@ void renderer_d3d9::pick_best_mode()
{
// check this mode
D3DDISPLAYMODE mode;
- HRESULT result = d3dintf->d3dobj->EnumAdapterModes(m_adapter, D3DFMT_X8R8G8B8, modenum, &mode);
+ HRESULT result = m_d3dobj->EnumAdapterModes(m_adapter, D3DFMT_X8R8G8B8, modenum, &mode);
if (FAILED(result))
break;
@@ -1326,7 +1371,7 @@ void renderer_d3d9::pick_best_mode()
size_score *= 0.1f;
// if we're looking for a particular mode, that's a winner
- if (mode.Width == win->m_win_config.width && mode.Height == win->m_win_config.height)
+ if (mode.Width == window().m_win_config.width && mode.Height == window().m_win_config.height)
size_score = 2.0f;
// compute refresh score
@@ -1337,7 +1382,7 @@ void renderer_d3d9::pick_best_mode()
refresh_score *= 0.1f;
// if we're looking for a particular refresh, make sure it matches
- if (mode.RefreshRate == win->m_win_config.refresh)
+ if (mode.RefreshRate == window().m_win_config.refresh)
refresh_score = 2.0f;
// weight size and refresh equally
@@ -1364,33 +1409,32 @@ void renderer_d3d9::pick_best_mode()
bool renderer_d3d9::update_window_size()
{
- auto win = assert_window();
-
// get the current window bounds
+ auto &win = dynamic_cast<win_window_info &>(window());
RECT client;
- GetClientRectExceptMenu(std::static_pointer_cast<win_window_info>(win)->platform_window(), &client, win->fullscreen());
+ GetClientRectExceptMenu(win.platform_window(), &client, window().fullscreen());
// if we have a device and matching width/height, nothing to do
- if (m_device != nullptr && rect_width(&client) == m_width && rect_height(&client) == m_height)
+ if (m_device && rect_width(&client) == m_width && rect_height(&client) == m_height)
{
// clear out any pending resizing if the area didn't change
- if (win->m_resize_state == RESIZE_STATE_PENDING)
- win->m_resize_state = RESIZE_STATE_NORMAL;
+ if (win.m_resize_state == win_window_info::RESIZE_STATE_PENDING)
+ win.m_resize_state = win_window_info::RESIZE_STATE_NORMAL;
return false;
}
// if we're in the middle of resizing, leave it alone as well
- if (win->m_resize_state == RESIZE_STATE_RESIZING)
+ if (win.m_resize_state == win_window_info::RESIZE_STATE_RESIZING)
return false;
// set the new bounds and create the device again
m_width = rect_width(&client);
m_height = rect_height(&client);
- if (device_create(std::static_pointer_cast<win_window_info>(win->main_window())->platform_window()))
+ if (device_create(win.main_window()->platform_window()))
return false;
// reset the resize state to normal, and indicate we made a change
- win->m_resize_state = RESIZE_STATE_NORMAL;
+ win.m_resize_state = win_window_info::RESIZE_STATE_NORMAL;
return true;
}
@@ -1401,8 +1445,6 @@ bool renderer_d3d9::update_window_size()
void renderer_d3d9::batch_vectors(int vector_count)
{
- auto win = assert_window();
-
float quad_width = 0.0f;
float quad_height = 0.0f;
float target_width = 0.0f;
@@ -1412,9 +1454,10 @@ void renderer_d3d9::batch_vectors(int vector_count)
int triangle_count = vector_count * 2;
m_vectorbatch = mesh_alloc(vertex_count);
m_batchindex = 0;
+ uint32_t tint = 0xffffffff;
uint32_t cached_flags = 0;
- for (render_primitive &prim : *win->m_primlist)
+ for (render_primitive &prim : *window().m_primlist)
{
switch (prim.type)
{
@@ -1423,6 +1466,12 @@ void renderer_d3d9::batch_vectors(int vector_count)
{
batch_vector(prim);
cached_flags = prim.flags;
+
+ const uint8_t a = (uint8_t)std::round(prim.color.a * 255);
+ const uint8_t r = (uint8_t)std::round(prim.color.r * 255);
+ const uint8_t g = (uint8_t)std::round(prim.color.g * 255);
+ const uint8_t b = (uint8_t)std::round(prim.color.b * 255);
+ tint = (a << 24) | (b << 16) | (g << 8) | r;
}
break;
@@ -1433,6 +1482,12 @@ void renderer_d3d9::batch_vectors(int vector_count)
quad_height = prim.get_quad_height();
target_width = prim.get_full_quad_width();
target_height = prim.get_full_quad_height();
+
+ const uint8_t a = (uint8_t)std::round(prim.color.a * 255);
+ const uint8_t r = (uint8_t)std::round(prim.color.r * 255);
+ const uint8_t g = (uint8_t)std::round(prim.color.g * 255);
+ const uint8_t b = (uint8_t)std::round(prim.color.b * 255);
+ tint = (a << 24) | (b << 16) | (g << 8) | r;
}
break;
@@ -1446,15 +1501,15 @@ void renderer_d3d9::batch_vectors(int vector_count)
if (m_shaders->enabled())
{
bool orientation_swap_xy =
- (win->machine().system().flags & ORIENTATION_SWAP_XY) == ORIENTATION_SWAP_XY;
+ (window().machine().system().flags & ORIENTATION_SWAP_XY) == ORIENTATION_SWAP_XY;
bool rotation_swap_xy =
- (win->target()->orientation() & ORIENTATION_SWAP_XY) == ORIENTATION_SWAP_XY;
+ (window().target()->orientation() & ORIENTATION_SWAP_XY) == ORIENTATION_SWAP_XY;
bool swap_xy = orientation_swap_xy ^ rotation_swap_xy;
- bool rotation_0 = win->target()->orientation() == ROT0;
- bool rotation_90 = win->target()->orientation() == ROT90;
- bool rotation_180 = win->target()->orientation() == ROT180;
- bool rotation_270 = win->target()->orientation() == ROT270;
+ bool rotation_0 = window().target()->orientation() == ROT0;
+ bool rotation_90 = window().target()->orientation() == ROT90;
+ bool rotation_180 = window().target()->orientation() == ROT180;
+ bool rotation_270 = window().target()->orientation() == ROT270;
bool flip_x =
((rotation_0 || rotation_270) && orientation_swap_xy) ||
((rotation_180 || rotation_270) && !orientation_swap_xy);
@@ -1510,7 +1565,7 @@ void renderer_d3d9::batch_vectors(int vector_count)
}
// now add a polygon entry
- m_poly[m_numpolys].init(D3DPT_TRIANGLELIST, triangle_count, vertex_count, cached_flags, nullptr, D3DTOP_MODULATE, quad_width, quad_height);
+ m_poly[m_numpolys].init(D3DPT_TRIANGLELIST, triangle_count, vertex_count, cached_flags, nullptr, D3DTOP_MODULATE, quad_width, quad_height, tint);
m_numpolys++;
}
@@ -1652,10 +1707,10 @@ void renderer_d3d9::draw_line(const render_primitive &prim)
vertex[3].v0 = stop.c.y;
// determine the color of the line
- auto r = (int32_t)(prim.color.r * 255.0f);
- auto g = (int32_t)(prim.color.g * 255.0f);
- auto b = (int32_t)(prim.color.b * 255.0f);
- auto a = (int32_t)(prim.color.a * 255.0f);
+ auto r = (int32_t)std::round(prim.color.r * 255.0f);
+ auto g = (int32_t)std::round(prim.color.g * 255.0f);
+ auto b = (int32_t)std::round(prim.color.b * 255.0f);
+ auto a = (int32_t)std::round(prim.color.a * 255.0f);
DWORD color = D3DCOLOR_ARGB(a, r, g, b);
// set the color, Z parameters to standard values
@@ -1667,7 +1722,7 @@ void renderer_d3d9::draw_line(const render_primitive &prim)
}
// now add a polygon entry
- m_poly[m_numpolys].init(D3DPT_TRIANGLESTRIP, 2, 4, prim.flags, nullptr, D3DTOP_MODULATE, 0.0f, 0.0f);
+ m_poly[m_numpolys].init(D3DPT_TRIANGLESTRIP, 2, 4, prim.flags, nullptr, D3DTOP_MODULATE, 0.0f, 0.0f, (uint32_t)color);
m_numpolys++;
}
@@ -1721,10 +1776,10 @@ void renderer_d3d9::draw_quad(const render_primitive &prim)
}
// determine the color, allowing for over modulation
- auto r = (int32_t)(prim.color.r * 255.0f);
- auto g = (int32_t)(prim.color.g * 255.0f);
- auto b = (int32_t)(prim.color.b * 255.0f);
- auto a = (int32_t)(prim.color.a * 255.0f);
+ auto r = (int32_t)std::round(prim.color.r * 255.0f);
+ auto g = (int32_t)std::round(prim.color.g * 255.0f);
+ auto b = (int32_t)std::round(prim.color.b * 255.0f);
+ auto a = (int32_t)std::round(prim.color.a * 255.0f);
DWORD color = D3DCOLOR_ARGB(a, r, g, b);
// adjust half pixel X/Y offset, set the color, Z parameters to standard values
@@ -1738,7 +1793,7 @@ void renderer_d3d9::draw_quad(const render_primitive &prim)
}
// now add a polygon entry
- m_poly[m_numpolys].init(D3DPT_TRIANGLESTRIP, 2, 4, prim.flags, texture, D3DTOP_MODULATE, quad_width, quad_height);
+ m_poly[m_numpolys].init(D3DPT_TRIANGLESTRIP, 2, 4, prim.flags, texture, D3DTOP_MODULATE, quad_width, quad_height, (uint32_t)color);
m_numpolys++;
}
@@ -1798,7 +1853,7 @@ void renderer_d3d9::primitive_flush_pending()
m_lockedbuf = nullptr;
// set the stream
- result = m_device->SetStreamSource(0, m_vertexbuf, 0, sizeof(vertex));
+ result = m_device->SetStreamSource(0, m_vertexbuf.Get(), 0, sizeof(vertex));
if (FAILED(result))
osd_printf_verbose("Direct3D: Error %08lX during device SetStreamSource call\n", result);
@@ -1826,9 +1881,17 @@ void renderer_d3d9::primitive_flush_pending()
newfilter = FALSE;
if (PRIMFLAG_GET_SCREENTEX(flags))
newfilter = video_config.filter;
- set_filter(newfilter);
- set_wrap(PRIMFLAG_GET_TEXWRAP(flags) ? D3DTADDRESS_WRAP : D3DTADDRESS_CLAMP);
- set_modmode(m_poly[polynum].modmode());
+
+ if (m_shaders->enabled())
+ {
+ m_shaders->set_filter(newfilter);
+ }
+ else
+ {
+ set_filter(newfilter);
+ set_wrap(PRIMFLAG_GET_TEXWRAP(flags) ? D3DTADDRESS_WRAP : D3DTADDRESS_CLAMP);
+ set_modmode(m_poly[polynum].modmode());
+ }
}
if (vertnum + m_poly[polynum].numverts() > m_numverts)
@@ -1841,9 +1904,6 @@ void renderer_d3d9::primitive_flush_pending()
if(m_shaders->enabled())
{
- // reset blend mode (handled by shader passes)
- set_blendmode(BLENDMODE_NONE);
-
m_shaders->render_quad(&m_poly[polynum], vertnum);
}
else
@@ -1896,19 +1956,6 @@ void renderer_d3d9::set_sliders_dirty()
texture_info::~texture_info()
{
- if (m_d3dfinaltex != nullptr)
- {
- if (m_d3dtex == m_d3dfinaltex)
- m_d3dtex = nullptr;
-
- m_d3dfinaltex->Release();
- }
-
- if (m_d3dtex != nullptr)
- m_d3dtex->Release();
-
- if (m_d3dsurface != nullptr)
- m_d3dsurface->Release();
}
@@ -1916,153 +1963,117 @@ texture_info::~texture_info()
// texture_info constructor
//============================================================
-texture_info::texture_info(d3d_texture_manager *manager, const render_texinfo* texsource, int prescale, uint32_t flags)
+texture_info::texture_info(d3d_texture_manager &manager, const render_texinfo* texsource, int prescale, uint32_t flags)
+ : m_texture_manager(manager)
+ , m_renderer(manager.get_d3d())
+ , m_hash(manager.texture_compute_hash(texsource, flags))
+ , m_flags(flags)
+ , m_texinfo(*texsource)
+ , m_type(!PRIMFLAG_GET_SCREENTEX(flags) ? TEXTURE_TYPE_PLAIN : TEXTURE_TYPE_DYNAMIC) // required to compute texture size
+ , m_xprescale(PRIMFLAG_GET_SCREENTEX(flags) ? prescale : 1)
+ , m_yprescale(PRIMFLAG_GET_SCREENTEX(flags) ? prescale : 1)
{
- HRESULT result;
-
- // fill in the core data
- m_texture_manager = manager;
- m_renderer = m_texture_manager->get_d3d();
- m_hash = m_texture_manager->texture_compute_hash(texsource, flags);
- m_flags = flags;
- m_texinfo = *texsource;
- m_xprescale = prescale;
- m_yprescale = prescale;
-
- m_d3dtex = nullptr;
- m_d3dsurface = nullptr;
- m_d3dfinaltex = nullptr;
-
- // determine texture type, required to compute texture size
- if (!PRIMFLAG_GET_SCREENTEX(flags))
- {
- m_type = TEXTURE_TYPE_PLAIN;
- }
- else
- {
- m_type = TEXTURE_TYPE_DYNAMIC;
- }
-
// compute the size
compute_size(texsource->width, texsource->height);
- // non-screen textures are easy
if (!PRIMFLAG_GET_SCREENTEX(flags))
{
+ // non-screen textures are easy
assert(PRIMFLAG_TEXFORMAT(flags) != TEXFORMAT_YUY16);
- result = m_renderer->get_device()->CreateTexture(m_rawdims.c.x, m_rawdims.c.y, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &m_d3dtex, nullptr);
+ const HRESULT result = m_renderer.get_device()->CreateTexture(m_rawdims.c.x, m_rawdims.c.y, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &m_d3dtex, nullptr);
if (FAILED(result))
goto error;
+
m_d3dfinaltex = m_d3dtex;
}
-
- // screen textures are allocated differently
else
{
- D3DFORMAT format;
- DWORD usage = D3DUSAGE_DYNAMIC;
- D3DPOOL pool = D3DPOOL_DEFAULT;
- int maxdim = std::max(m_renderer->get_presentation()->BackBufferWidth, m_renderer->get_presentation()->BackBufferHeight);
+ // screen textures are allocated differently
// pick the format
+ const DWORD usage = D3DUSAGE_DYNAMIC;
+ const D3DPOOL pool = D3DPOOL_DEFAULT;
+ D3DFORMAT format;
if (PRIMFLAG_GET_TEXFORMAT(flags) == TEXFORMAT_YUY16)
- {
- format = m_texture_manager->get_yuv_format();
- }
+ format = m_texture_manager.get_yuv_format();
else if (PRIMFLAG_GET_TEXFORMAT(flags) == TEXFORMAT_ARGB32)
- {
format = D3DFMT_A8R8G8B8;
- }
else
- {
- format = m_renderer->get_screen_format();
- }
+ format = m_renderer.get_screen_format();
// don't prescale above screen size
- while (m_xprescale > 1 && m_rawdims.c.x * m_xprescale >= 2 * maxdim)
- {
+ const int maxdim = std::max(
+ m_renderer.get_presentation()->BackBufferWidth,
+ m_renderer.get_presentation()->BackBufferHeight);
+
+ while ((m_xprescale > 1) && ((m_rawdims.c.x * m_xprescale) >= (2 * maxdim)))
m_xprescale--;
- }
- while (m_xprescale > 1 && m_rawdims.c.x * m_xprescale > manager->get_max_texture_width())
- {
+ while ((m_xprescale > 1) && ((m_rawdims.c.x * m_xprescale) > manager.get_max_texture_width()))
m_xprescale--;
- }
- while (m_yprescale > 1 && m_rawdims.c.y * m_yprescale >= 2 * maxdim)
- {
+
+ while ((m_yprescale > 1) && ((m_rawdims.c.y * m_yprescale) >= (2 * maxdim)))
m_yprescale--;
- }
- while (m_yprescale > 1 && m_rawdims.c.y * m_yprescale > manager->get_max_texture_height())
- {
+ while ((m_yprescale > 1) && ((m_rawdims.c.y * m_yprescale) > manager.get_max_texture_height()))
m_yprescale--;
- }
-
- auto win = m_renderer->assert_window();
- int prescale = win->prescale();
- if (m_xprescale != prescale || m_yprescale != prescale)
- {
+ const int prescale = m_renderer.window().prescale();
+ if ((m_xprescale != prescale) || (m_yprescale != prescale))
osd_printf_verbose("Direct3D: adjusting prescale from %dx%d to %dx%d\n", prescale, prescale, m_xprescale, m_yprescale);
- }
// loop until we allocate something or error
+ HRESULT result;
for (int attempt = 0; attempt < 2; attempt++)
{
- // second attempt is always 1:1
- if (attempt == 1)
- {
- m_xprescale = m_yprescale = 1;
- }
-
- // screen textures with no prescaling are pretty easy
- if (m_xprescale == 1 && m_yprescale == 1)
+ if ((m_xprescale == 1) && (m_yprescale == 1))
{
- result = m_renderer->get_device()->CreateTexture(m_rawdims.c.x, m_rawdims.c.y, 1, usage, format, pool, &m_d3dtex, nullptr);
+ // screen textures with no prescaling are pretty easy
+ result = m_renderer.get_device()->CreateTexture(m_rawdims.c.x, m_rawdims.c.y, 1, usage, format, pool, &m_d3dtex, nullptr);
if (result == D3D_OK)
{
m_d3dfinaltex = m_d3dtex;
break;
}
}
- // screen textures with prescaling require two allocations
else
{
- result = m_renderer->get_device()->CreateTexture(m_rawdims.c.x, m_rawdims.c.y, 1, usage, format, pool, &m_d3dtex, nullptr);
- if (FAILED(result))
+ // screen textures with prescaling require two allocations
+ result = m_renderer.get_device()->CreateTexture(m_rawdims.c.x, m_rawdims.c.y, 1, usage, format, pool, &m_d3dtex, nullptr);
+ if (result == D3D_OK)
{
- continue;
- }
+ // for the target surface, we allocate a render target texture
+ const int scwidth = m_rawdims.c.x * m_xprescale;
+ const int scheight = m_rawdims.c.y * m_yprescale;
- // for the target surface, we allocate a render target texture
- int scwidth = m_rawdims.c.x * m_xprescale;
- int scheight = m_rawdims.c.y * m_yprescale;
+ // target surfaces typically cannot be YCbCr, so we always pick RGB in that case
+ const D3DFORMAT finalfmt = (format != m_texture_manager.get_yuv_format()) ? format : D3DFMT_A8R8G8B8;
- // target surfaces typically cannot be YCbCr, so we always pick RGB in that case
- D3DFORMAT finalfmt = (format != m_texture_manager->get_yuv_format()) ? format : D3DFMT_A8R8G8B8;
+ result = m_renderer.get_device()->CreateTexture(scwidth, scheight, 1, D3DUSAGE_RENDERTARGET, finalfmt, D3DPOOL_DEFAULT, &m_d3dfinaltex, nullptr);
+ if (result == D3D_OK)
+ break;
- result = m_renderer->get_device()->CreateTexture(scwidth, scheight, 1, D3DUSAGE_RENDERTARGET, finalfmt, D3DPOOL_DEFAULT, &m_d3dfinaltex, nullptr);
- if (result == D3D_OK)
- {
- break;
+ m_d3dtex.Reset();
}
-
- m_d3dtex->Release();
- m_d3dtex = nullptr;
}
+
+ // second attempt is always 1:1
+ m_xprescale = m_yprescale = 1;
}
+ if (FAILED(result))
+ goto error;
}
// copy the data to the texture
+ assert(m_d3dtex);
+ assert(m_d3dfinaltex);
set_data(texsource, flags);
return;
error:
- d3dintf->post_fx_available = false;
+ m_renderer.set_post_fx_unavailable();
osd_printf_error("Direct3D: Critical warning: A texture failed to allocate. Expect things to get bad quickly.\n");
- if (m_d3dsurface != nullptr)
- m_d3dsurface->Release();
- if (m_d3dtex != nullptr)
- m_d3dtex->Release();
+ m_d3dsurface.Reset();
+ m_d3dtex.Reset();
}
@@ -2076,11 +2087,11 @@ void texture_info::compute_size_subroutine(int texwidth, int texheight, int* p_w
int finalwidth = texwidth;
// adjust the aspect ratio if we need to
- while (finalwidth < finalheight && finalheight / finalwidth > m_texture_manager->get_max_texture_aspect())
+ while (finalwidth < finalheight && finalheight / finalwidth > m_texture_manager.get_max_texture_aspect())
{
finalwidth *= 2;
}
- while (finalheight < finalwidth && finalwidth / finalheight > m_texture_manager->get_max_texture_aspect())
+ while (finalheight < finalwidth && finalwidth / finalheight > m_texture_manager.get_max_texture_aspect())
{
finalheight *= 2;
}
@@ -2102,7 +2113,7 @@ void texture_info::compute_size(int texwidth, int texheight)
m_xborderpix = 0;
m_yborderpix = 0;
- bool shaders_enabled = m_renderer->get_shaders()->enabled();
+ bool shaders_enabled = m_renderer.get_shaders()->enabled();
bool wrap_texture = (m_flags & PRIMFLAG_TEXWRAP_MASK) == PRIMFLAG_TEXWRAP_MASK;
// skip border when shaders are enabled
@@ -2126,7 +2137,7 @@ void texture_info::compute_size(int texwidth, int texheight)
compute_size_subroutine(finalwidth, finalheight, &finalwidth, &finalheight);
// if we added pixels for the border, and that just barely pushed us over, take it back
- if (finalwidth > m_texture_manager->get_max_texture_width() || finalheight > m_texture_manager->get_max_texture_height())
+ if (finalwidth > m_texture_manager.get_max_texture_width() || finalheight > m_texture_manager.get_max_texture_height())
{
finalheight = texheight;
finalwidth = texwidth;
@@ -2139,10 +2150,18 @@ void texture_info::compute_size(int texwidth, int texheight)
}
// if we're above the max width/height, do what?
- if (finalwidth > m_texture_manager->get_max_texture_width() || finalheight > m_texture_manager->get_max_texture_height())
+ if (finalwidth > m_texture_manager.get_max_texture_width() || finalheight > m_texture_manager.get_max_texture_height())
{
static bool printed = false;
- if (!printed) osd_printf_warning("Texture too big! (wanted: %dx%d, max is %dx%d)\n", finalwidth, finalheight, (int)m_texture_manager->get_max_texture_width(), (int)m_texture_manager->get_max_texture_height());
+ if (!printed)
+ {
+ osd_printf_warning(
+ "Texture too big! (wanted: %dx%d, max is %dx%d)\n",
+ finalwidth,
+ finalheight,
+ m_texture_manager.get_max_texture_width(),
+ m_texture_manager.get_max_texture_height());
+ }
printed = true;
}
@@ -2395,9 +2414,9 @@ void texture_info::set_data(const render_texinfo *texsource, uint32_t flags)
break;
case TEXFORMAT_YUY16:
- if (m_texture_manager->get_yuv_format() == D3DFMT_YUY2)
+ if (m_texture_manager.get_yuv_format() == D3DFMT_YUY2)
copyline_yuy16_to_yuy2((uint16_t *)dst, (uint16_t *)texsource->base + srcy * texsource->rowpixels, texsource->width, texsource->palette);
- else if (m_texture_manager->get_yuv_format() == D3DFMT_UYVY)
+ else if (m_texture_manager.get_yuv_format() == D3DFMT_UYVY)
copyline_yuy16_to_uyvy((uint16_t *)dst, (uint16_t *)texsource->base + srcy * texsource->rowpixels, texsource->width, texsource->palette);
else
copyline_yuy16_to_argb((uint32_t *)dst, (uint16_t *)texsource->base + srcy * texsource->rowpixels, texsource->width, texsource->palette);
@@ -2432,48 +2451,51 @@ void texture_info::set_data(const render_texinfo *texsource, uint32_t flags)
void texture_info::prescale()
{
- IDirect3DSurface9 *scale_surface;
- HRESULT result;
- int i;
-
// if we don't need to, just skip it
- if (m_d3dtex == m_d3dfinaltex)
+ if (m_d3dtex.Get() == m_d3dfinaltex.Get())
+ {
+ assert(m_xprescale == 1);
+ assert(m_yprescale == 1);
return;
+ }
+
+ assert(m_d3dtex);
+ assert((m_xprescale > 1) || (m_yprescale > 1));
+ HRESULT result;
// for all cases, we need to get the surface of the render target
+ Microsoft::WRL::ComPtr<IDirect3DSurface9> scale_surface;
result = m_d3dfinaltex->GetSurfaceLevel(0, &scale_surface);
if (FAILED(result))
osd_printf_verbose("Direct3D: Error %08lX during texture GetSurfaceLevel call\n", result);
// if we have an offscreen plain surface, we can just StretchRect to it
- IDirect3DSurface9 *backbuffer;
-
- assert(m_d3dtex != nullptr);
// first remember the original render target and set the new one
- result = m_renderer->get_device()->GetRenderTarget(0, &backbuffer);
+ Microsoft::WRL::ComPtr<IDirect3DSurface9> backbuffer;
+ result = m_renderer.get_device()->GetRenderTarget(0, &backbuffer);
if (FAILED(result))
osd_printf_verbose("Direct3D: Error %08lX during device GetRenderTarget call\n", result);
- result = m_renderer->get_device()->SetRenderTarget(0, scale_surface);
+ result = m_renderer.get_device()->SetRenderTarget(0, scale_surface.Get());
if (FAILED(result))
osd_printf_verbose("Direct3D: Error %08lX during device SetRenderTarget call 1\n", result);
- m_renderer->reset_render_states();
+ m_renderer.reset_render_states();
// start the scene
- result = m_renderer->get_device()->BeginScene();
+ result = m_renderer.get_device()->BeginScene();
if (FAILED(result))
osd_printf_verbose("Direct3D: Error %08lX during device BeginScene call\n", result);
// configure the rendering pipeline
- m_renderer->set_filter(FALSE);
- m_renderer->set_blendmode(BLENDMODE_NONE);
- result = m_renderer->get_device()->SetTexture(0, m_d3dtex);
+ m_renderer.set_filter(FALSE);
+ m_renderer.set_blendmode(BLENDMODE_NONE);
+ result = m_renderer.get_device()->SetTexture(0, m_d3dtex.Get());
if (FAILED(result))
osd_printf_verbose("Direct3D: Error %08lX during device SetTexture call\n", result);
// lock the vertex buffer
vertex *lockedbuf;
- result = m_renderer->get_vertex_buffer()->Lock(0, 0, (VOID **)&lockedbuf, D3DLOCK_DISCARD);
+ result = m_renderer.get_vertex_buffer()->Lock(0, 0, (VOID **)&lockedbuf, D3DLOCK_DISCARD);
if (FAILED(result))
osd_printf_verbose("Direct3D: Error %08lX during vertex buffer lock call\n", result);
@@ -2498,7 +2520,7 @@ void texture_info::prescale()
lockedbuf[3].v0 = (float)(m_texinfo.height + 2 * m_yborderpix) / (float)m_rawdims.c.y;
// reset the remaining vertex parameters
- for (i = 0; i < 4; i++)
+ for (int i = 0; i < 4; i++)
{
lockedbuf[i].z = 0.0f;
lockedbuf[i].rhw = 1.0f;
@@ -2506,32 +2528,32 @@ void texture_info::prescale()
}
// unlock the vertex buffer
- result = m_renderer->get_vertex_buffer()->Unlock();
+ result = m_renderer.get_vertex_buffer()->Unlock();
if (FAILED(result))
osd_printf_verbose("Direct3D: Error %08lX during vertex buffer unlock call\n", result);
// set the stream and draw the triangle strip
- result = m_renderer->get_device()->SetStreamSource(0, m_renderer->get_vertex_buffer(), 0, sizeof(vertex));
+ result = m_renderer.get_device()->SetStreamSource(0, m_renderer.get_vertex_buffer(), 0, sizeof(vertex));
if (FAILED(result))
osd_printf_verbose("Direct3D: Error %08lX during device SetStreamSource call\n", result);
- result = m_renderer->get_device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
+ result = m_renderer.get_device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
if (FAILED(result))
osd_printf_verbose("Direct3D: Error %08lX during device DrawPrimitive call\n", result);
// end the scene
- result = m_renderer->get_device()->EndScene();
+ result = m_renderer.get_device()->EndScene();
if (FAILED(result))
osd_printf_verbose("Direct3D: Error %08lX during device end_scene call\n", result);
// reset the render target and release our reference to the backbuffer
- result = m_renderer->get_device()->SetRenderTarget(0, backbuffer);
+ result = m_renderer.get_device()->SetRenderTarget(0, backbuffer.Get());
if (FAILED(result))
osd_printf_verbose("Direct3D: Error %08lX during device SetRenderTarget call 2\n", result);
- backbuffer->Release();
- m_renderer->reset_render_states();
+ backbuffer.Reset();
+ m_renderer.reset_render_states();
// release our reference to the target surface
- scale_surface->Release();
+ scale_surface.Reset();
}
@@ -2541,35 +2563,6 @@ void texture_info::prescale()
d3d_render_target::~d3d_render_target()
{
- for (int index = 0; index < MAX_BLOOM_COUNT; index++)
- {
- if (bloom_texture[index] != nullptr)
- bloom_texture[index]->Release();
-
- if (bloom_surface[index] != nullptr)
- bloom_surface[index]->Release();
- }
-
- for (int index = 0; index < 2; index++)
- {
- if (source_texture[index] != nullptr)
- source_texture[index]->Release();
-
- if (source_surface[index] != nullptr)
- source_surface[index]->Release();
-
- if (target_texture[index] != nullptr)
- target_texture[index]->Release();
-
- if (target_surface[index] != nullptr)
- target_surface[index]->Release();
- }
-
- if (cache_texture != nullptr)
- cache_texture->Release();
-
- if (cache_surface != nullptr)
- cache_surface->Release();
}
@@ -2610,9 +2603,7 @@ bool d3d_render_target::init(renderer_d3d9 *d3d, int source_width, int source_he
cache_texture->GetSurfaceLevel(0, &cache_surface);
- auto win = d3d->assert_window();
-
- const screen_device *first_screen = screen_device_enumerator(win->machine().root_device()).first();
+ const screen_device *first_screen = screen_device_enumerator(d3d->window().machine().root_device()).first();
bool vector_screen =
first_screen != nullptr &&
first_screen->screen_type() == SCREEN_TYPE_VECTOR;
diff --git a/src/osd/modules/render/drawd3d.h b/src/osd/modules/render/drawd3d.h
index 2fa4a30873c..3ab7651d87c 100644
--- a/src/osd/modules/render/drawd3d.h
+++ b/src/osd/modules/render/drawd3d.h
@@ -10,20 +10,24 @@
#pragma once
+#include "d3d/d3dcomm.h"
-#ifdef OSD_WINDOWS
+#include "modules/lib/osdlib.h"
+#include "modules/osdwindow.h"
+
+#include "sliderdirtynotifier.h"
#include <windows.h>
#include <tchar.h>
#include <mmsystem.h>
#include <d3d9.h>
#include <d3dx9.h>
-#include <cmath>
#undef interface
-#include "d3d/d3dcomm.h"
-#include "sliderdirtynotifier.h"
-#include "modules/lib/osdlib.h"
+#include <memory>
+#include <vector>
+#include <cmath>
+
//============================================================
// CONSTANTS
@@ -36,15 +40,6 @@
// TYPE DEFINITIONS
//============================================================
-struct d3d_base
-{
- // internal objects
- IDirect3D9 *d3dobj;
- bool post_fx_available;
-
- osd::dynamic_module::ptr d3d9_dll;
-};
-
class shaders;
struct hlsl_options;
@@ -52,11 +47,10 @@ struct hlsl_options;
class renderer_d3d9 : public osd_renderer, public slider_dirty_notifier
{
public:
- renderer_d3d9(std::shared_ptr<osd_window> window);
- virtual ~renderer_d3d9();
+ using IDirect3D9Ptr = Microsoft::WRL::ComPtr<IDirect3D9>;
- static bool init(running_machine &machine);
- static void exit();
+ renderer_d3d9(osd_window &window, const IDirect3D9Ptr &d3dobj);
+ virtual ~renderer_d3d9();
virtual int create() override;
virtual render_primitive_list *get_primitives() override;
@@ -113,11 +107,13 @@ public:
vec2f get_dims() const { return vec2f(m_width, m_height); }
int get_height() const { return m_height; }
int get_refresh() const { return m_refresh; }
+ bool post_fx_available() const { return m_post_fx_available; }
+ void set_post_fx_unavailable() { m_post_fx_available = false; }
- IDirect3DDevice9 * get_device() const { return m_device; }
+ IDirect3DDevice9 * get_device() const { return m_device.Get(); }
D3DPRESENT_PARAMETERS * get_presentation() { return &m_presentation; }
- IDirect3DVertexBuffer9 *get_vertex_buffer() const { return m_vertexbuf; }
+ IDirect3DVertexBuffer9 *get_vertex_buffer() const { return m_vertexbuf.Get(); }
void set_toggle(bool toggle) { m_toggle = toggle; }
@@ -125,27 +121,32 @@ public:
D3DFORMAT get_pixel_format() const { return m_pixformat; }
D3DDISPLAYMODE get_origmode() const { return m_origmode; }
- uint32_t get_last_texture_flags() const { return m_last_texture_flags; }
+ uint32_t get_last_texture_flags() const { return m_last_texture_flags; }
d3d_texture_manager * get_texture_manager() const { return m_texture_manager.get(); }
texture_info * get_default_texture();
- shaders * get_shaders() const { return m_shaders; }
+ shaders * get_shaders() const { return m_shaders.get(); }
private:
+ using IDirect3DDevice9Ptr = Microsoft::WRL::ComPtr<IDirect3DDevice9>;
+ using IDirect3DVertexBuffer9Ptr = Microsoft::WRL::ComPtr<IDirect3DVertexBuffer9>;
+
+ const IDirect3D9Ptr m_d3dobj; // Direct3D 9 API object
int m_adapter; // ordinal adapter number
int m_width; // current width
int m_height; // current height
int m_refresh; // current refresh rate
int m_create_error_count; // number of consecutive create errors
+ bool m_post_fx_available;
- IDirect3DDevice9 * m_device; // pointer to the Direct3DDevice object
+ IDirect3DDevice9Ptr m_device; // pointer to the Direct3DDevice object
int m_gamma_supported; // is full screen gamma supported?
D3DPRESENT_PARAMETERS m_presentation; // set of presentation parameters
D3DDISPLAYMODE m_origmode; // original display mode for the adapter
D3DFORMAT m_pixformat; // pixel format we are using
- IDirect3DVertexBuffer9 *m_vertexbuf; // pointer to the vertex buffer object
+ IDirect3DVertexBuffer9Ptr m_vertexbuf; // pointer to the vertex buffer object
vertex * m_lockedbuf; // pointer to the locked vertex buffer
int m_numverts; // number of accumulated vertices
@@ -160,20 +161,18 @@ private:
D3DFORMAT m_screen_format; // format to use for screen textures
texture_info * m_last_texture; // previous texture
- uint32_t m_last_texture_flags; // previous texture flags
+ uint32_t m_last_texture_flags; // previous texture flags
int m_last_blendenable; // previous blendmode
int m_last_blendop; // previous blendmode
int m_last_blendsrc; // previous blendmode
int m_last_blenddst; // previous blendmode
int m_last_filter; // previous texture filter
- uint32_t m_last_wrap; // previous wrap state
+ uint32_t m_last_wrap; // previous wrap state
int m_last_modmode; // previous texture modulation
- shaders * m_shaders; // HLSL interface
+ std::unique_ptr<shaders> m_shaders; // HLSL interface
std::unique_ptr<d3d_texture_manager> m_texture_manager; // texture manager
};
-#endif // OSD_WINDOWS
-
#endif // MAME_OSD_MODULES_RENDER_DRAWD3D_H
diff --git a/src/osd/modules/render/drawgdi.cpp b/src/osd/modules/render/drawgdi.cpp
index 32dac94c24a..f922ca24e8f 100644
--- a/src/osd/modules/render/drawgdi.cpp
+++ b/src/osd/modules/render/drawgdi.cpp
@@ -2,21 +2,53 @@
// copyright-holders:Aaron Giles
//============================================================
//
-// drawgdi.c - Win32 GDI drawing
+// drawgdi.cpp - Win32 GDI drawing
//
//============================================================
+#include "render_module.h"
+
+#include "modules/osdmodule.h"
+
+#if defined(OSD_WINDOWS)
+
+#include "window.h"
+
+// emu
#include "emu.h"
-#include "drawgdi.h"
#include "rendersw.hxx"
-//============================================================
-// destructor
-//============================================================
+// standard windows headers
+#include <windows.h>
+
+
+namespace osd {
+
+namespace {
-renderer_gdi::~renderer_gdi()
+// renderer_gdi is the information for the current screen
+class renderer_gdi : public osd_renderer
{
-}
+public:
+ renderer_gdi(osd_window &window)
+ : osd_renderer(window)
+ , m_bmdata(nullptr)
+ , m_bmsize(0)
+ {
+ }
+
+ virtual int create() override;
+ virtual render_primitive_list *get_primitives() override;
+ virtual int draw(const int update) override;
+ virtual void save() override {}
+ virtual void record() override {}
+ virtual void toggle_fsfx() override {}
+
+private:
+ BITMAPINFO m_bminfo;
+ std::unique_ptr<uint8_t []> m_bmdata;
+ size_t m_bmsize;
+};
//============================================================
// renderer_gdi::create
@@ -34,6 +66,7 @@ int renderer_gdi::create()
m_bminfo.bmiHeader.biYPelsPerMeter = 0;
m_bminfo.bmiHeader.biClrUsed = 0;
m_bminfo.bmiHeader.biClrImportant = 0;
+
return 0;
}
@@ -43,16 +76,12 @@ int renderer_gdi::create()
render_primitive_list *renderer_gdi::get_primitives()
{
- auto win = try_getwindow();
- if (win == nullptr)
+ osd_dim const dimensions = window().get_size();
+ if ((dimensions.width() <= 0) || (dimensions.height() <= 0))
return nullptr;
- RECT client;
- GetClientRect(std::static_pointer_cast<win_window_info>(win)->platform_window(), &client);
- if ((rect_width(&client) == 0) || (rect_height(&client) == 0))
- return nullptr;
- win->target()->set_bounds(rect_width(&client), rect_height(&client), win->pixel_aspect());
- return &win->target()->get_primitives();
+ window().target()->set_bounds(dimensions.width(), dimensions.height(), window().pixel_aspect());
+ return &window().target()->get_primitives();
}
//============================================================
@@ -61,23 +90,24 @@ render_primitive_list *renderer_gdi::get_primitives()
int renderer_gdi::draw(const int update)
{
- auto win = assert_window();
+ auto &win = dynamic_cast<win_window_info &>(window());
// we don't have any special resize behaviors
- if (win->m_resize_state == RESIZE_STATE_PENDING)
- win->m_resize_state = RESIZE_STATE_NORMAL;
+ if (win.m_resize_state == win_window_info::RESIZE_STATE_PENDING)
+ win.m_resize_state = win_window_info::RESIZE_STATE_NORMAL;
// get the target bounds
RECT bounds;
- GetClientRect(std::static_pointer_cast<win_window_info>(win)->platform_window(), &bounds);
+ GetClientRect(win.platform_window(), &bounds);
// compute width/height/pitch of target
- int width = rect_width(&bounds);
- int height = rect_height(&bounds);
- int pitch = (width + 3) & ~3;
+ osd_dim const dimensions = win.get_size();
+ int const width = dimensions.width();
+ int const height = dimensions.height();
+ int const pitch = (width + 3) & ~3;
// make sure our temporary bitmap is big enough
- if (pitch * height * 4 > m_bmsize)
+ if ((pitch * height * 4) > m_bmsize)
{
m_bmsize = pitch * height * 4 * 2;
m_bmdata.reset();
@@ -85,9 +115,9 @@ int renderer_gdi::draw(const int update)
}
// draw the primitives to the bitmap
- win->m_primlist->acquire_lock();
- software_renderer<uint32_t, 0,0,0, 16,8,0>::draw_primitives(*win->m_primlist, m_bmdata.get(), width, height, pitch);
- win->m_primlist->release_lock();
+ win.m_primlist->acquire_lock();
+ software_renderer<uint32_t, 0,0,0, 16,8,0>::draw_primitives(*win.m_primlist, m_bmdata.get(), width, height, pitch);
+ win.m_primlist->release_lock();
// fill in bitmap-specific info
m_bminfo.bmiHeader.biWidth = pitch;
@@ -95,8 +125,43 @@ int renderer_gdi::draw(const int update)
// blit to the screen
StretchDIBits(
- win->m_dc, 0, 0, width, height,
+ win.m_dc, 0, 0, width, height,
0, 0, width, height,
m_bmdata.get(), &m_bminfo, DIB_RGB_COLORS, SRCCOPY);
+
return 0;
}
+
+
+class video_gdi : public osd_module, public render_module
+{
+public:
+ video_gdi() : osd_module(OSD_RENDERER_PROVIDER, "gdi") { }
+
+ virtual int init(osd_interface &osd, osd_options const &options) override { return 0; }
+ virtual void exit() override { }
+
+ virtual std::unique_ptr<osd_renderer> create(osd_window &window) override;
+
+protected:
+ virtual unsigned flags() const override { return FLAG_INTERACTIVE; }
+};
+
+std::unique_ptr<osd_renderer> video_gdi::create(osd_window &window)
+{
+ return std::make_unique<renderer_gdi>(window);
+}
+
+} // anonymous namespace
+
+} // namespace osd
+
+
+#else // defined(OSD_WINDOWS)
+
+namespace osd { namespace { MODULE_NOT_SUPPORTED(video_gdi, OSD_RENDERER_PROVIDER, "gdi") } }
+
+#endif // defined(OSD_WINDOWS)
+
+
+MODULE_DEFINITION(RENDERER_GDI, osd::video_gdi)
diff --git a/src/osd/modules/render/drawgdi.h b/src/osd/modules/render/drawgdi.h
deleted file mode 100644
index 0dfc4bf2641..00000000000
--- a/src/osd/modules/render/drawgdi.h
+++ /dev/null
@@ -1,55 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Aaron Giles
-//============================================================
-//
-// drawgdi.h - Win32 GDI drawing
-//
-//============================================================
-#ifndef MAME_OSD_MODULES_RENDER_DRAWGDI_H
-#define MAME_OSD_MODULES_RENDER_DRAWGDI_H
-
-#pragma once
-
-
-// standard windows headers
-#include <windows.h>
-
-// MAME headers
-
-// MAMEOS headers
-#include "window.h"
-
-
-//============================================================
-// TYPE DEFINITIONS
-//============================================================
-
-/* renderer_gdi is the information for the current screen */
-class renderer_gdi : public osd_renderer
-{
-public:
- renderer_gdi(std::shared_ptr<osd_window> window)
- : osd_renderer(window, FLAG_NONE)
- , m_bmdata(nullptr)
- , m_bmsize(0)
- {
- }
- virtual ~renderer_gdi();
-
- static bool init(running_machine &machine) { return false; }
- static void exit() { }
-
- virtual int create() override;
- virtual render_primitive_list *get_primitives() override;
- virtual int draw(const int update) override;
- virtual void save() override {}
- virtual void record() override {}
- virtual void toggle_fsfx() override {}
-
-private:
- BITMAPINFO m_bminfo;
- std::unique_ptr<uint8_t []> m_bmdata;
- size_t m_bmsize;
-};
-
-#endif // MAME_OSD_MODULES_RENDER_DRAWGDI_H
diff --git a/src/osd/modules/render/drawnone.cpp b/src/osd/modules/render/drawnone.cpp
index 6f591879038..55ce1bbed18 100644
--- a/src/osd/modules/render/drawnone.cpp
+++ b/src/osd/modules/render/drawnone.cpp
@@ -6,25 +6,76 @@
//
//============================================================
-// standard windows headers
-#include <windows.h>
+#include "render_module.h"
-#include "drawnone.h"
+#include "modules/lib/osdobj_common.h"
+#include "modules/osdmodule.h"
+#include "modules/osdwindow.h"
-//============================================================
-// drawnone_window_get_primitives
-//============================================================
+#include "main.h"
+#include "render.h"
+
+#include <memory>
+
+
+namespace osd {
+
+namespace {
+
+class renderer_none : public osd_renderer
+{
+public:
+ renderer_none(osd_window &window) : osd_renderer(window) { }
+
+ virtual int create() override { return 0; }
+ virtual render_primitive_list *get_primitives() override;
+ virtual int draw(const int update) override { return 0; }
+ virtual void save() override { }
+ virtual void record() override { }
+ virtual void toggle_fsfx() override { }
+};
render_primitive_list *renderer_none::get_primitives()
{
- auto win = try_getwindow();
- if (win == nullptr)
+ osd_dim const dimensions = window().get_size();
+ if ((dimensions.width() <= 0) || (dimensions.height() <= 0))
return nullptr;
- RECT client;
- GetClientRect(std::static_pointer_cast<win_window_info>(win)->platform_window(), &client);
- if ((rect_width(&client) == 0) || (rect_height(&client) == 0))
- return nullptr;
- win->target()->set_bounds(rect_width(&client), rect_height(&client), win->pixel_aspect());
- return &win->target()->get_primitives();
+ window().target()->set_bounds(dimensions.width(), dimensions.height(), window().pixel_aspect());
+ return &window().target()->get_primitives();
}
+
+
+class video_none : public osd_module, public render_module
+{
+public:
+ video_none() : osd_module(OSD_RENDERER_PROVIDER, "none") { }
+
+ virtual int init(osd_interface &osd, osd_options const &options) override;
+ virtual void exit() override { }
+
+ virtual std::unique_ptr<osd_renderer> create(osd_window &window) override;
+
+protected:
+ virtual unsigned flags() const override { return 0; }
+};
+
+int video_none::init(osd_interface &osd, osd_options const &options)
+{
+ if (!emulator_info::standalone() && (options.seconds_to_run() == 0))
+ osd_printf_warning("Warning: -video none doesn't make much sense without -seconds_to_run\n");
+
+ return 0;
+}
+
+std::unique_ptr<osd_renderer> video_none::create(osd_window &window)
+{
+ return std::make_unique<renderer_none>(window);
+}
+
+} // anonymous namespace
+
+} // namespace osd
+
+
+MODULE_DEFINITION(RENDERER_NONE, osd::video_none)
diff --git a/src/osd/modules/render/drawnone.h b/src/osd/modules/render/drawnone.h
deleted file mode 100644
index c884f969204..00000000000
--- a/src/osd/modules/render/drawnone.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Aaron Giles
-//============================================================
-//
-// drawnone.h - stub "nothing" drawer
-//
-//============================================================
-
-#ifndef __DRAWNONE__
-#define __DRAWNONE__
-
-#include "window.h"
-
-class renderer_none : public osd_renderer
-{
-public:
- renderer_none(std::shared_ptr<osd_window> window)
- : osd_renderer(window, FLAG_NONE) { }
-
- virtual ~renderer_none() { }
-
- static bool init(running_machine &machine) { return false; }
- static void exit() { }
-
- virtual int create() override { return 0; }
- virtual render_primitive_list *get_primitives() override;
- virtual int draw(const int update) override { return 0; }
- virtual void save() override { }
- virtual void record() override { }
- virtual void toggle_fsfx() override { }
-};
-
-#endif // __DRAWNONE__
diff --git a/src/osd/modules/render/drawogl.cpp b/src/osd/modules/render/drawogl.cpp
index 9e200f3817c..f9f76946bf4 100644
--- a/src/osd/modules/render/drawogl.cpp
+++ b/src/osd/modules/render/drawogl.cpp
@@ -12,37 +12,60 @@
//
//============================================================
-// standard C headers
-#include <cmath>
-#include <cstdio>
+#include "render_module.h"
+
+#include "modules/osdmodule.h"
+
+#if USE_OPENGL
-// MAME headers
+// will be picked up from specific OSD implementation
+#include "window.h"
+
+// OSD common headers
+#include "modules/lib/osdlib.h"
+#include "modules/lib/osdobj_common.h"
+#include "modules/opengl/gl_shader_mgr.h"
#include "osdcomm.h"
-#include "emu.h"
-#include "emuopts.h"
-#ifdef OSD_MAC
+// OSD headers
+#if defined(OSD_WINDOWS)
+typedef uint64_t HashT;
+#include "winglcontext.h"
+#elif defined(OSD_MAC)
#define GL_SILENCE_DEPRECATION (1)
+#include "osdmac.h"
+#else
+#include "osdsdl.h"
+#include "sdlglcontext.h"
#endif
+// emu
+#include "emucore.h"
+#include "emuopts.h"
+#include "render.h"
+
+
#if !defined(OSD_WINDOWS) && !defined(OSD_MAC)
+
// standard SDL headers
#define TOBEMIGRATED 1
#include <SDL2/SDL.h>
-#endif
-#include "modules/lib/osdlib.h"
-#include "modules/lib/osdobj_common.h"
+#endif // !defined(OSD_WINDOWS && !defined(OSD_MAC)
-// OpenGL headers
-#include "modules/opengl/osd_opengl.h"
-#include "modules/opengl/gl_shader_tool.h"
-#include "modules/opengl/gl_shader_mgr.h"
+// standard C headers
+#include <cmath>
+#include <cstdio>
+#include <memory>
+#include <utility>
+
#if defined(SDLMAME_MACOSX) || defined(OSD_MAC)
+
#include <cstring>
#include <cstdio>
+
#include <sys/types.h>
#include <sys/sysctl.h>
@@ -72,7 +95,13 @@ typedef void (APIENTRYP PFNGLBINDRENDERBUFFEREXTPROC) (GLenum m_target, GLuint r
typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEEXTPROC) (GLenum m_target, GLenum internalformat, GLsizei width, GLsizei height);
typedef void (APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC) (GLenum m_target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
typedef void (APIENTRYP PFNGLDELETERENDERBUFFERSEXTPROC) (GLsizei n, const GLuint *renderbuffers);
-#endif
+
+#endif // defined(SDLMAME_MACOSX) || defined(OSD_MAC)
+
+
+namespace osd {
+
+namespace {
// make sure the extensions compile OK everywhere
#ifndef GL_TEXTURE_STORAGE_HINT_APPLE
@@ -128,7 +157,283 @@ typedef void (APIENTRYP PFNGLDELETERENDERBUFFERSEXTPROC) (GLsizei n, const GLuin
#define GL_DEPTH_COMPONENT32 0x81A7
#endif
-#include "drawogl.h"
+
+//============================================================
+// Configuration
+//============================================================
+
+#define GLSL_SHADER_MAX 10
+
+struct ogl_video_config
+{
+ ogl_video_config() = default;
+
+ bool vbo = false;
+ bool pbo = false;
+ bool allowtexturerect = false; // allow GL_ARB_texture_rectangle, default: no
+ bool forcepow2texture = false; // force power of two textures, default: no
+ bool glsl = false;
+ int glsl_filter = 0; // glsl filtering, >0 disables filter
+ std::string glsl_shader_mamebm[GLSL_SHADER_MAX]; // custom glsl shader set, mame bitmap
+ int glsl_shader_mamebm_num = 0; // custom glsl shader set number, mame bitmap
+ std::string glsl_shader_scrn[GLSL_SHADER_MAX]; // custom glsl shader set, screen bitmap
+ int glsl_shader_scrn_num = 0; // custom glsl shader number, screen bitmap
+};
+
+
+//============================================================
+// Textures
+//============================================================
+
+/* ogl_texture_info holds information about a texture */
+class ogl_texture_info
+{
+public:
+ ogl_texture_info(
+#if defined(USE_DISPATCH_GL)
+ osd_gl_dispatch *gld
+#endif
+ )
+#if defined(USE_DISPATCH_GL)
+ : gl_dispatch(gld)
+#endif
+ {
+ for (int i=0; i<2; i++)
+ {
+ mpass_textureunit[i] = 0;
+ mpass_texture_mamebm[i] = 0;
+ mpass_fbo_mamebm[i] = 0;
+ mpass_texture_scrn[i] = 0;
+ mpass_fbo_scrn[i] = 0;
+ }
+ for (int i=0; i<8; i++)
+ texCoord[i] = 0.0f;
+ }
+
+#if defined(USE_DISPATCH_GL)
+ osd_gl_dispatch *const gl_dispatch; // name is magic, can't be changed
+#endif
+ HashT hash = 0; // hash value for the texture (must be >= pointer size)
+ uint32_t flags = 0; // rendering flags
+ render_texinfo texinfo; // copy of the texture info
+ int rawwidth = 0, rawheight = 0; // raw width/height of the texture
+ int rawwidth_create = 0; // raw width/height, pow2 compatible, if needed
+ int rawheight_create = 0; // (create and initial set the texture, not for copy!)
+ int type = 0; // what type of texture are we?
+ int format = 0; // texture format
+ int borderpix = 0; // do we have a 1 pixel border?
+ int xprescale = 0; // what is our X prescale factor?
+ int yprescale = 0; // what is our Y prescale factor?
+ int nocopy = 0; // must the texture date be copied?
+
+ uint32_t texture = 0; // OpenGL texture "name"/ID
+
+ GLenum texTarget = 0; // OpenGL texture target
+ int texpow2 = 0; // Is this texture pow2
+
+ uint32_t mpass_dest_idx = 0; // Multipass dest idx [0..1]
+ uint32_t mpass_textureunit[2]; // texture unit names for GLSL
+
+ uint32_t mpass_texture_mamebm[2]; // Multipass OpenGL texture "name"/ID for the shader
+ uint32_t mpass_fbo_mamebm[2]; // framebuffer object for this texture, multipass
+ uint32_t mpass_texture_scrn[2]; // Multipass OpenGL texture "name"/ID for the shader
+ uint32_t mpass_fbo_scrn[2]; // framebuffer object for this texture, multipass
+
+ uint32_t pbo = 0; // pixel buffer object for this texture (DYNAMIC only!)
+ uint32_t *data = nullptr; // pixels for the texture
+ bool data_own = false; // do we own / allocated it ?
+ GLfloat texCoord[8];
+ GLuint texCoordBufferName;
+
+};
+
+// renderer_ogl is the information about OpenGL for the current screen
+class renderer_ogl : public osd_renderer
+{
+public:
+ renderer_ogl(osd_window &window, ogl_video_config const &ogl_config)
+ : osd_renderer(window)
+ , m_ogl_config(ogl_config)
+ , m_blittimer(0)
+ , m_width(0)
+ , m_height(0)
+ , m_blit_dim(0, 0)
+ , m_initialized(0)
+ , m_last_blendmode(0)
+ , m_texture_max_width(0)
+ , m_texture_max_height(0)
+ , m_texpoweroftwo(0)
+ , m_usevbo(0)
+ , m_usepbo(0)
+ , m_usefbo(0)
+ , m_useglsl(0)
+ , m_glsl_program_num(0)
+ , m_glsl_program_mb2sc(0)
+ , m_usetexturerect(0)
+ , m_init_context(0)
+ , m_last_hofs(0.0f)
+ , m_last_vofs(0.0f)
+ , m_surf_w(0)
+ , m_surf_h(0)
+ {
+ for (int i=0; i < HASH_SIZE + OVERFLOW_SIZE; i++)
+ m_texhash[i] = nullptr;
+ for (int i=0; i < 2*GLSL_SHADER_MAX; i++)
+ m_glsl_program[i] = 0;
+ for (int i=0; i < 8; i++)
+ m_texVerticex[i] = 0.0f;
+ }
+ virtual ~renderer_ogl()
+ {
+ // free the memory in the window
+ destroy_all_textures();
+ }
+
+ virtual int create() override;
+ virtual int draw(const int update) override;
+
+#ifndef OSD_WINDOWS
+ virtual int xy_to_render_target(const int x, const int y, int *xt, int *yt) override;
+#endif
+ virtual render_primitive_list *get_primitives() override
+ {
+ osd_dim nd = window().get_size();
+ if (nd != m_blit_dim)
+ {
+ m_blit_dim = nd;
+ notify_changed();
+ }
+ if ((m_blit_dim.width() == 0) || (m_blit_dim.height() == 0))
+ return nullptr;
+ window().target()->set_bounds(m_blit_dim.width(), m_blit_dim.height(), window().pixel_aspect());
+ return &window().target()->get_primitives();
+ }
+
+#ifdef OSD_WINDOWS
+ virtual void save() override { }
+ virtual void record() override { }
+ virtual void toggle_fsfx() override { }
+#endif
+
+private:
+ static const uint32_t HASH_SIZE = ((1 << 18) + 1);
+ static const uint32_t OVERFLOW_SIZE = (1 << 12);
+
+ void destroy_all_textures();
+
+ void loadGLExtensions();
+ void loadgl_functions();
+ void initialize_gl();
+ void set_blendmode(int blendmode);
+ HashT texture_compute_hash(const render_texinfo *texture, uint32_t flags);
+ void texture_compute_type_subroutine(const render_texinfo *texsource, ogl_texture_info *texture, uint32_t flags);
+ void texture_compute_size_subroutine(ogl_texture_info *texture, uint32_t flags,
+ uint32_t width, uint32_t height,
+ int* p_width, int* p_height, int* p_width_create, int* p_height_create);
+ void texture_compute_size_type(const render_texinfo *texsource, ogl_texture_info *texture, uint32_t flags);
+ ogl_texture_info *texture_create(const render_texinfo *texsource, uint32_t flags);
+ int texture_shader_create(const render_texinfo *texsource, ogl_texture_info *texture, uint32_t flags);
+ ogl_texture_info *texture_find(const render_primitive *prim);
+ void texture_coord_update(ogl_texture_info *texture, const render_primitive *prim, int shaderIdx);
+ void texture_mpass_flip(ogl_texture_info *texture, int shaderIdx);
+ void texture_shader_update(ogl_texture_info *texture, render_container *container, int shaderIdx);
+ ogl_texture_info * texture_update(const render_primitive *prim, int shaderIdx);
+ void texture_disable(ogl_texture_info * texture);
+ void texture_all_disable();
+
+ int gl_checkFramebufferStatus() const;
+ int texture_fbo_create(uint32_t text_unit, uint32_t text_name, uint32_t fbo_name, int width, int height) const;
+ void texture_set_data(ogl_texture_info *texture, const render_texinfo *texsource, uint32_t flags) const;
+
+ int gl_check_error(bool log, const char *file, int line) const
+ {
+ GLenum const glerr = glGetError();
+ if (GL_NO_ERROR != glerr)
+ {
+ if (log)
+ osd_printf_warning("%s:%d: GL Error: %d 0x%X\n", file, line, int(glerr), unsigned(glerr));
+ }
+ return (GL_NO_ERROR != glerr) ? glerr : 0;
+ }
+
+#define GL_CHECK_ERROR_QUIET() gl_check_error(false, __FILE__, __LINE__)
+#define GL_CHECK_ERROR_NORMAL() gl_check_error(true, __FILE__, __LINE__)
+
+ ogl_video_config const &m_ogl_config;
+
+ int32_t m_blittimer;
+ int m_width;
+ int m_height;
+ osd_dim m_blit_dim;
+
+ std::unique_ptr<osd_gl_context> m_gl_context;
+ std::unique_ptr<glsl_shader_info> m_shader_tool;
+
+ int m_initialized; // is everything well initialized, i.e. all GL stuff etc.
+ // 3D info (GL mode only)
+ ogl_texture_info * m_texhash[HASH_SIZE + OVERFLOW_SIZE];
+ int m_last_blendmode; // previous blendmode
+ int32_t m_texture_max_width; // texture maximum width
+ int32_t m_texture_max_height; // texture maximum height
+ int m_texpoweroftwo; // must textures be power-of-2 sized?
+ int m_usevbo; // runtime check if VBO is available
+ int m_usepbo; // runtime check if PBO is available
+ int m_usefbo; // runtime check if FBO is available
+ int m_useglsl; // runtime check if GLSL is available
+
+ GLhandleARB m_glsl_program[2*GLSL_SHADER_MAX]; // GLSL programs, or 0
+ int m_glsl_program_num; // number of GLSL programs
+ int m_glsl_program_mb2sc; // GLSL program idx, which transforms
+ // the mame-bitmap. screen-bitmap (size/rotation/..)
+ // All progs <= glsl_program_mb2sc using the mame bitmap
+ // as input, otherwise the screen bitmap.
+ // All progs >= glsl_program_mb2sc using the screen bitmap
+ // as output, otherwise the mame bitmap.
+ int m_usetexturerect; // use ARB_texture_rectangle for non-power-of-2, general use
+
+ int m_init_context; // initialize context before next draw
+
+ float m_last_hofs;
+ float m_last_vofs;
+
+ // Static vars from draogl_window_dra
+ int32_t m_surf_w;
+ int32_t m_surf_h;
+ GLfloat m_texVerticex[8];
+
+#if defined(USE_DISPATCH_GL)
+ std::unique_ptr<osd_gl_dispatch> gl_dispatch; // name is magic, can't be changed
+#endif
+
+ // OGL 1.3
+#if defined(GL_ARB_multitexture) && !defined(OSD_MAC)
+ PFNGLACTIVETEXTUREARBPROC m_glActiveTexture = nullptr;
+#else
+ PFNGLACTIVETEXTUREPROC m_glActiveTexture = nullptr;
+#endif
+
+ // VBO
+ PFNGLGENBUFFERSPROC m_glGenBuffers = nullptr;
+ PFNGLDELETEBUFFERSPROC m_glDeleteBuffers = nullptr;
+ PFNGLBINDBUFFERPROC m_glBindBuffer = nullptr;
+ PFNGLBUFFERDATAPROC m_glBufferData = nullptr;
+ PFNGLBUFFERSUBDATAPROC m_glBufferSubData = nullptr;
+
+ // PBO
+ PFNGLMAPBUFFERPROC m_glMapBuffer = nullptr;
+ PFNGLUNMAPBUFFERPROC m_glUnmapBuffer = nullptr;
+
+ // FBO
+ PFNGLISFRAMEBUFFEREXTPROC m_glIsFramebuffer = nullptr;
+ PFNGLBINDFRAMEBUFFEREXTPROC m_glBindFramebuffer = nullptr;
+ PFNGLDELETEFRAMEBUFFERSEXTPROC m_glDeleteFramebuffers = nullptr;
+ PFNGLGENFRAMEBUFFERSEXTPROC m_glGenFramebuffers = nullptr;
+ PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC m_glCheckFramebufferStatus = nullptr;
+ PFNGLFRAMEBUFFERTEXTURE2DEXTPROC m_glFramebufferTexture2D = nullptr;
+
+ static bool s_shown_video_info;
+};
+
//============================================================
// DEBUGGING
@@ -241,103 +546,22 @@ void renderer_ogl::set_blendmode(int blendmode)
}
}
-//============================================================
-// STATIC VARIABLES
-//============================================================
-
-// OGL 1.3
-#if defined(GL_ARB_multitexture) && !defined(OSD_MAC)
-static PFNGLACTIVETEXTUREARBPROC pfn_glActiveTexture = nullptr;
-#else
-static PFNGLACTIVETEXTUREPROC pfn_glActiveTexture = nullptr;
-#endif
-
-// VBO
-static PFNGLGENBUFFERSPROC pfn_glGenBuffers = nullptr;
-static PFNGLDELETEBUFFERSPROC pfn_glDeleteBuffers = nullptr;
-static PFNGLBINDBUFFERPROC pfn_glBindBuffer = nullptr;
-static PFNGLBUFFERDATAPROC pfn_glBufferData = nullptr;
-static PFNGLBUFFERSUBDATAPROC pfn_glBufferSubData = nullptr;
-
-// PBO
-static PFNGLMAPBUFFERPROC pfn_glMapBuffer = nullptr;
-static PFNGLUNMAPBUFFERPROC pfn_glUnmapBuffer = nullptr;
-
-// FBO
-static PFNGLISFRAMEBUFFEREXTPROC pfn_glIsFramebuffer = nullptr;
-static PFNGLBINDFRAMEBUFFEREXTPROC pfn_glBindFramebuffer = nullptr;
-static PFNGLDELETEFRAMEBUFFERSEXTPROC pfn_glDeleteFramebuffers = nullptr;
-static PFNGLGENFRAMEBUFFERSEXTPROC pfn_glGenFramebuffers = nullptr;
-static PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC pfn_glCheckFramebufferStatus = nullptr;
-static PFNGLFRAMEBUFFERTEXTURE2DEXTPROC pfn_glFramebufferTexture2D = nullptr;
-
-static int glsl_shader_feature = GLSL_SHADER_FEAT_PLAIN;
-
-//============================================================
-// Textures
-//============================================================
-
-static void texture_set_data(ogl_texture_info *texture, const render_texinfo *texsource, uint32_t flags);
+static int glsl_shader_feature = glsl_shader_info::FEAT_PLAIN; // FIXME: why is this static?
//============================================================
// Static Variables
//============================================================
bool renderer_ogl::s_shown_video_info = false;
-bool renderer_ogl::s_dll_loaded = false;
-
-void renderer_ogl::init(running_machine &machine)
-{
- s_dll_loaded = false;
-
- load_gl_lib(machine);
-#if defined(OSD_WINDOWS)
- osd_printf_verbose("Using Windows OpenGL driver\n");
-#else
- osd_printf_verbose("Using SDL multi-window OpenGL driver (SDL 2.0+)\n");
-#endif
-}
-
-//============================================================
-// CONSTRUCTOR & DESTRUCTOR
-//============================================================
-
-renderer_ogl::~renderer_ogl()
-{
- // free the memory in the window
- destroy_all_textures();
-
- delete m_gl_context;
- m_gl_context = nullptr;
-}
-
-void renderer_ogl::exit()
-{
- for (int i = 0; i < video_config.glsl_shader_mamebm_num; i++)
- {
- if (nullptr != video_config.glsl_shader_mamebm[i])
- {
- free(video_config.glsl_shader_mamebm[i]);
- video_config.glsl_shader_mamebm[i] = nullptr;
- }
- }
- for (int i =0; i < video_config.glsl_shader_scrn_num; i++)
- {
- if (nullptr != video_config.glsl_shader_scrn[i])
- {
- free(video_config.glsl_shader_scrn[i]);
- video_config.glsl_shader_scrn[i] = nullptr;
- }
- }
-}
//============================================================
// Load the OGL function addresses
//============================================================
-static void loadgl_functions(osd_gl_context *context)
+void renderer_ogl::loadgl_functions()
{
-#ifdef USE_DISPATCH_GL
+#if defined(USE_DISPATCH_GL)
+ gl_dispatch = std::make_unique<osd_gl_dispatch>();
int err_count = 0;
@@ -345,11 +569,11 @@ static void loadgl_functions(osd_gl_context *context)
* while func will be expanded to disp_p->glBegin
*/
- #define OSD_GL(ret,func,params) \
- if (!( func = (ret (APIENTRY *)params) context->getProcAddress( #func ) )) \
- { err_count++; osd_printf_error("GL function %s not found!\n", #func ); }
+ #define OSD_GL(ret, func, params) \
+ if (!m_gl_context->get_proc_address(func, #func)) \
+ { err_count++; osd_printf_error("GL function %s not found!\n", #func); }
- #define OSD_GL_UNUSED(ret,func,params)
+ #define OSD_GL_UNUSED(ret, func, params)
#define GET_GLFUNC 1
#include "modules/opengl/osd_opengl.h"
@@ -361,45 +585,6 @@ static void loadgl_functions(osd_gl_context *context)
#endif
}
-//============================================================
-// Load GL library
-//============================================================
-
-#ifdef USE_DISPATCH_GL
-osd_gl_dispatch *gl_dispatch = nullptr;
-#endif
-
-void renderer_ogl::load_gl_lib(running_machine &machine)
-{
- if (!s_dll_loaded)
- {
-#ifndef OSD_WINDOWS
-#ifdef USE_DISPATCH_GL
- /*
- * directfb and and x11 use this env var
- * SDL_VIDEO_GL_DRIVER
- */
- const char *stemp;
-
- stemp = downcast<sdl_options &>(machine.options()).gl_lib();
- if (stemp != nullptr && strcmp(stemp, OSDOPTVAL_AUTO) == 0)
- stemp = nullptr;
-
- if (SDL_GL_LoadLibrary(stemp) != 0) // Load library (default for e==nullptr
- {
- fatalerror("Unable to load opengl library: %s\n", stemp ? stemp : "<default>");
- }
- osd_printf_verbose("Loaded opengl shared library: %s\n", stemp ? stemp : "<default>");
- /* FIXME: must be freed as well */
-#endif
-#endif
-#ifdef USE_DISPATCH_GL
- gl_dispatch = new osd_gl_dispatch;
-#endif
- s_dll_loaded = true;
- }
-}
-
void renderer_ogl::initialize_gl()
{
int has_and_allow_texturerect = 0;
@@ -425,7 +610,7 @@ void renderer_ogl::initialize_gl()
m_usefbo = 0;
m_useglsl = 0;
- if (video_config.allowtexturerect && (strstr(extstr, "GL_ARB_texture_rectangle") || strstr(extstr, "GL_EXT_texture_rectangle")))
+ if (m_ogl_config.allowtexturerect && (strstr(extstr, "GL_ARB_texture_rectangle") || strstr(extstr, "GL_EXT_texture_rectangle")))
{
has_and_allow_texturerect = 1;
if (!s_shown_video_info)
@@ -435,7 +620,7 @@ void renderer_ogl::initialize_gl()
}
// does this card support non-power-of-two sized textures? (they're faster, so use them if possible)
- if ( !video_config.forcepow2texture && strstr(extstr, "GL_ARB_texture_non_power_of_two"))
+ if ( !m_ogl_config.forcepow2texture && strstr(extstr, "GL_ARB_texture_non_power_of_two"))
{
if (!s_shown_video_info)
{
@@ -465,7 +650,7 @@ void renderer_ogl::initialize_gl()
if (strstr(extstr, "GL_ARB_vertex_buffer_object"))
{
- m_usevbo = video_config.vbo;
+ m_usevbo = m_ogl_config.vbo;
if (!s_shown_video_info)
{
if(m_usevbo)
@@ -479,7 +664,7 @@ void renderer_ogl::initialize_gl()
{
if( m_usevbo )
{
- m_usepbo = video_config.pbo;
+ m_usepbo = m_ogl_config.pbo;
if (!s_shown_video_info)
{
if(m_usepbo)
@@ -522,7 +707,7 @@ void renderer_ogl::initialize_gl()
strstr(extstr, "GL_ARB_fragment_shader")
)
{
- m_useglsl = video_config.glsl;
+ m_useglsl = m_ogl_config.glsl;
if (!s_shown_video_info)
{
if(m_useglsl)
@@ -562,24 +747,22 @@ void renderer_ogl::initialize_gl()
int renderer_ogl::create()
{
- auto win = assert_window();
-
// create renderer
#if defined(OSD_WINDOWS)
- m_gl_context = new win_gl_context(std::static_pointer_cast<win_window_info>(win)->platform_window());
+ m_gl_context.reset(new win_gl_context(dynamic_cast<win_window_info &>(window()).platform_window()));
#elif defined(OSD_MAC)
// TODO
-// m_gl_context = new mac_gl_context(std::static_pointer_cast<mac_window_info>(win)->platform_window());
+// m_gl_context.reset(new mac_gl_context(dynamic_cast<mac_window_info &>(window()).platform_window()));
#else
- m_gl_context = new sdl_gl_context(std::static_pointer_cast<sdl_window_info>(win)->platform_window());
+ m_gl_context.reset(new sdl_gl_context(dynamic_cast<sdl_window_info &>(window()).platform_window()));
#endif
- if (m_gl_context->LastErrorMsg() != nullptr)
+ if (!*m_gl_context)
{
- osd_printf_error("%s\n", m_gl_context->LastErrorMsg());
+ char const *const msg = m_gl_context->last_error_message();
+ osd_printf_error("Creating OpenGL context failed: %s\n", msg ? msg : "unknown error");
return 1;
}
- m_gl_context->SetSwapInterval(video_config.waitvsync ? 1 : 0);
-
+ m_gl_context->set_swap_interval(video_config.waitvsync ? 1 : 0);
m_blittimer = 0;
m_surf_w = 0;
@@ -595,10 +778,9 @@ int renderer_ogl::create()
/* load any GL function addresses
* this must be done here because we need a context
*/
- loadgl_functions(m_gl_context);
+ loadgl_functions();
initialize_gl();
-
m_init_context = 0;
osd_printf_verbose("Leave renderer_ogl::create\n");
@@ -628,27 +810,15 @@ int renderer_ogl::xy_to_render_target(int x, int y, int *xt, int *yt)
void renderer_ogl::destroy_all_textures()
{
- ogl_texture_info *texture = nullptr;
- bool lock=false;
- int i;
- if ( !m_initialized )
+ if (!m_initialized)
return;
- auto win = try_getwindow();
-
- // During destroy this can get called
- // and the window is no longer available
- if (win == nullptr)
- return;
+ m_gl_context->make_current();
- m_gl_context->MakeCurrent();
-
- if(win->m_primlist)
- {
- lock=true;
- win->m_primlist->acquire_lock();
- }
+ bool const lock = bool(window().m_primlist);
+ if (lock)
+ window().m_primlist->acquire_lock();
glFinish();
@@ -656,41 +826,39 @@ void renderer_ogl::destroy_all_textures()
glFinish();
glDisableClientState(GL_VERTEX_ARRAY);
- i=0;
- while (i<HASH_SIZE+OVERFLOW_SIZE)
+ for (int i = 0; i < (HASH_SIZE + OVERFLOW_SIZE); ++i)
{
- texture = m_texhash[i];
- m_texhash[i] = nullptr;
- if (texture != nullptr)
+ ogl_texture_info *const texture = std::exchange(m_texhash[i], nullptr);
+ if (texture)
{
- if(m_usevbo)
+ if (m_usevbo)
{
- pfn_glDeleteBuffers( 1, &(texture->texCoordBufferName) );
+ m_glDeleteBuffers( 1, &(texture->texCoordBufferName) );
texture->texCoordBufferName=0;
}
- if(m_usepbo && texture->pbo)
+ if (m_usepbo && texture->pbo)
{
- pfn_glDeleteBuffers( 1, (GLuint *)&(texture->pbo) );
+ m_glDeleteBuffers( 1, (GLuint *)&(texture->pbo) );
texture->pbo=0;
}
- if( m_glsl_program_num > 1 )
+ if (m_glsl_program_num > 1)
{
assert(m_usefbo);
- pfn_glDeleteFramebuffers(2, (GLuint *)&texture->mpass_fbo_mamebm[0]);
+ m_glDeleteFramebuffers(2, (GLuint *)&texture->mpass_fbo_mamebm[0]);
glDeleteTextures(2, (GLuint *)&texture->mpass_texture_mamebm[0]);
}
- if ( m_glsl_program_mb2sc < m_glsl_program_num - 1 )
+ if (m_glsl_program_mb2sc < m_glsl_program_num - 1)
{
assert(m_usefbo);
- pfn_glDeleteFramebuffers(2, (GLuint *)&texture->mpass_fbo_scrn[0]);
+ m_glDeleteFramebuffers(2, (GLuint *)&texture->mpass_fbo_scrn[0]);
glDeleteTextures(2, (GLuint *)&texture->mpass_texture_scrn[0]);
}
glDeleteTextures(1, (GLuint *)&texture->texture);
- if ( texture->data_own )
+ if (texture->data_own)
{
free(texture->data);
texture->data=nullptr;
@@ -698,18 +866,14 @@ void renderer_ogl::destroy_all_textures()
}
delete texture;
}
- i++;
- }
- if ( m_useglsl )
- {
- glsl_shader_free(m_glsl);
- m_glsl = nullptr;
}
+ m_shader_tool.reset();
+
m_initialized = 0;
if (lock)
- win->m_primlist->release_lock();
+ window().m_primlist->release_lock();
}
//============================================================
// loadGLExtensions
@@ -745,178 +909,138 @@ void renderer_ogl::loadGLExtensions()
// Get Pointers To The GL Functions
// VBO:
- if( m_usevbo )
+ if (m_usevbo)
{
- pfn_glGenBuffers = (PFNGLGENBUFFERSPROC) m_gl_context->getProcAddress("glGenBuffers");
- pfn_glDeleteBuffers = (PFNGLDELETEBUFFERSPROC) m_gl_context->getProcAddress("glDeleteBuffers");
- pfn_glBindBuffer = (PFNGLBINDBUFFERPROC) m_gl_context->getProcAddress("glBindBuffer");
- pfn_glBufferData = (PFNGLBUFFERDATAPROC) m_gl_context->getProcAddress("glBufferData");
- pfn_glBufferSubData = (PFNGLBUFFERSUBDATAPROC) m_gl_context->getProcAddress("glBufferSubData");
+ m_gl_context->get_proc_address(m_glGenBuffers, "glGenBuffers");
+ m_gl_context->get_proc_address(m_glDeleteBuffers, "glDeleteBuffers");
+ m_gl_context->get_proc_address(m_glBindBuffer, "glBindBuffer");
+ m_gl_context->get_proc_address(m_glBufferData, "glBufferData");
+ m_gl_context->get_proc_address(m_glBufferSubData, "glBufferSubData");
}
// PBO:
- if ( m_usepbo )
+ if (m_usepbo)
{
- pfn_glMapBuffer = (PFNGLMAPBUFFERPROC) m_gl_context->getProcAddress("glMapBuffer");
- pfn_glUnmapBuffer= (PFNGLUNMAPBUFFERPROC) m_gl_context->getProcAddress("glUnmapBuffer");
+ m_gl_context->get_proc_address(m_glMapBuffer, "glMapBuffer");
+ m_gl_context->get_proc_address(m_glUnmapBuffer, "glUnmapBuffer");
}
// FBO:
- if ( m_usefbo )
+ if (m_usefbo)
{
- pfn_glIsFramebuffer = (PFNGLISFRAMEBUFFEREXTPROC) m_gl_context->getProcAddress("glIsFramebufferEXT");
- pfn_glBindFramebuffer = (PFNGLBINDFRAMEBUFFEREXTPROC) m_gl_context->getProcAddress("glBindFramebufferEXT");
- pfn_glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSEXTPROC) m_gl_context->getProcAddress("glDeleteFramebuffersEXT");
- pfn_glGenFramebuffers = (PFNGLGENFRAMEBUFFERSEXTPROC) m_gl_context->getProcAddress("glGenFramebuffersEXT");
- pfn_glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) m_gl_context->getProcAddress("glCheckFramebufferStatusEXT");
- pfn_glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC) m_gl_context->getProcAddress("glFramebufferTexture2DEXT");
+ m_gl_context->get_proc_address(m_glIsFramebuffer, "glIsFramebufferEXT");
+ m_gl_context->get_proc_address(m_glBindFramebuffer, "glBindFramebufferEXT");
+ m_gl_context->get_proc_address(m_glDeleteFramebuffers, "glDeleteFramebuffersEXT");
+ m_gl_context->get_proc_address(m_glGenFramebuffers, "glGenFramebuffersEXT");
+ m_gl_context->get_proc_address(m_glCheckFramebufferStatus, "glCheckFramebufferStatusEXT");
+ m_gl_context->get_proc_address(m_glFramebufferTexture2D, "glFramebufferTexture2DEXT");
}
- if ( m_usevbo &&
- ( !pfn_glGenBuffers || !pfn_glDeleteBuffers ||
- !pfn_glBindBuffer || !pfn_glBufferData || !pfn_glBufferSubData
- ) )
+ if (m_usevbo && (!m_glGenBuffers || !m_glDeleteBuffers || !m_glBindBuffer || !m_glBufferData || !m_glBufferSubData))
{
- m_usepbo=false;
+ m_usepbo = false;
if (_once)
{
- osd_printf_warning("OpenGL: VBO not supported, missing: ");
- if (!pfn_glGenBuffers)
- {
- osd_printf_warning("glGenBuffers, ");
- }
- if (!pfn_glDeleteBuffers)
- {
- osd_printf_warning("glDeleteBuffers");
- }
- if (!pfn_glBindBuffer)
- {
- osd_printf_warning("glBindBuffer, ");
- }
- if (!pfn_glBufferData)
- {
- osd_printf_warning("glBufferData, ");
- }
- if (!pfn_glBufferSubData)
- {
- osd_printf_warning("glBufferSubData, ");
- }
+ osd_printf_warning("OpenGL: VBO not supported, missing:");
+ if (!m_glGenBuffers)
+ osd_printf_warning(" glGenBuffers");
+ if (!m_glDeleteBuffers)
+ osd_printf_warning(" glDeleteBuffers");
+ if (!m_glBindBuffer)
+ osd_printf_warning(" glBindBuffer");
+ if (!m_glBufferData)
+ osd_printf_warning(" glBufferData");
+ if (!m_glBufferSubData)
+ osd_printf_warning(" glBufferSubData");
osd_printf_warning("\n");
}
- if ( m_usevbo )
+ if (m_usevbo)
{
if (_once)
- {
osd_printf_warning("OpenGL: PBO not supported, no VBO support.\n");
- }
- m_usepbo=false;
+ m_usepbo = false;
}
}
- if ( m_usepbo && ( !pfn_glMapBuffer || !pfn_glUnmapBuffer ) )
+ if (m_usepbo && (!m_glMapBuffer || !m_glUnmapBuffer))
{
- m_usepbo=false;
+ m_usepbo = false;
if (_once)
{
- osd_printf_warning("OpenGL: PBO not supported, missing: ");
- if (!pfn_glMapBuffer)
- {
- osd_printf_warning("glMapBuffer, ");
- }
- if (!pfn_glUnmapBuffer)
- {
- osd_printf_warning("glUnmapBuffer, ");
- }
+ osd_printf_warning("OpenGL: PBO not supported, missing:");
+ if (!m_glMapBuffer)
+ osd_printf_warning(" glMapBuffer");
+ if (!m_glUnmapBuffer)
+ osd_printf_warning(" glUnmapBuffer");
osd_printf_warning("\n");
}
}
if ( m_usefbo &&
- ( !pfn_glIsFramebuffer || !pfn_glBindFramebuffer || !pfn_glDeleteFramebuffers ||
- !pfn_glGenFramebuffers || !pfn_glCheckFramebufferStatus || !pfn_glFramebufferTexture2D
+ ( !m_glIsFramebuffer || !m_glBindFramebuffer || !m_glDeleteFramebuffers ||
+ !m_glGenFramebuffers || !m_glCheckFramebufferStatus || !m_glFramebufferTexture2D
))
{
- m_usefbo=false;
+ m_usefbo = false;
if (_once)
{
- osd_printf_warning("OpenGL: FBO not supported, missing: ");
- if (!pfn_glIsFramebuffer)
- {
- osd_printf_warning("pfn_glIsFramebuffer, ");
- }
- if (!pfn_glBindFramebuffer)
- {
- osd_printf_warning("pfn_glBindFramebuffer, ");
- }
- if (!pfn_glDeleteFramebuffers)
- {
- osd_printf_warning("pfn_glDeleteFramebuffers, ");
- }
- if (!pfn_glGenFramebuffers)
- {
- osd_printf_warning("pfn_glGenFramebuffers, ");
- }
- if (!pfn_glCheckFramebufferStatus)
- {
- osd_printf_warning("pfn_glCheckFramebufferStatus, ");
- }
- if (!pfn_glFramebufferTexture2D)
- {
- osd_printf_warning("pfn_glFramebufferTexture2D, ");
- }
+ osd_printf_warning("OpenGL: FBO not supported, missing:");
+ if (!m_glIsFramebuffer)
+ osd_printf_warning(" m_glIsFramebuffer");
+ if (!m_glBindFramebuffer)
+ osd_printf_warning(" m_glBindFramebuffer");
+ if (!m_glDeleteFramebuffers)
+ osd_printf_warning(" m_glDeleteFramebuffers");
+ if (!m_glGenFramebuffers)
+ osd_printf_warning(" m_glGenFramebuffers");
+ if (!m_glCheckFramebufferStatus)
+ osd_printf_warning(" m_glCheckFramebufferStatus");
+ if (!m_glFramebufferTexture2D)
+ osd_printf_warning(" m_glFramebufferTexture2D");
osd_printf_warning("\n");
}
}
if (_once)
{
- if ( m_usevbo )
- {
+ if (m_usevbo)
osd_printf_verbose("OpenGL: VBO supported\n");
- }
else
- {
osd_printf_warning("OpenGL: VBO not supported\n");
- }
- if ( m_usepbo )
- {
+ if (m_usepbo)
osd_printf_verbose("OpenGL: PBO supported\n");
- }
else
- {
osd_printf_warning("OpenGL: PBO not supported\n");
- }
- if ( m_usefbo )
- {
+ if (m_usefbo)
osd_printf_verbose("OpenGL: FBO supported\n");
- }
else
- {
osd_printf_warning("OpenGL: FBO not supported\n");
- }
}
- if ( m_useglsl )
+ if (m_useglsl)
{
#if defined(GL_ARB_multitexture) && !defined(OSD_MAC)
- pfn_glActiveTexture = (PFNGLACTIVETEXTUREARBPROC) m_gl_context->getProcAddress("glActiveTextureARB");
+ m_gl_context->get_proc_address(m_glActiveTexture, "glActiveTextureARB");
#else
- pfn_glActiveTexture = (PFNGLACTIVETEXTUREPROC) m_gl_context->getProcAddress("glActiveTexture");
+ m_gl_context->get_proc_address(m_glActiveTexture, "glActiveTexture");
#endif
- if (!pfn_glActiveTexture)
+ if (!m_glActiveTexture)
{
if (_once)
- {
osd_printf_warning("OpenGL: GLSL disabled, glActiveTexture(ARB) not supported\n");
- }
m_useglsl = 0;
}
}
- if ( m_useglsl )
+ if (m_useglsl)
{
- m_glsl = glsl_shader_init(m_gl_context);
- m_useglsl = (m_glsl != nullptr ? 1 : 0);
+ m_shader_tool = glsl_shader_info::init(
+ *m_gl_context
+#if defined(USE_DISPATCH_GL)
+ , gl_dispatch.get()
+#endif
+ );
+ m_useglsl = (m_shader_tool ? 1 : 0);
if ( ! m_useglsl )
{
@@ -927,9 +1051,9 @@ void renderer_ogl::loadGLExtensions()
}
}
- if ( m_useglsl )
+ if (m_useglsl)
{
- if (assert_window()->prescale() != 1 )
+ if (window().prescale() != 1 )
{
m_useglsl = 0;
if (_once)
@@ -939,15 +1063,14 @@ void renderer_ogl::loadGLExtensions()
}
}
- if ( m_useglsl )
+ if (m_useglsl)
{
- int i;
video_config.filter = false;
- glsl_shader_feature = GLSL_SHADER_FEAT_PLAIN;
+ glsl_shader_feature = glsl_shader_info::FEAT_PLAIN;
m_glsl_program_num = 0;
m_glsl_program_mb2sc = 0;
- for(i=0; i<video_config.glsl_shader_mamebm_num; i++)
+ for (int i=0; i<m_ogl_config.glsl_shader_mamebm_num; i++)
{
if ( !m_usefbo && m_glsl_program_num==1 )
{
@@ -958,60 +1081,65 @@ void renderer_ogl::loadGLExtensions()
break;
}
- if ( glsl_shader_add_mamebm(m_glsl, video_config.glsl_shader_mamebm[i], m_glsl_program_num) )
+ if ( m_shader_tool->add_mamebm(m_ogl_config.glsl_shader_mamebm[i].c_str(), m_glsl_program_num) )
{
osd_printf_error("OpenGL: GLSL loading mame bitmap shader %d failed (%s)\n",
- i, video_config.glsl_shader_mamebm[i]);
- } else {
- glsl_shader_feature = GLSL_SHADER_FEAT_CUSTOM;
+ i, m_ogl_config.glsl_shader_mamebm[i]);
+ }
+ else
+ {
+ glsl_shader_feature = glsl_shader_info::FEAT_CUSTOM;
if (_once)
{
osd_printf_verbose("OpenGL: GLSL using mame bitmap shader filter %d: '%s'\n",
- m_glsl_program_num, video_config.glsl_shader_mamebm[i]);
+ m_glsl_program_num, m_ogl_config.glsl_shader_mamebm[i]);
}
m_glsl_program_mb2sc = m_glsl_program_num; // the last mame_bitmap (mb) shader does it.
m_glsl_program_num++;
}
}
- if ( video_config.glsl_shader_scrn_num > 0 && m_glsl_program_num==0 )
+ if ( m_ogl_config.glsl_shader_scrn_num > 0 && m_glsl_program_num==0 )
{
osd_printf_verbose("OpenGL: GLSL cannot use screen bitmap shader without bitmap shader\n");
}
- for(i=0; m_usefbo && m_glsl_program_num>0 && i<video_config.glsl_shader_scrn_num; i++)
+ for(int i=0; m_usefbo && m_glsl_program_num>0 && i<m_ogl_config.glsl_shader_scrn_num; i++)
{
- if ( glsl_shader_add_scrn(m_glsl, video_config.glsl_shader_scrn[i],
- m_glsl_program_num-1-m_glsl_program_mb2sc) )
+ if ( m_shader_tool->add_scrn(m_ogl_config.glsl_shader_scrn[i].c_str(), m_glsl_program_num-1-m_glsl_program_mb2sc) )
{
osd_printf_error("OpenGL: GLSL loading screen bitmap shader %d failed (%s)\n",
- i, video_config.glsl_shader_scrn[i]);
- } else {
+ i, m_ogl_config.glsl_shader_scrn[i]);
+ }
+ else
+ {
if (_once)
{
osd_printf_verbose("OpenGL: GLSL using screen bitmap shader filter %d: '%s'\n",
- m_glsl_program_num, video_config.glsl_shader_scrn[i]);
+ m_glsl_program_num, m_ogl_config.glsl_shader_scrn[i]);
}
m_glsl_program_num++;
}
}
if ( 0==m_glsl_program_num &&
- 0 <= video_config.glsl_filter && video_config.glsl_filter < GLSL_SHADER_FEAT_INT_NUMBER )
+ 0 <= m_ogl_config.glsl_filter && m_ogl_config.glsl_filter < glsl_shader_info::FEAT_INT_NUMBER )
{
m_glsl_program_mb2sc = m_glsl_program_num; // the last mame_bitmap (mb) shader does it.
m_glsl_program_num++;
- glsl_shader_feature = video_config.glsl_filter;
+ glsl_shader_feature = m_ogl_config.glsl_filter;
if (_once)
{
osd_printf_verbose("OpenGL: GLSL using shader filter '%s', idx: %d, num %d (vid filter: %d)\n",
- glsl_shader_get_filter_name_mamebm(glsl_shader_feature),
+ m_shader_tool->get_filter_name_mamebm(glsl_shader_feature),
glsl_shader_feature, m_glsl_program_num, video_config.filter);
}
}
- } else {
+ }
+ else
+ {
if (_once)
{
osd_printf_verbose("OpenGL: using vid filter: %d\n", video_config.filter);
@@ -1031,16 +1159,7 @@ int renderer_ogl::draw(const int update)
float vofs, hofs;
int pendingPrimitive=GL_NO_PRIMITIVE, curPrimitive=GL_NO_PRIMITIVE;
-#ifdef TOBEMIGRATED
- if (video_config.novideo)
- {
- return 0;
- }
-#endif
-
- auto win = assert_window();
-
- osd_dim wdim = win->get_size();
+ osd_dim wdim = window().get_size();
if (has_flags(FI_CHANGED) || (wdim.width() != m_width) || (wdim.height() != m_height))
{
@@ -1052,7 +1171,7 @@ int renderer_ogl::draw(const int update)
clear_flags(FI_CHANGED);
}
- m_gl_context->MakeCurrent();
+ m_gl_context->make_current();
if (m_init_context)
{
@@ -1192,16 +1311,15 @@ int renderer_ogl::draw(const int update)
hofs = (cw - m_blit_dim.width()) / 2.0f;
}
}
-#else
#endif
m_last_hofs = hofs;
m_last_vofs = vofs;
- win->m_primlist->acquire_lock();
+ window().m_primlist->acquire_lock();
// now draw
- for (render_primitive &prim : *win->m_primlist)
+ for (render_primitive &prim : *window().m_primlist)
{
int i;
@@ -1236,7 +1354,10 @@ int renderer_ogl::draw(const int update)
if(pendingPrimitive!=curPrimitive)
{
- glLineWidth(prim.width);
+ if (curPrimitive==GL_POINTS)
+ glPointSize(prim.width);
+ else
+ glLineWidth(prim.width);
glBegin(curPrimitive);
pendingPrimitive=curPrimitive;
}
@@ -1407,10 +1528,10 @@ int renderer_ogl::draw(const int update)
pendingPrimitive=GL_NO_PRIMITIVE;
}
- win->m_primlist->release_lock();
+ window().m_primlist->release_lock();
m_init_context = 0;
- m_gl_context->SwapBuffer();
+ m_gl_context->swap_buffer();
return 0;
}
@@ -1543,9 +1664,8 @@ void renderer_ogl::texture_compute_size_subroutine(ogl_texture_info *texture, ui
while (texture->yprescale > 1 && height_create * texture->yprescale > m_texture_max_height)
texture->yprescale--;
- auto win = assert_window();
- if (PRIMFLAG_GET_SCREENTEX(flags) && (texture->xprescale != win->prescale() || texture->yprescale != win->prescale()))
- osd_printf_warning("SDL: adjusting prescale from %dx%d to %dx%d\n", win->prescale(), win->prescale(), texture->xprescale, texture->yprescale);
+ if (PRIMFLAG_GET_SCREENTEX(flags) && (texture->xprescale != window().prescale() || texture->yprescale != window().prescale()))
+ osd_printf_warning("SDL: adjusting prescale from %dx%d to %dx%d\n", window().prescale(), window().prescale(), texture->xprescale, texture->yprescale);
width *= texture->xprescale;
height *= texture->yprescale;
@@ -1640,10 +1760,9 @@ void renderer_ogl::texture_compute_size_type(const render_texinfo *texsource, og
// texture_create
//============================================================
-static int gl_checkFramebufferStatus()
+int renderer_ogl::gl_checkFramebufferStatus() const
{
- GLenum status;
- status=(GLenum)pfn_glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT);
+ GLenum const status = (GLenum)m_glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT);
switch(status) {
case GL_FRAMEBUFFER_COMPLETE_EXT:
return 0;
@@ -1683,14 +1802,14 @@ static int gl_checkFramebufferStatus()
return -1;
}
-static int texture_fbo_create(uint32_t text_unit, uint32_t text_name, uint32_t fbo_name, int width, int height)
+int renderer_ogl::texture_fbo_create(uint32_t text_unit, uint32_t text_name, uint32_t fbo_name, int width, int height) const
{
- pfn_glActiveTexture(text_unit);
- pfn_glBindFramebuffer(GL_FRAMEBUFFER_EXT, fbo_name);
+ m_glActiveTexture(text_unit);
+ m_glBindFramebuffer(GL_FRAMEBUFFER_EXT, fbo_name);
glBindTexture(GL_TEXTURE_2D, text_name);
{
GLint _width, _height;
- if ( gl_texture_check_size(GL_TEXTURE_2D, 0, GL_RGBA8, width, height,
+ if ( m_shader_tool->texture_check_size(GL_TEXTURE_2D, 0, GL_RGBA8, width, height,
0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, &_width, &_height, 1) )
{
osd_printf_error("cannot create fbo texture, req: %dx%d, avail: %dx%d - bail out\n",
@@ -1708,7 +1827,7 @@ static int texture_fbo_create(uint32_t text_unit, uint32_t text_name, uint32_t f
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- pfn_glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
+ m_glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_2D, text_name, 0);
if ( gl_checkFramebufferStatus() )
@@ -1745,51 +1864,49 @@ int renderer_ogl::texture_shader_create(const render_texinfo *texsource, ogl_tex
for(i=0; i<m_glsl_program_num; i++)
{
if ( i<=m_glsl_program_mb2sc )
- {
- m_glsl_program[i] = glsl_shader_get_program_mamebm(glsl_shader_feature, i);
- } else {
- m_glsl_program[i] = glsl_shader_get_program_scrn(i-1-m_glsl_program_mb2sc);
- }
- pfn_glUseProgramObjectARB(m_glsl_program[i]);
+ m_glsl_program[i] = m_shader_tool->get_program_mamebm(glsl_shader_feature, i);
+ else
+ m_glsl_program[i] = m_shader_tool->get_program_scrn(i-1-m_glsl_program_mb2sc);
+ m_shader_tool->pfn_glUseProgramObjectARB(m_glsl_program[i]);
if ( i<=m_glsl_program_mb2sc )
{
// GL_TEXTURE0 GLSL Uniforms
- uniform_location = pfn_glGetUniformLocationARB(m_glsl_program[i], "color_texture");
- pfn_glUniform1iARB(uniform_location, 0);
+ uniform_location = m_shader_tool->pfn_glGetUniformLocationARB(m_glsl_program[i], "color_texture");
+ m_shader_tool->pfn_glUniform1iARB(uniform_location, 0);
GL_CHECK_ERROR_NORMAL();
}
{
GLfloat color_texture_sz[2] = { (GLfloat)texture->rawwidth, (GLfloat)texture->rawheight };
- uniform_location = pfn_glGetUniformLocationARB(m_glsl_program[i], "color_texture_sz");
- pfn_glUniform2fvARB(uniform_location, 1, &(color_texture_sz[0]));
+ uniform_location = m_shader_tool->pfn_glGetUniformLocationARB(m_glsl_program[i], "color_texture_sz");
+ m_shader_tool->pfn_glUniform2fvARB(uniform_location, 1, &(color_texture_sz[0]));
GL_CHECK_ERROR_NORMAL();
}
GLfloat color_texture_pow2_sz[2] = { (GLfloat)texture->rawwidth_create, (GLfloat)texture->rawheight_create };
- uniform_location = pfn_glGetUniformLocationARB(m_glsl_program[i], "color_texture_pow2_sz");
- pfn_glUniform2fvARB(uniform_location, 1, &(color_texture_pow2_sz[0]));
+ uniform_location = m_shader_tool->pfn_glGetUniformLocationARB(m_glsl_program[i], "color_texture_pow2_sz");
+ m_shader_tool->pfn_glUniform2fvARB(uniform_location, 1, &(color_texture_pow2_sz[0]));
GL_CHECK_ERROR_NORMAL();
GLfloat screen_texture_sz[2] = { (GLfloat) m_blit_dim.width(), (GLfloat) m_blit_dim.height() };
- uniform_location = pfn_glGetUniformLocationARB(m_glsl_program[i], "screen_texture_sz");
- pfn_glUniform2fvARB(uniform_location, 1, &(screen_texture_sz[0]));
+ uniform_location = m_shader_tool->pfn_glGetUniformLocationARB(m_glsl_program[i], "screen_texture_sz");
+ m_shader_tool->pfn_glUniform2fvARB(uniform_location, 1, &(screen_texture_sz[0]));
GL_CHECK_ERROR_NORMAL();
GLfloat screen_texture_pow2_sz[2] = { (GLfloat)surf_w_pow2, (GLfloat)surf_h_pow2 };
- uniform_location = pfn_glGetUniformLocationARB(m_glsl_program[i], "screen_texture_pow2_sz");
- pfn_glUniform2fvARB(uniform_location, 1, &(screen_texture_pow2_sz[0]));
+ uniform_location = m_shader_tool->pfn_glGetUniformLocationARB(m_glsl_program[i], "screen_texture_pow2_sz");
+ m_shader_tool->pfn_glUniform2fvARB(uniform_location, 1, &(screen_texture_pow2_sz[0]));
GL_CHECK_ERROR_NORMAL();
}
- pfn_glUseProgramObjectARB(m_glsl_program[0]); // start with 1st shader
+ m_shader_tool->pfn_glUseProgramObjectARB(m_glsl_program[0]); // start with 1st shader
if( m_glsl_program_num > 1 )
{
// multipass mode
// GL_TEXTURE2/GL_TEXTURE3
- pfn_glGenFramebuffers(2, (GLuint *)&texture->mpass_fbo_mamebm[0]);
+ m_glGenFramebuffers(2, (GLuint *)&texture->mpass_fbo_mamebm[0]);
glGenTextures(2, (GLuint *)&texture->mpass_texture_mamebm[0]);
for (i=0; i<2; i++)
@@ -1803,7 +1920,7 @@ int renderer_ogl::texture_shader_create(const render_texinfo *texsource, ogl_tex
}
}
- pfn_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
+ m_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
osd_printf_verbose("GL texture: mpass mame-bmp 2x %dx%d (pow2 %dx%d)\n",
texture->rawwidth, texture->rawheight, texture->rawwidth_create, texture->rawheight_create);
@@ -1813,7 +1930,7 @@ int renderer_ogl::texture_shader_create(const render_texinfo *texsource, ogl_tex
{
// multipass mode
// GL_TEXTURE2/GL_TEXTURE3
- pfn_glGenFramebuffers(2, (GLuint *)&texture->mpass_fbo_scrn[0]);
+ m_glGenFramebuffers(2, (GLuint *)&texture->mpass_fbo_scrn[0]);
glGenTextures(2, (GLuint *)&texture->mpass_texture_scrn[0]);
for (i=0; i<2; i++)
@@ -1834,14 +1951,14 @@ int renderer_ogl::texture_shader_create(const render_texinfo *texsource, ogl_tex
// GL_TEXTURE0
// get a name for this texture
glGenTextures(1, (GLuint *)&texture->texture);
- pfn_glActiveTexture(GL_TEXTURE0);
+ m_glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture->texture);
glPixelStorei(GL_UNPACK_ROW_LENGTH, texture->rawwidth_create);
uint32_t * dummy = nullptr;
GLint _width, _height;
- if ( gl_texture_check_size(GL_TEXTURE_2D, 0, GL_RGBA8,
+ if ( m_shader_tool->texture_check_size(GL_TEXTURE_2D, 0, GL_RGBA8,
texture->rawwidth_create, texture->rawheight_create,
0,
GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
@@ -1863,7 +1980,7 @@ int renderer_ogl::texture_shader_create(const render_texinfo *texsource, ogl_tex
if ((PRIMFLAG_GET_SCREENTEX(flags)) && video_config.filter)
{
- assert( glsl_shader_feature == GLSL_SHADER_FEAT_PLAIN );
+ assert( glsl_shader_feature == glsl_shader_info::FEAT_PLAIN );
// screen textures get the user's choice of filtering
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
@@ -1898,7 +2015,11 @@ ogl_texture_info *renderer_ogl::texture_create(const render_texinfo *texsource,
ogl_texture_info *texture;
// allocate a new texture
- texture = new ogl_texture_info;
+ texture = new ogl_texture_info(
+#if defined(USE_DISPATCH_GL)
+ gl_dispatch.get()
+#endif
+ );
// fill in the core data
texture->hash = texture_compute_hash(texsource, flags);
@@ -1907,9 +2028,8 @@ ogl_texture_info *renderer_ogl::texture_create(const render_texinfo *texsource,
texture->texinfo.seqid = -1; // force set data
if (PRIMFLAG_GET_SCREENTEX(flags))
{
- auto win = assert_window();
- texture->xprescale = win->prescale();
- texture->yprescale = win->prescale();
+ texture->xprescale = window().prescale();
+ texture->yprescale = window().prescale();
}
else
{
@@ -1963,7 +2083,7 @@ ogl_texture_info *renderer_ogl::texture_create(const render_texinfo *texsource,
if ( texture->type != TEXTURE_TYPE_SHADER && m_useglsl)
{
- pfn_glUseProgramObjectARB(0); // back to fixed function pipeline
+ m_shader_tool->pfn_glUseProgramObjectARB(0); // back to fixed function pipeline
}
if ( texture->type==TEXTURE_TYPE_SHADER )
@@ -2028,12 +2148,12 @@ ogl_texture_info *renderer_ogl::texture_create(const render_texinfo *texsource,
assert(m_usepbo);
// create the PBO
- pfn_glGenBuffers(1, (GLuint *)&texture->pbo);
+ m_glGenBuffers(1, (GLuint *)&texture->pbo);
- pfn_glBindBuffer( GL_PIXEL_UNPACK_BUFFER_ARB, texture->pbo);
+ m_glBindBuffer( GL_PIXEL_UNPACK_BUFFER_ARB, texture->pbo);
// set up the PBO dimension, ..
- pfn_glBufferData(GL_PIXEL_UNPACK_BUFFER_ARB,
+ m_glBufferData(GL_PIXEL_UNPACK_BUFFER_ARB,
texture->rawwidth * texture->rawheight * sizeof(uint32_t),
nullptr, GL_STREAM_DRAW);
}
@@ -2063,10 +2183,10 @@ ogl_texture_info *renderer_ogl::texture_create(const render_texinfo *texsource,
if (m_usevbo)
{
// Generate And Bind The Texture Coordinate Buffer
- pfn_glGenBuffers( 1, &(texture->texCoordBufferName) );
- pfn_glBindBuffer( GL_ARRAY_BUFFER_ARB, texture->texCoordBufferName );
+ m_glGenBuffers( 1, &(texture->texCoordBufferName) );
+ m_glBindBuffer( GL_ARRAY_BUFFER_ARB, texture->texCoordBufferName );
// Load The Data
- pfn_glBufferData( GL_ARRAY_BUFFER_ARB, 4*2*sizeof(GLfloat), texture->texCoord, GL_STREAM_DRAW );
+ m_glBufferData( GL_ARRAY_BUFFER_ARB, 4*2*sizeof(GLfloat), texture->texCoord, GL_STREAM_DRAW );
glTexCoordPointer( 2, GL_FLOAT, 0, (char *) nullptr ); // we are using ARB VBO buffers
}
else
@@ -2327,14 +2447,14 @@ static inline void copyline_yuy16_to_argb(uint32_t *dst, const uint16_t *src, in
// texture_set_data
//============================================================
-static void texture_set_data(ogl_texture_info *texture, const render_texinfo *texsource, uint32_t flags)
+void renderer_ogl::texture_set_data(ogl_texture_info *texture, const render_texinfo *texsource, uint32_t flags) const
{
if ( texture->type == TEXTURE_TYPE_DYNAMIC )
{
assert(texture->pbo);
assert(!texture->nocopy);
- texture->data = (uint32_t *) pfn_glMapBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY);
+ texture->data = (uint32_t *) m_glMapBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY);
}
// note that nocopy and borderpix are mutually exclusive, IOW
@@ -2401,7 +2521,7 @@ static void texture_set_data(ogl_texture_info *texture, const render_texinfo *te
if ( texture->type == TEXTURE_TYPE_SHADER )
{
- pfn_glActiveTexture(GL_TEXTURE0);
+ m_glActiveTexture(GL_TEXTURE0);
glBindTexture(texture->texTarget, texture->texture);
if (texture->nocopy)
@@ -2420,7 +2540,7 @@ static void texture_set_data(ogl_texture_info *texture, const render_texinfo *te
glPixelStorei(GL_UNPACK_ROW_LENGTH, texture->rawwidth);
// unmap the buffer from the CPU space so it can DMA
- pfn_glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER_ARB);
+ m_glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER_ARB);
// kick off the DMA
glTexSubImage2D(texture->texTarget, 0, 0, 0, texture->rawwidth, texture->rawheight,
@@ -2570,12 +2690,12 @@ void renderer_ogl::texture_mpass_flip(ogl_texture_info *texture, int shaderIdx)
if ( shaderIdx>0 )
{
int uniform_location;
- uniform_location = pfn_glGetUniformLocationARB(m_glsl_program[shaderIdx], "mpass_texture");
- pfn_glUniform1iARB(uniform_location, texture->mpass_textureunit[mpass_src_idx]-GL_TEXTURE0);
+ uniform_location = m_shader_tool->pfn_glGetUniformLocationARB(m_glsl_program[shaderIdx], "mpass_texture");
+ m_shader_tool->pfn_glUniform1iARB(uniform_location, texture->mpass_textureunit[mpass_src_idx]-GL_TEXTURE0);
GL_CHECK_ERROR_NORMAL();
}
- pfn_glActiveTexture(texture->mpass_textureunit[mpass_src_idx]);
+ m_glActiveTexture(texture->mpass_textureunit[mpass_src_idx]);
if ( shaderIdx<=m_glsl_program_mb2sc )
{
glBindTexture(texture->texTarget, texture->mpass_texture_mamebm[mpass_src_idx]);
@@ -2584,22 +2704,22 @@ void renderer_ogl::texture_mpass_flip(ogl_texture_info *texture, int shaderIdx)
{
glBindTexture(texture->texTarget, texture->mpass_texture_scrn[mpass_src_idx]);
}
- pfn_glActiveTexture(texture->mpass_textureunit[texture->mpass_dest_idx]);
+ m_glActiveTexture(texture->mpass_textureunit[texture->mpass_dest_idx]);
glBindTexture(texture->texTarget, 0);
- pfn_glActiveTexture(texture->mpass_textureunit[texture->mpass_dest_idx]);
+ m_glActiveTexture(texture->mpass_textureunit[texture->mpass_dest_idx]);
if ( shaderIdx<m_glsl_program_num-1 )
{
if ( shaderIdx>=m_glsl_program_mb2sc )
{
glBindTexture(texture->texTarget, texture->mpass_texture_scrn[texture->mpass_dest_idx]);
- pfn_glBindFramebuffer(GL_FRAMEBUFFER_EXT, texture->mpass_fbo_scrn[texture->mpass_dest_idx]);
+ m_glBindFramebuffer(GL_FRAMEBUFFER_EXT, texture->mpass_fbo_scrn[texture->mpass_dest_idx]);
}
else
{
glBindTexture(texture->texTarget, texture->mpass_texture_mamebm[texture->mpass_dest_idx]);
- pfn_glBindFramebuffer(GL_FRAMEBUFFER_EXT, texture->mpass_fbo_mamebm[texture->mpass_dest_idx]);
+ m_glBindFramebuffer(GL_FRAMEBUFFER_EXT, texture->mpass_fbo_mamebm[texture->mpass_dest_idx]);
}
if ( shaderIdx==0 )
@@ -2620,7 +2740,7 @@ void renderer_ogl::texture_mpass_flip(ogl_texture_info *texture, int shaderIdx)
else
{
glBindTexture(texture->texTarget, 0);
- pfn_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
+ m_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
if ( m_glsl_program_mb2sc == m_glsl_program_num-1 )
{
@@ -2628,7 +2748,7 @@ void renderer_ogl::texture_mpass_flip(ogl_texture_info *texture, int shaderIdx)
GL_CHECK_ERROR_NORMAL();
}
- pfn_glActiveTexture(GL_TEXTURE0);
+ m_glActiveTexture(GL_TEXTURE0);
glBindTexture(texture->texTarget, 0);
}
}
@@ -2649,8 +2769,8 @@ void renderer_ogl::texture_shader_update(ogl_texture_info *texture, render_conta
vid_attributes[1] = settings.m_contrast;
vid_attributes[2] = settings.m_brightness;
vid_attributes[3] = 0.0f;
- uniform_location = pfn_glGetUniformLocationARB(m_glsl_program[shaderIdx], "vid_attributes");
- pfn_glUniform4fvARB(uniform_location, 1, &(vid_attributes[shaderIdx]));
+ uniform_location = m_shader_tool->pfn_glGetUniformLocationARB(m_glsl_program[shaderIdx], "vid_attributes");
+ m_shader_tool->pfn_glUniform4fvARB(uniform_location, 1, &(vid_attributes[shaderIdx]));
if ( GL_CHECK_ERROR_QUIET() ) {
osd_printf_verbose("GLSL: could not set 'vid_attributes' for shader prog idx %d\n", shaderIdx);
}
@@ -2671,12 +2791,12 @@ ogl_texture_info * renderer_ogl::texture_update(const render_primitive *prim, in
{
if ( texture->type == TEXTURE_TYPE_SHADER )
{
- pfn_glUseProgramObjectARB(m_glsl_program[shaderIdx]); // back to our shader
+ m_shader_tool->pfn_glUseProgramObjectARB(m_glsl_program[shaderIdx]); // back to our shader
}
else if ( texture->type == TEXTURE_TYPE_DYNAMIC )
{
assert ( m_usepbo ) ;
- pfn_glBindBuffer( GL_PIXEL_UNPACK_BUFFER_ARB, texture->pbo);
+ m_glBindBuffer( GL_PIXEL_UNPACK_BUFFER_ARB, texture->pbo);
glEnable(texture->texTarget);
}
else
@@ -2716,9 +2836,9 @@ ogl_texture_info * renderer_ogl::texture_update(const render_primitive *prim, in
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
if(m_usevbo)
{
- pfn_glBindBuffer( GL_ARRAY_BUFFER_ARB, texture->texCoordBufferName );
+ m_glBindBuffer( GL_ARRAY_BUFFER_ARB, texture->texCoordBufferName );
// Load The Data
- pfn_glBufferSubData( GL_ARRAY_BUFFER_ARB, 0, 4*2*sizeof(GLfloat), texture->texCoord );
+ m_glBufferSubData( GL_ARRAY_BUFFER_ARB, 0, 4*2*sizeof(GLfloat), texture->texCoord );
glTexCoordPointer( 2, GL_FLOAT, 0, (char *) nullptr ); // we are using ARB VBO buffers
}
else
@@ -2735,34 +2855,41 @@ void renderer_ogl::texture_disable(ogl_texture_info * texture)
if ( texture->type == TEXTURE_TYPE_SHADER )
{
assert ( m_useglsl );
- pfn_glUseProgramObjectARB(0); // back to fixed function pipeline
- } else if ( texture->type == TEXTURE_TYPE_DYNAMIC )
+ m_shader_tool->pfn_glUseProgramObjectARB(0); // back to fixed function pipeline
+ }
+ else if ( texture->type == TEXTURE_TYPE_DYNAMIC )
{
- pfn_glBindBuffer( GL_PIXEL_UNPACK_BUFFER_ARB, 0);
+ m_glBindBuffer( GL_PIXEL_UNPACK_BUFFER_ARB, 0);
glDisable(texture->texTarget);
- } else {
+ }
+ else
+ {
glDisable(texture->texTarget);
}
}
void renderer_ogl::texture_all_disable()
{
- if ( m_useglsl )
+ if (m_useglsl)
{
- pfn_glUseProgramObjectARB(0); // back to fixed function pipeline
+ m_shader_tool->pfn_glUseProgramObjectARB(0); // back to fixed function pipeline
- pfn_glActiveTexture(GL_TEXTURE3);
+ m_glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_2D, 0);
- if ( m_usefbo ) pfn_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
- pfn_glActiveTexture(GL_TEXTURE2);
+ if (m_usefbo)
+ m_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
+ m_glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, 0);
- if ( m_usefbo ) pfn_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
- pfn_glActiveTexture(GL_TEXTURE1);
+ if (m_usefbo)
+ m_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
+ m_glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, 0);
- if ( m_usefbo ) pfn_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
- pfn_glActiveTexture(GL_TEXTURE0);
+ if (m_usefbo)
+ m_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
+ m_glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, 0);
- if ( m_usefbo ) pfn_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
+ if (m_usefbo)
+ m_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
}
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
@@ -2775,10 +2902,140 @@ void renderer_ogl::texture_all_disable()
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
if(m_usevbo)
{
- pfn_glBindBuffer( GL_ARRAY_BUFFER_ARB, 0); // unbind ..
+ m_glBindBuffer( GL_ARRAY_BUFFER_ARB, 0); // unbind ..
}
if ( m_usepbo )
{
- pfn_glBindBuffer( GL_PIXEL_UNPACK_BUFFER_ARB, 0);
+ m_glBindBuffer( GL_PIXEL_UNPACK_BUFFER_ARB, 0);
+ }
+}
+
+
+class video_opengl : public osd_module, public render_module
+{
+public:
+ video_opengl()
+ : osd_module(OSD_RENDERER_PROVIDER, "opengl")
+#if defined(USE_DISPATCH_GL)
+ , m_dll_loaded(false)
+#endif
+ {
+ }
+ ~video_opengl() { exit(); }
+
+ virtual int init(osd_interface &osd, osd_options const &options) override;
+ virtual void exit() override;
+
+ virtual std::unique_ptr<osd_renderer> create(osd_window &window) override;
+
+protected:
+ virtual unsigned flags() const override { return FLAG_INTERACTIVE | FLAG_SDL_NEEDS_OPENGL; }
+
+private:
+ ogl_video_config m_ogl_config;
+#if defined(USE_DISPATCH_GL)
+ bool m_dll_loaded;
+#endif
+};
+
+int video_opengl::init(osd_interface &osd, osd_options const &options)
+{
+ m_ogl_config.vbo = options.gl_vbo();
+ m_ogl_config.pbo = options.gl_pbo();
+ m_ogl_config.allowtexturerect = !options.gl_no_texture_rect();
+ m_ogl_config.forcepow2texture = options.gl_force_pow2_texture();
+ m_ogl_config.glsl = options.gl_glsl();
+ if (m_ogl_config.glsl)
+ {
+ m_ogl_config.glsl_filter = options.glsl_filter();
+
+ m_ogl_config.glsl_shader_mamebm_num = 0;
+ for (int i = 0; i < GLSL_SHADER_MAX; i++)
+ {
+ char const *const stemp = options.shader_mame(i);
+ if (stemp && *stemp && strcmp(stemp, OSDOPTVAL_NONE))
+ m_ogl_config.glsl_shader_mamebm[m_ogl_config.glsl_shader_mamebm_num++] = stemp;
+ }
+
+ m_ogl_config.glsl_shader_scrn_num = 0;
+ for (int i = 0; i < GLSL_SHADER_MAX; i++)
+ {
+ char const *const stemp = options.shader_screen(i);
+ if (stemp && *stemp && strcmp(stemp, OSDOPTVAL_NONE))
+ m_ogl_config.glsl_shader_scrn[m_ogl_config.glsl_shader_scrn_num++] = stemp;
+ }
+ }
+ else
+ {
+ m_ogl_config.glsl_filter = 0;
+
+ m_ogl_config.glsl_shader_mamebm_num = 0;
+ for (std::string &s : m_ogl_config.glsl_shader_mamebm)
+ s.clear();
+
+ m_ogl_config.glsl_shader_scrn_num = 0;
+ for (std::string &s : m_ogl_config.glsl_shader_scrn)
+ s.clear();
+ }
+
+#if defined(USE_DISPATCH_GL)
+#if defined(OSD_SDL)
+ if (!m_dll_loaded)
+ {
+ // directfb and and x11 use this env var: SDL_VIDEO_GL_DRIVER
+ char const *libname = dynamic_cast<sdl_options const &>(options).gl_lib();
+ if (libname && (!*libname || !std::strcmp(libname, OSDOPTVAL_AUTO)))
+ libname = nullptr;
+
+ if (SDL_GL_LoadLibrary(libname) != 0)
+ {
+ osd_printf_error("Unable to load OpenGL shared library: %s\n", libname ? libname : "<default>");
+ return -1;
+ }
+
+ osd_printf_verbose("Loaded OpenGL shared library: %s\n", libname ? libname : "<default>");
}
+#endif // defined(OSD_SDL)
+ m_dll_loaded = true;
+#endif // defined(USE_DISPATCH_GL)
+
+#if defined(OSD_WINDOWS)
+ osd_printf_verbose("Using Windows OpenGL driver\n");
+#else // defined(OSD_WINDOWS)
+ osd_printf_verbose("Using SDL multi-window OpenGL driver (SDL 2.0+)\n");
+#endif // defined(OSD_WINDOWS)
+
+ return 0;
+}
+
+void video_opengl::exit()
+{
+#if defined(USE_DISPATCH_GL)
+#if defined(OSD_SDL)
+ if (m_dll_loaded)
+ SDL_GL_UnloadLibrary();
+#endif // defined(OSD_SDL)
+ m_dll_loaded = false;
+#endif // defined(USE_DISPATCH_GL)
+
+ m_ogl_config = ogl_video_config();
+}
+
+std::unique_ptr<osd_renderer> video_opengl::create(osd_window &window)
+{
+ return std::make_unique<renderer_ogl>(window, m_ogl_config);
}
+
+} // anonymous namespace
+
+} // namespace osd
+
+
+#else // USE_OPENGL
+
+namespace osd { namespace { MODULE_NOT_SUPPORTED(video_opengl, OSD_RENDERER_PROVIDER, "opengl") } }
+
+#endif // USE_OPENGL
+
+
+MODULE_DEFINITION(RENDERER_OPENGL, osd::video_opengl)
diff --git a/src/osd/modules/render/drawogl.h b/src/osd/modules/render/drawogl.h
deleted file mode 100644
index 61b9794353c..00000000000
--- a/src/osd/modules/render/drawogl.h
+++ /dev/null
@@ -1,244 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Olivier Galibert, R. Belmont
-//============================================================
-//
-// drawogl.h - SDL software and OpenGL implementation
-//
-// SDLMAME by Olivier Galibert and R. Belmont
-//
-//============================================================
-#ifndef MAME_OSD_MODULES_RENDER_DRAWOGL_H
-#define MAME_OSD_MODULES_RENDER_DRAWOGL_H
-
-#pragma once
-
-// OSD headers
-#ifndef OSD_WINDOWS
-#ifdef OSD_MAC
-#include "osdmac.h"
-#else
-#include "osdsdl.h"
-#endif
-#include "window.h"
-#else
-#include "../windows/window.h"
-typedef uint64_t HashT;
-#endif
-
-#if defined(OSD_WINDOWS)
-#include "winglcontext.h"
-#elif defined (OSD_MAC)
-#else
-#include "sdlglcontext.h"
-#endif
-
-#include "modules/opengl/gl_shader_mgr.h"
-
-#include "emucore.h"
-#include "render.h"
-
-//============================================================
-// Textures
-//============================================================
-
-/* ogl_texture_info holds information about a texture */
-class ogl_texture_info
-{
-public:
- ogl_texture_info()
- : hash(0), flags(0), rawwidth(0), rawheight(0),
- rawwidth_create(0), rawheight_create(0),
- type(0), format(0), borderpix(0), xprescale(0), yprescale(0), nocopy(0),
- texture(0), texTarget(0), texpow2(0), mpass_dest_idx(0), pbo(0), data(nullptr),
- data_own(0), texCoordBufferName(0)
- {
- for (int i=0; i<2; i++)
- {
- mpass_textureunit[i] = 0;
- mpass_texture_mamebm[i] = 0;
- mpass_fbo_mamebm[i] = 0;
- mpass_texture_scrn[i] = 0;
- mpass_fbo_scrn[i] = 0;
- }
- for (int i=0; i<8; i++)
- texCoord[i] = 0.0f;
- }
-
- HashT hash; // hash value for the texture (must be >= pointer size)
- uint32_t flags; // rendering flags
- render_texinfo texinfo; // copy of the texture info
- int rawwidth, rawheight; // raw width/height of the texture
- int rawwidth_create; // raw width/height, pow2 compatible, if needed
- int rawheight_create; // (create and initial set the texture, not for copy!)
- int type; // what type of texture are we?
- int format; // texture format
- int borderpix; // do we have a 1 pixel border?
- int xprescale; // what is our X prescale factor?
- int yprescale; // what is our Y prescale factor?
- int nocopy; // must the texture date be copied?
-
- uint32_t texture; // OpenGL texture "name"/ID
-
- GLenum texTarget; // OpenGL texture target
- int texpow2; // Is this texture pow2
-
- uint32_t mpass_dest_idx; // Multipass dest idx [0..1]
- uint32_t mpass_textureunit[2]; // texture unit names for GLSL
-
- uint32_t mpass_texture_mamebm[2];// Multipass OpenGL texture "name"/ID for the shader
- uint32_t mpass_fbo_mamebm[2]; // framebuffer object for this texture, multipass
- uint32_t mpass_texture_scrn[2]; // Multipass OpenGL texture "name"/ID for the shader
- uint32_t mpass_fbo_scrn[2]; // framebuffer object for this texture, multipass
-
- uint32_t pbo; // pixel buffer object for this texture (DYNAMIC only!)
- uint32_t *data; // pixels for the texture
- int data_own; // do we own / allocated it ?
- GLfloat texCoord[8];
- GLuint texCoordBufferName;
-
-};
-
-/* renderer_ogl is the information about OpenGL for the current screen */
-class renderer_ogl : public osd_renderer
-{
-public:
- renderer_ogl(std::shared_ptr<osd_window> window)
- : osd_renderer(window, FLAG_NEEDS_OPENGL)
- , m_blittimer(0)
- , m_width(0)
- , m_height(0)
- , m_blit_dim(0, 0)
- , m_gl_context(nullptr)
- , m_initialized(0)
- , m_last_blendmode(0)
- , m_texture_max_width(0)
- , m_texture_max_height(0)
- , m_texpoweroftwo(0)
- , m_usevbo(0)
- , m_usepbo(0)
- , m_usefbo(0)
- , m_useglsl(0)
- , m_glsl(nullptr)
- , m_glsl_program_num(0)
- , m_glsl_program_mb2sc(0)
- , m_usetexturerect(0)
- , m_init_context(0)
- , m_last_hofs(0.0f)
- , m_last_vofs(0.0f)
- , m_surf_w(0)
- , m_surf_h(0)
- {
- for (int i=0; i < HASH_SIZE + OVERFLOW_SIZE; i++)
- m_texhash[i] = nullptr;
- for (int i=0; i < 2*GLSL_SHADER_MAX; i++)
- m_glsl_program[i] = 0;
- for (int i=0; i < 8; i++)
- m_texVerticex[i] = 0.0f;
- }
- virtual ~renderer_ogl();
-
- static void init(running_machine &machine);
- static void exit();
-
- virtual int create() override;
- virtual int draw(const int update) override;
-
-#ifndef OSD_WINDOWS
- virtual int xy_to_render_target(const int x, const int y, int *xt, int *yt) override;
-#endif
- virtual render_primitive_list *get_primitives() override
- {
- auto win = try_getwindow();
- if (win == nullptr)
- return nullptr;
-
- osd_dim nd = win->get_size();
- if (nd != m_blit_dim)
- {
- m_blit_dim = nd;
- notify_changed();
- }
- if ((m_blit_dim.width() == 0) || (m_blit_dim.height() == 0))
- return nullptr;
- win->target()->set_bounds(m_blit_dim.width(), m_blit_dim.height(), win->pixel_aspect());
- return &win->target()->get_primitives();
- }
-
-#ifdef OSD_WINDOWS
- virtual void save() override { }
- virtual void record() override { }
- virtual void toggle_fsfx() override { }
-#endif
-
-private:
- static const uint32_t HASH_SIZE = ((1 << 10) + 1);
- static const uint32_t OVERFLOW_SIZE = (1 << 10);
-
- void destroy_all_textures();
-
- static void load_gl_lib(running_machine &machine);
- void loadGLExtensions();
- void initialize_gl();
- void set_blendmode(int blendmode);
- HashT texture_compute_hash(const render_texinfo *texture, uint32_t flags);
- void texture_compute_type_subroutine(const render_texinfo *texsource, ogl_texture_info *texture, uint32_t flags);
- void texture_compute_size_subroutine(ogl_texture_info *texture, uint32_t flags,
- uint32_t width, uint32_t height,
- int* p_width, int* p_height, int* p_width_create, int* p_height_create);
- void texture_compute_size_type(const render_texinfo *texsource, ogl_texture_info *texture, uint32_t flags);
- ogl_texture_info *texture_create(const render_texinfo *texsource, uint32_t flags);
- int texture_shader_create(const render_texinfo *texsource, ogl_texture_info *texture, uint32_t flags);
- ogl_texture_info *texture_find(const render_primitive *prim);
- void texture_coord_update(ogl_texture_info *texture, const render_primitive *prim, int shaderIdx);
- void texture_mpass_flip(ogl_texture_info *texture, int shaderIdx);
- void texture_shader_update(ogl_texture_info *texture, render_container *container, int shaderIdx);
- ogl_texture_info * texture_update(const render_primitive *prim, int shaderIdx);
- void texture_disable(ogl_texture_info * texture);
- void texture_all_disable();
-
- int32_t m_blittimer;
- int m_width;
- int m_height;
- osd_dim m_blit_dim;
-
- osd_gl_context *m_gl_context;
-
- int m_initialized; // is everything well initialized, i.e. all GL stuff etc.
- // 3D info (GL mode only)
- ogl_texture_info * m_texhash[HASH_SIZE + OVERFLOW_SIZE];
- int m_last_blendmode; // previous blendmode
- int32_t m_texture_max_width; // texture maximum width
- int32_t m_texture_max_height; // texture maximum height
- int m_texpoweroftwo; // must textures be power-of-2 sized?
- int m_usevbo; // runtime check if VBO is available
- int m_usepbo; // runtime check if PBO is available
- int m_usefbo; // runtime check if FBO is available
- int m_useglsl; // runtime check if GLSL is available
-
- glsl_shader_info *m_glsl; // glsl_shader_info
-
- GLhandleARB m_glsl_program[2*GLSL_SHADER_MAX]; // GLSL programs, or 0
- int m_glsl_program_num; // number of GLSL programs
- int m_glsl_program_mb2sc; // GLSL program idx, which transforms
- // the mame-bitmap. screen-bitmap (size/rotation/..)
- // All progs <= glsl_program_mb2sc using the mame bitmap
- // as input, otherwise the screen bitmap.
- // All progs >= glsl_program_mb2sc using the screen bitmap
- // as output, otherwise the mame bitmap.
- int m_usetexturerect; // use ARB_texture_rectangle for non-power-of-2, general use
-
- int m_init_context; // initialize context before next draw
-
- float m_last_hofs;
- float m_last_vofs;
-
- // Static vars from draogl_window_dra
- int32_t m_surf_w;
- int32_t m_surf_h;
- GLfloat m_texVerticex[8];
-
- static bool s_shown_video_info;
- static bool s_dll_loaded;
-};
-
-#endif // MAME_OSD_MODULES_RENDER_DRAWOGL_H
diff --git a/src/osd/modules/render/drawsdl.cpp b/src/osd/modules/render/drawsdl.cpp
index 9e5de59c412..b1a9e93f42e 100644
--- a/src/osd/modules/render/drawsdl.cpp
+++ b/src/osd/modules/render/drawsdl.cpp
@@ -2,7 +2,7 @@
// copyright-holders:Couriersud, Olivier Galibert, R. Belmont
//============================================================
//
-// drawsdl.c - SDL software and OpenGL implementation
+// drawsdl.cpp - SDL software and OpenGL implementation
//
// SDLMAME by Olivier Galibert and R. Belmont
//
@@ -10,28 +10,37 @@
//
//============================================================
-// standard C headers
-#include <cmath>
-#include <cstdio>
+#include "render_module.h"
+
+#include "modules/osdmodule.h"
+
+#if defined(OSD_SDL)
+
+// from specific OSD implementation
+#include "sdlopts.h"
+#include "window.h"
+
+// general OSD headers
+#include "modules/monitor/monitor_module.h"
// MAME headers
#include "emucore.h"
-#include "ui/uimain.h"
+#include "render.h"
#include "rendersw.hxx"
-// standard SDL headers
+//#include "ui/uimain.h"
+
#include <SDL2/SDL.h>
-// OSD headers
-#include "osdsdl.h"
-#include "window.h"
+// standard C headers
+#include <cmath>
+#include <cstdio>
+#include <memory>
-#include "drawsdl.h"
-#include "modules/monitor/monitor_module.h"
-//============================================================
-// DEBUGGING
-//============================================================
+namespace osd {
+
+namespace {
//============================================================
// CONSTANTS
@@ -41,60 +50,90 @@
#define DRAW2_SCALEMODE_LINEAR "1"
#define DRAW2_SCALEMODE_BEST "2"
-//============================================================
-// PROTOTYPES
-//============================================================
-
-// YUV overlays
-
-static void yuv_RGB_to_YV12(const uint16_t *bitmap, uint8_t *ptr, const int pitch, \
- const uint32_t *lookup, const int width, const int height);
-static void yuv_RGB_to_YV12X2(const uint16_t *bitmap, uint8_t *ptr, const int pitch, \
- const uint32_t *lookup, const int width, const int height);
-static void yuv_RGB_to_YUY2(const uint16_t *bitmap, uint8_t *ptr, const int pitch, \
- const uint32_t *lookup, const int width, const int height);
-static void yuv_RGB_to_YUY2X2(const uint16_t *bitmap, uint8_t *ptr, const int pitch, \
- const uint32_t *lookup, const int width, const int height);
-
-// Static declarations
-static const sdl_scale_mode scale_modes[] =
+struct sdl_scale_mode
{
- { "none", 0, 0, 1, 1, DRAW2_SCALEMODE_NEAREST, 0, nullptr },
- { "hwblit", 1, 0, 1, 1, DRAW2_SCALEMODE_LINEAR, 0, nullptr },
- { "hwbest", 1, 0, 1, 1, DRAW2_SCALEMODE_BEST, 0, nullptr },
- /* SDL1.2 uses interpolation as well */
- { "yv12", 1, 1, 1, 1, DRAW2_SCALEMODE_BEST, SDL_PIXELFORMAT_YV12, yuv_RGB_to_YV12 },
- { "yv12x2", 1, 1, 2, 2, DRAW2_SCALEMODE_BEST, SDL_PIXELFORMAT_YV12, yuv_RGB_to_YV12X2 },
- { "yuy2", 1, 1, 1, 1, DRAW2_SCALEMODE_BEST, SDL_PIXELFORMAT_YUY2, yuv_RGB_to_YUY2 },
- { "yuy2x2", 1, 1, 2, 1, DRAW2_SCALEMODE_BEST, SDL_PIXELFORMAT_YUY2, yuv_RGB_to_YUY2X2 },
- { nullptr }
+ const char *name;
+ int is_scale; /* Scale mode? */
+ int is_yuv; /* Yuv mode? */
+ int mult_w; /* Width multiplier */
+ int mult_h; /* Height multiplier */
+ const char *sdl_scale_mode_hint; /* what to use as a hint ? */
+ int pixel_format; /* Pixel/Overlay format */
+ void (*yuv_blit)(const uint16_t *bitmap, uint8_t *ptr, const int pitch, const uint32_t *lookup, const int width, const int height);
};
-int drawsdl_scale_mode(const char *s)
-{
- const sdl_scale_mode *sm = scale_modes;
- int index;
- index = 0;
- while (sm->name != nullptr)
+// renderer_sdl1 is the information about SDL for the current screen
+class renderer_sdl1 : public osd_renderer
+{
+public:
+
+ renderer_sdl1(osd_window &w, sdl_scale_mode const &scale_mode)
+ : osd_renderer(w)
+ , m_scale_mode(scale_mode)
+ , m_sdl_renderer(nullptr)
+ , m_texture_id(nullptr)
+ , m_yuv_lookup()
+ , m_yuv_bitmap()
+ //, m_hw_scale_width(0)
+ //, m_hw_scale_height(0)
+ , m_last_hofs(0)
+ , m_last_vofs(0)
+ , m_blit_dim(0, 0)
+ , m_last_dim(0, 0)
{
- if (strcmp(sm->name, s) == 0)
- return index;
- index++;
- sm++;
}
- return -1;
-}
+ virtual ~renderer_sdl1();
+
+ virtual int create() override;
+ virtual int draw(const int update) override;
+ virtual int xy_to_render_target(const int x, const int y, int *xt, int *yt) override;
+ virtual render_primitive_list *get_primitives() override;
+
+private:
+ void show_info(struct SDL_RendererInfo *render_info);
+
+ void destroy_all_textures();
+ void yuv_init();
+ void setup_texture(const osd_dim &size);
+ void yuv_lookup_set(unsigned int pen, unsigned char red,
+ unsigned char green, unsigned char blue);
+
+ int32_t m_blittimer;
+
+ sdl_scale_mode const &m_scale_mode;
+ SDL_Renderer *m_sdl_renderer;
+ SDL_Texture *m_texture_id;
+
+ // YUV overlay
+ std::unique_ptr<uint32_t []> m_yuv_lookup;
+ std::unique_ptr<uint16_t []> m_yuv_bitmap;
+
+ // if we leave scaling to SDL and the underlying driver, this
+ // is the render_target_width/height to use
+
+ int m_last_hofs;
+ int m_last_vofs;
+ osd_dim m_blit_dim;
+ osd_dim m_last_dim;
+};
+
//============================================================
-// drawsdl_init
+// PROTOTYPES
//============================================================
-void renderer_sdl1::init(running_machine &machine)
-{
- osd_printf_verbose("Using SDL multi-window soft driver (SDL 2.0+)\n");
-}
+// YUV overlays
+
+static void yuv_RGB_to_YV12(const uint16_t *bitmap, uint8_t *ptr, const int pitch,
+ const uint32_t *lookup, const int width, const int height);
+static void yuv_RGB_to_YV12X2(const uint16_t *bitmap, uint8_t *ptr, const int pitch,
+ const uint32_t *lookup, const int width, const int height);
+static void yuv_RGB_to_YUY2(const uint16_t *bitmap, uint8_t *ptr, const int pitch,
+ const uint32_t *lookup, const int width, const int height);
+static void yuv_RGB_to_YUY2X2(const uint16_t *bitmap, uint8_t *ptr, const int pitch,
+ const uint32_t *lookup, const int width, const int height);
//============================================================
// setup_texture for window
@@ -102,38 +141,35 @@ void renderer_sdl1::init(running_machine &machine)
void renderer_sdl1::setup_texture(const osd_dim &size)
{
- const sdl_scale_mode *sdl_sm = &scale_modes[video_config.scale_mode];
SDL_DisplayMode mode;
uint32_t fmt;
- auto win = assert_window();
-
// Determine preferred pixelformat and set up yuv if necessary
- SDL_GetCurrentDisplayMode(win->monitor()->oshandle(), &mode);
+ SDL_GetCurrentDisplayMode(window().monitor()->oshandle(), &mode);
m_yuv_bitmap.reset();
- fmt = (sdl_sm->pixel_format ? sdl_sm->pixel_format : mode.format);
+ fmt = (m_scale_mode.pixel_format ? m_scale_mode.pixel_format : mode.format);
- if (sdl_sm->is_scale)
+ if (m_scale_mode.is_scale)
{
int m_hw_scale_width = 0;
int m_hw_scale_height = 0;
- win->target()->compute_minimum_size(m_hw_scale_width, m_hw_scale_height);
- if (win->prescale())
+ window().target()->compute_minimum_size(m_hw_scale_width, m_hw_scale_height);
+ if (window().prescale())
{
- m_hw_scale_width *= win->prescale();
- m_hw_scale_height *= win->prescale();
+ m_hw_scale_width *= window().prescale();
+ m_hw_scale_height *= window().prescale();
/* This must be a multiple of 2 */
m_hw_scale_width = (m_hw_scale_width + 1) & ~1;
}
- if (sdl_sm->is_yuv)
+ if (m_scale_mode.is_yuv)
m_yuv_bitmap = std::make_unique<uint16_t []>(m_hw_scale_width * m_hw_scale_height);
- int w = m_hw_scale_width * sdl_sm->mult_w;
- int h = m_hw_scale_height * sdl_sm->mult_h;
+ int w = m_hw_scale_width * m_scale_mode.mult_w;
+ int h = m_hw_scale_height * m_scale_mode.mult_h;
m_texture_id = SDL_CreateTexture(m_sdl_renderer, fmt, SDL_TEXTUREACCESS_STREAMING, w, h);
@@ -182,26 +218,23 @@ void renderer_sdl1::show_info(struct SDL_RendererInfo *render_info)
int renderer_sdl1::create()
{
- const sdl_scale_mode *sm = &scale_modes[video_config.scale_mode];
-
- auto win = assert_window();
// create renderer
/* set hints ... */
- SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, sm->sdl_scale_mode_hint);
+ SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, m_scale_mode.sdl_scale_mode_hint);
if (video_config.waitvsync)
- m_sdl_renderer = SDL_CreateRenderer(std::dynamic_pointer_cast<sdl_window_info>(win)->platform_window(), -1, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED);
+ m_sdl_renderer = SDL_CreateRenderer(dynamic_cast<sdl_window_info &>(window()).platform_window(), -1, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED);
else
- m_sdl_renderer = SDL_CreateRenderer(std::dynamic_pointer_cast<sdl_window_info>(win)->platform_window(), -1, SDL_RENDERER_ACCELERATED);
+ m_sdl_renderer = SDL_CreateRenderer(dynamic_cast<sdl_window_info &>(window()).platform_window(), -1, SDL_RENDERER_ACCELERATED);
if (!m_sdl_renderer)
{
if (video_config.waitvsync)
- m_sdl_renderer = SDL_CreateRenderer(std::dynamic_pointer_cast<sdl_window_info>(win)->platform_window(), -1, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_SOFTWARE);
+ m_sdl_renderer = SDL_CreateRenderer(dynamic_cast<sdl_window_info &>(window()).platform_window(), -1, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_SOFTWARE);
else
- m_sdl_renderer = SDL_CreateRenderer(std::dynamic_pointer_cast<sdl_window_info>(win)->platform_window(), -1, SDL_RENDERER_SOFTWARE);
+ m_sdl_renderer = SDL_CreateRenderer(dynamic_cast<sdl_window_info &>(window()).platform_window(), -1, SDL_RENDERER_SOFTWARE);
}
if (!m_sdl_renderer)
@@ -216,18 +249,18 @@ int renderer_sdl1::create()
// Check scale mode
- if (sm->pixel_format)
+ if (m_scale_mode.pixel_format)
{
int i;
int found = 0;
for (i=0; i < render_info.num_texture_formats; i++)
- if (sm->pixel_format == render_info.texture_formats[i])
+ if (m_scale_mode.pixel_format == render_info.texture_formats[i])
found = 1;
if (!found)
{
- fatalerror("window: Scale mode %s not supported!", sm->name);
+ fatalerror("window: Scale mode %s not supported!", m_scale_mode.name);
}
}
@@ -288,7 +321,6 @@ void renderer_sdl1::destroy_all_textures()
int renderer_sdl1::draw(int update)
{
- const sdl_scale_mode *sm = &scale_modes[video_config.scale_mode];
uint8_t *surfptr;
int32_t pitch;
Uint32 rmask, gmask, bmask;
@@ -296,14 +328,7 @@ int renderer_sdl1::draw(int update)
int32_t vofs, hofs, blitwidth, blitheight, ch, cw;
int bpp;
- if (video_config.novideo)
- {
- return 0;
- }
-
- auto win = assert_window();
-
- osd_dim wdim = win->get_size();
+ osd_dim wdim = window().get_size();
if (has_flags(FI_CHANGED) || (wdim != m_last_dim))
{
destroy_all_textures();
@@ -370,15 +395,15 @@ int renderer_sdl1::draw(int update)
m_last_hofs = hofs;
m_last_vofs = vofs;
- win->m_primlist->acquire_lock();
+ window().m_primlist->acquire_lock();
int mamewidth, mameheight;
Uint32 fmt = 0;
int access = 0;
SDL_QueryTexture(m_texture_id, &fmt, &access, &mamewidth, &mameheight);
- mamewidth /= sm->mult_w;
- mameheight /= sm->mult_h;
+ mamewidth /= m_scale_mode.mult_w;
+ mameheight /= m_scale_mode.mult_h;
//printf("w h %d %d %d %d\n", mamewidth, mameheight, blitwidth, blitheight);
// rescale bounds
@@ -388,7 +413,7 @@ int renderer_sdl1::draw(int update)
// FIXME: this could be a lot easier if we get the primlist here!
// Bounds would be set fit for purpose and done!
- for (render_primitive &prim : *win->m_primlist)
+ for (render_primitive &prim : *window().m_primlist)
{
prim.bounds.x0 = floor(fw * prim.bounds.x0 + 0.5f);
prim.bounds.x1 = floor(fw * prim.bounds.x1 + 0.5f);
@@ -397,32 +422,32 @@ int renderer_sdl1::draw(int update)
}
// render to it
- if (!sm->is_yuv)
+ if (!m_scale_mode.is_yuv)
{
switch (rmask)
{
case 0xff000000:
- software_renderer<uint32_t, 0,0,0, 24,16,8>::draw_primitives(*win->m_primlist, surfptr, mamewidth, mameheight, pitch / 4);
+ software_renderer<uint32_t, 0,0,0, 24,16,8>::draw_primitives(*window().m_primlist, surfptr, mamewidth, mameheight, pitch / 4);
break;
case 0x0000ff00:
- software_renderer<uint32_t, 0,0,0, 8,16,24>::draw_primitives(*win->m_primlist, surfptr, mamewidth, mameheight, pitch / 4);
+ software_renderer<uint32_t, 0,0,0, 8,16,24>::draw_primitives(*window().m_primlist, surfptr, mamewidth, mameheight, pitch / 4);
break;
case 0x00ff0000:
- software_renderer<uint32_t, 0,0,0, 16,8,0>::draw_primitives(*win->m_primlist, surfptr, mamewidth, mameheight, pitch / 4);
+ software_renderer<uint32_t, 0,0,0, 16,8,0>::draw_primitives(*window().m_primlist, surfptr, mamewidth, mameheight, pitch / 4);
break;
case 0x000000ff:
- software_renderer<uint32_t, 0,0,0, 0,8,16>::draw_primitives(*win->m_primlist, surfptr, mamewidth, mameheight, pitch / 4);
+ software_renderer<uint32_t, 0,0,0, 0,8,16>::draw_primitives(*window().m_primlist, surfptr, mamewidth, mameheight, pitch / 4);
break;
case 0xf800:
- software_renderer<uint16_t, 3,2,3, 11,5,0>::draw_primitives(*win->m_primlist, surfptr, mamewidth, mameheight, pitch / 2);
+ software_renderer<uint16_t, 3,2,3, 11,5,0>::draw_primitives(*window().m_primlist, surfptr, mamewidth, mameheight, pitch / 2);
break;
case 0x7c00:
- software_renderer<uint16_t, 3,3,3, 10,5,0>::draw_primitives(*win->m_primlist, surfptr, mamewidth, mameheight, pitch / 2);
+ software_renderer<uint16_t, 3,3,3, 10,5,0>::draw_primitives(*window().m_primlist, surfptr, mamewidth, mameheight, pitch / 2);
break;
default:
@@ -434,11 +459,11 @@ int renderer_sdl1::draw(int update)
{
assert (m_yuv_bitmap != nullptr);
assert (surfptr != nullptr);
- software_renderer<uint16_t, 3,3,3, 10,5,0>::draw_primitives(*win->m_primlist, m_yuv_bitmap.get(), mamewidth, mameheight, mamewidth);
- sm->yuv_blit(m_yuv_bitmap.get(), surfptr, pitch, m_yuv_lookup.get(), mamewidth, mameheight);
+ software_renderer<uint16_t, 3,3,3, 10,5,0>::draw_primitives(*window().m_primlist, m_yuv_bitmap.get(), mamewidth, mameheight, mamewidth);
+ m_scale_mode.yuv_blit(m_yuv_bitmap.get(), surfptr, pitch, m_yuv_lookup.get(), mamewidth, mameheight);
}
- win->m_primlist->release_lock();
+ window().m_primlist->release_lock();
// unlock and flip
SDL_UnlockTexture(m_texture_id);
@@ -527,7 +552,7 @@ void renderer_sdl1::yuv_init()
//uint32_t *lookup = sdl->m_yuv_lookup;
-static void yuv_RGB_to_YV12(const uint16_t *bitmap, uint8_t *ptr, const int pitch, \
+static void yuv_RGB_to_YV12(const uint16_t *bitmap, uint8_t *ptr, const int pitch,
const uint32_t *lookup, const int width, const int height)
{
int x, y;
@@ -581,7 +606,7 @@ static void yuv_RGB_to_YV12(const uint16_t *bitmap, uint8_t *ptr, const int pitc
}
}
-static void yuv_RGB_to_YV12X2(const uint16_t *bitmap, uint8_t *ptr, const int pitch, \
+static void yuv_RGB_to_YV12X2(const uint16_t *bitmap, uint8_t *ptr, const int pitch,
const uint32_t *lookup, const int width, const int height)
{
/* this one is used when scale==2 */
@@ -616,7 +641,7 @@ static void yuv_RGB_to_YV12X2(const uint16_t *bitmap, uint8_t *ptr, const int pi
}
}
-static void yuv_RGB_to_YUY2(const uint16_t *bitmap, uint8_t *ptr, const int pitch, \
+static void yuv_RGB_to_YUY2(const uint16_t *bitmap, uint8_t *ptr, const int pitch,
const uint32_t *lookup, const int width, const int height)
{
/* this one is used when scale==2 */
@@ -642,7 +667,7 @@ static void yuv_RGB_to_YUY2(const uint16_t *bitmap, uint8_t *ptr, const int pitc
}
}
-static void yuv_RGB_to_YUY2X2(const uint16_t *bitmap, uint8_t *ptr, const int pitch, \
+static void yuv_RGB_to_YUY2X2(const uint16_t *bitmap, uint8_t *ptr, const int pitch,
const uint32_t *lookup, const int width, const int height)
{
/* this one is used when scale==2 */
@@ -666,16 +691,98 @@ static void yuv_RGB_to_YUY2X2(const uint16_t *bitmap, uint8_t *ptr, const int pi
render_primitive_list *renderer_sdl1::get_primitives()
{
- auto win = try_getwindow();
- if (win == nullptr)
- return nullptr;
-
- osd_dim nd = win->get_size();
+ osd_dim nd = window().get_size();
if (nd != m_blit_dim)
{
m_blit_dim = nd;
notify_changed();
}
- win->target()->set_bounds(m_blit_dim.width(), m_blit_dim.height(), win->pixel_aspect());
- return &win->target()->get_primitives();
+ window().target()->set_bounds(m_blit_dim.width(), m_blit_dim.height(), window().pixel_aspect());
+ return &window().target()->get_primitives();
+}
+
+
+class video_sdl1 : public osd_module, public render_module
+{
+public:
+ video_sdl1()
+ : osd_module(OSD_RENDERER_PROVIDER, "soft")
+ , m_scale_mode(-1)
+ {
+ }
+
+ virtual int init(osd_interface &osd, osd_options const &options) override;
+ virtual void exit() override { }
+
+ virtual std::unique_ptr<osd_renderer> create(osd_window &window) override;
+
+protected:
+ virtual unsigned flags() const override { return FLAG_INTERACTIVE; }
+
+private:
+ static int get_scale_mode(char const *modestr);
+
+ int m_scale_mode;
+
+ static sdl_scale_mode const s_scale_modes[];
+};
+
+int video_sdl1::init(osd_interface &osd, osd_options const &options)
+{
+ osd_printf_verbose("Using SDL multi-window soft driver (SDL 2.0+)\n");
+
+ // yuv settings ...
+ char const *const modestr = dynamic_cast<sdl_options const &>(options).scale_mode();
+ m_scale_mode = get_scale_mode(modestr);
+ if (m_scale_mode < 0)
+ {
+ osd_printf_warning("Invalid yuvmode value %s; reverting to none\n", modestr);
+ m_scale_mode = 0;
+ }
+
+ return 0;
+}
+
+std::unique_ptr<osd_renderer> video_sdl1::create(osd_window &window)
+{
+ return std::make_unique<renderer_sdl1>(window, s_scale_modes[m_scale_mode]);
}
+
+int video_sdl1::get_scale_mode(char const *modestr)
+{
+ const sdl_scale_mode *sm = s_scale_modes;
+ int index = 0;
+ while (sm->name)
+ {
+ if (!strcmp(sm->name, modestr))
+ return index;
+ index++;
+ sm++;
+ }
+ return -1;
+}
+
+sdl_scale_mode const video_sdl1::s_scale_modes[] = {
+ { "none", 0, 0, 1, 1, DRAW2_SCALEMODE_NEAREST, 0, nullptr },
+ { "hwblit", 1, 0, 1, 1, DRAW2_SCALEMODE_LINEAR, 0, nullptr },
+ { "hwbest", 1, 0, 1, 1, DRAW2_SCALEMODE_BEST, 0, nullptr },
+ /* SDL1.2 uses interpolation as well */
+ { "yv12", 1, 1, 1, 1, DRAW2_SCALEMODE_BEST, SDL_PIXELFORMAT_YV12, yuv_RGB_to_YV12 },
+ { "yv12x2", 1, 1, 2, 2, DRAW2_SCALEMODE_BEST, SDL_PIXELFORMAT_YV12, yuv_RGB_to_YV12X2 },
+ { "yuy2", 1, 1, 1, 1, DRAW2_SCALEMODE_BEST, SDL_PIXELFORMAT_YUY2, yuv_RGB_to_YUY2 },
+ { "yuy2x2", 1, 1, 2, 1, DRAW2_SCALEMODE_BEST, SDL_PIXELFORMAT_YUY2, yuv_RGB_to_YUY2X2 },
+ { nullptr } };
+
+} // anonymous namespace
+
+} // namespace osd
+
+
+#else // defined(OSD_SDL)
+
+namespace osd { namespace { MODULE_NOT_SUPPORTED(video_sdl1, OSD_RENDERER_PROVIDER, "soft") } }
+
+#endif // defined(OSD_SDL)
+
+
+MODULE_DEFINITION(RENDERER_SDL1, osd::video_sdl1)
diff --git a/src/osd/modules/render/drawsdl.h b/src/osd/modules/render/drawsdl.h
deleted file mode 100644
index bc8246a632d..00000000000
--- a/src/osd/modules/render/drawsdl.h
+++ /dev/null
@@ -1,88 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Couriersud, Olivier Galibert, R. Belmont
-//============================================================
-//
-// drawsdl.h - SDL software and OpenGL implementation
-//
-// SDLMAME by Olivier Galibert and R. Belmont
-//
-// yuvmodes by Couriersud
-//
-//============================================================
-
-#ifndef MAME_OSD_MODULES_RENDER_DRAWSDL_H
-#define MAME_OSD_MODULES_RENDER_DRAWSDL_H
-
-#pragma once
-
-#include <SDL2/SDL.h>
-
-/* renderer_sdl1 is the information about SDL for the current screen */
-class renderer_sdl1 : public osd_renderer
-{
-public:
-
- renderer_sdl1(std::shared_ptr<osd_window> w, int extra_flags)
- : osd_renderer(w, FLAG_NEEDS_OPENGL | extra_flags)
- , m_sdl_renderer(nullptr)
- , m_texture_id(nullptr)
- , m_yuv_lookup()
- , m_yuv_bitmap()
- //, m_hw_scale_width(0)
- //, m_hw_scale_height(0)
- , m_last_hofs(0)
- , m_last_vofs(0)
- , m_blit_dim(0, 0)
- , m_last_dim(0, 0)
- {
- }
- virtual ~renderer_sdl1();
-
- static void init(running_machine &machine);
- static void exit() { }
-
- virtual int create() override;
- virtual int draw(const int update) override;
- virtual int xy_to_render_target(const int x, const int y, int *xt, int *yt) override;
- virtual render_primitive_list *get_primitives() override;
-
-private:
- void show_info(struct SDL_RendererInfo *render_info);
-
- void destroy_all_textures();
- void yuv_init();
- void setup_texture(const osd_dim &size);
- void yuv_lookup_set(unsigned int pen, unsigned char red,
- unsigned char green, unsigned char blue);
-
- int32_t m_blittimer;
-
- SDL_Renderer *m_sdl_renderer;
- SDL_Texture *m_texture_id;
-
- // YUV overlay
- std::unique_ptr<uint32_t []> m_yuv_lookup;
- std::unique_ptr<uint16_t []> m_yuv_bitmap;
-
- // if we leave scaling to SDL and the underlying driver, this
- // is the render_target_width/height to use
-
- int m_last_hofs;
- int m_last_vofs;
- osd_dim m_blit_dim;
- osd_dim m_last_dim;
-};
-
-struct sdl_scale_mode
-{
- const char *name;
- int is_scale; /* Scale mode? */
- int is_yuv; /* Yuv mode? */
- int mult_w; /* Width multiplier */
- int mult_h; /* Height multiplier */
- const char *sdl_scale_mode_hint; /* what to use as a hint ? */
- int pixel_format; /* Pixel/Overlay format */
- void (*yuv_blit)(const uint16_t *bitmap, uint8_t *ptr, const int pitch, const uint32_t *lookup, const int width, const int height);
-};
-
-#endif // MAME_OSD_MODULES_RENDER_DRAWSDL_H
diff --git a/src/osd/modules/render/render_module.h b/src/osd/modules/render/render_module.h
new file mode 100644
index 00000000000..b22f35fdb3c
--- /dev/null
+++ b/src/osd/modules/render/render_module.h
@@ -0,0 +1,38 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+#ifndef MAME_OSD_MODULES_RENDER_RENDER_MODULE_H
+#define MAME_OSD_MODULES_RENDER_RENDER_MODULE_H
+
+#pragma once
+
+#include "osdepend.h"
+#include "modules/osdmodule.h"
+
+#include <memory>
+
+
+#define OSD_RENDERER_PROVIDER "video"
+
+
+class osd_renderer;
+class osd_window;
+
+
+class render_module
+{
+public:
+ virtual ~render_module() = default;
+
+ virtual std::unique_ptr<osd_renderer> create(osd_window &window) = 0;
+
+ bool is_interactive() const { return flags() & FLAG_INTERACTIVE; }
+ bool sdl_needs_opengl() const { return flags() & FLAG_SDL_NEEDS_OPENGL; }
+
+protected:
+ static inline constexpr unsigned FLAG_INTERACTIVE = 1;
+ static inline constexpr unsigned FLAG_SDL_NEEDS_OPENGL = 2;
+
+ virtual unsigned flags() const = 0;
+};
+
+#endif // MAME_OSD_MODULES_RENDER_RENDER_MODULE_H
diff --git a/src/osd/modules/render/sdlglcontext.h b/src/osd/modules/render/sdlglcontext.h
index b8ff4d72aa2..d2055060bd6 100644
--- a/src/osd/modules/render/sdlglcontext.h
+++ b/src/osd/modules/render/sdlglcontext.h
@@ -8,61 +8,76 @@
//
//============================================================
+#ifndef MAME_RENDER_SDLGLCONTEXT_H
+#define MAME_RENDER_SDLGLCONTEXT_H
+
#pragma once
-#ifndef __SDL_GL_CONTEXT__
-#define __SDL_GL_CONTEXT__
+#include "modules/opengl/osd_opengl.h"
+
+#include "strformat.h"
#include <SDL2/SDL.h>
-#include "modules/opengl/osd_opengl.h"
+
+#include <string>
+
class sdl_gl_context : public osd_gl_context
{
public:
- sdl_gl_context(SDL_Window *window) : osd_gl_context(), m_context(0), m_window(window)
+ sdl_gl_context(SDL_Window *window) : m_context(0), m_window(window)
{
- m_error[0] = 0;
m_context = SDL_GL_CreateContext(window);
- if (!m_context)
+ if (!m_context)
{
- snprintf(m_error,255, "OpenGL not supported on this driver: %s", SDL_GetError());
+ try { m_error = util::string_format("OpenGL not supported on this driver: %s", SDL_GetError()); }
+ catch (...) { m_error.clear(); }
}
}
+
virtual ~sdl_gl_context()
{
- SDL_GL_DeleteContext(m_context);
+ if (m_context)
+ SDL_GL_DeleteContext(m_context);
}
- virtual void MakeCurrent() override
+
+ virtual explicit operator bool() const override
+ {
+ return bool(m_context);
+ }
+
+ virtual void make_current() override
{
SDL_GL_MakeCurrent(m_window, m_context);
}
- virtual int SetSwapInterval(const int swap) override
+ virtual bool set_swap_interval(const int swap) override
{
- return SDL_GL_SetSwapInterval(swap);
+ return 0 == SDL_GL_SetSwapInterval(swap);
}
- virtual const char *LastErrorMsg() override
+ virtual const char *last_error_message() override
{
- if (m_error[0] == 0)
- return nullptr;
+ if (!m_error.empty())
+ return m_error.c_str();
else
- return m_error;
+ return nullptr;
}
- virtual void *getProcAddress(const char *proc) override
+
+ virtual void *get_proc_address(const char *proc) override
{
return SDL_GL_GetProcAddress(proc);
}
- virtual void SwapBuffer() override
+ virtual void swap_buffer() override
{
SDL_GL_SwapWindow(m_window);
}
private:
SDL_GLContext m_context;
- SDL_Window *m_window;
- char m_error[256];
+ SDL_Window *const m_window;
+ std::string m_error;
};
-#endif // __SDL_GL_CONTEXT__
+#endif // MAME_RENDER_SDLGLCONTEXT_H
diff --git a/src/osd/modules/render/winglcontext.h b/src/osd/modules/render/winglcontext.h
index f0cb1b6af77..48d1462d2f6 100644
--- a/src/osd/modules/render/winglcontext.h
+++ b/src/osd/modules/render/winglcontext.h
@@ -7,168 +7,197 @@
// SDLMAME by Olivier Galibert and R. Belmont
//
//============================================================
+#ifndef MAME_RENDER_WINGLCONTEXT_H
+#define MAME_RENDER_WINGLCONTEXT_H
#pragma once
-#ifndef __WIN_GL_CONTEXT__
-#define __WIN_GL_CONTEXT__
-
#include "modules/opengl/osd_opengl.h"
#include "modules/lib/osdlib.h"
-// Typedefs for dynamically loaded functions
-typedef PROC (WINAPI *wglGetProcAddress_fn)(LPCSTR);
-typedef HGLRC (WINAPI *wglCreateContext_fn)(HDC);
-typedef BOOL (WINAPI *wglDeleteContext_fn)(HGLRC);
-typedef BOOL (WINAPI *wglMakeCurrent_fn)(HDC, HGLRC);
+#include "strconv.h"
+
+#include <cstring>
+#include <string>
-typedef const char * (WINAPI *wglGetExtensionsStringEXT_fn)(void);
-typedef BOOL (WINAPI *wglSwapIntervalEXT_fn)(int);
-typedef int (WINAPI *wglGetSwapIntervalEXT_fn)(void);
class win_gl_context : public osd_gl_context
{
public:
- win_gl_context(HWND window) : osd_gl_context(), m_context(0), m_window(nullptr), m_hdc(0)
- {
- m_error[0] = 0;
+ using osd_gl_context::get_proc_address;
+ win_gl_context(HWND window) : m_context(nullptr), m_window(window), m_hdc(nullptr)
+ {
+ // open DLL and bind required functions
opengl32_dll = osd::dynamic_module::open({ "opengl32.dll" });
-
pfn_wglGetProcAddress = opengl32_dll->bind<wglGetProcAddress_fn>("wglGetProcAddress");
pfn_wglCreateContext = opengl32_dll->bind<wglCreateContext_fn>("wglCreateContext");
pfn_wglDeleteContext = opengl32_dll->bind<wglDeleteContext_fn>("wglDeleteContext");
pfn_wglMakeCurrent = opengl32_dll->bind<wglMakeCurrent_fn>("wglMakeCurrent");
+ if (!pfn_wglGetProcAddress || !pfn_wglCreateContext || !pfn_wglDeleteContext || !pfn_wglMakeCurrent)
+ return;
- if (pfn_wglGetProcAddress == nullptr || pfn_wglCreateContext == nullptr ||
- pfn_wglDeleteContext == nullptr || pfn_wglMakeCurrent == nullptr)
+ m_hdc = GetDC(window);
+ if (!m_hdc)
{
+ get_last_error_string();
return;
}
- pfn_wglGetExtensionsStringEXT = (wglGetExtensionsStringEXT_fn)(*pfn_wglGetProcAddress)("wglGetExtensionsStringEXT");
+ if (setupPixelFormat())
+ {
+ m_context = (*pfn_wglCreateContext)(m_hdc);
+ if (!m_context)
+ get_last_error_string();
+ }
+ if (!m_context)
+ return;
+
+ (*pfn_wglMakeCurrent)(m_hdc, m_context);
+ get_proc_address(pfn_wglGetExtensionsStringEXT, "wglGetExtensionsStringEXT");
if (WGLExtensionSupported("WGL_EXT_swap_control"))
{
- pfn_wglSwapIntervalEXT = (BOOL (WINAPI *) (int)) getProcAddress("wglSwapIntervalEXT");
- pfn_wglGetSwapIntervalEXT = (int (WINAPI *) (void)) getProcAddress("wglGetSwapIntervalEXT");
+ get_proc_address(pfn_wglSwapIntervalEXT, "wglSwapIntervalEXT");
+ get_proc_address(pfn_wglGetSwapIntervalEXT, "wglGetSwapIntervalEXT");
}
else
{
pfn_wglSwapIntervalEXT = nullptr;
pfn_wglGetSwapIntervalEXT = nullptr;
}
-
- m_hdc = GetDC(window);
- if (!setupPixelFormat(m_hdc))
- {
- m_context = (*pfn_wglCreateContext)(m_hdc);
- if (!m_context)
- {
- FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, GetLastError(), 0, m_error, 255, nullptr);
- return;
- }
- (*pfn_wglMakeCurrent)(m_hdc, m_context);
- }
}
virtual ~win_gl_context()
{
- (*pfn_wglDeleteContext)(m_context);
- ReleaseDC(m_window, m_hdc);
+ if (m_context)
+ (*pfn_wglDeleteContext)(m_context);
+
+ if (m_hdc)
+ ReleaseDC(m_window, m_hdc);
+ }
+
+ virtual explicit operator bool() const override
+ {
+ return bool(m_context);
}
- virtual void MakeCurrent() override
+ virtual void make_current() override
{
(*pfn_wglMakeCurrent)(m_hdc, m_context);
}
- virtual const char *LastErrorMsg() override
+ virtual const char *last_error_message() override
{
- if (m_error[0] == 0)
- return nullptr;
+ if (!m_error.empty())
+ return m_error.c_str();
else
- return m_error;
+ return nullptr;
}
- virtual void *getProcAddress(const char *proc) override
+ virtual void *get_proc_address(const char *proc) override
{
- return (void *)(*pfn_wglGetProcAddress)(proc);
+ return reinterpret_cast<void *>(uintptr_t((*pfn_wglGetProcAddress)(proc)));
}
- virtual int SetSwapInterval(const int swap) override
+ virtual bool set_swap_interval(const int swap) override
{
- if (pfn_wglSwapIntervalEXT != nullptr)
- {
- pfn_wglSwapIntervalEXT(swap ? 1 : 0);
- }
- return 0;
+ if (!pfn_wglSwapIntervalEXT)
+ return false;
+
+ pfn_wglSwapIntervalEXT(swap ? 1 : 0);
+ return true;
}
- virtual void SwapBuffer() override
+ virtual void swap_buffer() override
{
SwapBuffers(m_hdc);
//wglSwapLayerBuffers(GetDC(window().m_hwnd), WGL_SWAP_MAIN_PLANE);
}
private:
+ // Typedefs for dynamically loaded functions
+ typedef PROC (WINAPI *wglGetProcAddress_fn)(LPCSTR);
+ typedef HGLRC (WINAPI *wglCreateContext_fn)(HDC);
+ typedef BOOL (WINAPI *wglDeleteContext_fn)(HGLRC);
+ typedef BOOL (WINAPI *wglMakeCurrent_fn)(HDC, HGLRC);
- int setupPixelFormat(HDC hDC)
+ typedef const char * (WINAPI *wglGetExtensionsStringEXT_fn)();
+ typedef BOOL (WINAPI *wglSwapIntervalEXT_fn)(int);
+ typedef int (WINAPI *wglGetSwapIntervalEXT_fn)();
+
+ bool setupPixelFormat()
{
PIXELFORMATDESCRIPTOR pfd = {
- sizeof(PIXELFORMATDESCRIPTOR), /* size */
- 1, /* version */
- PFD_SUPPORT_OPENGL |
- PFD_DRAW_TO_WINDOW |
- PFD_DOUBLEBUFFER, /* support double-buffering */
- PFD_TYPE_RGBA, /* color type */
- 32, /* prefered color depth */
- 0, 0, 0, 0, 0, 0, /* color bits (ignored) */
- 0, /* no alpha buffer */
- 0, /* alpha bits (ignored) */
- 0, /* no accumulation buffer */
- 0, 0, 0, 0, /* accum bits (ignored) */
- 16, /* depth buffer */
- 0, /* no stencil buffer */
- 0, /* no auxiliary buffers */
- PFD_MAIN_PLANE, /* main layer */
- 0, /* reserved */
- 0, 0, 0, /* no layer, visible, damage masks */
- };
-
- int pixelFormat = ChoosePixelFormat(hDC, &pfd);
-
+ sizeof(PIXELFORMATDESCRIPTOR), // size
+ 1, // version
+ PFD_SUPPORT_OPENGL |
+ PFD_DRAW_TO_WINDOW |
+ PFD_DOUBLEBUFFER, // support double-buffering
+ PFD_TYPE_RGBA, // color type
+ 32, // prefered color depth
+ 0, 0, 0, 0, 0, 0, // color bits (ignored)
+ 0, // no alpha buffer
+ 0, // alpha bits (ignored)
+ 0, // no accumulation buffer
+ 0, 0, 0, 0, // accum bits (ignored)
+ 16, // depth buffer
+ 0, // no stencil buffer
+ 0, // no auxiliary buffers
+ PFD_MAIN_PLANE, // main layer
+ 0, // reserved
+ 0, 0, 0, // no layer, visible, damage masks
+ };
+
+ const int pixelFormat = ChoosePixelFormat(m_hdc, &pfd);
if (pixelFormat == 0)
{
- strcpy(m_error, "ChoosePixelFormat failed.");
- return 1;
+ get_last_error_string();
+ return false;
}
- if (SetPixelFormat(hDC, pixelFormat, &pfd) != TRUE)
+ if (SetPixelFormat(m_hdc, pixelFormat, &pfd) != TRUE)
{
- strcpy(m_error, "SetPixelFormat failed.");
- return 1;
+ get_last_error_string();
+ return false;
}
- return 0;
+
+ return true;
}
bool WGLExtensionSupported(const char *extension_name)
{
- if (pfn_wglGetExtensionsStringEXT == nullptr)
+ if (!pfn_wglGetExtensionsStringEXT)
return false;
- // printf("%s\n", pfn_wglGetExtensionsStringEXT());
+ return strstr(pfn_wglGetExtensionsStringEXT(), extension_name) != nullptr;
+ }
- if (strstr(pfn_wglGetExtensionsStringEXT(), extension_name) != nullptr)
- return true;
- else
- return false;
+ void get_last_error_string()
+ {
+ LPTSTR buffer = nullptr;
+ const auto result = FormatMessage(
+ FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER,
+ nullptr,
+ GetLastError(),
+ 0,
+ LPTSTR(&buffer),
+ 0,
+ nullptr);
+ if (!result || !buffer)
+ {
+ m_error.clear();
+ return;
+ }
+ try { m_error = osd::text::from_tstring(buffer); }
+ catch (...) { m_error.clear(); }
+ LocalFree(buffer);
}
HGLRC m_context;
- HWND m_window;
+ HWND const m_window;
HDC m_hdc;
- char m_error[256];
+ std::string m_error;
osd::dynamic_module::ptr opengl32_dll;
wglGetProcAddress_fn pfn_wglGetProcAddress;
@@ -181,4 +210,4 @@ private:
wglGetSwapIntervalEXT_fn pfn_wglGetSwapIntervalEXT;
};
-#endif // __WIN_GL_CONTEXT__
+#endif // MAME_RENDER_WINGLCONTEXT_H
diff --git a/src/osd/modules/sound/coreaudio_sound.cpp b/src/osd/modules/sound/coreaudio_sound.cpp
index dcc74ec5fe9..2cdb9291168 100644
--- a/src/osd/modules/sound/coreaudio_sound.cpp
+++ b/src/osd/modules/sound/coreaudio_sound.cpp
@@ -8,10 +8,11 @@
#include "sound_module.h"
#include "modules/osdmodule.h"
-#include "modules/lib/osdobj_common.h"
#ifdef SDLMAME_MACOSX
+#include "modules/lib/osdobj_common.h"
+
#include <AvailabilityMacros.h>
#include <AudioToolbox/AudioToolbox.h>
#include <AudioUnit/AudioUnit.h>
@@ -24,16 +25,9 @@
#include <cstring>
-#ifdef MAC_OS_X_VERSION_MAX_ALLOWED
-
-#if MAC_OS_X_VERSION_MAX_ALLOWED < 1060
-
-typedef ComponentDescription AudioComponentDescription;
-
-#endif // MAC_OS_X_VERSION_MAX_ALLOWED < 1060
-
-#endif // MAC_OS_X_VERSION_MAX_ALLOWED
+namespace osd {
+namespace {
class sound_coreaudio : public osd_module, public sound_module
{
@@ -43,6 +37,8 @@ public:
sound_module(),
m_graph(nullptr),
m_node_count(0),
+ m_sample_rate(0),
+ m_audio_latency(0),
m_sample_bytes(0),
m_headroom(0),
m_buffer_size(0),
@@ -59,7 +55,7 @@ public:
{
}
- virtual int init(osd_options const &options) override;
+ virtual int init(osd_interface &osd, osd_options const &options) override;
virtual void exit() override;
// sound_module
@@ -173,25 +169,29 @@ private:
unsigned m_node_count;
node_detail m_node_details[EFFECT_COUNT_MAX + 2];
- uint32_t m_sample_bytes;
- uint32_t m_headroom;
- uint32_t m_buffer_size;
+ int m_sample_rate;
+ int m_audio_latency;
+ uint32_t m_sample_bytes;
+ uint32_t m_headroom;
+ uint32_t m_buffer_size;
std::unique_ptr<int8_t []> m_buffer;
- uint32_t m_playpos;
- uint32_t m_writepos;
+ uint32_t m_playpos;
+ uint32_t m_writepos;
bool m_in_underrun;
- int32_t m_scale;
+ int32_t m_scale;
unsigned m_overflows;
unsigned m_underflows;
};
-int sound_coreaudio::init(const osd_options &options)
+int sound_coreaudio::init(osd_interface &osd, const osd_options &options)
{
OSStatus err;
// Don't bother with any of this if sound is disabled
- if (sample_rate() == 0)
+ m_sample_rate = options.sample_rate();
+ m_audio_latency = options.audio_latency();
+ if (m_sample_rate == 0)
return 0;
// Create the output graph
@@ -201,7 +201,7 @@ int sound_coreaudio::init(const osd_options &options)
// Set audio stream format for two-channel native-endian 16-bit packed linear PCM
AudioStreamBasicDescription format;
- format.mSampleRate = sample_rate();
+ format.mSampleRate = m_sample_rate;
format.mFormatID = kAudioFormatLinearPCM;
format.mFormatFlags = kAudioFormatFlagsNativeEndian
| kLinearPCMFormatFlagIsSignedInteger
@@ -226,8 +226,8 @@ int sound_coreaudio::init(const osd_options &options)
m_sample_bytes = format.mBytesPerFrame;
// Allocate buffer
- m_headroom = m_sample_bytes * (clamped_latency() * sample_rate() / 40);
- m_buffer_size = m_sample_bytes * std::max<uint32_t>(sample_rate() * (clamped_latency() + 3) / 40, 256U);
+ m_headroom = m_sample_bytes * (clamped_latency() * m_sample_rate / 40);
+ m_buffer_size = m_sample_bytes * std::max<uint32_t>(m_sample_rate * (clamped_latency() + 3) / 40, 256U);
try
{
m_buffer = std::make_unique<int8_t []>(m_buffer_size);
@@ -292,7 +292,7 @@ void sound_coreaudio::exit()
void sound_coreaudio::update_audio_stream(bool is_throttled, int16_t const *buffer, int samples_this_frame)
{
- if ((sample_rate() == 0) || !m_buffer)
+ if ((m_sample_rate == 0) || !m_buffer)
return;
uint32_t const bytes_this_frame = samples_this_frame * m_sample_bytes;
@@ -927,16 +927,17 @@ CFPropertyListRef sound_coreaudio::load_property_list(char const *name) const
return nullptr;
}
- CFStringRef msg = nullptr;
- CFPropertyListRef const result = CFPropertyListCreateFromXMLData(
+ CFErrorRef msg = nullptr;
+ CFPropertyListRef const result = CFPropertyListCreateWithData(
nullptr,
data,
kCFPropertyListImmutable,
+ nullptr,
&msg);
CFRelease(data);
if ((nullptr == result) || (nullptr != msg))
{
- std::unique_ptr<char []> const buf = (nullptr != msg) ? convert_cfstring_to_utf8(msg) : nullptr;
+ std::unique_ptr<char []> const buf = (nullptr != msg) ? convert_cfstring_to_utf8(CFErrorCopyDescription(msg)) : nullptr;
if (nullptr != msg)
CFRelease(msg);
@@ -1013,8 +1014,14 @@ OSStatus sound_coreaudio::render_callback(
return ((sound_coreaudio *)refcon)->render(action_flags, timestamp, bus_number, number_frames, data);
}
-#else /* SDLMAME_MACOSX */
- MODULE_NOT_SUPPORTED(sound_coreaudio, OSD_SOUND_PROVIDER, "coreaudio")
-#endif
+} // anonymous namespace
+
+} // namespace osd
+
+#else // SDLMAME_MACOSX
+
+namespace osd { namespace { MODULE_NOT_SUPPORTED(sound_coreaudio, OSD_SOUND_PROVIDER, "coreaudio") } }
+
+#endif // SDLMAME_MACOSX
-MODULE_DEFINITION(SOUND_COREAUDIO, sound_coreaudio)
+MODULE_DEFINITION(SOUND_COREAUDIO, osd::sound_coreaudio)
diff --git a/src/osd/modules/sound/direct_sound.cpp b/src/osd/modules/sound/direct_sound.cpp
index ff4ba567c2c..0e89bb1ac0d 100644
--- a/src/osd/modules/sound/direct_sound.cpp
+++ b/src/osd/modules/sound/direct_sound.cpp
@@ -12,14 +12,16 @@
#if defined(OSD_WINDOWS) || defined(SDLMAME_WIN32)
// MAME headers
-#include "osdcore.h"
-#include "osdepend.h"
#include "emuopts.h"
+// osd headers
+#include "modules/lib/osdobj_common.h"
+#include "osdepend.h"
+#include "osdcore.h"
+
#ifdef SDLMAME_WIN32
-#include "../../sdl/osdsdl.h"
+#include "sdl/window.h"
#include <SDL2/SDL_syswm.h>
-#include "../../sdl/window.h"
#else
#include "winmain.h"
#include "window.h"
@@ -48,6 +50,8 @@
#define LOG(...) do { if (LOG_SOUND) osd_printf_verbose(__VA_ARGS__); } while(0)
+namespace osd {
+
namespace {
class buffer_base
@@ -203,10 +207,11 @@ private:
class sound_direct_sound : public osd_module, public sound_module
{
public:
-
sound_direct_sound() :
osd_module(OSD_SOUND_PROVIDER, "dsound"),
sound_module(),
+ m_sample_rate(0),
+ m_audio_latency(0),
m_bytes_per_sample(0),
m_primary_buffer(),
m_stream_buffer(),
@@ -215,9 +220,8 @@ public:
m_buffer_overflows(0)
{
}
- virtual ~sound_direct_sound() { }
- virtual int init(osd_options const &options) override;
+ virtual int init(osd_interface &osd, osd_options const &options) override;
virtual void exit() override;
// sound_module
@@ -233,6 +237,10 @@ private:
// DirectSound objects
Microsoft::WRL::ComPtr<IDirectSound> m_dsound;
+ // configuration
+ int m_sample_rate;
+ int m_audio_latency;
+
// descriptors and formats
uint32_t m_bytes_per_sample;
@@ -251,12 +259,16 @@ private:
// init
//============================================================
-int sound_direct_sound::init(osd_options const &options)
+int sound_direct_sound::init(osd_interface &osd, osd_options const &options)
{
- // attempt to initialize directsound
- // don't make it fatal if we can't -- we'll just run without sound
- dsound_init();
+ m_sample_rate = options.sample_rate();
+ m_audio_latency = options.audio_latency();
m_buffer_underflows = m_buffer_overflows = 0;
+
+ // attempt to initialize DirectSound
+ if (dsound_init() != DS_OK)
+ return -1;
+
return 0;
}
@@ -403,10 +415,14 @@ HRESULT sound_direct_sound::dsound_init()
#ifdef SDLMAME_WIN32
SDL_SysWMinfo wminfo;
SDL_VERSION(&wminfo.version);
- SDL_GetWindowWMInfo(std::dynamic_pointer_cast<sdl_window_info>(osd_common_t::s_window_list.front())->platform_window(), &wminfo);
+ if (!SDL_GetWindowWMInfo(dynamic_cast<sdl_window_info &>(*osd_common_t::window_list().front()).platform_window(), &wminfo))
+ {
+ result = DSERR_UNSUPPORTED; // just so it has something to return
+ goto error;
+ }
HWND const window = wminfo.info.win.window;
#else // SDLMAME_WIN32
- HWND const window = std::static_pointer_cast<win_window_info>(osd_common_t::s_window_list.front())->platform_window();
+ HWND const window = dynamic_cast<win_window_info &>(*osd_common_t::window_list().front()).platform_window();
#endif // SDLMAME_WIN32
result = m_dsound->SetCooperativeLevel(window, DSSCL_PRIORITY);
}
@@ -419,12 +435,13 @@ HRESULT sound_direct_sound::dsound_init()
{
// make a format description for what we want
WAVEFORMATEX stream_format;
- stream_format.wBitsPerSample = 16;
stream_format.wFormatTag = WAVE_FORMAT_PCM;
stream_format.nChannels = 2;
- stream_format.nSamplesPerSec = sample_rate();
+ stream_format.nSamplesPerSec = m_sample_rate;
+ stream_format.wBitsPerSample = 16;
stream_format.nBlockAlign = stream_format.wBitsPerSample * stream_format.nChannels / 8;
stream_format.nAvgBytesPerSec = stream_format.nSamplesPerSec * stream_format.nBlockAlign;
+ stream_format.cbSize = 0;
// compute the buffer size based on the output sample rate
int audio_latency = std::max(m_audio_latency, 1);
@@ -554,9 +571,14 @@ void sound_direct_sound::destroy_buffers()
} // anonymous namespace
+} // namespace osd
+
#else // defined(OSD_WINDOWS) || defined(SDLMAME_WIN32)
- MODULE_NOT_SUPPORTED(sound_direct_sound, OSD_SOUND_PROVIDER, "dsound")
+
+namespace osd { namespace { MODULE_NOT_SUPPORTED(sound_direct_sound, OSD_SOUND_PROVIDER, "dsound") } }
+
#endif // defined(OSD_WINDOWS) || defined(SDLMAME_WIN32)
-MODULE_DEFINITION(SOUND_DSOUND, sound_direct_sound)
+
+MODULE_DEFINITION(SOUND_DSOUND, osd::sound_direct_sound)
diff --git a/src/osd/modules/sound/js_sound.cpp b/src/osd/modules/sound/js_sound.cpp
index afcf6ec8f2b..7375d014141 100644
--- a/src/osd/modules/sound/js_sound.cpp
+++ b/src/osd/modules/sound/js_sound.cpp
@@ -11,7 +11,7 @@
#include "sound_module.h"
#include "modules/osdmodule.h"
-#if (defined(SDLMAME_EMSCRIPTEN))
+#if defined(SDLMAME_EMSCRIPTEN)
#include "emscripten.h"
@@ -19,36 +19,40 @@ class sound_js : public osd_module, public sound_module
{
public:
- sound_js()
- : osd_module(OSD_SOUND_PROVIDER, "js"), sound_module()
+ sound_js() : osd_module(OSD_SOUND_PROVIDER, "js"), sound_module()
{
}
virtual ~sound_js() { }
- virtual int init(const osd_options &options) { return 0; }
+ virtual int init(osd_interface &osd, const osd_options &options) { return 0; }
virtual void exit() { }
// sound_module
virtual void update_audio_stream(bool is_throttled, const int16_t *buffer, int samples_this_frame)
{
- EM_ASM_ARGS({
- // Forward audio stream update on to JS backend implementation.
- jsmame_update_audio_stream($0, $1);
- }, (unsigned int)buffer, samples_this_frame);
+ EM_ASM_ARGS(
+ {
+ // Forward audio stream update on to JS backend implementation.
+ jsmame_update_audio_stream($0, $1);
+ },
+ (unsigned int)buffer,
+ samples_this_frame);
}
+
virtual void set_mastervolume(int attenuation)
{
- EM_ASM_ARGS({
- // Forward volume update on to JS backend implementation.
- jsmame_set_mastervolume($0);
- }, attenuation);
+ EM_ASM_ARGS(
+ {
+ // Forward volume update on to JS backend implementation.
+ jsmame_set_mastervolume($0);
+ },
+ attenuation);
}
-
};
-#else /* SDLMAME_UNIX */
+#else // SDLMAME_EMSCRIPTEN
MODULE_NOT_SUPPORTED(sound_js, OSD_SOUND_PROVIDER, "js")
-#endif
+#endif // SDLMAME_EMSCRIPTEN
MODULE_DEFINITION(SOUND_JS, sound_js)
diff --git a/src/osd/modules/sound/js_sound.js b/src/osd/modules/sound/js_sound.js
index 5cbcc380c1b..571a5227f2b 100644
--- a/src/osd/modules/sound/js_sound.js
+++ b/src/osd/modules/sound/js_sound.js
@@ -173,10 +173,11 @@ function tick (event) {
start = 0;
}
}
- //Pad with silence if we're underrunning:
+ //Pad with latest if we're underrunning:
+ var idx = (index == 0 ? bufferSize : index) - 1;
while (index < 4096) {
- buffers[0][index] = 0;
- buffers[1][index++] = 0;
+ buffers[0][index] = buffers[0][idx];
+ buffers[1][index++] = buffers[1][idx];
}
//Deep inside the bowels of vendors bugs,
//we're using watchdog for a firefox bug,
diff --git a/src/osd/modules/sound/none.cpp b/src/osd/modules/sound/none.cpp
index 685cdc884c2..ba1085f436b 100644
--- a/src/osd/modules/sound/none.cpp
+++ b/src/osd/modules/sound/none.cpp
@@ -2,32 +2,40 @@
// copyright-holders:Miodrag Milanovic
/***************************************************************************
- none.c
+ none.cpp
Dummy sound interface.
*******************************************************************c********/
#include "sound_module.h"
+
#include "modules/osdmodule.h"
+
+namespace osd {
+
+namespace {
+
class sound_none : public osd_module, public sound_module
{
public:
- sound_none()
- : osd_module(OSD_SOUND_PROVIDER, "none"), sound_module()
+ sound_none() : osd_module(OSD_SOUND_PROVIDER, "none")
{
}
virtual ~sound_none() { }
- virtual int init(const osd_options &options) override { return 0; }
+ virtual int init(osd_interface &osd, const osd_options &options) override { return 0; }
virtual void exit() override { }
// sound_module
virtual void update_audio_stream(bool is_throttled, const int16_t *buffer, int samples_this_frame) override { }
virtual void set_mastervolume(int attenuation) override { }
-
};
-MODULE_DEFINITION(SOUND_NONE, sound_none)
+} // anonymous namespace
+
+} // namespace osd
+
+MODULE_DEFINITION(SOUND_NONE, osd::sound_none)
diff --git a/src/osd/modules/sound/pa_sound.cpp b/src/osd/modules/sound/pa_sound.cpp
index 9472f6812cb..d5bb96a25af 100644
--- a/src/osd/modules/sound/pa_sound.cpp
+++ b/src/osd/modules/sound/pa_sound.cpp
@@ -9,40 +9,45 @@
*******************************************************************c********/
#include "sound_module.h"
+
#include "modules/osdmodule.h"
#ifndef NO_USE_PORTAUDIO
-#include <portaudio.h>
#include "modules/lib/osdobj_common.h"
+#include "osdcore.h"
-#include <iostream>
-#include <fstream>
-#include <sstream>
+#include <portaudio.h>
+
+#include <algorithm>
#include <atomic>
-#include <cmath>
#include <climits>
-#include <algorithm>
+#include <cmath>
+#include <fstream>
+#include <iostream>
+#include <sstream>
#ifdef _WIN32
#include "pa_win_wasapi.h"
#endif
+
+namespace osd {
+
+namespace {
+
#define LOG_FILE "pa.log"
#define LOG_BUFCNT 0
-using osd::s16;
-
class sound_pa : public osd_module, public sound_module
{
public:
- sound_pa()
- : osd_module(OSD_SOUND_PROVIDER, "portaudio"), sound_module()
+ sound_pa() : osd_module(OSD_SOUND_PROVIDER, "portaudio")
{
}
virtual ~sound_pa() { }
- virtual int init(osd_options const &options) override;
+ virtual int init(osd_interface &osd, osd_options const &options) override;
virtual void exit() override;
// sound_module
@@ -152,6 +157,8 @@ private:
PaStream* m_pa_stream;
PaError err;
+ int m_sample_rate;
+ int m_audio_latency;
int m_attenuation;
audio_buffer<s16>* m_ab;
@@ -172,8 +179,12 @@ private:
#endif
};
-int sound_pa::init(osd_options const &options)
+int sound_pa::init(osd_interface &osd, osd_options const &options)
{
+ m_sample_rate = options.sample_rate();
+ if (!m_sample_rate)
+ return 0;
+
PaStreamParameters stream_params;
const PaStreamInfo* stream_info;
const PaHostApiInfo* api_info;
@@ -182,9 +193,6 @@ int sound_pa::init(osd_options const &options)
unsigned long frames_per_callback = paFramesPerBufferUnspecified;
double callback_interval;
- if (!sample_rate())
- return 0;
-
m_attenuation = options.volume();
m_underflows = 0;
m_overflows = 0;
@@ -194,7 +202,7 @@ int sound_pa::init(osd_options const &options)
m_skip_threshold_ticks = 0;
m_osd_tps = osd_ticks_per_second();
m_buffer_min_ct = INT_MAX;
- m_audio_latency = std::clamp<int>(m_audio_latency, LATENCY_MIN, LATENCY_MAX);
+ m_audio_latency = std::clamp<int>(options.audio_latency(), LATENCY_MIN, LATENCY_MAX);
try {
m_ab = new audio_buffer<s16>(m_sample_rate, 2);
@@ -366,7 +374,7 @@ int sound_pa::callback(s16* output_buffer, size_t number_of_samples)
int adjust = m_buffer_min_ct - m_skip_threshold / 2;
// if adjustment is less than two milliseconds, don't bother
- if (adjust / 2 > sample_rate() / 500) {
+ if (adjust / 2 > m_sample_rate / 500) {
m_ab->increment_playpos(adjust);
m_has_overflowed = true;
}
@@ -393,7 +401,7 @@ int sound_pa::callback(s16* output_buffer, size_t number_of_samples)
void sound_pa::update_audio_stream(bool is_throttled, const s16 *buffer, int samples_this_frame)
{
- if (!sample_rate())
+ if (!m_sample_rate)
return;
#if LOG_BUFCNT
@@ -428,7 +436,7 @@ void sound_pa::set_mastervolume(int attenuation)
void sound_pa::exit()
{
- if (!sample_rate())
+ if (!m_sample_rate)
return;
#if LOG_BUFCNT
@@ -458,8 +466,14 @@ void sound_pa::exit()
osd_printf_verbose("Sound: overflows=%d underflows=%d\n", m_overflows, m_underflows);
}
+} // anonymous namespace
+
+} // namespace osd
+
#else
- MODULE_NOT_SUPPORTED(sound_pa, OSD_SOUND_PROVIDER, "portaudio")
+
+namespace osd { namespace { MODULE_NOT_SUPPORTED(sound_pa, OSD_SOUND_PROVIDER, "portaudio") } }
+
#endif
-MODULE_DEFINITION(SOUND_PORTAUDIO, sound_pa)
+MODULE_DEFINITION(SOUND_PORTAUDIO, osd::sound_pa)
diff --git a/src/osd/modules/sound/pulse_sound.cpp b/src/osd/modules/sound/pulse_sound.cpp
index e9e6ea4d428..373913f9f91 100644
--- a/src/osd/modules/sound/pulse_sound.cpp
+++ b/src/osd/modules/sound/pulse_sound.cpp
@@ -38,7 +38,7 @@ public:
}
virtual ~sound_pulse() { }
- virtual int init(osd_options const &options) override;
+ virtual int init(osd_interface &osd, osd_options const &options) override;
virtual void exit() override;
virtual void update_audio_stream(bool is_throttled, const s16 *buffer, int samples_this_frame) override;
virtual void set_mastervolume(int attenuation) override;
@@ -120,7 +120,7 @@ char sound_pulse::get_main()
{
pollfd pfds[1];
pfds[0].fd = m_pipe_to_main[0];
- pfds[0].events = POLL_IN;
+ pfds[0].events = POLLIN;
pfds[0].revents = 0;
int err = poll(pfds, 1, -1);
if(err < 0)
@@ -273,7 +273,7 @@ void sound_pulse::stop_mainloop(int err)
pa_mainloop_quit(m_mainloop, err);
}
-int sound_pulse::init(osd_options const &options)
+int sound_pulse::init(osd_interface &osd, osd_options const &options)
{
m_last_sample = 0;
m_setting_volume = false;
@@ -296,24 +296,26 @@ int sound_pulse::init(osd_options const &options)
if(res != 'r')
return 1;
+ const int sample_rate = options.sample_rate();
+
pa_sample_spec ss;
#ifdef LSB_FIRST
ss.format = PA_SAMPLE_S16LE;
#else
ss.format = PA_SAMPLE_S16BE;
#endif
- ss.rate = sample_rate();
+ ss.rate = sample_rate;
ss.channels = 2;
m_stream = pa_stream_new(m_context, "main output", &ss, nullptr);
pa_stream_set_state_callback(m_stream, i_stream_notify, this);
pa_stream_set_write_callback(m_stream, i_stream_write_request, this);
pa_buffer_attr battr;
- battr.fragsize = sample_rate() / 1000;
+ battr.fragsize = sample_rate / 1000;
battr.maxlength = uint32_t(-1);
- battr.minreq = sample_rate() / 1000;
+ battr.minreq = sample_rate / 1000;
battr.prebuf = uint32_t(-1);
- battr.tlength = sample_rate() / 1000;
+ battr.tlength = sample_rate / 1000;
err = pa_stream_connect_playback(m_stream, nullptr, &battr, PA_STREAM_ADJUST_LATENCY, nullptr, nullptr);
if(err)
diff --git a/src/osd/modules/sound/sdl_sound.cpp b/src/osd/modules/sound/sdl_sound.cpp
index 9b65a6c176b..ba7082312ea 100644
--- a/src/osd/modules/sound/sdl_sound.cpp
+++ b/src/osd/modules/sound/sdl_sound.cpp
@@ -9,28 +9,34 @@
//============================================================
#include "sound_module.h"
+
#include "modules/osdmodule.h"
#if (defined(OSD_SDL) || defined(USE_SDL_SOUND))
-// standard sdl header
-#include <SDL2/SDL.h>
-
-// MAME headers
-#include "emuopts.h"
+#include "modules/lib/osdobj_common.h"
#include "osdcore.h"
-#include "../../sdl/osdsdl.h"
+// standard sdl header
+#include <SDL2/SDL.h>
#include <algorithm>
#include <fstream>
#include <memory>
+
+namespace osd {
+
+namespace {
+
//============================================================
// DEBUGGING
//============================================================
-#define LOG_SOUND 0
+#define LOG_SOUND 0
+
+#define SDLMAME_SOUND_LOG "sound.log"
+
//============================================================
// CLASS
@@ -41,18 +47,24 @@ class sound_sdl : public osd_module, public sound_module
public:
// number of samples per SDL callback
- static const int SDL_XFER_SAMPLES = 512;
+ static inline constexpr int SDL_XFER_SAMPLES = 512;
sound_sdl() :
osd_module(OSD_SOUND_PROVIDER, "sdl"), sound_module(),
+ sample_rate(0),
+ sdl_xfer_samples(SDL_XFER_SAMPLES),
stream_in_initialized(0),
- attenuation(0), buf_locked(0), stream_buffer(nullptr), stream_buffer_size(0), buffer_underflows(0), buffer_overflows(0)
-{
- sdl_xfer_samples = SDL_XFER_SAMPLES;
+ attenuation(0),
+ buf_locked(0),
+ stream_buffer(nullptr),
+ stream_buffer_size(0),
+ buffer_underflows(0),
+ buffer_overflows(0)
+ {
}
virtual ~sound_sdl() { }
- virtual int init(const osd_options &options) override;
+ virtual int init(osd_interface &osd, const osd_options &options) override;
virtual void exit() override;
// sound_module
@@ -86,6 +98,7 @@ private:
int sdl_create_buffers();
void sdl_destroy_buffers();
+ int sample_rate;
int sdl_xfer_samples;
int stream_in_initialized;
int attenuation;
@@ -239,10 +252,9 @@ void sound_sdl::copy_sample_data(bool is_throttled, const int16_t *data, int byt
void sound_sdl::update_audio_stream(bool is_throttled, const int16_t *buffer, int samples_this_frame)
{
// if nothing to do, don't do it
- if (sample_rate() == 0 || !stream_buffer)
+ if (sample_rate == 0 || !stream_buffer)
return;
-
if (!stream_in_initialized)
{
// Fill in some zeros to prevent an initial buffer underflow
@@ -330,7 +342,7 @@ void sound_sdl::sdl_callback(void *userdata, Uint8 *stream, int len)
// sound_sdl::init
//============================================================
-int sound_sdl::init(const osd_options &options)
+int sound_sdl::init(osd_interface &osd, const osd_options &options)
{
int n_channels = 2;
int audio_latency;
@@ -340,7 +352,8 @@ int sound_sdl::init(const osd_options &options)
sound_log = std::make_unique<std::ofstream>(SDLMAME_SOUND_LOG);
// skip if sound disabled
- if (sample_rate() != 0)
+ sample_rate = options.sample_rate();
+ if (sample_rate != 0)
{
if (SDL_InitSubSystem(SDL_INIT_AUDIO))
{
@@ -356,7 +369,7 @@ int sound_sdl::init(const osd_options &options)
stream_in_initialized = 0;
// set up the audio specs
- aspec.freq = sample_rate();
+ aspec.freq = sample_rate;
aspec.format = AUDIO_S16SYS; // keep endian independent
aspec.channels = n_channels;
aspec.samples = sdl_xfer_samples;
@@ -372,10 +385,10 @@ int sound_sdl::init(const osd_options &options)
sdl_xfer_samples = obtained.samples;
// pin audio latency
- audio_latency = std::clamp(m_audio_latency, 1, MAX_AUDIO_LATENCY);
+ audio_latency = std::clamp(options.audio_latency(), 1, MAX_AUDIO_LATENCY);
// compute the buffer sizes
- stream_buffer_size = (sample_rate() * 2 * sizeof(int16_t) * (2 + audio_latency)) / 30;
+ stream_buffer_size = (sample_rate * 2 * sizeof(int16_t) * (2 + audio_latency)) / 30;
stream_buffer_size = (stream_buffer_size / 1024) * 1024;
if (stream_buffer_size < 1024)
stream_buffer_size = 1024;
@@ -409,7 +422,7 @@ int sound_sdl::init(const osd_options &options)
void sound_sdl::exit()
{
// if nothing to do, don't do it
- if (sample_rate() == 0)
+ if (sample_rate == 0)
return;
osd_printf_verbose("sdl_kill: closing audio\n");
@@ -456,10 +469,15 @@ void sound_sdl::sdl_destroy_buffers()
stream_buffer.reset();
}
+} // anonymous namespace
+
+} // namespace osd
+
+
+#else // (defined(OSD_SDL) || defined(USE_SDL_SOUND))
+namespace osd { namespace { MODULE_NOT_SUPPORTED(sound_sdl, OSD_SOUND_PROVIDER, "sdl") } }
-#else /* SDLMAME_UNIX */
- MODULE_NOT_SUPPORTED(sound_sdl, OSD_SOUND_PROVIDER, "sdl")
#endif
-MODULE_DEFINITION(SOUND_SDL, sound_sdl)
+MODULE_DEFINITION(SOUND_SDL, osd::sound_sdl)
diff --git a/src/osd/modules/sound/sound_module.h b/src/osd/modules/sound/sound_module.h
index b72f50f7c8c..088da5ea8d0 100644
--- a/src/osd/modules/sound/sound_module.h
+++ b/src/osd/modules/sound/sound_module.h
@@ -4,9 +4,10 @@
* sound_module.h
*
*/
+#ifndef MAME_OSD_SOUND_SOUND_MODULE_H
+#define MAME_OSD_SOUND_SOUND_MODULE_H
-#ifndef SOUND_MODULE_H_
-#define SOUND_MODULE_H_
+#pragma once
#include <cstdint>
@@ -19,17 +20,10 @@
class sound_module
{
public:
- sound_module() : m_sample_rate(0), m_audio_latency(1) { }
-
- virtual ~sound_module() { }
+ virtual ~sound_module() = default;
virtual void update_audio_stream(bool is_throttled, const int16_t *buffer, int samples_this_frame) = 0;
virtual void set_mastervolume(int attenuation) = 0;
-
- int sample_rate() const { return m_sample_rate; }
-
- int m_sample_rate;
- int m_audio_latency;
};
-#endif /* FONT_MODULE_H_ */
+#endif // MAME_OSD_SOUND_SOUND_MODULE_H
diff --git a/src/osd/modules/sound/xaudio2_sound.cpp b/src/osd/modules/sound/xaudio2_sound.cpp
index 2b797e7ec8f..d0243ba1267 100644
--- a/src/osd/modules/sound/xaudio2_sound.cpp
+++ b/src/osd/modules/sound/xaudio2_sound.cpp
@@ -7,19 +7,17 @@
//====================================================================
#include "sound_module.h"
-#include "modules/osdmodule.h"
-
-#if defined(OSD_WINDOWS)
-
-// standard windows headers
-#include <windows.h>
-#include <wrl/client.h>
+#include "modules/osdmodule.h"
-// XAudio2 include
-#include <xaudio2.h>
+#if defined(OSD_WINDOWS) | defined(SDLMAME_WIN32)
-#undef interface
+// OSD headers
+#include "modules/lib/osdlib.h"
+#include "modules/lib/osdobj_common.h"
+#include "osdcore.h"
+#include "osdepend.h"
+#include "windows/winutil.h"
// stdlib includes
#include <algorithm>
@@ -28,13 +26,18 @@
#include <queue>
#include <thread>
-// MAME headers
-#include "osdcore.h"
-#include "osdepend.h"
+// standard windows headers
+#include <windows.h>
-#include "winutil.h"
+#include <wrl/client.h>
+
+// XAudio2 include
+#include <xaudio2.h>
-#include "modules/lib/osdlib.h"
+
+namespace osd {
+
+namespace {
//============================================================
// Constants
@@ -181,29 +184,6 @@ public:
// The main class for the XAudio2 sound module implementation
class sound_xaudio2 : public osd_module, public sound_module, public IXAudio2VoiceCallback
{
-private:
- Microsoft::WRL::ComPtr<IXAudio2> m_xAudio2;
- mastering_voice_ptr m_masterVoice;
- src_voice_ptr m_sourceVoice;
- DWORD m_sample_bytes;
- std::unique_ptr<BYTE[]> m_buffer;
- DWORD m_buffer_size;
- DWORD m_buffer_count;
- DWORD m_writepos;
- std::mutex m_buffer_lock;
- HANDLE m_hEventBufferCompleted;
- HANDLE m_hEventDataAvailable;
- HANDLE m_hEventExiting;
- std::thread m_audioThread;
- std::queue<xaudio2_buffer> m_queue;
- std::unique_ptr<bufferpool> m_buffer_pool;
- uint32_t m_overflows;
- uint32_t m_underflows;
- BOOL m_in_underflow;
- BOOL m_initialized;
- OSD_DYNAMIC_API(xaudio2, "XAudio2_9.dll", "XAudio2_8.dll");
- OSD_DYNAMIC_API_FN(xaudio2, HRESULT, WINAPI, XAudio2Create, IXAudio2 **, uint32_t, XAUDIO2_PROCESSOR);
-
public:
sound_xaudio2() :
osd_module(OSD_SOUND_PROVIDER, "xaudio2"),
@@ -211,6 +191,8 @@ public:
m_xAudio2(nullptr),
m_masterVoice(nullptr),
m_sourceVoice(nullptr),
+ m_sample_rate(0),
+ m_audio_latency(0),
m_sample_bytes(0),
m_buffer(nullptr),
m_buffer_size(0),
@@ -227,26 +209,24 @@ public:
{
}
- virtual ~sound_xaudio2() { }
-
bool probe() override;
- int init(osd_options const &options) override;
+ int init(osd_interface &osd, osd_options const &options) override;
void exit() override;
// sound_module
void update_audio_stream(bool is_throttled, int16_t const *buffer, int samples_this_frame) override;
void set_mastervolume(int attenuation) override;
+private:
// Xaudio callbacks
- void STDAPICALLTYPE OnVoiceProcessingPassStart(uint32_t bytes_required) override;
- void STDAPICALLTYPE OnVoiceProcessingPassEnd() override {}
- void STDAPICALLTYPE OnStreamEnd() override {}
- void STDAPICALLTYPE OnBufferStart(void* pBufferContext) override {}
- void STDAPICALLTYPE OnLoopEnd(void* pBufferContext) override {}
- void STDAPICALLTYPE OnVoiceError(void* pBufferContext, HRESULT error) override {}
- void STDAPICALLTYPE OnBufferEnd(void *pBufferContext) override;
+ void STDAPICALLTYPE OnVoiceProcessingPassStart(uint32_t bytes_required) noexcept override;
+ void STDAPICALLTYPE OnVoiceProcessingPassEnd() noexcept override {}
+ void STDAPICALLTYPE OnStreamEnd() noexcept override {}
+ void STDAPICALLTYPE OnBufferStart(void* pBufferContext) noexcept override {}
+ void STDAPICALLTYPE OnLoopEnd(void* pBufferContext) noexcept override {}
+ void STDAPICALLTYPE OnVoiceError(void* pBufferContext, HRESULT error) noexcept override {}
+ void STDAPICALLTYPE OnBufferEnd(void *pBufferContext) noexcept override;
-private:
void create_buffers(const WAVEFORMATEX &format);
HRESULT create_voices(const WAVEFORMATEX &format);
void process_audio();
@@ -254,6 +234,31 @@ private:
void submit_needed();
void roll_buffer();
BOOL submit_next_queued();
+
+ Microsoft::WRL::ComPtr<IXAudio2> m_xAudio2;
+ mastering_voice_ptr m_masterVoice;
+ src_voice_ptr m_sourceVoice;
+ int m_sample_rate;
+ int m_audio_latency;
+ DWORD m_sample_bytes;
+ std::unique_ptr<BYTE[]> m_buffer;
+ DWORD m_buffer_size;
+ DWORD m_buffer_count;
+ DWORD m_writepos;
+ std::mutex m_buffer_lock;
+ HANDLE m_hEventBufferCompleted;
+ HANDLE m_hEventDataAvailable;
+ HANDLE m_hEventExiting;
+ std::thread m_audioThread;
+ std::queue<xaudio2_buffer> m_queue;
+ std::unique_ptr<bufferpool> m_buffer_pool;
+ uint32_t m_overflows;
+ uint32_t m_underflows;
+ BOOL m_in_underflow;
+ BOOL m_initialized;
+
+ OSD_DYNAMIC_API(xaudio2, "XAudio2_9.dll", "XAudio2_8.dll");
+ OSD_DYNAMIC_API_FN(xaudio2, HRESULT, WINAPI, XAudio2Create, IXAudio2 **, uint32_t, XAUDIO2_PROCESSOR);
};
//============================================================
@@ -269,14 +274,9 @@ bool sound_xaudio2::probe()
// init
//============================================================
-int sound_xaudio2::init(osd_options const &options)
+int sound_xaudio2::init(osd_interface &osd, osd_options const &options)
{
- HRESULT result;
- WAVEFORMATEX format = {0};
- auto init_start = std::chrono::system_clock::now();
- std::chrono::milliseconds init_time;
-
- CoInitializeEx(nullptr, COINIT_MULTITHREADED);
+ auto const init_start = std::chrono::system_clock::now();
// Make sure our XAudio2Create entrypoint is bound
if (!OSD_DYNAMIC_API_TEST(XAudio2Create))
@@ -285,6 +285,13 @@ int sound_xaudio2::init(osd_options const &options)
return 1;
}
+ HRESULT result;
+ std::chrono::milliseconds init_time;
+ WAVEFORMATEX format = { 0 };
+
+ m_sample_rate = options.sample_rate();
+ m_audio_latency = options.audio_latency();
+
// Create the IXAudio2 object
HR_GOERR(OSD_DYNAMIC_CALL(XAudio2Create, m_xAudio2.GetAddressOf(), 0, XAUDIO2_DEFAULT_PROCESSOR));
@@ -292,7 +299,7 @@ int sound_xaudio2::init(osd_options const &options)
format.wBitsPerSample = 16;
format.wFormatTag = WAVE_FORMAT_PCM;
format.nChannels = 2;
- format.nSamplesPerSec = sample_rate();
+ format.nSamplesPerSec = m_sample_rate;
format.nBlockAlign = format.wBitsPerSample * format.nChannels / 8;
format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign;
@@ -311,10 +318,10 @@ int sound_xaudio2::init(osd_options const &options)
HR_GOERR(m_sourceVoice->Start());
// Start the thread listening
- m_audioThread = std::thread([](sound_xaudio2* self) { self->process_audio(); }, this);
+ m_audioThread = std::thread([] (sound_xaudio2 *self) { self->process_audio(); }, this);
init_time = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - init_start);
- osd_printf_verbose("Sound: XAudio2 initialized. %d ms.\n", static_cast<int>(init_time.count()));
+ osd_printf_verbose("Sound: XAudio2 initialized. %d ms.\n", init_time.count());
m_initialized = TRUE;
return 0;
@@ -377,7 +384,7 @@ void sound_xaudio2::update_audio_stream(
int16_t const *buffer,
int samples_this_frame)
{
- if (!m_initialized || sample_rate() == 0 || !m_buffer)
+ if (!m_initialized || m_sample_rate == 0 || !m_buffer)
return;
uint32_t const bytes_this_frame = samples_this_frame * m_sample_bytes;
@@ -437,7 +444,7 @@ void sound_xaudio2::set_mastervolume(int attenuation)
//============================================================
// The XAudio2 voice callback triggered when a buffer finishes playing
-void sound_xaudio2::OnBufferEnd(void *pBufferContext)
+void sound_xaudio2::OnBufferEnd(void *pBufferContext) noexcept
{
BYTE* completed_buffer = static_cast<BYTE*>(pBufferContext);
if (completed_buffer != nullptr)
@@ -454,7 +461,7 @@ void sound_xaudio2::OnBufferEnd(void *pBufferContext)
//============================================================
// The XAudio2 voice callback triggered on every pass
-void sound_xaudio2::OnVoiceProcessingPassStart(uint32_t bytes_required)
+void sound_xaudio2::OnVoiceProcessingPassStart(uint32_t bytes_required) noexcept
{
if (bytes_required == 0)
{
@@ -528,7 +535,7 @@ HRESULT sound_xaudio2::create_voices(const WAVEFORMATEX &format)
m_xAudio2->CreateMasteringVoice(
&temp_master_voice,
format.nChannels,
- sample_rate()));
+ m_sample_rate));
m_masterVoice = mastering_voice_ptr(temp_master_voice);
@@ -695,9 +702,15 @@ void sound_xaudio2::roll_buffer()
}
}
+} // anonymous namespace
+
+} // namespace osd
+
#else
-MODULE_NOT_SUPPORTED(sound_xaudio2, OSD_SOUND_PROVIDER, "xaudio2")
+
+namespace osd { namespace { MODULE_NOT_SUPPORTED(sound_xaudio2, OSD_SOUND_PROVIDER, "xaudio2") } }
+
#endif
-MODULE_DEFINITION(SOUND_XAUDIO2, sound_xaudio2)
+MODULE_DEFINITION(SOUND_XAUDIO2, osd::sound_xaudio2)