Skip to content

Commit

Permalink
Merge pull request #18 from trapexit/to-imag
Browse files Browse the repository at this point in the history
Add support for creating 3DO IMAG files
  • Loading branch information
trapexit authored Apr 9, 2023
2 parents efb7bb6 + ce28d06 commit a977144
Show file tree
Hide file tree
Showing 15 changed files with 846 additions and 48 deletions.
17 changes: 9 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@ Subcommands:
docs print links to relevant documentation
info prints info about the file
list-chunks list 3DO file chunks
to-cel convert image to CEL
to-cel convert image to 3DO CEL
to-banner convert image to banner
to-imag convert image to 3DO IMAG
to-bmp convert image to BMP
to-png convert image to PNG
to-jpg convert image to JPG
Expand All @@ -41,7 +42,6 @@ All subcommands have their own help and arguments. Use `--help` or
* dump APPSCRN from ISO
* dump-chunks
* concat-chunks
* to IMAG
* to ANIM
* ability to write text chunks
* figure out NFS HSPT chunk
Expand All @@ -57,14 +57,15 @@ different ideas so the code is not entirely consistent. Will clean up as needed.

## Documentation

* https://3dodev.com
* https://3dodev.com/documentation/file_formats
* https://3dodev.com/documentation/development/opera/pf25/ppgfldr/ggsfldr/gpgfldr/3gpg
* https://3dodev.com/documentation/development/opera/pf25/ppgfldr/ggsfldr/gpgfldr/5gpg
* https://3dodev.com/documentation/file_formats/media/container/3do
* https://3dodev.com/documentation/file_formats/media/image/bannerscreen
* https://3dodev.com/documentation/file_formats/games/nfs
* https://3dodev.com/documentation/development/opera/pf25/ppgfldr/ggsfldr/gpgfldr/00gpg1


## Other Links

* https://3dodev.com
* https://github.com/trapexit/3dt
* https://github.com/trapexit/3do-devkit
* 3DO Dev Repo: https://3dodev.com
* 3DO Disc Tool: https://github.com/trapexit/3dt
* 'Modern' 3DO DevKit: https://github.com/trapexit/3do-devkit
85 changes: 45 additions & 40 deletions src/byteswap.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,35 +21,43 @@
#include "endian.hpp"

#include <cstdint>
#include <type_traits>


static
inline
uint32_t
byteswap(const uint32_t v_)
int8_t
byteswap(const int8_t v_)
{
return (((v_ & UINT32_C(0x000000FF)) << 24) |
((v_ & UINT32_C(0x0000FF00)) << 8) |
((v_ & UINT32_C(0x00FF0000)) >> 8) |
((v_ & UINT32_C(0xFF000000)) >> 24));
return v_;
}

static
inline
uint32_t
byteswap_if_little_endian(const uint32_t v_)
uint8_t
byteswap(const uint8_t v_)
{
if(is_little_endian())
return byteswap(v_);
return v_;
}

static
inline
void
byteswap_if_little_endian(uint32_t *v_)
int16_t
byteswap(const int16_t v_)
{
*v_ = byteswap_if_little_endian(*v_);
return (((v_ & INT16_C(0x00FF)) << 8) |
((v_ & INT16_C(0xFF00)) >> 8));

}

static
inline
uint16_t
byteswap(const uint16_t v_)
{
return (((v_ & UINT16_C(0x00FF)) << 8) |
((v_ & UINT16_C(0xFF00)) >> 8));

}

static
Expand All @@ -65,54 +73,51 @@ byteswap(const int32_t v_)

static
inline
int32_t
byteswap_if_little_endian(const int32_t v_)
uint32_t
byteswap(const uint32_t v_)
{
if(is_little_endian())
return byteswap(v_);
return v_;
return (((v_ & UINT32_C(0x000000FF)) << 24) |
((v_ & UINT32_C(0x0000FF00)) << 8) |
((v_ & UINT32_C(0x00FF0000)) >> 8) |
((v_ & UINT32_C(0xFF000000)) >> 24));
}

template<typename T>
static
inline
void
byteswap_if_little_endian(int32_t *v_)
typename std::enable_if<std::is_fundamental<T>::value, T>::type
byteswap_if_little_endian(const T v_)
{
*v_ = byteswap_if_little_endian(*v_);
if(is_little_endian())
return byteswap(v_);
return v_;
}

