chris spencer
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
< <