189 lines
4.7 KiB
C++
189 lines
4.7 KiB
C++
#ifndef __HQN_H__
|
|
#define __HQN_H__
|
|
|
|
#include <cstdint>
|
|
#include <stdio.h>
|
|
#include <emuInstance.hpp>
|
|
|
|
#define BLIT_SIZE 65536
|
|
|
|
// Creating emulator instance
|
|
|
|
namespace hqn
|
|
{
|
|
|
|
typedef const char *error_t;
|
|
|
|
class HQNState;
|
|
|
|
class HQNListener
|
|
{
|
|
public:
|
|
HQNListener() = default;
|
|
virtual ~HQNListener() = default;
|
|
|
|
virtual void onLoadROM(HQNState *state, const char *filename) = 0;
|
|
virtual void onAdvanceFrame(HQNState *state) = 0;
|
|
virtual void onLoadState(HQNState *state) = 0;
|
|
};
|
|
|
|
/*
|
|
State which is maintained by the emulator driver.
|
|
|
|
This should normally be obtained using hqn_get_state() if you are in a lua
|
|
function.
|
|
*/
|
|
class HQNState
|
|
{
|
|
public:
|
|
|
|
/* A reference to the emulator instance. */
|
|
emulator_t *m_emu;
|
|
|
|
static const int32_t *NES_VIDEO_PALETTE;
|
|
|
|
/**
|
|
* Constructor.
|
|
*/
|
|
HQNState();
|
|
~HQNState();
|
|
|
|
void setEmulatorPointer(void* const emuPtr) { m_emu = (emulator_t*)emuPtr; }
|
|
|
|
/*
|
|
The joypad data for the two joypads available to an NES.
|
|
This is directly available because I'm lazy.
|
|
*/
|
|
uint32_t joypad[2];
|
|
|
|
/* Get the emulator this state uses. */
|
|
inline emulator_t *emu() const
|
|
{ return m_emu; }
|
|
|
|
|
|
/*
|
|
Advance the emulator by one frame. If sleep is true and there is a frame
|
|
limit set advanceFrame() will sleep in order to limit the framerate.
|
|
Returns NULL or error string.
|
|
*/
|
|
error_t advanceFrame(bool sleep=true);
|
|
|
|
/*
|
|
Save the game state. This can be restored at any time.
|
|
*/
|
|
error_t saveState(void *dest, size_t size, size_t *size_out);
|
|
|
|
/*
|
|
Get the size (bytes) of a savestate.
|
|
Use this to allocate enough space for the saveState method.
|
|
*/
|
|
error_t saveStateSize(size_t *size) const;
|
|
|
|
/*
|
|
Load the emulator state from data.
|
|
This should be data produced by saveState().
|
|
*/
|
|
error_t loadState(const char *data, size_t size);
|
|
|
|
|
|
error_t setSampleRate(int rate);
|
|
|
|
/**
|
|
* Set a limit to the framerate.
|
|
* 0 means no limit.
|
|
*/
|
|
void setFramerate(int fps);
|
|
|
|
/**
|
|
* Get the current framerate limit.
|
|
*/
|
|
int getFramerate() const;
|
|
|
|
/**
|
|
* Get the calculated frames per second.
|
|
*/
|
|
double getFPS() const;
|
|
|
|
inline HQNListener *getListener() const
|
|
{ return m_listener; }
|
|
|
|
inline void setListener(HQNListener *l)
|
|
{ m_listener = l; }
|
|
|
|
/**
|
|
* Get the state of the keyboard. Use this to update the keyboard state.
|
|
*/
|
|
inline uint8_t *getKeyboard()
|
|
{ return m_keyboard; }
|
|
|
|
private:
|
|
/* ROM file stored in memory because reasons */
|
|
uint8_t *m_romData;
|
|
size_t m_romSize;
|
|
/* Minimum milliseconds between each frame. */
|
|
uint32_t m_msPerFrame;
|
|
/* time value of previous frame. */
|
|
uint32_t m_prevFrame;
|
|
/* The listener */
|
|
HQNListener *m_listener;
|
|
/* Keyboard state */
|
|
uint8_t m_keyboard[256];
|
|
/* Number of frames we've processed */
|
|
uint32_t m_frames;
|
|
/* How long it took to process the previous frame */
|
|
uint32_t m_frameTime;
|
|
uint32_t m_initialFrame;
|
|
};
|
|
|
|
/*
|
|
Print the usage message.
|
|
@param filename used to specify the name of the exe file, may be NULL.
|
|
*/
|
|
void printUsage(const char *filename);
|
|
|
|
} // end namespace hqn
|
|
|
|
// Copied from bizinterface.cpp in BizHawk/quicknes
|
|
inline void saveBlit(const void *ePtr, int32_t *dest, const int32_t *colors, int cropleft, int croptop, int cropright, int cropbottom)
|
|
{
|
|
// what is the point of the 256 color bitmap and the dynamic color allocation to it?
|
|
// why not just render directly to a 512 color bitmap with static palette positions?
|
|
// emulator_t *e = m_emu; // e was a parameter but since this is now part of a class, it's just in here
|
|
// const int srcpitch = e->frame().pitch;
|
|
// const unsigned char *src = e->frame().pixels;
|
|
// const unsigned char *const srcend = src + (e->image_height - cropbottom) * srcpitch;
|
|
//
|
|
// const short *lut = e->frame().palette;
|
|
//
|
|
// const int rowlen = 256 - cropleft - cropright;
|
|
//
|
|
// src += cropleft;
|
|
// src += croptop * srcpitch;
|
|
//
|
|
// for (; src < srcend; src += srcpitch)
|
|
// {
|
|
// for (int i = 0; i < rowlen; i++)
|
|
// {
|
|
// *dest++ = colors[lut[src[i]]];
|
|
// }
|
|
// }
|
|
|
|
const emulator_t *e = (emulator_t*) ePtr;
|
|
const unsigned char *in_pixels = e->frame().pixels;
|
|
if (in_pixels == NULL) return;
|
|
int32_t *out_pixels = dest;
|
|
|
|
for (unsigned h = 0; h < emulator_t::image_height; h++, in_pixels += e->frame().pitch, out_pixels += emulator_t::image_width)
|
|
for (unsigned w = 0; w < emulator_t::image_width; w++)
|
|
{
|
|
unsigned col = e->frame().palette[in_pixels[w]];
|
|
const emulator_t::rgb_t& rgb = e->nes_colors[col];
|
|
unsigned r = rgb.red;
|
|
unsigned g = rgb.green;
|
|
unsigned b = rgb.blue;
|
|
out_pixels[w] = (r << 16) | (g << 8) | (b << 0);
|
|
}
|
|
}
|
|
|
|
#endif /* __HQN_H__ */
|