template<typename T>
static
inline
uint16_t
byteswap(const uint16_t v_)
typename std::enable_if<std::is_pointer<T>::value, void>::type
byteswap_if_little_endian(const T v_)
{
return (((v_ & UINT16_C(0x00FF)) << 8) |
((v_ & UINT16_C(0xFF00)) >> 8));

*v_ = byteswap_if_little_endian(*v_);
}

template<typename T>
static
inline
uint16_t
byteswap_if_little_endian(const uint16_t v_)
typename std::enable_if<std::is_fundamental<T>::value, T>::type
byteswap_if_big_endian(const T v_)
{
if(is_little_endian())
if(is_big_endian())
return byteswap(v_);
return v_;
}

template<typename T>
static
inline
uint8_t
byteswap(const uint8_t v_)
{
return v_;
}

static
inline
uint8_t
byteswap_if_little_endian(const uint8_t v_)
typename std::enable_if<std::is_pointer<T>::value, void>::type
byteswap_if_big_endian(const T v_)
{
return v_;
*v_ = byteswap_if_big_endian(*v_);
}
65 changes: 65 additions & 0 deletions src/convert_bitmap_to_imag.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
ISC License
Copyright (c) 2023, Antonio SJ Musumeci <trapexit@spawn.link>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

#include "convert_bitmap_to_imag.hpp"

#include "image_control_chunk.hpp"
#include "pdat.hpp"
#include "convert.hpp"

void
convert::bitmap_to_imag(const Bitmap &bitmap_,
DataRW &data_)
{
ByteVec pdat;
ImageControlChunk icc;

icc.id = "IMAG";
icc.chunk_size = sizeof(icc);
icc.w = bitmap_.w;
icc.h = bitmap_.h;
icc.bytesperrow = (2 * bitmap_.w);
icc.bitsperpixel = 16;
icc.numcomponents = 3;
icc.numplanes = 1;
icc.colorspace = 0;
icc.comptype = 0;
icc.hvformat = 0;
icc.pixelorder = 1;
icc.version = 0;

data_.write((const uint8_t*)"IMAG",4);
data_.writebe(icc.chunk_size);
data_.writebe(icc.w);
data_.writebe(icc.h);
data_.writebe(icc.bytesperrow);
data_.writebe(icc.bitsperpixel);
data_.writebe(icc.numcomponents);
data_.writebe(icc.numplanes);
data_.writebe(icc.colorspace);
data_.writebe(icc.comptype);
data_.writebe(icc.hvformat);
data_.writebe(icc.pixelorder);
data_.writebe(icc.version);

convert::bitmap_to_uncoded_unpacked_lrform_16bpp(bitmap_,pdat);

data_.write((const uint8_t*)"PDAT",4);
data_.writebe((uint32_t)(4 + 4 + pdat.size()));
data_.write(pdat.data(),pdat.size());
}
29 changes: 29 additions & 0 deletions src/convert_bitmap_to_imag.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
ISC License
Copyright (c) 2023, Antonio SJ Musumeci <trapexit@spawn.link>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

#pragma once

#include "bitmap.hpp"
#include "datarw.hpp"

namespace convert
{
void
bitmap_to_imag(const Bitmap &bitmap,
DataRW &data);
}
88 changes: 88 additions & 0 deletions src/datarw.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
#include "datarw.hpp"
#include "byteswap.hpp"

void
DataRW::rewind()
{
return seek(0);
}

void
DataRW::rewind(const size_t bytes_)
{
return seek(tell() - bytes_);
}

void
DataRW::skip(const size_t bytes_)
{
return seek(tell() + bytes_);
}

void
DataRW::skip_to_2byte_boundary()
{
return skip(tell() & 1);
}

void
DataRW::skip_to_4byte_boundary()
{
size_t offset;

offset = tell();
if(offset & 0x3)
return skip(4 - (offset & 0x3));
}

void
DataRW::skip_to_8byte_boundary()
{
size_t offset;

offset = tell();
if(offset & 0x7)
return skip(8 - (offset & 0x7));
}

char
DataRW::c()
{
char c;

read((uint8_t*)&c,sizeof(c));

return c;
}

int8_t
DataRW::i8()
{
return (int8_t)c();
}

uint8_t
DataRW::u8()
{
return (uint8_t)c();
}

int16_t
DataRW::i16be()
{
int16_t i;

read((uint8_t*)&i,sizeof(i));

return byteswap_if_little_endian(i);
}

int16_t
DataRW::i16le()
{
int16_t i;

read((uint8_t*)&i,sizeof(i));

return byteswap_if_big_endian(i);
}
Loading

0 comments on commit a977144

Please sign in to comment.