chris spencer

Upload: shree-bhaskar-shastri

Post on 03-Jun-2018

227 views

Category:

Documents


0 download

TRANSCRIPT

  • 8/12/2019 Chris Spencer

    1/14

    Linking to a WinSxS DLL that might not be therePosted on February 9, 2014 by Chris Spencer

    Sometimes it is necessary to link to a DLL that might not be installed on the users system. Usually this is to addsupport for new features, but to still gracefully handle the case where it is not available. For eample, you might

    want to use Direct! "" on #indows $, but fall back to Direct! % on #indows !&.

    'his is generally (uite straightforward to achieve by using LoadLibraryand GetProcAddress at runtime to load the

    re(uired library if its available)

    'his process becomes somewhat more complicated when using a side*by*side DLL, due to the way they are

    loaded. Linking to SS DLLs re(uires you to include an entry in the application manifest which allows the SS

    loader to find the right DLL. 'o use #indows +ista style common controls, for eample, you have to insert the

    following as a dependent assembly into your manifest)

    f the SS DLL is not present on the users machine then the application will fail to start. -owever, you cant

    simply remove it and try to load it at runtime instead, as then the call to LoadLibrarywont be able to find it.

    'he solution to this catch* re(uires you to embed a separate manifest in the application resources which

    references the assembly, modify the activation contetto load this manifest at runtime, then finally try to load

    the DLL. For the sake of clarity, ve omitted any error checking in the code below.

    f the DLL isnt available, CreateActCtxwill return INVALID_HANDLE_VALUE and GetLastError() will return

    ERROR_SXS_CAN_GEN_ACCX . f the activation contet is successfully created then it is simply a case of activating it and

    loading the library as normal)

    Chris Spencer

    !"#$

    %&'

    HMODULEd#d!! * LoadLibrary+(L,d#d!!-d..,)/if(d#d!!)0 autoD#D!!CreateDe1ice_ *

    reinterpret_cast2decltype(3D#D!!CreateDe1ice)4( GetProcAddress(d#d!!5 ,D#D!!CreateDe1ice,))/ 66 ---7

    !"

    #$%&'

    2assemblyIdentity ty8e*,9i:#",

    :a;e*,Co:tro.s, 1ersio:*,&-?-?-?, 8rocessorArc@itectre*,x&, 8b.icBeyoe:*,&%%b&$!$$cc=!d=, .a:ae*,F,64

    !"#$%&'

    ACCX+ actctx * 0 ? 7/actctx-cbSie * sizeof(actctx)/actctx-d9.as * ACCX_LAG_RESOURCE_NA

  • 8/12/2019 Chris Spencer

    2/14

    'he activation contet is no longer re(uired after loading the DLL, so its a good idea to clean up after yourself)

    'his techni(ue is also useful if you want to support multiple different versions of the same library by including a

    separate manifest for each version of the library you support and trying each of them in order at runtime until

    one of them works.

    / complete eample which attempts to load three different versions of the 0icrosoft Flight Simulator

    Sim1onnect SD2 can be downloaded here) Sim1onnectLoader.3ip.

    Posted in programming | Comments Off

    Ineffective small functor optimisation in Visual Studio 2012Posted on February 2, 2014 by Chris Spencer

    144"" introduced the stdJJ=:ctio:class, which acts as a generic wrapper around something callable 5a functor6.

    /mong other things, these are very useful for callback functions, as they allow non*static member functions to

    be used, which isnt possible with stock function pointers without some wrangling. / common idiom is to use an

    opa(ue contet pointer along with a static member function that calls a non*static member function to do the

    actual work)

    stdJJ=:ctio: simplifies this as it can hold any functor, meaning it can hold a member function pointer along with

    a pointer to the associated ob7ect)

    # .ibrary * LoadLibrary+(L,KorLib-d..,)/

    !"

    Deacti1ateActCtx(?5 cooie)/Re.easeActCtx(acti1atio:Co:text)/

    !"#$%

    &'!?!!!"!#!$!%!&!'!!

    "?"!"""#"$"%"&

    "oid.o:O8eratio:("oid(Fca..bac)("oidFco:text)5 "oidFco:text)0 66 Do so;e 9or t@e: i:1oe t@e ca..bac =:ctio: ca..bac(co:text)/

    7class

  • 8/12/2019 Chris Spencer

    3/14

    #hen using stdJJbi:d, arguments can be bound, meaning their value is fied when the functor is created, or

    unbound using placeholders, meaning their value is set when the functor is invoked)

    mplementations of stdJJ=:ctio:will typically optimise the common case of small functors 5such as a member

    function pointer and an ob7ect, which would typically take 8 bytes on a 9*bit architecture6 by allocating them

    on the stack, while larger functors will go on the heap, which is where the point of this post lies. 'he +isual

    Studio :" implementation allocates "; bytes of stack space for small functors, which should be plenty of spacefor most use cases. Unfortunately, there is a lot of waste in the implementation. 'he functor is wrapped in a

    _:c_i;8.ob7ect, which, in addition to holding the functor, has an allocator and a base class with virtual methods.

    'he virtual methods add < bytes to the class for the virtual function pointer table, and the allocator, although it

    is an empty stdJJa..ocator, must be addressable, and due to alignment re(uirements adds another < bytes. 'his

    means the "; bytes of space available for the small functor optimisation is now cut down to 7ust 8 bytes.

    8 bytes is of course enough to hold a member function and ob7ect pointer, but we now run into an issue with the

    implementation of stdJJbi:d. 'he +isual Studio :" implementation of stdJJbi:duses < bytes for every

    placeholder. 'his means the result of bi:d(3

  • 8/12/2019 Chris Spencer

    4/14

    'he =oost implementation fares much better in comparison. boostJJ=:ctio:allocates < bytes on the stack for

    functors, and it does not wrap the functor in anything, meaning the full space is available. /dditionally,

    placeholders in boostJJbi:dtake no space at all. 'his means there is a full "; bytes available for bound arguments

    before the functor will be forced onto heap in boostJJ=:ctio:.

    'he small functor optimisation can be important in applications that make heavy use of functors as it will avoid a

    large number of small heap allocations. /s such, would recommend sticking to the =oost versions if you are

    targeting +isual Studio :".

    Note:'he above is based on my analysis of the code in =oost and the +isual Studio :" headers and may

    contain errors. &lease leave a comment if you think ve made a mistake> t also does not reflect behaviour in the

    ;

  • 8/12/2019 Chris Spencer

    5/14

    n the local variables window navigate to @isExce8tio: 8ara;s8Exce8tio:Obect . 'his carries the pointer to the

    ob7ect that was thrown.

    ?etting the type of the eception ob7ect may take a bit of guesswork, but can probably be determined by looking

    at 8@ro9I:=o, or at where the eception was thrown in the code. @therwise, the stdJJexce8tio: base class is usually

    fine anyway. n this case it is stdJJsyste;_error .

    1opy the address into the watch window and add an appropriate cast. Aou now have all the eception

    information you need> Aou may need to switch to the frame in which the eception was thrown in your

    application for the cast to work, otherwise the debugger wont know about the type you specified.

    #e can see here that we failed to open some super*important file with an error code of 9, whichwe know means

    the file doesnt eist.

    Unfortunately, sometimes you might find your eception information has been optimised away)

    s Spencer http://cwspencer.co.uk/blog/

    14 6/1/2014 8:13 PM

  • 8/12/2019 Chris Spencer

    6/14

    f this happens youre pretty much out of luck for any eisting crash dumps, but if you switch to method two

    then future dumps should be more useful.

    'he second method involves installing your own unhandled eception filter and forcing the process to eit

    immediately, while still preserving the eception information. generally prefer this method because it is more

    reliable and easier to work with.

    First thing to do is define your unhandled eception filter)

    LONG WINAPI unhandledExceptionFilter(EXCEPTION_POINTERS *exInfo)

    {

    RaiseFailFastException(exInfo->ExceptionRecord,

    exInfo->ContextRecord, 0);

    return EXCEPTION_CONTINUE_SEARCH; // Not reached

    }

    int main()

    {

    SetUnhandledExceptionFilter(unhandledExceptionFilter);

    // ...

    }

    -ere we use Raiseai.astExce8tio: to kill the process immediately and invoke #indows Brror Ceporting to create

    your crash dump. 'his bypasses whatever the 1 runtime does which causes it to lose your eception information

    and you get a much more useful dialog when you enter the debugger)

    'his time weve got both the type of the eception and its address 5which in this case is ?x??"D#6. &ut this in

    your watch window in the same way as described before and you will have your eception ob7ect>

    Bonus:Aou can get#BC to generate full crash dumpswhen your program crashes and you dont have a

    debugger attached by creating the D+ORDregistry key HBEK_LOCAL_

  • 8/12/2019 Chris Spencer

    7/14

    /s my final year university pro7ect am building an emulator and source*level debugger for the ?ame =oy and

    ?ame =oy 1olor todays post is about the troubles have had whilst emulating the sound system for the ?ame

    =oy. 'he technical details about how the ?ame =oy sound hardware works is not important for this post the

    problem is with getting the audio after it has been emulated to the sound card. /udio buffer underflows and

    overflows have been causing me much frustration ever since wrote the initial implementation a few months

    back, as each time it happens it creates an audible skip in the playback. initially 7ust assumed it was because

    the SDL audio library re(uests audio from a separate thread 5m still not convinced this is a good idea, eventhough it turned out not to be the cause of the problem6. =ecause of this moved the sound generation code into

    the audio thread so it was generated on demand.

    'his seemed to to work pretty well, mainly because the ?ame =oy sound system is almost completely isolated

    from everything else the game 7ust sets a couple of registers indicating what tone it wants to play then the sound

    hardware goes away and generates the appropriate tones. @f course, as is (uite typical with old consoles, games

    like to push the hardware to the limit, which means timings must be etremely accurate in order for an emulator

    to work correctly. /s it turns out, in &okemon Aellow when the game plays the E&ikachu sound, the game forces

    the sound hardware to play the sample*based sound 5something which it is not very good at as standard6 by

    switching the sound on and off as fast as the 1&U will allow. aturally this doesnt work at all when the sound

    emulation thread is only getting switched in every few hundred milliseconds, so was forced to bring the sound

    emulation back into the main thread for the sound to be emulated correctly.

    /nd so the skipping came back with itG

    Still convinced that the threading was the problem decided to rebuild the sound emulation on top of

    0icrosofts #/S/&. ot only is #/S/& closer to the hardware than higher level abstractions like SDL,

    meaning reduced latency and better (uality, but, crucially, it can all run in the same thread. So after spending

    several hours writing a #/S/& backend that ended up being five times longer than the SDL backend 5it

    wouldnt be a 0icrosoft /& if it wasnt significantly more complicated than everything else6, it was still

    skippingG ot impressed.

    /fter this focused more on how fast the samples were actually being generated versus how fast they were being

    consumed. /fter adding a bit of instrumentation code found that the samples were being generated about ::

    -3 too slowly. #hoops. should point at here that had two synchronisation timers running in parallel in my

    emulator) a simple idle loop that ran every frame to keep from the emulator running too fast, and the audio

    timer which the operating systemHaudio hardware uses to re(uest samples at the correct rate. fied up the idle

    loop timer and got it generating the sound at eactly the right rate 4H* " -3. 'his fied the problem to a large

    etent, but it was skipping much more than would like.

    ts about now that it hit me that the solution had been staring me in the face the entire time) use only one

    timer. 'he audio timer is re(uired to make any sound, so the idle loop timer had to go. nstead replaced it with

    a callback in the audio backend which is called at a fied fre(uency derived from the audio clock based on when

    it re(uests new sound data. 'he sound samples could now be generated at eactly the rate they were re(uired

    and overflows and underflows simply stopped happening. still opted to keep the #/S/& backend because the

    SDL backend still seems to skip periodically, but even with SDL the problem is basically gone.

    ve put this here in the hopes it might be useful to someone know had trouble finding any useful

    information from my searches.

    Posted in programming | Comments Off

    s Spencer http://cwspencer.co.uk/blog/

    14 6/1/2014 8:13 PM

  • 8/12/2019 Chris Spencer

    8/14

    The Ambiguity of Flight PlansPosted on August 26, 2011 by Chris Spencer

    Some time ago wrote a utility to convert a flight plan route into a series of waypoints so it could be used by

    other applications. @n the face of it, this seems like a pretty simple task all you need to do is convert something

    like this)

    EGLL BUZAD T420 WELIN EGBB

    nto this)

    EGLL BUZAD OLNEY WELIN EGBB

    $"?here is an airway all we need to do is find the waypoints on the airway between UADand +ELIN.

    Unfortunately, it turns out flight plan routes are actually (uite ambiguous. For eample, you cant be certain

    whether $"?is the name of an airway, or if it is a waypoint that should be directly flown to. n this case its prettyeasy as there are no waypoints named $"?, so it must be an airway. @ften times, however, there will be many

    waypoints and airways going by the same name throughout the world, so you 7ust have to make a best guess

    based on the surrounding contet. 0uch tweaking was necessary in order to get it to a state where it wouldnt

    re7ect valid routes as invalid.

    / particularly memorable issue had was with this route, purely because it was the only route in the large test

    set had which had the problem)

    EGPH TLA N864 DCS [...]

    Decoded, this means fly from Bdinburgh /irport via a 'alla SD to LA, then follow the N&$airway to DCS. dont

    consider SDs while parsing as there is usually more than one with the same endpoint instead 7ust take the

    waypoint with that name closest to the airport then continue from there. -owever, for some reason with this

    particular route was getting errors saying it couldnt find N&$after LA. /s it turns out there is an D= with the

    same name in the area, and as it happens the D= is :." 0 closer to the airport than the +@C to which the

    airway is attached. 'his issue forced me to change the logic for handling direct routings such that it will look at

    all the potential waypoints for an attached airway with the name of the following token before giving up and 7ust

    using the closest available.

    Posted in aviation, programming | Comments Off

    Back OnlinePosted on August 22, 2011 by Chris Spencer

    Finally, after a long period of downtime, am back online. =ack when the site was first set up it was hosted for

    free by a friend of mine in echange for some programming help with 144. Unfortunately, made the mistake of

    allowing said friend to register the domain in his name. Some time later he closed his hosting down, and was

    stuck with a domain couldnt use and didnt actually own. tried to get him to transfer the domain ownershipto me, but he was unable to do so for whatever reason, and he was always very difficult to get hold of, so pretty

    much gave up.

    s Spencer http://cwspencer.co.uk/blog/

    14 6/1/2014 8:13 PM

  • 8/12/2019 Chris Spencer

    9/14

    -owever, the other day checked the status of the domain on a which and discovered it had epired and was free

    to re*register, which was weird because he claimed to have re*registered the domain when attempting to transfer

    ownership. =ut regardless, am finally in control of my own domain and have got a +&S set up with !L@, at the

    recommendation of another friend. Luckily had a backup of the #ord&ress database from before the server

    went down, and managed to find most of the uploaded media files still lying around on my computer, so not too

    much was lost.

    had a number of options for which Linu distributions could be pre*installed, which basically boiled down to

    the only two am familiar with) 1ent@S and ?entoo. initially set up ?entoo however, after a couple of failed

    kernel upgrades gave up and installed 1ent@S. 'he problem is that working on it remotely, youre basically

    stuck if the system fails to boot. &erhaps for the best anyway m more familiar with locking down 1ent@S from

    the ecellent ?uide to the Secure 1onfiguration of Ced -at Bnterprise Linu Iproduced by the S/ which

    have used to great effect at work.

    Setting up =D was an interesting challenge, as have never done anything with DS before. /n unusual

    aspect of !L@ is that they dont provide nameservers, so you have to set up your own, but that raises the

    (uestion) how does one resolve the nameserver :s!-c9s8e:cer-co- when trying to resolve c9s8e:cer-co-J 'urns out

    that is achieved with the help of so called Kglue records. 'he & address of the name server is stored in a glue

    record on the -co-top*level domain. ow when someone needs to resolve c9s8e:cer-co- , they use the glue

    record to resolve :s!-c9s8e:cer-co- to %-!'"-"#-! and subse(uently (uery my =D server to resolve

    c9s8e:cer-co-, which of course also comes out to %-!'"-"#-! as everything is running on the same server.

    Posted in linux, self | Comments Off

    Homebrew Earpiece for the Yaesu FT-60Posted on August 17, 2010 by Chris Spencer

    m going to the =ournemouth /ir Festivalthis week, and of course will be bringing my -' for that etra /'1

    goodness. Unfortunately though, the Aaesu F'*;: doesnt have a normal headphones socket. t does have a

    9.Imm 7ack socket, but it has four contacts, and plugging in a normal three contact connector grounds the &''.

    o good.

    checked the manual, and it seems need theAaesu 0-*9$/

  • 8/12/2019 Chris Spencer

    10/14

    'his is actually four electrically separate circuits. 'he computer side is completely isolated from the radio side to

    prevent a ground loopfrom distorting the signal. will eplain each section of the circuit below.

    0ost 5if not all6 amateur radio data mode applications have an option of activating the C'S line on a serial port

    when transmitting this is used to activate the &'' circuit on the rig. /n opto*isolator is used to isolate the two

    sides of the circuit. 'his consists of an LBD and a phototransistor. #hen current flows through the LBD, current

    is allowed to flow through the transistor, grounding the &'' line and activating the transmitter. / ".kQ resistor

    is used to reduce the current reaching the LBD the CS*9 specification allows for up to I+, which is too much

    for the diode. 'he D" diode acts as a shunt. #hen the C'S line is Eoff, it can be up to *I+, which would damage

    the LBD in the opto*isolator if allowed to flow through it. nstead the current flows through the diode and out

    the C'S line.

    et is the transmit audio input. 'his is connected to the line out connection on the &1 sound card. 'his time an

    audio transformer is used to isolate the two circuits. 'he manual for my rig specifies the maimum input level is

  • 8/12/2019 Chris Spencer

    11/14

    Bverything went perfectly on the first attempt didnt break anything, receive and transmit audio, and &'' all

    work perfectly. f you want to build your own encourage you to check the links in the footnotes as they provide

    more detail. 'his circuit ought to work for any rig with a 0ini*D ; input 5usually marked Edata6. ll be happy

    to answer any (uestions if you leave a comment.

    Posted in amateur radio, elecronics | Comments Off

    Decoding the Yaesu FT-7800 Clone Data FormatPosted on July 24, 2010 by Chris Spencer

    bought a data cable for my radio a few days ago to connect it to my computer so could program the memories

    more easily. figured instead of buying the programming software d try to decode the data format the radio

    uses and write my own. ts 7ust more fun that way.

    'he premise is simple enough, you need to make the application act like the radio and use clone mode to get the

    memory dump from the rig. @nce you have made your changes you do the same thing in reverse to send the databack.

    'he transfer protocol is pretty simple, its essentially a file transfer protocol which always sends a file of the same

    si3e. Upon enabling clone transmit mode on the rig it sends the /S1 string K/-:";u. ts not clear eactly

    what this means so 7ust check for it verbatim. Upon receiving this you send back an /12 character 5:T:;6 and

    the radio starts spewing out its data.

    'he data is sent in ;< byte packets,O". ts not really a packet in the normal sense, theres no header data or

    anything like that, its 7ust a ;< byte block of raw data.P after each of which an /12 must be sent. 'he rig sends

  • 8/12/2019 Chris Spencer

    12/14

    decoded and included the character set in the table below.

    Dec Hex Oct Character Glyph

    : : : :

    " " " "

    9 9 9 9

    < <