mame/src/lib/util/bitmap.h
Aaron Giles f0823886a6 Major CHD/chdman update. The CHD version number has been increased
from 4 to 5. This means any diff CHDs will no longer work. If you
absolutely need to keep the data for any existing ones you have,
find both the diff CHD and the original CHD for the game in question 
and upgrade using these commands:

  rename diff\game.dif diff\game-old.dif
  chdman copy -i diff\game-old.dif -ip roms\game.chd -o diff\game.dif -op roms\game.chd -c none

Specifics regarding this change:

Defined a new CHD version 5. New features/behaviors of this version:
  - support for up to 4 codecs; each block can use 1 of the 4
  - new LZMA codec, which tends to do better than zlib overall
  - new FLAC codec, primarily used for CDs (but can be applied anywhere)
  - upgraded AVHuff codec now uses FLAC for encoding audio
  - new Huffman codec, used to catch more nearly-uncompressable blocks
  - compressed CHDs now use a compressed map for significant savings
  - CHDs now are aware of a "unit" size; each hunk holds 1 or more units
     (in general units map to sectors for hard disks/CDs)
  - diff'ing against a parent now diffs at the unit level, greatly
     improving compression

Rewrote and modernized chd.c. CHD versions prior to 3 are unsupported,
and version 3/4 CHDs are only supported for reading. Creating a new
CHD now leaves the file open.  Added methods to read and write at the 
unit and byte level, removing the need to handle this manually. Added
metadata access methods that pass astrings and dynamic_buffers to
simplify the interfaces. A companion class chd_compressor now
implements full multithreaded compression, analyzing and compressing
multiple hunks independently in parallel. Split the codec 
implementations out into a separate file chdcodec.*

Updated harddisk.c and cdrom.c to rely on the caching/byte-level read/
write capabilities of the chd_file class. cdrom.c (and chdman) now also 
pad CDs to 4-frame boundaries instead of hunk boundaries, ensuring that
the same SHA1 hashes are produced regardless of the hunk size.

Rewrote chdman.exe entirely, switching from positional parameters to
proper options. Use "chdman help" to get a list of commands, and
"chdman help <command>" to get help for any particular command. Many 
redundant commands were removed now that additional flexibility is
available. Some basic mappings:

  Old: chdman -createblankhd <out.chd> <cyls> <heads> <secs>
  New: chdman createhd -o <out.chd> -chs <cyls>,<heads>,<secs>

  Old: chdman -createuncomphd <in.raw> <out.chd> ....
  New: chdman createhd -i <in.raw> -o <out.chd> -c none ....

  Old: chdman -verifyfix <in.chd>
  New: chdman verify -i <in.chd> -f

  Old: chdman -merge <parent.chd> <diff.chd> <out.chd>
  New: chdman copy -i <diff.chd> -ip <parent.chd> -o <out.chd>

  Old: chdman -diff <parent.chd> <compare.chd> <diff.chd>
  New: chdman copy -i <compare.chd> -o <diff.chd> -op <parent.chd>

  Old: chdman -update <in.chd> <out.chd>
  New: chdman copy -i <in.chd> -o <out.chd>

Added new core file coretmpl.h to hold core template classes. For now
just one class, dynamic_array<> is defined, which acts like an array
of a given object but which can be appended to and/or resized. Also
defines dynamic_buffer as dynamic_array<UINT8> for holding an 
arbitrary buffer of bytes. Expect to see these used a lot.

Added new core helper hashing.c/.h which defines classes for each of
the common hashing methods and creator classes to wrap the 
computation of these hashes. A future work item is to reimplement
the core emulator hashing code using these.

Split bit buffer helpers out into C++ classes and into their own
public header in bitstream.h.

Updated huffman.c/.h to C++, and changed the interface to make it
more flexible to use in nonstandard ways. Also added huffman compression
of the static tree for slightly better compression rates.

Created flac.c/.h as simplified C++ wrappers around the FLAC interface.
A future work item is to convert the samples sound device to a modern
device and leverage this for reading FLAC files.

