########################################################################## # # Copyright 2011 Jose Fonseca # All Rights Reserved. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. # ##########################################################################/ """D3D retracer generator.""" import sys from dllretrace import DllRetracer as Retracer from specs.stdapi import API from specs.d3d import ddraw, HWND from specs.ddraw import DDCREATE_LPGUID class D3DRetracer(Retracer): def retraceApi(self, api): print '// Swizzling mapping for lock addresses' print 'static std::map _maps;' print # TODO: Keep a table of windows print 'static HWND g_hWnd;' print Retracer.retraceApi(self, api) def invokeInterfaceMethod(self, interface, method): # keep track of the last used device for state dumping if interface.name in ('IDirect3DDevice7',): if method.name == 'Release': print r' if (call.ret->toUInt() == 0) {' print r' d3d7Dumper.unbindDevice(_this);' print r' }' else: print r' d3d7Dumper.bindDevice(_this);' # create windows as neccessary hWndArg = method.getArgByType(HWND) if hWndArg is not None: # FIXME: Try to guess the window size (e.g., from IDirectDrawSurface7::Blt) print r' if (!g_hWnd) {' print r' g_hWnd = d3dretrace::createWindow(512, 512);' print r' }' print r' %s = g_hWnd;' % hWndArg.name if method.name == 'Lock': # Reset _DONOTWAIT flags. Otherwise they may fail, and we have no # way to cope with it (other than retry). mapFlagsArg = method.getArgByName('dwFlags') if mapFlagsArg is not None: print r' dwFlags &= ~DDLOCK_DONOTWAIT;' print r' dwFlags |= DDLOCK_WAIT;' Retracer.invokeInterfaceMethod(self, interface, method) if method.name == 'CreateDevice': print r' if (FAILED(_result)) {' print r' exit(1);' print r' }' # notify frame has been completed # process events after presents if interface.name == 'IDirectDrawSurface7' and method.name == 'Blt': print r' DDSCAPS2 ddsCaps;' print r' if (SUCCEEDED(_this->GetCaps(&ddsCaps)) &&' print r' (ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)) {' print r' retrace::frameComplete(call);' print r' d3dretrace::processEvents();' print r' }' if method.name == 'Lock': print ' VOID *_pbData = NULL;' print ' size_t _MappedSize = 0;' # FIXME: determine the mapping size #print ' _getMapInfo(_this, %s, _pbData, _MappedSize);' % ', '.join(method.argNames()[:-1]) print ' if (_MappedSize) {' print ' _maps[_this] = _pbData;' # TODO: check pitches match print ' } else {' print ' return;' print ' }' if method.name == 'Unlock': print ' VOID *_pbData = 0;' print ' _pbData = _maps[_this];' print ' if (_pbData) {' print ' retrace::delRegionByPointer(_pbData);' print ' _maps[_this] = 0;' print ' }' def extractArg(self, function, arg, arg_type, lvalue, rvalue): # Handle DDCREATE_* flags if arg.type is DDCREATE_LPGUID: print ' if (%s.toArray()) {' % rvalue Retracer.extractArg(self, function, arg, arg_type, lvalue, rvalue) print ' } else {' print ' %s = static_cast<%s>(%s.toPointer());' % (lvalue, arg_type, rvalue) print ' }' return Retracer.extractArg(self, function, arg, arg_type, lvalue, rvalue) def main(): print r'#include ' print print r'#include ' print print r'#include "d3dretrace.hpp"' print api = API() print r'#include "d3dimports.hpp"' api.addModule(ddraw) print print '''static d3dretrace::D3DDumper d3d7Dumper;''' print retracer = D3DRetracer() retracer.table_name = 'd3dretrace::ddraw_callbacks' retracer.retraceApi(api) if __name__ == '__main__': main()