blob: b507182e63d4b8cbf72e244bac29ccadef2897b8 [file] [log] [blame]
##########################################################################
#
# 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<void *, void *> _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 <string.h>')
print()
print(r'#include <iostream>')
print()
print(r'#include "d3dretrace.hpp"')
print()
api = API()
print(r'#include "d3dimports.hpp"')
api.addModule(ddraw)
print()
print('''static d3dretrace::D3DDumper<IDirect3DDevice7> d3d7Dumper;''')
print()
retracer = D3DRetracer()
retracer.table_name = 'd3dretrace::ddraw_callbacks'
retracer.retraceApi(api)
if __name__ == '__main__':
main()