Renamed avcomp.* to avhuff.*, updated to C++, and added support for
FLAC as the audio encoding mechanism. The old huffman audio is still
supported for decode only.

Added a variant of core_fload that loads to a dynamic_buffer.

Tweaked winwork.c a bit to not limit the maximum number of processors
unless the work queue was created with the WORK_QUEUE_FLAG_HIGH_FREQ
option. Further adjustments here are likely going to be necessary.

Fixed bug in aviio.c which caused errors when reading some AVI files.
2012-02-16 09:47:18 +00:00

422 lines
18 KiB
C++

/***************************************************************************
bitmap.h
Core bitmap routines.
****************************************************************************
Copyright Aaron Giles
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name 'MAME' nor the names of its contributors may be
used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
***************************************************************************/
#pragma once
#ifndef __BITMAP_H__
#define __BITMAP_H__
#include "osdcore.h"
#include "palette.h"
#include <assert.h>
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
// bitmap_format describes the various bitmap formats we use
enum bitmap_format
{
BITMAP_FORMAT_INVALID = 0, // invalid forma
BITMAP_FORMAT_IND8, // 8bpp indexed
BITMAP_FORMAT_IND16, // 16bpp indexed
BITMAP_FORMAT_IND32, // 32bpp indexed
BITMAP_FORMAT_IND64, // 64bpp indexed
BITMAP_FORMAT_RGB32, // 32bpp 8-8-8 RGB
BITMAP_FORMAT_ARGB32, // 32bpp 8-8-8-8 ARGB
BITMAP_FORMAT_YUY16, // 16bpp 8-8 Y/Cb, Y/Cr in sequence
BITMAP_FORMAT_LAST
};
// ======================> rectangle
// rectangles describe a bitmap portion
class rectangle
{
public:
// construction/destruction
rectangle() { }
rectangle(INT32 minx, INT32 maxx, INT32 miny, INT32 maxy)
: min_x(minx), max_x(maxx), min_y(miny), max_y(maxy) { }
// compute intersection with another rect
rectangle &operator&=(const rectangle &src)
{
if (src.min_x > min_x) min_x = src.min_x;
if (src.max_x < max_x) max_x = src.max_x;
if (src.min_y > min_y) min_y = src.min_y;
if (src.max_y < max_y) max_y = src.max_y;
return *this;
}
// compute union with another rect
rectangle &operator|=(const rectangle &src)
{
if (src.min_x < min_x) min_x = src.min_x;
if (src.max_x > max_x) max_x = src.max_x;
if (src.min_y < min_y) min_y = src.min_y;
if (src.max_y > max_y) max_y = src.max_y;
return *this;
}
// other helpers
bool empty() const { return (min_x > max_x || min_y > max_y); }
bool contains(INT32 x, INT32 y) const { return (x >= min_x && x <= max_x && y >= min_y && y <= max_y); }
bool contains(const rectangle &rect) const { return (min_x <= rect.min_x && max_x >= rect.max_x && min_y <= rect.min_y && max_y >= rect.max_y); }
INT32 width() const { return max_x + 1 - min_x; }
INT32 height() const { return max_y + 1 - min_y; }
INT32 xcenter() const { return (min_x + max_x + 1) / 2; }
INT32 ycenter() const { return (min_y + max_y + 1) / 2; }
// setters
void set(INT32 minx, INT32 maxx, INT32 miny, INT32 maxy) { min_x = minx; max_x = maxx; min_y = miny; max_y = maxy; }
void setx(INT32 minx, INT32 maxx) { min_x = minx; max_x = maxx; }
void sety(INT32 miny, INT32 maxy) { min_y = miny; max_y = maxy; }
void set_width(INT32 width) { max_x = min_x + width - 1; }
void set_height(INT32 height) { max_y = min_y + height - 1; }
void set_origin(INT32 x, INT32 y) { max_x += x - min_x; max_y += y - min_y; min_x = x; min_y = y; }
void set_size(INT32 width, INT32 height) { set_width(width); set_height(height); }
// internal state
INT32 min_x; // minimum X, or left coordinate
INT32 max_x; // maximum X, or right coordinate (inclusive)
INT32 min_y; // minimum Y, or top coordinate
INT32 max_y; // maximum Y, or bottom coordinate (inclusive)
};
// ======================> bitmap_t
// bitmaps describe a rectangular array of pixels
class bitmap_t
{
private:
// prevent implicit copying
bitmap_t(const bitmap_t &);
bitmap_t &operator=(const bitmap_t &);
protected:
// construction/destruction -- subclasses only to ensure type correctness
bitmap_t(bitmap_format format, int bpp, int width = 0, int height = 0, int xslop = 0, int yslop = 0);
bitmap_t(bitmap_format format, int bpp, void *base, int width, int height, int rowpixels);
bitmap_t(bitmap_format format, int bpp, bitmap_t &source, const rectangle &subrect);
virtual ~bitmap_t();
public:
// allocation/deallocation
void reset();
// getters
INT32 width() const { return m_width; }
INT32 height() const { return m_height; }
INT32 rowpixels() const { return m_rowpixels; }
INT32 rowbytes() const { return m_rowpixels * m_bpp / 8; }
UINT8 bpp() const { return m_bpp; }
bitmap_format format() const { return m_format; }
bool valid() const { return (m_base != NULL); }
palette_t *palette() const { return m_palette; }
const rectangle &cliprect() const { return m_cliprect; }
// allocation/sizing
void allocate(int width, int height, int xslop = 0, int yslop = 0);
void resize(int width, int height, int xslop = 0, int yslop = 0);
// operations
void set_palette(palette_t *palette);
void fill(rgb_t color) { fill(color, m_cliprect); }
void fill(rgb_t color, const rectangle &cliprect);
void plot_box(int x, int y, int width, int height, UINT32 color)
{
rectangle clip(x, x + width - 1, y, y + height - 1);
fill(color, clip);
}
// pixel access
template<typename _PixelType>
_PixelType &pixt(INT32 y, INT32 x = 0) const { return *(reinterpret_cast<_PixelType *>(m_base) + y * m_rowpixels + x); }
void *raw_pixptr(INT32 y, INT32 x = 0) const { return reinterpret_cast<UINT8 *>(m_base) + (y * m_rowpixels + x) * m_bpp / 8; }
protected:
// for use by subclasses only to ensure type correctness
void wrap(void *base, int width, int height, int rowpixels);
void wrap(const bitmap_t &source, const rectangle &subrect);
private:
// internal helpers
INT32 compute_rowpixels(int width, int xslop);
void compute_base(int xslop, int yslop);
// internal state
UINT8 * m_alloc; // pointer to allocated pixel memory
UINT32 m_allocbytes; // size of our allocation
void * m_base; // pointer to pixel (0,0) (adjusted for padding)
INT32 m_rowpixels; // pixels per row (including padding)
INT32 m_width; // width of the bitmap
INT32 m_height; // height of the bitmap
bitmap_format m_format; // format of the bitmap
UINT8 m_bpp; // bits per pixel
palette_t * m_palette; // optional palette
rectangle m_cliprect; // a clipping rectangle covering the full bitmap
};
// ======================> bitmap8_t, bitmap16_t, bitmap32_t, bitmap64_t
// 8bpp bitmaps
class bitmap8_t : public bitmap_t
{
private:
// private helpers
bool valid_format(bitmap_format format) const { return (format == BITMAP_FORMAT_IND8); }
protected:
// construction/destruction -- subclasses only
bitmap8_t(bitmap_format format, int width = 0, int height = 0, int xslop = 0, int yslop = 0) : bitmap_t(format, 8, width, height, xslop, yslop) { }
bitmap8_t(bitmap_format format, UINT8 *base, int width, int height, int rowpixels) : bitmap_t(format, 8, base, width, height, rowpixels) { assert(valid_format(format)); }
bitmap8_t(bitmap_format format, bitmap8_t &source, const rectangle &subrect) : bitmap_t(format, 8, source, subrect) { }
public:
// getters
UINT8 bpp() const { return 8; }
// pixel accessors
typedef UINT8 pixel_t;
pixel_t &pix(INT32 y, INT32 x = 0) const { return pixt<pixel_t>(y, x); }
pixel_t &pix8(INT32 y, INT32 x = 0) const { return pixt<pixel_t>(y, x); }
};
// 16bpp bitmaps
class bitmap16_t : public bitmap_t
{
private:
// private helpers
bool valid_format(bitmap_format format) const { return (format == BITMAP_FORMAT_IND16 || format == BITMAP_FORMAT_YUY16); }
protected:
// construction/destruction -- subclasses only
bitmap16_t(bitmap_format format, int width = 0, int height = 0, int xslop = 0, int yslop = 0) : bitmap_t(format, 16, width, height, xslop, yslop) { assert(valid_format(format)); }
bitmap16_t(bitmap_format format, UINT16 *base, int width, int height, int rowpixels) : bitmap_t(format, 16, base, width, height, rowpixels) { assert(valid_format(format)); }
bitmap16_t(bitmap_format format, bitmap16_t &source, const rectangle &subrect) : bitmap_t(format, 16, source, subrect) { }
public:
// getters
UINT8 bpp() const { return 16; }
// pixel accessors
typedef UINT16 pixel_t;
pixel_t &pix(INT32 y, INT32 x = 0) const { return pixt<pixel_t>(y, x); }
pixel_t &pix16(INT32 y, INT32 x = 0) const { return pixt<pixel_t>(y, x); }
};
// 32bpp bitmaps
class bitmap32_t : public bitmap_t
{
private:
// private helpers
bool valid_format(bitmap_format format) const { return (format == BITMAP_FORMAT_IND32 || format == BITMAP_FORMAT_RGB32 || format == BITMAP_FORMAT_ARGB32); }
protected:
// construction/destruction -- subclasses only
bitmap32_t(bitmap_format format, int width = 0, int height = 0, int xslop = 0, int yslop = 0) : bitmap_t(format, 32, width, height, xslop, yslop) { assert(valid_format(format)); }
bitmap32_t(bitmap_format format, UINT32 *base, int width, int height, int rowpixels) : bitmap_t(format, 32, base, width, height, rowpixels) { assert(valid_format(format)); }
bitmap32_t(bitmap_format format, bitmap32_t &source, const rectangle &subrect) : bitmap_t(format, 32, source, subrect) { }
public:
// getters
UINT8 bpp() const { return 32; }
// pixel accessors
typedef UINT32 pixel_t;
pixel_t &pix(INT32 y, INT32 x = 0) const { return pixt<pixel_t>(y, x); }
pixel_t &pix32(INT32 y, INT32 x = 0) const { return pixt<pixel_t>(y, x); }
};
// 64bpp bitmaps
class bitmap64_t : public bitmap_t
{
private:
// private helpers
bool valid_format(bitmap_format format) const { return (format == BITMAP_FORMAT_IND64); }
protected:
// construction/destruction -- subclasses only
bitmap64_t(bitmap_format format, int width = 0, int height = 0, int xslop = 0, int yslop = 0) : bitmap_t(format, 64, width, height, xslop, yslop) { assert(valid_format(format)); }
bitmap64_t(bitmap_format format, UINT64 *base, int width, int height, int rowpixels) : bitmap_t(format, 64, base, width, height, rowpixels) { assert(valid_format(format)); }
bitmap64_t(bitmap_format format, bitmap64_t &source, const rectangle &subrect) : bitmap_t(format, 64, source, subrect) { }
public:
// getters
UINT8 bpp() const { return 64; }
// pixel accessors
typedef UINT64 pixel_t;
pixel_t &pix(INT32 y, INT32 x = 0) const { return pixt<pixel_t>(y, x); }
pixel_t &pix64(INT32 y, INT32 x = 0) const { return pixt<pixel_t>(y, x); }
};
// ======================> bitmap_ind8, bitmap_ind16, bitmap_ind32, bitmap_ind64
// BITMAP_FORMAT_IND8 bitmaps
class bitmap_ind8 : public bitmap8_t
{
static const bitmap_format k_bitmap_format = BITMAP_FORMAT_IND8;
public:
// construction/destruction
bitmap_ind8(int width = 0, int height = 0, int xslop = 0, int yslop = 0) : bitmap8_t(k_bitmap_format, width, height, xslop, yslop) { }
bitmap_ind8(UINT8 *base, int width, int height, int rowpixels) : bitmap8_t(k_bitmap_format, base, width, height, rowpixels) { }
bitmap_ind8(bitmap_ind8 &source, const rectangle &subrect) : bitmap8_t(k_bitmap_format, source, subrect) { }
void wrap(UINT8 *base, int width, int height, int rowpixels) { bitmap_t::wrap(base, width, height, rowpixels); }
void wrap(const bitmap_ind8 &source, const rectangle &subrect) { bitmap_t::wrap(static_cast<const bitmap_t &>(source), subrect); }
// getters
bitmap_format format() const { return k_bitmap_format; }
};
// BITMAP_FORMAT_IND16 bitmaps
class bitmap_ind16 : public bitmap16_t
{
static const bitmap_format k_bitmap_format = BITMAP_FORMAT_IND16;
public:
// construction/destruction
bitmap_ind16(int width = 0, int height = 0, int xslop = 0, int yslop = 0) : bitmap16_t(k_bitmap_format, width, height, xslop, yslop) { }
bitmap_ind16(UINT16 *base, int width, int height, int rowpixels) : bitmap16_t(k_bitmap_format, base, width, height, rowpixels) { }
bitmap_ind16(bitmap_ind16 &source, const rectangle &subrect) : bitmap16_t(k_bitmap_format, source, subrect) { }
void wrap(UINT16 *base, int width, int height, int rowpixels) { bitmap_t::wrap(base, width, height, rowpixels); }
void wrap(const bitmap_ind8 &source, const rectangle &subrect) { bitmap_t::wrap(static_cast<const bitmap_t &>(source), subrect); }
// getters
bitmap_format format() const { return k_bitmap_format; }
};
// BITMAP_FORMAT_IND32 bitmaps
class bitmap_ind32 : public bitmap32_t
{
static const bitmap_format k_bitmap_format = BITMAP_FORMAT_IND32;
public:
// construction/destruction
bitmap_ind32(int width = 0, int height = 0, int xslop = 0, int yslop = 0) : bitmap32_t(k_bitmap_format, width, height, xslop, yslop) { }
bitmap_ind32(UINT32 *base, int width, int height, int rowpixels) : bitmap32_t(k_bitmap_format, base, width, height, rowpixels) { }
bitmap_ind32(bitmap_ind32 &source, const rectangle &subrect) : bitmap32_t(k_bitmap_format, source, subrect) { }
void wrap(UINT32 *base, int width, int height, int rowpixels) { bitmap_t::wrap(base, width, height, rowpixels); }
void wrap(const bitmap_ind8 &source, const rectangle &subrect) { bitmap_t::wrap(static_cast<const bitmap_t &>(source), subrect); }
// getters
bitmap_format format() const { return k_bitmap_format; }
};
// BITMAP_FORMAT_IND64 bitmaps
class bitmap_ind64 : public bitmap64_t
{
static const bitmap_format k_bitmap_format = BITMAP_FORMAT_IND64;
public:
// construction/destruction
bitmap_ind64(int width = 0, int height = 0, int xslop = 0, int yslop = 0) : bitmap64_t(k_bitmap_format, width, height, xslop, yslop) { }
bitmap_ind64(UINT64 *base, int width, int height, int rowpixels) : bitmap64_t(k_bitmap_format, base, width, height, rowpixels) { }
bitmap_ind64(bitmap_ind64 &source, const rectangle &subrect) : bitmap64_t(k_bitmap_format, source, subrect) { }
void wrap(UINT64 *base, int width, int height, int rowpixels) { bitmap_t::wrap(base, width, height, rowpixels); }
void wrap(const bitmap_ind8 &source, const rectangle &subrect) { bitmap_t::wrap(static_cast<const bitmap_t &>(source), subrect); }
// getters
bitmap_format format() const { return k_bitmap_format; }
};
// ======================> bitmap_yuy16, bitmap_rgb32, bitmap_argb32
// BITMAP_FORMAT_YUY16 bitmaps
class bitmap_yuy16 : public bitmap16_t
{
static const bitmap_format k_bitmap_format = BITMAP_FORMAT_YUY16;
public:
// construction/destruction
bitmap_yuy16(int width = 0, int height = 0, int xslop = 0, int yslop = 0) : bitmap16_t(k_bitmap_format, width, height, xslop, yslop) { }
bitmap_yuy16(UINT16 *base, int width, int height, int rowpixels) : bitmap16_t(k_bitmap_format, base, width, height, rowpixels) { }
bitmap_yuy16(bitmap_yuy16 &source, const rectangle &subrect) : bitmap16_t(k_bitmap_format, source, subrect) { }
void wrap(UINT16 *base, int width, int height, int rowpixels) { bitmap_t::wrap(base, width, height, rowpixels); }
void wrap(const bitmap_yuy16 &source, const rectangle &subrect) { bitmap_t::wrap(static_cast<const bitmap_t &>(source), subrect); }
// getters
bitmap_format format() const { return k_bitmap_format; }
};
// BITMAP_FORMAT_RGB32 bitmaps
class bitmap_rgb32 : public bitmap32_t
{
static const bitmap_format k_bitmap_format = BITMAP_FORMAT_RGB32;
public:
// construction/destruction
bitmap_rgb32(int width = 0, int height = 0, int xslop = 0, int yslop = 0) : bitmap32_t(k_bitmap_format, width, height, xslop, yslop) { }
bitmap_rgb32(UINT32 *base, int width, int height, int rowpixels) : bitmap32_t(k_bitmap_format, base, width, height, rowpixels) { }
bitmap_rgb32(bitmap_rgb32 &source, const rectangle &subrect) : bitmap32_t(k_bitmap_format, source, subrect) { }
void wrap(UINT32 *base, int width, int height, int rowpixels) { bitmap_t::wrap(base, width, height, rowpixels); }
void wrap(const bitmap_rgb32 &source, const rectangle &subrect) { bitmap_t::wrap(static_cast<const bitmap_t &>(source), subrect); }
// getters
bitmap_format format() const { return k_bitmap_format; }
};
// BITMAP_FORMAT_ARGB32 bitmaps
class bitmap_argb32 : public bitmap32_t
{
static const bitmap_format k_bitmap_format = BITMAP_FORMAT_ARGB32;
public:
// construction/destruction
bitmap_argb32(int width = 0, int height = 0, int xslop = 0, int yslop = 0) : bitmap32_t(k_bitmap_format, width, height, xslop, yslop) { }
bitmap_argb32(UINT32 *base, int width, int height, int rowpixels) : bitmap32_t(k_bitmap_format, base, width, height, rowpixels) { }
bitmap_argb32(bitmap_argb32 &source, const rectangle &subrect) : bitmap32_t(k_bitmap_format, source, subrect) { }
void wrap(UINT32 *base, int width, int height, int rowpixels) { bitmap_t::wrap(base, width, height, rowpixels); }
void wrap(const bitmap_argb32 &source, const rectangle &subrect) { bitmap_t::wrap(static_cast<const bitmap_t &>(source), subrect); }
// getters
bitmap_format format() const { return k_bitmap_format; }
};
#endif // __BITMAP_H__