Source code
===========

This is the source code to my BBC emulator. It includes everything you
need, except for wxWindows. It's set up as a VC++6 workspace -- the
relevant file as beebm_wx/beebm_wx.dsw.

You must have the Intel C++ compiler. I've been using v6. v5 certainly
used to work.

If you have VC7, you shouldn't need the Intel C++ compiler. (I
haven't got VC7 installed so I can't test it. It certainly used to
work, though, because I spent a day putting fixes in to make it so!)
Load the workspace, and say "Yes to all" when asked about conversion. 

I don't claim that the code is brilliant, or that continued development
has improved it in any way, but it does appear to work... and I have
some good ideas about what not to do in future :)

DirectX3
========

By default the emulator uses DirectDraw and DirectSound from DirectX3,
and DirectInput from DirectX8. You can define the DX3_ONLY preprocessor
define to use DirectInput from DirectX3. The emulator should then work
on NT4. (However, it's not possible to grab the Windows key with
DirectX3, so Zalaga is a bit hard to play unless you redefine the
keyboard.)

There's a config set up so I can easily make a DirectX3 version for
releasing -- "Release DX3". There's no corresponding Debug config; you
will have to set up such a thing yourself.

wxWindows
=========

I used wxWindows-2.4.1; you should too! (There are some bugs in 2.4.0
that must be fixed for the emulator to work.)

Ensure your WXWIN environment variable is set.

Debug
=====

The debug build has a few extra features. Disassemble to RAM saves the
result to a file in the CWD. The rest let you select output file.

Porting
=======

There's a small portability layer. It's supposed to make it easy to
port. N.B. -- This is going to get changed to something more C++esque.

Quick overview
==============

Each component (apart from the timers) stores its current state in a
struct a pointer to which the user keeps. These structs are opaque and
should be managed entirely through the relevant functions. The structs
can contain whatever you would like.

HostTmr
=======

HostTmr supplies timer services.

void HostTmr_Start();

	Starts the timer services. There is no error return; it's assumed
    the function will find the best set of timers it can, and that some
    kind of timer is always available.

void HostTmr_Stop();

	Stops the timer services.

void HostTmr_ReadMilliseconds(int *value);

	Gets the current millisecond count in *value. This is the count of
    milliseconds since whenever.
    
typedef T HostTmr_HfValue;

	HostTmr_HfValue is the type required to store a high frequency
    counter reading. For example, on Windows, this could be a __int64
    (if using QueryPerformanceCounter), or an int (if just using
    HostTmr_ReadMilliseconds), and so on.

void HostTmr_ReadHf(HostTmr_HfValue *value);

	Get the current high frequency counter value in *value.
    
HostGfx
=======

HostGfx supplies graphics services. These should somehow display a
MxN 3bpp bitmap. The bitmap will be M'xN bytes in size, row then column,
with each byte being of the form 00000BGR. This gives 8 possible
colours.

You will probably have to convert this data by hand. However it's
possible some systems could use it verbatim, so the emulator does no
conversion of its own.

HostGfxState *HostGfx_Start(wxWindow *window);

	Starts the graphics system. 'window' is the window in which the
    graphics will appear.
    
    Returns 0 on error.

void HostGfx_Stop(HostGfxState *state);

	Stop the given graphics system.

void HostGfx_Present(HostGfxState *state,
	const unsigned char *bitmap_3bit,int w,int h, unsigned pitch);

	Give a new bitmap to the graphics system. It will somehow store a
    copy of the bitmap for future showing with HostGfx_Show. It should
    then call HostGfx_Show.

void HostGfx_Show(HostGfxState *state);

	Shows the current bitmap. This should happen straight away! It might
    not be sufficient just to update the window's dirty area, because
    the screen must be updated more often than the system message loop
    will be run.
    
HostSnd
=======

HostSndState *HostSnd_Start(wxWindow *window);

	Start a new graphics system. 'window' is the window with which the
    sounds are associated.
    
    Returns 0 on error.

void HostSnd_Stop(HostSndState *state);

	Destroy the given sound system.

void HostSnd_SetSoundParameters(HostSndState *state,int hz,int bits,int channels,
	int len_samples);
    
    Set sound parameters. hz is the frequency, bits the number of bits,
    channels the number of channels (1=mono, 2=stereo, etc.) and
    len_samples the length of the playing buffer in _samples_.
    
	This function should always clear the sound data and reset the sound
    buffer's play position.

void HostSnd_PlayStart(HostSndState *state);
void HostSnd_PlayStop(HostSndState *state);

	Stop and start the sound.
    
int HostSnd_GetWriteArea(HostSndState *state,
	void **p1,unsigned *len1,
    void **p2,unsigned *len2);
    
    Fill in pointers to the area that needs writing to since last time
    the write area was determined. How you determine this area is up to
    you! I'm assuming that audio buffers are circular (as in
    DirectSound), so fill in *p1 and *len1 with pointer-to and length
    (in bytes) of first area and *p2 and *len2 likewise for the second
    area. Length and pointer are both 0 for non-region.
    
    Return values:
    
    	<0 error
        0 no bytes to be written
        >0 bytes to be written, *p1/*len1/*p2/*len2 filled in.

void HostSnd_CommitWriteArea(HostSndState *state);

	If HostSnd_GetWriteArea returned >0, this should be called once the
    write area is filled.

HostInp
=======

HostInp provides keyboard input. Joystick probably coming at some point.
It represents the keyboard state as an array of bytes, one for each key.
Each byte is 0 if that key is unpressed, or !0 if it is pressed.

HostInpState *HostInp_Start(wxWindow *window);

	Start input. Input should be that going to the given window.

void HostInp_Stop(HostInpState *state);

	Stop input.

//Poll devices.
void HostInp_Poll(HostInpState *state);

	Poll the devices -- update states, whatever.

void HostInp_GetKeyboardState(HostInpState *state,unsigned char *keyflags);

	Get the keyboard state. keyflags points to at least 256 items. 

void HostInp_GetKeyboardDownFlags(HostInpState *state,unsigned char *downflags);

	Get keyboard down flags. A down flag indicates if the key is pressed
    this poll but unpressed last poll.

static const unsigned HostInp_bad_key;

	The magic number that represents an invalid key. Can be whatever you
    like.

const char *HostInp_KeyNameFromCode(unsigned key_code);

	Get the name of a key given its code. (The code is the index
    into the keystates array.) Should never return 0 -- return "" if
    the key code is invalid.

unsigned HostInp_CodeFromKeyName(const char *key_name);

	Get the code for a key given its name. Return HostInp_bad_key if the
    name isn't valid.

Author
======

Tom Seddon <bbc@tomseddon.plus.com>
