/*
* $Id$
*
* (C) 2003-2006 Gabest
* (C) 2006-2010 see AUTHORS
*
* This file is part of mplayerc.
*
* Mplayerc is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* Mplayerc is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
#include "stdafx.h"
#include "Ifo.h"
#ifdef WORDS_BIGENDIAN
#define bswap_16(x) (x)
#define bswap_32(x) (x)
#define bswap_64(x) (x)
#else
// code from bits/byteswap.h (C) 1997, 1998 Free Software Foundation, Inc.
#define bswap_16(x) \
((((x) >> 8) & 0xff) | (((x) & 0xff) << 8))
// code from bits/byteswap.h (C) 1997, 1998 Free Software Foundation, Inc.
#define bswap_32(x) \
((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \
(((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24))
#define bswap_64(x) \
(__extension__ \
({ union { __extension__ unsigned long long int __ll; \
unsigned long int __l[2]; } __w, __r; \
__w.__ll = (x); \
__r.__l[0] = bswap_32 (__w.__l[1]); \
__r.__l[1] = bswap_32 (__w.__l[0]); \
__r.__ll; }))
#endif
#ifdef WORDS_BIGENDIAN
#define be2me_16(x) (x)
#define be2me_32(x) (x)
#define be2me_64(x) (x)
#define le2me_16(x) bswap_16(x)
#define le2me_32(x) bswap_32(x)
#define le2me_64(x) bswap_64(x)
#else
#define be2me_16(x) bswap_16(x)
#define be2me_32(x) bswap_32(x)
#define be2me_64(x) bswap_64(x)
#define le2me_16(x) (x)
#define le2me_32(x) (x)
#define le2me_64(x) (x)
#endif
#define DVD_VIDEO_LB_LEN 2048
#define IFO_HDR_LEN 8
#define LU_SUB_LEN 8
extern HANDLE (__stdcall * Real_CreateFileW)(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile);
unsigned __int32 get4bytes (const BYTE* buf)
{
return be2me_32 (*((unsigned __int32 *)buf));
}
// VMG files
#define OFF_VMGM_PGCI_UT(buf) get4bytes (buf + 200)
// VTS files
#define OFF_VTSM_PGCI_UT(buf) get4bytes (buf + 208)
#define OFF_VTS_PGCIT(buf) get4bytes (buf + 204)
CIfo::CIfo()
{
m_pBuffer = NULL;
m_pPGCI = NULL;
m_pPGCIT = NULL;
m_dwSize = 0;
}
int CIfo::GetMiscPGCI (CIfo::ifo_hdr_t *hdr, int title, uint8_t **ptr)
{
pgci_sub_t *pgci_sub;
*ptr = (uint8_t *) hdr;
*ptr += IFO_HDR_LEN;
pgci_sub = (pgci_sub_t *) *ptr + title;
*ptr = (uint8_t *) hdr + be2me_32 (pgci_sub->start);
return 0;
}
void CIfo::RemovePgciUOPs (uint8_t *ptr)
{
ifo_hdr_t* hdr = (ifo_hdr_t *) ptr;
uint16_t num;
int i;
ptr += IFO_HDR_LEN;
num = be2me_16(hdr->num);
for (i=1; i<=num; i++) {
lu_sub_t *lu_sub = (lu_sub_t *) ptr;
UNUSED_ALWAYS(lu_sub);
ptr += LU_SUB_LEN;
}
for (i=0; inum); i++) {
uint8_t *ptr;
if (GetMiscPGCI (hdr, i, &ptr) >= 0) {
pgc_t* pgc = (pgc_t*) ptr;
pgc->prohibited_ops = 0;
}
}
}
CIfo::pgc_t* CIfo::GetFirstPGC()
{
if (m_pBuffer) {
return (pgc_t*) (m_pBuffer + 0x0400);
} else {
return NULL;
}
}
CIfo::pgc_t* CIfo::GetPGCI(const int title, const ifo_hdr_t* hdr)
{
CIfo::pgci_sub_t *pgci_sub;
uint8_t *ptr;
ptr = (uint8_t *) hdr;
ptr += IFO_HDR_LEN;
pgci_sub = (pgci_sub_t *) ptr + title;
ptr = (uint8_t *) hdr + be2me_32 (pgci_sub->start);
/* jdw */
if ( ptr >= ( (uint8_t *) hdr + be2me_32 ( hdr->len ))) {
return NULL ;
}
/* /jdw */
return (pgc_t *) ptr;
}
bool CIfo::IsVTS()
{
if (m_dwSize<12 || (strncmp ((char*)m_pBuffer, "DVDVIDEO-VTS", 12)!=0)) {
return false;
}
return true;
}
bool CIfo::IsVMG()
{
if (m_dwSize<12 || (strncmp ((char*)m_pBuffer, "DVDVIDEO-VMG", 12)!=0)) {
return false;
}
return true;
}
bool CIfo::OpenFile (LPCTSTR strFile)
{
bool bRet = false;
HANDLE hFile;
hFile = Real_CreateFileW((LPTSTR) strFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
ASSERT (hFile != INVALID_HANDLE_VALUE);
if (hFile != INVALID_HANDLE_VALUE) {
DWORD dwSize = GetFileSize (hFile, NULL);
m_pBuffer = DNew BYTE [dwSize];
ReadFile (hFile, m_pBuffer, dwSize, &m_dwSize, NULL);
CloseHandle (hFile);
if (IsVTS() && (OFF_VTSM_PGCI_UT(m_pBuffer)!=0)) {
m_pPGCI = (ifo_hdr_t*)(m_pBuffer + OFF_VTSM_PGCI_UT(m_pBuffer) * DVD_VIDEO_LB_LEN);
m_pPGCIT = (ifo_hdr_t*)(m_pBuffer + OFF_VTS_PGCIT(m_pBuffer) * DVD_VIDEO_LB_LEN);
} else if (IsVMG() && (OFF_VMGM_PGCI_UT(m_pBuffer)!=0)) {
m_pPGCI = (ifo_hdr_t*)(m_pBuffer + OFF_VMGM_PGCI_UT(m_pBuffer) * DVD_VIDEO_LB_LEN);
}
bRet = (m_pPGCI != NULL);
}
return bRet;
}
bool CIfo::RemoveUOPs()
{
pgc_t* pgc;
if (m_pPGCI) {
pgc = GetFirstPGC();
pgc->prohibited_ops = 0;
for (int i=0; inum); i++) {
pgc = GetPGCI(i, m_pPGCI);
if (pgc) {
RemovePgciUOPs ((uint8_t*)pgc);
}
}
}
if (m_pPGCIT) {
for (int i=0; inum); i++) {
pgc = GetPGCI(i, m_pPGCIT);
if (pgc) {
pgc->prohibited_ops = 0;
}
}
}
return true;
}
bool CIfo::SaveFile (LPCTSTR strFile)
{
bool bRet = false;
HANDLE m_hFile;
if (m_pBuffer) {
m_hFile = Real_CreateFileW((LPTSTR) strFile, GENERIC_WRITE|GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
ASSERT (m_hFile != INVALID_HANDLE_VALUE);
if (m_hFile != INVALID_HANDLE_VALUE) {
DWORD dwSize;
WriteFile (m_hFile, m_pBuffer, m_dwSize, &dwSize, NULL);
CloseHandle(m_hFile);
bRet = true;
}
}
return bRet;
}
CIfo::~CIfo(void)
{
delete[] m_pBuffer;
}