Compare commits

..

8 Commits

1231 changed files with 153972 additions and 2608 deletions

3
.gitignore vendored
View File

@ -14,3 +14,6 @@
/AxibugEmuOnline.Client/ProjectSettings/AutoStreamingSettings.asset
/AxibugEmuOnline.Client/Logs
/virtuanessrc097-master/save
/virtuanessrc097-master/.vs
/virtuanessrc097-master/Debug
/virtuanessrc097-master/VirtualNES.ini

File diff suppressed because it is too large Load Diff

View File

@ -3,45 +3,50 @@ using System.Diagnostics;
using UnityEngine;
using VirtualNes.Core;
public class AudioProvider : MonoBehaviour
namespace AxibugEmuOnline.Client
{
[SerializeField]
private AudioSource m_as;
private SoundBuffer _buffer = new SoundBuffer(4096);
public void Initialize()
public class AudioProvider : MonoBehaviour
{
var dummy = AudioClip.Create("dummy", 1, 1, AudioSettings.outputSampleRate, false);
[SerializeField]
private AudioSource m_as;
dummy.SetData(new float[] { 1 }, 0);
m_as.clip = dummy; //just to let unity play the audiosource
m_as.loop = true;
m_as.spatialBlend = 1;
m_as.Play();
}
private SoundBuffer _buffer = new SoundBuffer(4096);
void OnAudioFilterRead(float[] data, int channels)
{
int step = channels;
var bufferCount = _buffer.Available();
for (int i = 0; i < data.Length; i += step)
public void Initialize()
{
float rawFloat = 0;
if (_buffer.TryRead(out byte rawData))
rawFloat = rawData / 255f;
var dummy = AudioClip.Create("dummy", 1, 1, AudioSettings.outputSampleRate, false);
data[i] = rawFloat;
for (int fill = 1; fill < step; fill++)
data[i + fill] = rawFloat;
dummy.SetData(new float[] { 1 }, 0);
m_as.clip = dummy; //just to let unity play the audiosource
m_as.loop = true;
m_as.spatialBlend = 1;
m_as.Play();
}
void OnAudioFilterRead(float[] data, int channels)
{
int step = channels;
var bufferCount = _buffer.Available();
for (int i = 0; i < data.Length; i += step)
{
float rawFloat = 0;
if (_buffer.TryRead(out byte rawData))
rawFloat = rawData / 255f;
data[i] = rawFloat;
for (int fill = 1; fill < step; fill++)
data[i + fill] = rawFloat;
}
}
public void ProcessSound(NES nes)
{
nes.apu.Process(_buffer, (uint)(Supporter.Config.sound.nRate * Time.deltaTime));
}
}
public void ProcessSound(NES nes)
{
nes.apu.Process(_buffer, (uint)(Supporter.Config.sound.nRate * Time.deltaTime));
}
}
}

View File

@ -17,7 +17,7 @@ namespace AxibugEmuOnline.Client
private void Start()
{
Application.targetFrameRate = 60;
StartGame("tstd2.nes");
StartGame("ff1.nes");
}
public void StartGame(string romName)
@ -44,7 +44,6 @@ namespace AxibugEmuOnline.Client
m_nesIns = null;
}
private void Update()
{
if (m_nesIns != null)

View File

@ -30,7 +30,7 @@ Transform:
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 4232056521131536011}
m_RootOrder: 1
m_RootOrder: 2
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &9003897287163669553
MonoBehaviour:
@ -141,6 +141,78 @@ AudioSource:
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
--- !u!1 &3545890545112170401
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1038087993597378172}
- component: {fileID: 3032498056073774270}
- component: {fileID: 634277252673086327}
m_Layer: 5
m_Name: Viewer
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &1038087993597378172
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3545890545112170401}
m_LocalRotation: {x: 1, y: 0, z: 0, w: 0}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 4232056520494431727}
m_RootOrder: 1
m_LocalEulerAnglesHint: {x: 180, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 1}
m_AnchorMax: {x: 0, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 128, y: 256}
m_Pivot: {x: 0, y: 0}
--- !u!222 &3032498056073774270
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3545890545112170401}
m_CullTransparentMesh: 1
--- !u!114 &634277252673086327
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3545890545112170401}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 1344c3c82d62a2a41a3576d8abb8e3ea, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Texture: {fileID: 8400000, guid: ffe34aaf87e4b9942b4c2ac05943d444, type: 2}
m_UVRect:
serializedVersion: 2
x: 0
y: 0
width: 1
height: 1
--- !u!1 &4232056520112715746
GameObject:
m_ObjectHideFlags: 0
@ -168,8 +240,7 @@ Transform:
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children:
- {fileID: 4232056520494431727}
m_Children: []
m_Father: {fileID: 4232056521131536011}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
@ -217,8 +288,9 @@ RectTransform:
m_LocalScale: {x: 0, y: 0, z: 0}
m_Children:
- {fileID: 4232056521759880275}
m_Father: {fileID: 4232056520112715745}
m_RootOrder: 0
- {fileID: 1038087993597378172}
m_Father: {fileID: 4232056521131536011}
m_RootOrder: 3
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
@ -315,7 +387,9 @@ Transform:
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children:
- {fileID: 4232056520112715745}
- {fileID: 393435831810118449}
- {fileID: 4785916497946256520}
- {fileID: 4232056520494431727}
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
@ -405,3 +479,47 @@ MonoBehaviour:
y: 0
width: 1
height: 1
--- !u!1 &7856060136050839404
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 393435831810118449}
- component: {fileID: 499856625911497759}
m_Layer: 0
m_Name: PatternViewer
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &393435831810118449
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7856060136050839404}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 4232056521131536011}
m_RootOrder: 1
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &499856625911497759
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7856060136050839404}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: c7a50c189f5be5b4ea54de444f8488a0, type: 3}
m_Name:
m_EditorClassIdentifier:
img: {fileID: 634277252673086327}

View File

@ -7,10 +7,18 @@ using System.Threading.Tasks;
using UnityEngine;
using VirtualNes.Core;
namespace AxibugEmuOnline.Client.Assets.Script.NesEmulator
namespace AxibugEmuOnline.Client
{
public static class PaletteDefine
{
public struct RGBQUAD
{
public byte rgbBlue;
public byte rgbGreen;
public byte rgbRed;
public byte rgbReserved;
}
public class PALBUF
{
public byte r;
@ -108,6 +116,33 @@ namespace AxibugEmuOnline.Client.Assets.Script.NesEmulator
new PALBUF(0x00, 0x00, 0x00),
};
#region 256
// Color
public static RGBQUAD[][] m_cpPalette = new RGBQUAD[8][]
{
new RGBQUAD[64*2],
new RGBQUAD[64*2],
new RGBQUAD[64*2],
new RGBQUAD[64*2],
new RGBQUAD[64*2],
new RGBQUAD[64*2],
new RGBQUAD[64*2],
new RGBQUAD[64*2],
};
// Monochrome
public static RGBQUAD[][] m_mpPalette = new RGBQUAD[8][]
{
new RGBQUAD[64*2],
new RGBQUAD[64*2],
new RGBQUAD[64*2],
new RGBQUAD[64*2],
new RGBQUAD[64*2],
new RGBQUAD[64*2],
new RGBQUAD[64*2],
new RGBQUAD[64*2],
};
#endregion
#region
// Color
public static uint[][] m_cnPalette = new uint[8][]
@ -161,6 +196,18 @@ namespace AxibugEmuOnline.Client.Assets.Script.NesEmulator
};
#endregion
public static RGBQUAD[] GetPaletteData()
{
RGBQUAD[] rgb = new RGBQUAD[256];
for (int i = 0; i < 64; i++)
{
rgb[i] = m_cpPalette[0][i];
rgb[i + 0x40] = m_mpPalette[0][i];
}
return rgb;
}
static PaletteDefine()
{
int Rbit = 0, Gbit = 0, Bbit = 0;
@ -186,6 +233,13 @@ namespace AxibugEmuOnline.Client.Assets.Script.NesEmulator
Gs = (uint)(PalConvTbl[j][1] * m_PaletteBuf[i].g * m_nScanlineColor / 100.0f);
Bs = (uint)(PalConvTbl[j][2] * m_PaletteBuf[i].b * m_nScanlineColor / 100.0f);
m_cpPalette[j][i + 0x00].rgbRed = (byte)Rn;
m_cpPalette[j][i + 0x00].rgbGreen = (byte)Gn;
m_cpPalette[j][i + 0x00].rgbBlue = (byte)Bn;
m_cpPalette[j][i + 0x40].rgbRed = (byte)Rs;
m_cpPalette[j][i + 0x40].rgbGreen = (byte)Gs;
m_cpPalette[j][i + 0x40].rgbBlue = (byte)Bs;
m_cnPalette[j][i] = ((Rn >> (8 - Rbit)) << Rsft) | ((Gn >> (8 - Gbit)) << Gsft) | ((Bn >> (8 - Bbit)) << Bsft);
m_csPalette[j][i] = ((Rs >> (8 - Rbit)) << Rsft) | ((Gs >> (8 - Gbit)) << Gsft) | ((Bs >> (8 - Bbit)) << Bsft);
@ -216,6 +270,13 @@ namespace AxibugEmuOnline.Client.Assets.Script.NesEmulator
if (Gs > 0xFF) Gs = 0xFF;
if (Bs > 0xFF) Bs = 0xFF;
m_mpPalette[j][i + 0x00].rgbRed = (byte)Rn;
m_mpPalette[j][i + 0x00].rgbGreen = (byte)Gn;
m_mpPalette[j][i + 0x00].rgbBlue = (byte)Bn;
m_mpPalette[j][i + 0x40].rgbRed = (byte)Rs;
m_mpPalette[j][i + 0x40].rgbGreen = (byte)Gs;
m_mpPalette[j][i + 0x40].rgbBlue = (byte)Bs;
m_mnPalette[j][i] = ((Rn >> (8 - Rbit)) << Rsft) | ((Gn >> (8 - Gbit)) << Gsft) | ((Bn >> (8 - Bbit)) << Bsft);
m_msPalette[j][i] = ((Rs >> (8 - Rbit)) << Rsft) | ((Gs >> (8 - Gbit)) << Gsft) | ((Bs >> (8 - Bbit)) << Bsft);
}

View File

@ -0,0 +1,75 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using VirtualNes;
using static AxibugEmuOnline.Client.PaletteDefine;
namespace AxibugEmuOnline.Client
{
public class PatternViewer : MonoBehaviour
{
public RawImage img;
private Color32[] m_lpPattern = new Color32[128 * 256];
private Texture2D m_texture;
private Dictionary<byte, RGBQUAD> colors = new Dictionary<byte, RGBQUAD>();
private void Awake()
{
m_texture = new Texture2D(128, 256);
}
private void Update()
{
Paint();
}
public void Paint()
{
img.texture = m_texture;
var pal = MMU.SPPAL;
var palette = PaletteDefine.GetPaletteData();
colors[0] = palette[pal[0]];
colors[1] = palette[pal[1]];
colors[2] = palette[pal[2]];
colors[3] = palette[pal[3]];
for (int i = 0; i < 8; i++)
{
var Ptn = MMU.PPU_MEM_BANK[i];
int lpPtn = 0;
for (int p = 0; p < 64; p++)
{
int lpScn = i * 32 * 128 + (p & 15) * 8 + (p / 16) * 8 * 128;
for (int y = 0; y < 8; y++)
{
byte chr_l = Ptn[lpPtn + y];
byte chr_h = Ptn[lpPtn + y + 8];
m_lpPattern[lpScn + 0] = ToColor32(colors, (((chr_h >> 6) & 2) | ((chr_l >> 7) & 1)));
m_lpPattern[lpScn + 4] = ToColor32(colors, (((chr_h >> 2) & 2) | ((chr_l >> 3) & 1)));
m_lpPattern[lpScn + 1] = ToColor32(colors, (((chr_h >> 5) & 2) | ((chr_l >> 6) & 1)));
m_lpPattern[lpScn + 5] = ToColor32(colors, (((chr_h >> 1) & 2) | ((chr_l >> 2) & 1)));
m_lpPattern[lpScn + 2] = ToColor32(colors, (((chr_h >> 4) & 2) | ((chr_l >> 5) & 1)));
m_lpPattern[lpScn + 6] = ToColor32(colors, (((chr_h >> 0) & 2) | ((chr_l >> 1) & 1)));
m_lpPattern[lpScn + 3] = ToColor32(colors, (((chr_h >> 3) & 2) | ((chr_l >> 4) & 1)));
m_lpPattern[lpScn + 7] = ToColor32(colors, (((chr_h << 1) & 2) | ((chr_l >> 0) & 1)));
// Next line
lpScn += 128;
}
// Next pattern
lpPtn += 16;
}
}
m_texture.SetPixels32(m_lpPattern);
m_texture.Apply();
}
private Color32 ToColor32(Dictionary<byte, RGBQUAD> map, int v)
{
var raw = map[(byte)v];
return new Color32(raw.rgbRed, raw.rgbGreen, raw.rgbBlue, 255);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c7a50c189f5be5b4ea54de444f8488a0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,9 +1,7 @@
using AxibugEmuOnline.Client.Assets.Script.NesEmulator;
using System;
using System.Runtime.InteropServices;
using UnityEngine;
using UnityEngine.UI;
using VirtualNes.Core;
namespace AxibugEmuOnline.Client
{

View File

@ -34,6 +34,13 @@ namespace VirtualNes.Core
m_length = length;
}
public void SetArray(byte[] array, int offset)
{
m_rawArray = array;
m_offset = offset;
m_length = array.Length - offset;
}
public byte this[int index]
{
get

View File

@ -78,6 +78,13 @@ namespace VirtualNes
CPU_MEM_PAGE[page] = 0;
}
internal static void SetPROM_Bank(byte page, ByteArrayRef ptr, byte type)
{
CPU_MEM_BANK[page] = ptr;
CPU_MEM_TYPE[page] = type;
CPU_MEM_PAGE[page] = 0;
}
internal static void SetPROM_8K_Bank(byte page, int bank)
{
bank %= PROM_8K_SIZE;

View File

@ -81,9 +81,23 @@ namespace VirtualNes.Core
{
//todo : 实现加载mapper
switch (no)
{
case 4: return new Mapper004(parent);
case 16: return new Mapper016(parent);
{
case 0: return new Mapper000(parent);
case 1: return new Mapper001(parent);
case 2: return new Mapper002(parent);
case 3: return new Mapper003(parent);
case 4: return new Mapper004(parent);
case 5: return new Mapper005(parent);
case 6: return new Mapper006(parent);
case 7: return new Mapper007(parent);
case 8: return new Mapper008(parent);
case 9: return new Mapper009(parent);
case 10: return new Mapper010(parent);
case 11: return new Mapper011(parent);
case 12: return new Mapper012(parent);
case 13: return new Mapper013(parent);
case 15: return new Mapper015(parent);
case 16: return new Mapper016(parent);
case 17: return new Mapper017(parent);
case 18: return new Mapper018(parent);
case 19: return new Mapper019(parent);

View File

@ -0,0 +1,47 @@
//////////////////////////////////////////////////////////////////////////
// Mapper000 //
//////////////////////////////////////////////////////////////////////////
using static VirtualNes.MMU;
using static VirtualNes.Core.CPU;
using INT = System.Int32;
using BYTE = System.Byte;
using Codice.CM.Client.Differences;
namespace VirtualNes.Core
{
public class Mapper000 : Mapper
{
public Mapper000(NES parent) : base(parent) { }
public override void Reset()
{
switch (PROM_16K_SIZE)
{
default:
case 1: // 16K only
SetPROM_16K_Bank(4, 0);
SetPROM_16K_Bank(6, 0);
break;
case 2: // 32K
SetPROM_32K_Bank(0);
break;
}
uint crc = nes.rom.GetPROM_CRC();
if (crc == 0x4e7db5af)
{ // Circus Charlie(J)
nes.SetRenderMethod(EnumRenderMethod.POST_RENDER);
}
if (crc == 0x57970078)
{ // F-1 Race(J)
nes.SetRenderMethod(EnumRenderMethod.POST_RENDER);
}
if (crc == 0xaf2bbcbc // Mach Rider(JU)
|| crc == 0x3acd4bf1)
{ // Mach Rider(Alt)(JU)
nes.SetRenderMethod(EnumRenderMethod.POST_RENDER);
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c57bc13f96a8d064a885b65c6aebc351
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,416 @@
//////////////////////////////////////////////////////////////////////////
// Mapper001 Nintendo MMC1 //
//////////////////////////////////////////////////////////////////////////
using static VirtualNes.MMU;
using static VirtualNes.Core.CPU;
using INT = System.Int32;
using BYTE = System.Byte;
using Codice.CM.Client.Differences;
namespace VirtualNes.Core
{
public class Mapper001 : Mapper
{
uint last_addr;
BYTE patch;
BYTE wram_patch;
BYTE wram_bank;
BYTE wram_count;
BYTE[] reg = new byte[4];
BYTE shift, regbuf;
public Mapper001(NES parent) : base(parent) { }
public override void Reset()
{
reg[0] = 0x0C; // D3=1,D2=1
reg[1] = reg[2] = reg[3] = 0;
shift = regbuf = 0;
patch = 0;
wram_patch = 0;
if (PROM_16K_SIZE < 32)
{
SetPROM_32K_Bank(0, 1, PROM_8K_SIZE - 2, PROM_8K_SIZE - 1);
}
else
{
// For 512K/1M byte Cartridge
SetPROM_16K_Bank(4, 0);
SetPROM_16K_Bank(6, 16 - 1);
patch = 1;
}
if (VROM_8K_SIZE != 0)
{
// SetVROM_8K_Bank( 0 );
}
uint crc = nes.rom.GetPROM_CRC();
if (crc == 0xb8e16bd0)
{ // Snow Bros.(J)
patch = 2;
}
// if( crc == 0x9b565541 ) { // Triathron, The(J)
// nes.SetFrameIRQmode( FALSE );
// }
if (crc == 0xc96c6f04)
{ // Venus Senki(J)
nes.SetRenderMethod(EnumRenderMethod.POST_ALL_RENDER);
}
// if( crc == 0x5e3f7004 ) { // Softball Tengoku(J)
// }
if (crc == 0x4d2edf70)
{ // Night Rider(J)
nes.SetRenderMethod(EnumRenderMethod.TILE_RENDER);
}
if (crc == 0xcd2a73f0)
{ // Pirates!(U)
nes.SetRenderMethod(EnumRenderMethod.TILE_RENDER);
patch = 2;
}
// if( crc == 0x09efe54b ) { // Majaventure - Mahjong Senki(J)
// nes.SetFrameIRQmode( FALSE );
// }
if (crc == 0x11469ce3)
{ // Viva! Las Vegas(J)
}
if (crc == 0xd878ebf5)
{ // Ninja Ryukenden(J)
nes.SetRenderMethod(EnumRenderMethod.POST_ALL_RENDER);
}
// if( crc == 0x7bd7b849 ) { // Nekketsu Koukou - Dodgeball Bu(J)
// }
if (crc == 0x466efdc2)
{ // Final Fantasy(J)
nes.SetRenderMethod(EnumRenderMethod.TILE_RENDER);
nes.ppu.SetExtMonoMode(true);
}
if (crc == 0xc9556b36)
{ // Final Fantasy I&II(J)
nes.SetRenderMethod(EnumRenderMethod.TILE_RENDER);
nes.ppu.SetExtMonoMode(true);
nes.SetSAVERAM_SIZE(16 * 1024);
wram_patch = 2;
}
if (crc == 0x717e1169)
{ // Cosmic Wars(J)
nes.SetRenderMethod(EnumRenderMethod.PRE_ALL_RENDER);
}
if (crc == 0xC05D2034)
{ // Snake's Revenge(U)
nes.SetRenderMethod(EnumRenderMethod.PRE_ALL_RENDER);
}
if (crc == 0xb8747abf // Best Play - Pro Yakyuu Special(J)
|| crc == 0x29449ba9 // Nobunaga no Yabou - Zenkoku Ban(J)
|| crc == 0x2b11e0b0 // Nobunaga no Yabou - Zenkoku Ban(J)(alt)
|| crc == 0x4642dda6 // Nobunaga's Ambition(U)
|| crc == 0xfb69743a // Aoki Ookami to Shiroki Mejika - Genghis Khan(J)
|| crc == 0x2225c20f // Genghis Khan(U)
|| crc == 0xabbf7217 // Sangokushi(J)
)
{
nes.SetSAVERAM_SIZE(16 * 1024);
wram_patch = 1;
wram_bank = 0;
wram_count = 0;
}
}
private ByteArrayRef _PROM_BANK = new ByteArrayRef();
//void Mapper001::Write(WORD addr, BYTE data)
public override void Write(ushort addr, byte data)
{
// DEBUGOUT( "MMC1 %04X=%02X\n", addr&0xFFFF,data&0xFF );
if (wram_patch == 1 && addr == 0xBFFF)
{
wram_count++;
wram_bank += (byte)(data & 0x01);
if (wram_count == 5)
{
if (wram_bank != 0)
{
_PROM_BANK.SetArray(WRAM, 0x2000);
SetPROM_Bank(3, _PROM_BANK, BANKTYPE_RAM);
}
else
{
_PROM_BANK.SetArray(WRAM, 0x0000);
SetPROM_Bank(3, _PROM_BANK, BANKTYPE_RAM);
}
wram_bank = wram_count = 0;
}
}
if (patch != 1)
{
if ((addr & 0x6000) != (last_addr & 0x6000))
{
shift = regbuf = 0;
}
last_addr = addr;
}
if ((data & 0x80) != 0)
{
shift = regbuf = 0;
// reg[0] = 0x0C; // D3=1,D2=1
reg[0] |= 0x0C; // D3=1,D2=1 残りはリセットされない
return;
}
if ((data & 0x01) != 0) regbuf |= (byte)(1 << shift);
if (++shift < 5)
return;
addr = (ushort)((addr & 0x7FFF) >> 13);
reg[addr] = regbuf;
// DEBUGOUT( "MMC1 %d=%02X\n", addr&0xFFFF,regbuf&0xFF );
regbuf = 0;
shift = 0;
if (patch != 1)
{
// For Normal Cartridge
switch (addr)
{
case 0:
if ((reg[0] & 0x02) != 0)
{
if ((reg[0] & 0x01) != 0) SetVRAM_Mirror(VRAM_HMIRROR);
else SetVRAM_Mirror(VRAM_VMIRROR);
}
else
{
if ((reg[0] & 0x01) != 0) SetVRAM_Mirror(VRAM_MIRROR4H);
else SetVRAM_Mirror(VRAM_MIRROR4L);
}
break;
case 1:
// Register #1
if (VROM_1K_SIZE != 0)
{
if ((reg[0] & 0x10) != 0)
{
// CHR 4K bank lower($0000-$0FFF)
SetVROM_4K_Bank(0, reg[1]);
// CHR 4K bank higher($1000-$1FFF)
SetVROM_4K_Bank(4, reg[2]);
}
else
{
// CHR 8K bank($0000-$1FFF)
SetVROM_8K_Bank(reg[1] >> 1);
}
}
else
{
// For Romancia
if ((reg[0] & 0x10) != 0)
{
SetCRAM_4K_Bank(0, reg[1]);
}
}
break;
case 2:
// Register #2
if (VROM_1K_SIZE != 0)
{
if ((reg[0] & 0x10) != 0)
{
// CHR 4K bank lower($0000-$0FFF)
SetVROM_4K_Bank(0, reg[1]);
// CHR 4K bank higher($1000-$1FFF)
SetVROM_4K_Bank(4, reg[2]);
}
else
{
// CHR 8K bank($0000-$1FFF)
SetVROM_8K_Bank(reg[1] >> 1);
}
}
else
{
// For Romancia
if ((reg[0] & 0x10) != 0)
{
SetCRAM_4K_Bank(4, reg[2]);
}
}
break;
case 3:
if (!((reg[0] & 0x08) != 0))
{
// PRG 32K bank ($8000-$FFFF)
SetPROM_32K_Bank(reg[3] >> 1);
}
else
{
if ((reg[0] & 0x04) != 0)
{
// PRG 16K bank ($8000-$BFFF)
SetPROM_16K_Bank(4, reg[3]);
SetPROM_16K_Bank(6, PROM_16K_SIZE - 1);
}
else
{
// PRG 16K bank ($C000-$FFFF)
SetPROM_16K_Bank(6, reg[3]);
SetPROM_16K_Bank(4, 0);
}
}
break;
}
}
else
{
// For 512K/1M byte Cartridge
INT PROM_BASE = 0;
if (PROM_16K_SIZE >= 32)
{
PROM_BASE = reg[1] & 0x10;
}
// For FinalFantasy I&II
if (wram_patch == 2)
{
if (((reg[1] & 0x18) == 0))
{
_PROM_BANK.SetArray(WRAM, 0x0000);
SetPROM_Bank(3, _PROM_BANK, BANKTYPE_RAM);
}
else
{
_PROM_BANK.SetArray(WRAM, 0x2000);
SetPROM_Bank(3, _PROM_BANK, BANKTYPE_RAM);
}
}
// Register #0
if (addr == 0)
{
if ((reg[0] & 0x02) != 0)
{
if ((reg[0] & 0x01) != 0) SetVRAM_Mirror(VRAM_HMIRROR);
else SetVRAM_Mirror(VRAM_VMIRROR);
}
else
{
if ((reg[0] & 0x01) != 0) SetVRAM_Mirror(VRAM_MIRROR4H);
else SetVRAM_Mirror(VRAM_MIRROR4L);
}
}
// Register #1
if (VROM_1K_SIZE != 0)
{
if ((reg[0] & 0x10) != 0)
{
// CHR 4K bank lower($0000-$0FFF)
SetVROM_4K_Bank(0, reg[1]);
}
else
{
// CHR 8K bank($0000-$1FFF)
SetVROM_8K_Bank(reg[1] >> 1);
}
}
else
{
// For Romancia
if ((reg[0] & 0x10) != 0)
{
SetCRAM_4K_Bank(0, reg[1]);
}
}
// Register #2
if (VROM_1K_SIZE != 0)
{
if ((reg[0] & 0x10) != 0)
{
// CHR 4K bank higher($1000-$1FFF)
SetVROM_4K_Bank(4, reg[2]);
}
}
else
{
// For Romancia
if ((reg[0] & 0x10) != 0)
{
SetCRAM_4K_Bank(4, reg[2]);
}
}
// Register #3
if (((reg[0] & 0x08) == 0))
{
// PRG 32K bank ($8000-$FFFF)
SetPROM_32K_Bank((reg[3] & (0xF + PROM_BASE)) >> 1);
}
else
{
if ((reg[0] & 0x04) != 0)
{
// PRG 16K bank ($8000-$BFFF)
SetPROM_16K_Bank(4, PROM_BASE + (reg[3] & 0x0F));
if (PROM_16K_SIZE >= 32) SetPROM_16K_Bank(6, PROM_BASE + 16 - 1);
}
else
{
// PRG 16K bank ($C000-$FFFF)
SetPROM_16K_Bank(6, PROM_BASE + (reg[3] & 0x0F));
if (PROM_16K_SIZE >= 32) SetPROM_16K_Bank(4, PROM_BASE);
}
}
}
}
//void Mapper001::SaveState(LPBYTE p)
public override void SaveState(byte[] p)
{
p[0] = reg[0];
p[1] = reg[1];
p[2] = reg[2];
p[3] = reg[3];
p[4] = shift;
p[5] = regbuf;
p[6] = wram_bank;
p[7] = wram_count;
}
//void Mapper001::LoadState(LPBYTE p)
public override void LoadState(byte[] p)
{
reg[0] = p[0];
reg[1] = p[1];
reg[2] = p[2];
reg[3] = p[3];
shift = p[4];
regbuf = p[5];
wram_bank = p[6];
wram_count = p[7];
}
public override bool IsStateSave()
{
return true;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c921e7f594a988845856d30f6a925157
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,72 @@
//////////////////////////////////////////////////////////////////////////
// Mapper002 UNROM //
//////////////////////////////////////////////////////////////////////////
using static VirtualNes.MMU;
using static VirtualNes.Core.CPU;
using INT = System.Int32;
using BYTE = System.Byte;
using Codice.CM.Client.Differences;
namespace VirtualNes.Core
{
public class Mapper002 : Mapper
{
BYTE patch;
public Mapper002(NES parent) : base(parent) { }
public override void Reset()
{
SetPROM_32K_Bank(0, 1, PROM_8K_SIZE - 2, PROM_8K_SIZE - 1);
patch = 0;
uint crc = nes.rom.GetPROM_CRC();
// if( crc == 0x322c9b09 ) { // Metal Gear (Alt)(J)
//// nes.SetFrameIRQmode( FALSE );
// }
// if( crc == 0xe7a3867b ) { // Dragon Quest 2(Alt)(J)
// nes.SetFrameIRQmode( FALSE );
// }
//// if( crc == 0x9622fbd9 ) { // Ballblazer(J)
//// patch = 0;
//// }
if (crc == 0x8c3d54e8 // Ikari(J)
|| crc == 0x655efeed // Ikari Warriors(U)
|| crc == 0x538218b2)
{ // Ikari Warriors(E)
patch = 1;
}
if (crc == 0xb20c1030)
{ // Shanghai(J)(original)
patch = 2;
}
}
//void Mapper002::WriteLow(WORD addr, BYTE data)
public override void WriteLow(ushort addr, byte data)
{
if (!nes.rom.IsSAVERAM())
{
if (addr >= 0x5000 && patch == 1)
SetPROM_16K_Bank(4, data);
}
else
{
base.WriteLow(addr, data);
}
}
//void Mapper002::Write(WORD addr, BYTE data)
public override void Write(ushort addr, byte data)
{
if (patch != 2)
SetPROM_16K_Bank(4, data);
else
SetPROM_16K_Bank(4, data >> 4);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: bb072eff593853c41974a6d3b8bc1f93
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,66 @@
//////////////////////////////////////////////////////////////////////////
// Mapper003 CNROM //
//////////////////////////////////////////////////////////////////////////
using static VirtualNes.MMU;
using static VirtualNes.Core.CPU;
using INT = System.Int32;
using BYTE = System.Byte;
using Codice.CM.Client.Differences;
namespace VirtualNes.Core
{
public class Mapper003 : Mapper
{
public Mapper003(NES parent) : base(parent) { }
public override void Reset()
{
switch (PROM_16K_SIZE)
{
case 1: // 16K only
SetPROM_16K_Bank(4, 0);
SetPROM_16K_Bank(6, 0);
break;
case 2: // 32K
SetPROM_32K_Bank(0);
break;
}
// nes.SetRenderMethod( NES::TILE_RENDER );
uint crc = nes.rom.GetPROM_CRC();
if (crc == 0x2b72fe7e)
{ // Ganso Saiyuuki - Super Monkey Dai Bouken(J)
nes.SetRenderMethod(EnumRenderMethod.TILE_RENDER);
nes.ppu.SetExtNameTableMode(true);
}
// if( crc == 0xE44D95B5 ) { // ひみつw
// }
}
#if FALSE//0
void Mapper003::WriteLow( WORD addr, BYTE data )
{
if( patch ) {
Mapper::WriteLow( addr, data );
} else {
if( nes.rom.IsSAVERAM() ) {
Mapper::WriteLow( addr, data );
} else {
if( addr >= 0x4800 ) {
SetVROM_8K_Bank( data & 0x03 );
}
}
}
}
#endif
//void Mapper003::Write(WORD addr, BYTE data)
public override void Write(ushort addr, byte data)
{
SetVROM_8K_Bank(data);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d63147469fd9c5540882a5a89799462b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,846 @@
//////////////////////////////////////////////////////////////////////////
// Mapper005 Nintendo MMC5 //
//////////////////////////////////////////////////////////////////////////
using System;
using static VirtualNes.Core.CPU;
using static VirtualNes.Core.PPU;
using static VirtualNes.MMU;
using BYTE = System.Byte;
using INT = System.Int32;
namespace VirtualNes.Core
{
public class Mapper005 : Mapper
{
public const int MMC5_IRQ_METAL = 1 << 0;
BYTE sram_size;
BYTE prg_size; // $5100
BYTE chr_size; // $5101
BYTE sram_we_a, sram_we_b; // $5102-$5103
BYTE graphic_mode; // $5104
BYTE nametable_mode; // $5105
BYTE[] nametable_type = new byte[4]; // $5105 use
BYTE sram_page; // $5113
BYTE fill_chr, fill_pal; // $5106-$5107
BYTE split_control; // $5200
BYTE split_scroll; // $5201
BYTE split_page; // $5202
BYTE split_x;
ushort split_addr;
ushort split_yofs;
BYTE chr_type;
BYTE chr_mode; // $5120-$512B use
//BYTE chr_page[2][8];
BYTE[,] chr_page = new byte[2, 8]; // $5120-$512B
// BGパターン用バンク
ByteArrayRef[] BG_MEM_BANK = new ByteArrayRef[8]{
new ByteArrayRef(),
new ByteArrayRef(),
new ByteArrayRef(),
new ByteArrayRef(),
new ByteArrayRef(),
new ByteArrayRef(),
new ByteArrayRef(),
new ByteArrayRef(),
};
BYTE[] BG_MEM_PAGE = new byte[8];
BYTE irq_status; // $5204(R)
BYTE irq_enable; // $5204(W)
BYTE irq_line; // $5203
BYTE irq_scanline;
BYTE irq_clear; // HSyncで使用
BYTE irq_type;
BYTE mult_a, mult_b; // $5205-$5206
public Mapper005(NES parent) : base(parent) { }
public override void Reset()
{
byte i;
prg_size = 3;
chr_size = 3;
sram_we_a = 0x00;
sram_we_b = 0x00;
graphic_mode = 0;
nametable_mode = 0;
for (i = 0; i < 4; i++)
{
nametable_type[i] = 0;
}
fill_chr = fill_pal = 0;
split_control = split_scroll = split_page = 0;
irq_enable = 0;
irq_status = 0;
irq_scanline = 0;
irq_line = 0;
irq_clear = 0;
irq_type = 0;
mult_a = mult_b = 0;
chr_type = 0;
chr_mode = 0;
for (i = 0; i < 8; i++)
{
chr_page[0, i] = i;
chr_page[1, i] = (byte)(4 + (i & 0x03));
}
SetPROM_32K_Bank(PROM_8K_SIZE - 1, PROM_8K_SIZE - 1, PROM_8K_SIZE - 1, PROM_8K_SIZE - 1);
SetVROM_8K_Bank(0);
for (i = 0; i < 8; i++)
{
BG_MEM_BANK[i].SetArray(VROM, 0x0400 * i);
BG_MEM_PAGE[i] = i;
}
// SRAM設定
SetBank_SRAM(3, 0);
sram_size = 0;
nes.SetSAVERAM_SIZE(16 * 1024);
uint crc = nes.rom.GetPROM_CRC();
if (crc == 0x2b548d75 // Bandit Kings of Ancient China(U)
|| crc == 0xf4cd4998 // Dai Koukai Jidai(J)
|| crc == 0x8fa95456 // Ishin no Arashi(J)
|| crc == 0x98c8e090 // Nobunaga no Yabou - Sengoku Gunyuu Den(J)
|| crc == 0x8e9a5e2f // L'Empereur(Alt)(U)
|| crc == 0x57e3218b // L'Empereur(U)
|| crc == 0x2f50bd38 // L'Empereur(J)
|| crc == 0xb56958d1 // Nobunaga's Ambition 2(U)
|| crc == 0xe6c28c5f // Suikoden - Tenmei no Chikai(J)
|| crc == 0xcd35e2e9)
{ // Uncharted Waters(U)
sram_size = 1;
nes.SetSAVERAM_SIZE(32 * 1024);
}
else
if (crc == 0xf4120e58 // Aoki Ookami to Shiroki Mejika - Genchou Hishi(J)
|| crc == 0x286613d8 // Nobunaga no Yabou - Bushou Fuuun Roku(J)
|| crc == 0x11eaad26 // Romance of the Three Kingdoms 2(U)
|| crc == 0x95ba5733)
{ // Sangokushi 2(J)
sram_size = 2;
nes.SetSAVERAM_SIZE(64 * 1024);
}
if (crc == 0x95ca9ec7)
{ // Castlevania 3 - Dracula's Curse(U)
nes.SetRenderMethod(EnumRenderMethod.TILE_RENDER);
}
if (crc == 0xcd9acf43)
{ // Metal Slader Glory(J)
irq_type = MMC5_IRQ_METAL;
}
if (crc == 0xe91548d8)
{ // Shin 4 Nin Uchi Mahjong - Yakuman Tengoku(J)
chr_type = 1;
}
nes.ppu.SetExtLatchMode(true);
nes.apu.SelectExSound(8);
}
//BYTE Mapper005::ReadLow(WORD addr)
public override byte ReadLow(ushort addr)
{
BYTE data = (BYTE)(addr >> 8);
switch (addr)
{
case 0x5015:
data = nes.apu.ExRead(addr);
break;
case 0x5204:
data = irq_status;
// irq_status = 0;
irq_status = (byte)(irq_status & ~0x80);
nes.cpu.ClrIRQ(IRQ_MAPPER);
break;
case 0x5205:
data = (byte)(mult_a * mult_b);
break;
case 0x5206:
data = (BYTE)((mult_a * mult_b) >> 8);
break;
}
if (addr >= 0x5C00 && addr <= 0x5FFF)
{
if (graphic_mode >= 2)
{ // ExRAM mode
data = VRAM[0x0800 + (addr & 0x3FF)];
}
}
else if (addr >= 0x6000 && addr <= 0x7FFF)
{
data = base.ReadLow(addr);
}
return data;
}
//void Mapper005::WriteLow(WORD addr, BYTE data)
public override void WriteLow(ushort addr, byte data)
{
byte i;
switch (addr)
{
case 0x5100:
prg_size = (byte)(data & 0x03);
break;
case 0x5101:
chr_size = (byte)(data & 0x03);
break;
case 0x5102:
sram_we_a = (byte)(data & 0x03);
break;
case 0x5103:
sram_we_b = (byte)(data & 0x03);
break;
case 0x5104:
graphic_mode = (byte)(data & 0x03);
break;
case 0x5105:
nametable_mode = data;
for (i = 0; i < 4; i++)
{
nametable_type[i] = (byte)(data & 0x03);
SetVRAM_1K_Bank((byte)(8 + i), nametable_type[i]);
data >>= 2;
}
break;
case 0x5106:
fill_chr = data;
break;
case 0x5107:
fill_pal = (byte)(data & 0x03);
break;
case 0x5113:
SetBank_SRAM(3, (byte)(data & 0x07));
break;
case 0x5114:
case 0x5115:
case 0x5116:
case 0x5117:
SetBank_CPU(addr, data);
break;
case 0x5120:
case 0x5121:
case 0x5122:
case 0x5123:
case 0x5124:
case 0x5125:
case 0x5126:
case 0x5127:
chr_mode = 0;
chr_page[0, addr & 0x07] = data;
SetBank_PPU();
break;
case 0x5128:
case 0x5129:
case 0x512A:
case 0x512B:
chr_mode = 1;
chr_page[1, (addr & 0x03) + 0] = data;
chr_page[1, (addr & 0x03) + 4] = data;
SetBank_PPU();
break;
case 0x5200:
split_control = data;
break;
case 0x5201:
split_scroll = data;
break;
case 0x5202:
split_page = (byte)(data & 0x3F);
break;
case 0x5203:
irq_line = data;
nes.cpu.ClrIRQ(IRQ_MAPPER);
break;
case 0x5204:
irq_enable = data;
nes.cpu.ClrIRQ(IRQ_MAPPER);
break;
case 0x5205:
mult_a = data;
break;
case 0x5206:
mult_b = data;
break;
default:
if (addr >= 0x5000 && addr <= 0x5015)
{
nes.apu.ExWrite(addr, data);
}
else if (addr >= 0x5C00 && addr <= 0x5FFF)
{
if (graphic_mode == 2)
{ // ExRAM
VRAM[0x0800 + (addr & 0x3FF)] = data;
}
else if (graphic_mode != 3)
{ // Split,ExGraphic
if ((irq_status & 0x40) != 0)
{
VRAM[0x0800 + (addr & 0x3FF)] = data;
}
else
{
VRAM[0x0800 + (addr & 0x3FF)] = 0;
}
}
}
else if (addr >= 0x6000 && addr <= 0x7FFF)
{
if ((sram_we_a == 0x02) && (sram_we_b == 0x01))
{
if (CPU_MEM_TYPE[3] == BANKTYPE_RAM)
{
CPU_MEM_BANK[3][addr & 0x1FFF] = data;
}
}
}
break;
}
}
//void Mapper005::Write(WORD addr, BYTE data)
public override void Write(ushort addr, byte data)
{
if (sram_we_a == 0x02 && sram_we_b == 0x01)
{
if (addr >= 0x8000 && addr < 0xE000)
{
if (CPU_MEM_TYPE[addr >> 13] == BANKTYPE_RAM)
{
CPU_MEM_BANK[addr >> 13][addr & 0x1FFF] = data;
}
}
}
}
void SetBank_CPU(uint addr, BYTE data)
{
if ((data & 0x80) != 0)
{
// PROM Bank
switch (addr & 7)
{
case 4:
if (prg_size == 3)
{
SetPROM_8K_Bank(4, data & 0x7F);
}
break;
case 5:
if (prg_size == 1 || prg_size == 2)
{
SetPROM_16K_Bank(4, (data & 0x7F) >> 1);
}
else if (prg_size == 3)
{
SetPROM_8K_Bank(5, (data & 0x7F));
}
break;
case 6:
if (prg_size == 2 || prg_size == 3)
{
SetPROM_8K_Bank(6, (data & 0x7F));
}
break;
case 7:
if (prg_size == 0)
{
SetPROM_32K_Bank((data & 0x7F) >> 2);
}
else if (prg_size == 1)
{
SetPROM_16K_Bank(6, (data & 0x7F) >> 1);
}
else if (prg_size == 2 || prg_size == 3)
{
SetPROM_8K_Bank(7, (data & 0x7F));
}
break;
}
}
else
{
// WRAM Bank
switch (addr & 7)
{
case 4:
if (prg_size == 3)
{
SetBank_SRAM(4, (byte)(data & 0x07));
}
break;
case 5:
if (prg_size == 1 || prg_size == 2)
{
SetBank_SRAM(4, (byte)((data & 0x06) + 0));
SetBank_SRAM(5, (byte)((data & 0x06) + 1));
}
else if (prg_size == 3)
{
SetBank_SRAM(5, (byte)(data & 0x07));
}
break;
case 6:
if (prg_size == 2 || prg_size == 3)
{
SetBank_SRAM(6, (byte)(data & 0x07));
}
break;
}
}
}
private ByteArrayRef _prom_bank = new ByteArrayRef();
void SetBank_SRAM(BYTE page, BYTE data)
{
if (sram_size == 0) data = (byte)((data > 3) ? 8 : 0);
if (sram_size == 1) data = (byte)((data > 3) ? 1 : 0);
if (sram_size == 2) data = (byte)((data > 3) ? 8 : data);
if (sram_size == 3) data = (byte)((data > 3) ? 4 : data);
if (data != 8)
{
int offset = 0x2000 * data;
_prom_bank.SetArray(WRAM, offset, WRAM.Length - offset);
SetPROM_Bank(page, _prom_bank, BANKTYPE_RAM);
CPU_MEM_PAGE[page] = data;
}
else
{
CPU_MEM_TYPE[page] = BANKTYPE_ROM;
}
}
void SetBank_PPU()
{
INT i;
if (chr_mode == 0)
{
// PPU SP Bank
switch (chr_size)
{
case 0:
SetVROM_8K_Bank(chr_page[0, 7]);
break;
case 1:
SetVROM_4K_Bank(0, chr_page[0, 3]);
SetVROM_4K_Bank(4, chr_page[0, 7]);
break;
case 2:
SetVROM_2K_Bank(0, chr_page[0, 1]);
SetVROM_2K_Bank(2, chr_page[0, 3]);
SetVROM_2K_Bank(4, chr_page[0, 5]);
SetVROM_2K_Bank(6, chr_page[0, 7]);
break;
case 3:
SetVROM_8K_Bank(chr_page[0, 0],
chr_page[0, 1],
chr_page[0, 2],
chr_page[0, 3],
chr_page[0, 4],
chr_page[0, 5],
chr_page[0, 6],
chr_page[0, 7]);
break;
}
}
else if (chr_mode == 1)
{
// PPU BG Bank
switch (chr_size)
{
case 0:
for (i = 0; i < 8; i++)
{
BG_MEM_BANK[i].SetArray(VROM, 0x2000 * (chr_page[1, 7] % VROM_8K_SIZE) + 0x0400 * i);
BG_MEM_PAGE[i] = (byte)((chr_page[1, 7] % VROM_8K_SIZE) * 8 + i);
}
break;
case 1:
for (i = 0; i < 4; i++)
{
BG_MEM_BANK[i + 0].SetArray(VROM, 0x1000 * (chr_page[1, 3] % VROM_4K_SIZE) + 0x0400 * i);
BG_MEM_BANK[i + 4].SetArray(VROM, 0x1000 * (chr_page[1, 7] % VROM_4K_SIZE) + 0x0400 * i);
BG_MEM_PAGE[i + 0] = (byte)((chr_page[1, 3] % VROM_4K_SIZE) * 4 + i);
BG_MEM_PAGE[i + 4] = (byte)((chr_page[1, 7] % VROM_4K_SIZE) * 4 + i);
}
break;
case 2:
for (i = 0; i < 2; i++)
{
BG_MEM_BANK[i + 0].SetArray(VROM, 0x0800 * (chr_page[1, 1] % VROM_2K_SIZE) + 0x0400 * i);
BG_MEM_BANK[i + 2].SetArray(VROM, 0x0800 * (chr_page[1, 3] % VROM_2K_SIZE) + 0x0400 * i);
BG_MEM_BANK[i + 4].SetArray(VROM, 0x0800 * (chr_page[1, 5] % VROM_2K_SIZE) + 0x0400 * i);
BG_MEM_BANK[i + 6].SetArray(VROM, 0x0800 * (chr_page[1, 7] % VROM_2K_SIZE) + 0x0400 * i);
BG_MEM_PAGE[i + 0] = (byte)((chr_page[1, 1] % VROM_2K_SIZE) * 2 + i);
BG_MEM_PAGE[i + 2] = (byte)((chr_page[1, 3] % VROM_2K_SIZE) * 2 + i);
BG_MEM_PAGE[i + 4] = (byte)((chr_page[1, 5] % VROM_2K_SIZE) * 2 + i);
BG_MEM_PAGE[i + 6] = (byte)((chr_page[1, 7] % VROM_2K_SIZE) * 2 + i);
}
break;
case 3:
for (i = 0; i < 8; i++)
{
BG_MEM_BANK[i].SetArray(VROM, 0x0400 * (chr_page[1, i] % VROM_1K_SIZE));
BG_MEM_PAGE[i] = (byte)((chr_page[1, i] % VROM_1K_SIZE) + i);
}
break;
}
}
}
public override void HSync(int scanline)
{
if ((irq_type & MMC5_IRQ_METAL) != 0)
{
if (irq_scanline == irq_line)
{
irq_status |= 0x80;
}
}
// if( nes.ppu.IsDispON() && scanline < 239 ) {
if (nes.ppu.IsDispON() && scanline < 240)
{
irq_scanline++;
irq_status |= 0x40;
irq_clear = 0;
}
else if ((irq_type & MMC5_IRQ_METAL) != 0)
{
irq_scanline = 0;
irq_status = (byte)(irq_status & ~0x80);
irq_status = (byte)(irq_status & ~0x40);
}
if ((irq_type & MMC5_IRQ_METAL) == 0)
{
if (irq_scanline == irq_line)
{
irq_status |= 0x80;
}
if (++irq_clear > 2)
{
irq_scanline = 0;
irq_status = (byte)(irq_status & ~0x80);
irq_status = (byte)(irq_status & ~0x40);
nes.cpu.ClrIRQ(IRQ_MAPPER);
}
}
if ((irq_enable & 0x80) != 0 && (irq_status & 0x80) != 0 && (irq_status & 0x40) != 0)
{
nes.cpu.SetIRQ(IRQ_MAPPER);
/// nes.cpu.IRQ_NotPending();
}
// For Split mode!
if (scanline == 0)
{
split_yofs = (ushort)(split_scroll & 0x07);
split_addr = (ushort)(((split_scroll & 0xF8) << 2));
}
else if (nes.ppu.IsDispON())
{
if (split_yofs == 7)
{
split_yofs = 0;
if ((split_addr & 0x03E0) == 0x03A0)
{
split_addr &= 0x001F;
}
else
{
if ((split_addr & 0x03E0) == 0x03E0)
{
split_addr &= 0x001F;
}
else
{
split_addr += 0x0020;
}
}
}
else
{
split_yofs++;
}
}
}
//void Mapper005::PPU_ExtLatchX(INT x)
public override void PPU_ExtLatchX(int x)
{
split_x = (byte)x;
}
//void Mapper005::PPU_ExtLatch(WORD addr, BYTE& chr_l, BYTE& chr_h, BYTE& attr )
public override void PPU_ExtLatch(ushort addr, ref byte chr_l, ref byte chr_h, ref byte attr)
{
ushort ntbladr, attradr, tileadr, tileofs;
ushort tile_yofs;
uint tilebank;
bool bSplit;
tile_yofs = nes.ppu.GetTILEY();
bSplit = false;
if ((split_control & 0x80) != 0)
{
if ((split_control & 0x40) == 0)
{
// Left side
if ((split_control & 0x1F) > split_x)
{
bSplit = true;
}
}
else
{
// Right side
if ((split_control & 0x1F) <= split_x)
{
bSplit = true;
}
}
}
if (!bSplit)
{
if (nametable_type[(addr & 0x0C00) >> 10] == 3)
{
// Fill mode
if (graphic_mode == 1)
{
// ExGraphic mode
ntbladr = (ushort)(0x2000 + (addr & 0x0FFF));
// Get Nametable
tileadr = (ushort)(fill_chr * 0x10 + tile_yofs);
// Get TileBank
tilebank = (uint)(0x1000 * ((VRAM[0x0800 + (ntbladr & 0x03FF)] & 0x3F) % VROM_4K_SIZE));
// Attribute
attr = (byte)((fill_pal << 2) & 0x0C);
// Get Pattern
chr_l = VROM[tilebank + tileadr];
chr_h = VROM[tilebank + tileadr + 8];
}
else
{
// Normal
tileofs = (ushort)((PPUREG[0] & PPU_BGTBL_BIT) != 0 ? 0x1000 : 0x0000);
tileadr = (ushort)(tileofs + fill_chr * 0x10 + tile_yofs);
attr = (byte)((fill_pal << 2) & 0x0C);
// Get Pattern
if (chr_type != 0)
{
chr_l = PPU_MEM_BANK[tileadr >> 10][tileadr & 0x03FF];
chr_h = PPU_MEM_BANK[tileadr >> 10][(tileadr & 0x03FF) + 8];
}
else
{
chr_l = BG_MEM_BANK[tileadr >> 10][tileadr & 0x03FF];
chr_h = BG_MEM_BANK[tileadr >> 10][(tileadr & 0x03FF) + 8];
}
}
}
else if (graphic_mode == 1)
{
// ExGraphic mode
ntbladr = (ushort)(0x2000 + (addr & 0x0FFF));
// Get Nametable
tileadr = (ushort)(PPU_MEM_BANK[ntbladr >> 10][ntbladr & 0x03FF] * 0x10 + tile_yofs);
// Get TileBank
tilebank = (uint)(0x1000 * ((VRAM[0x0800 + (ntbladr & 0x03FF)] & 0x3F) % VROM_4K_SIZE));
// Get Attribute
attr = (byte)((VRAM[0x0800 + (ntbladr & 0x03FF)] & 0xC0) >> 4);
// Get Pattern
chr_l = VROM[tilebank + tileadr];
chr_h = VROM[tilebank + tileadr + 8];
}
else
{
// Normal or ExVRAM
tileofs = (ushort)((PPUREG[0] & PPU_BGTBL_BIT) != 0 ? 0x1000 : 0x0000);
ntbladr = (ushort)(0x2000 + (addr & 0x0FFF));
attradr = (ushort)(0x23C0 + (addr & 0x0C00) + ((addr & 0x0380) >> 4) + ((addr & 0x001C) >> 2));
// Get Nametable
tileadr = (ushort)(tileofs + PPU_MEM_BANK[ntbladr >> 10][ntbladr & 0x03FF] * 0x10 + tile_yofs);
// Get Attribute
attr = PPU_MEM_BANK[attradr >> 10][attradr & 0x03FF];
if ((ntbladr & 0x0002) != 0) attr >>= 2;
if ((ntbladr & 0x0040) != 0) attr >>= 4;
attr = (byte)((attr & 0x03) << 2);
// Get Pattern
if (chr_type != 0)
{
chr_l = PPU_MEM_BANK[tileadr >> 10][tileadr & 0x03FF];
chr_h = PPU_MEM_BANK[tileadr >> 10][(tileadr & 0x03FF) + 8];
}
else
{
chr_l = BG_MEM_BANK[tileadr >> 10][tileadr & 0x03FF];
chr_h = BG_MEM_BANK[tileadr >> 10][(tileadr & 0x03FF) + 8];
}
}
}
else
{
ntbladr = (ushort)(((split_addr & 0x03E0) | (split_x & 0x1F)) & 0x03FF);
// Get Split TileBank
tilebank = (uint)(0x1000 * (split_page % VROM_4K_SIZE));
tileadr = (ushort)(VRAM[0x0800 + ntbladr] * 0x10 + split_yofs);
// Get Attribute
attradr = (ushort)(0x03C0 + ((ntbladr & 0x0380) >> 4) + ((ntbladr & 0x001C) >> 2));
attr = VRAM[0x0800 + attradr];
if ((ntbladr & 0x0002) != 0) attr >>= 2;
if ((ntbladr & 0x0040) != 0) attr >>= 4;
attr = (byte)((attr & 0x03) << 2);
// Get Pattern
chr_l = VROM[tilebank + tileadr];
chr_h = VROM[tilebank + tileadr + 8];
}
}
//void Mapper005::SaveState(LPBYTE p)
public override void SaveState(byte[] p)
{
p[0] = prg_size;
p[1] = chr_size;
p[2] = sram_we_a;
p[3] = sram_we_b;
p[4] = graphic_mode;
p[5] = nametable_mode;
p[6] = nametable_type[0];
p[7] = nametable_type[1];
p[8] = nametable_type[2];
p[9] = nametable_type[3];
p[10] = sram_page;
p[11] = fill_chr;
p[12] = fill_pal;
p[13] = split_control;
p[14] = split_scroll;
p[15] = split_page;
p[16] = chr_mode;
p[17] = irq_status;
p[18] = irq_enable;
p[19] = irq_line;
p[20] = irq_scanline;
p[21] = irq_clear;
p[22] = mult_a;
p[23] = mult_b;
INT i, j;
for (j = 0; j < 2; j++)
{
for (i = 0; i < 8; i++)
{
p[24 + j * 8 + i] = chr_page[j, i];
}
}
// for( i = 0; i < 8; i++ ) {
// p[40+i] = BG_MEM_PAGE[i];
// }
}
//void Mapper005::LoadState(LPBYTE p)
public override void LoadState(byte[] p)
{
prg_size = p[0];
chr_size = p[1];
sram_we_a = p[2];
sram_we_b = p[3];
graphic_mode = p[4];
nametable_mode = p[5];
nametable_type[0] = p[6];
nametable_type[1] = p[7];
nametable_type[2] = p[8];
nametable_type[3] = p[9];
sram_page = p[10];
fill_chr = p[11];
fill_pal = p[12];
split_control = p[13];
split_scroll = p[14];
split_page = p[15];
chr_mode = p[16];
irq_status = p[17];
irq_enable = p[18];
irq_line = p[19];
irq_scanline = p[20];
irq_clear = p[21];
mult_a = p[22];
mult_b = p[23];
INT i, j;
for (j = 0; j < 2; j++)
{
for (i = 0; i < 8; i++)
{
chr_page[j, i] = p[24 + j * 8 + i];
}
}
// // BGバンクの再設定処理
// for( i = 0; i < 8; i++ ) {
// BG_MEM_PAGE[i] = p[40+i]%VROM_1K_SIZE;
// }
// for( i = 0; i < 8; i++ ) {
// BG_MEM_BANK[i] = VROM+0x0400*BG_MEM_PAGE[i];
// }
SetBank_PPU();
}
public override bool IsStateSave()
{
return true;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 26977049b3ea7ad4fa3b5c35a325ae48
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,112 @@
//////////////////////////////////////////////////////////////////////////
// Mapper006 FFE F4xxx //
//////////////////////////////////////////////////////////////////////////
using static VirtualNes.MMU;
using static VirtualNes.Core.CPU;
using INT = System.Int32;
using BYTE = System.Byte;
using Codice.CM.Client.Differences;
namespace VirtualNes.Core
{
public class Mapper006 : Mapper
{
BYTE irq_enable;
INT irq_counter;
public Mapper006(NES parent) : base(parent) { }
public override void Reset()
{
SetPROM_32K_Bank(0, 1, 14, 15);
if (VROM_1K_SIZE != 0)
{
SetVROM_8K_Bank(0);
}
else
{
SetCRAM_8K_Bank(0);
}
irq_enable = 0;
irq_counter = 0;
}
//void Mapper006::WriteLow(WORD addr, BYTE data)
public override void WriteLow(ushort addr, byte data)
{
switch (addr)
{
case 0x42FE:
if ((data & 0x10) != 0) SetVRAM_Mirror(VRAM_MIRROR4H);
else SetVRAM_Mirror(VRAM_MIRROR4L);
break;
case 0x42FF:
if ((data & 0x10) != 0) SetVRAM_Mirror(VRAM_HMIRROR);
else SetVRAM_Mirror(VRAM_VMIRROR);
break;
case 0x4501:
irq_enable = 0;
nes.cpu.ClrIRQ(IRQ_MAPPER);
break;
case 0x4502:
irq_counter = (irq_counter & 0xFF00) | data;
break;
case 0x4503:
irq_counter = (irq_counter & 0x00FF) | ((INT)data << 8);
irq_enable = 0xFF;
nes.cpu.ClrIRQ(IRQ_MAPPER);
break;
default:
base.WriteLow(addr, data);
break;
}
}
//void Mapper006::Write(WORD addr, BYTE data)
public override void Write(ushort addr, byte data)
{
SetPROM_16K_Bank(4, (data & 0x3C) >> 2);
SetCRAM_8K_Bank(data & 0x03);
}
//void Mapper006::HSync(INT scanline)
public override void HSync(int scanline)
{
if (irq_enable != 0)
{
irq_counter += 133;
if (irq_counter >= 0xFFFF)
{
// nes.cpu.IRQ();
irq_counter = 0;
nes.cpu.SetIRQ(IRQ_MAPPER);
}
}
}
//void Mapper006::SaveState(LPBYTE p)
public override void SaveState(byte[] p)
{
//p[0] = irq_enable;
//*(INT*)&p[1] = irq_counter;
}
//void Mapper006::LoadState(LPBYTE p)
public override void LoadState(byte[] p)
{
//irq_enable = p[0];
//irq_counter = *(INT*)&p[1];
}
public override bool IsStateSave()
{
return true;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0672fe1374d484f4ab1c824d0882bfdd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,59 @@
//////////////////////////////////////////////////////////////////////////
// Mapper007 AOROM/AMROM //
//////////////////////////////////////////////////////////////////////////
using static VirtualNes.MMU;
using static VirtualNes.Core.CPU;
using INT = System.Int32;
using BYTE = System.Byte;
using Codice.CM.Client.Differences;
using UnityEngine.UIElements;
namespace VirtualNes.Core
{
public class Mapper007 : Mapper
{
BYTE patch;
public Mapper007(NES parent) : base(parent) { }
public override void Reset()
{
patch = 0;
SetPROM_32K_Bank(0);
SetVRAM_Mirror(VRAM_MIRROR4L);
uint crc = nes.rom.GetPROM_CRC();
if (crc == 0x3c9fe649)
{ // WWF Wrestlemania Challenge(U)
SetVRAM_Mirror(VRAM_VMIRROR);
patch = 1;
}
if (crc == 0x09874777)
{ // Marble Madness(U)
nes.SetRenderMethod( EnumRenderMethod.TILE_RENDER);
}
if (crc == 0x279710DC // Battletoads (U)
|| crc == 0xCEB65B06)
{ // Battletoads Double Dragon (U)
nes.SetRenderMethod( EnumRenderMethod.PRE_ALL_RENDER);
//::memset(WRAM, 0, sizeof(WRAM));
MemoryUtility.ZEROMEMORY(WRAM, WRAM.Length);
}
}
//void Mapper007::Write(WORD addr, BYTE data)
public override void Write(ushort addr, byte data)
{
SetPROM_32K_Bank(data & 0x07);
if (patch!=0)
{
if ((data & 0x10)!=0) SetVRAM_Mirror(VRAM_MIRROR4H);
else SetVRAM_Mirror(VRAM_MIRROR4L);
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 063872d968d91234a9a22755e3db7aab
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,32 @@
//////////////////////////////////////////////////////////////////////////
// Mapper008 FFE F3xxx //
//////////////////////////////////////////////////////////////////////////
using static VirtualNes.MMU;
using static VirtualNes.Core.CPU;
using INT = System.Int32;
using BYTE = System.Byte;
using Codice.CM.Client.Differences;
namespace VirtualNes.Core
{
public class Mapper008 : Mapper
{
public Mapper008(NES parent) : base(parent) { }
public override void Reset()
{
SetPROM_32K_Bank(0, 1, 2, 3);
SetVROM_8K_Bank(0);
}
//void Mapper008::Write(WORD addr, BYTE data)
public override void Write(ushort addr, byte data)
{
SetPROM_16K_Bank(4, (data & 0xF8) >> 3);
SetVROM_8K_Bank(data & 0x07);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7e39136ad8af00f4c95499cab3a0aa45
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,129 @@
//////////////////////////////////////////////////////////////////////////
// Mapper009 Nintendo MMC2 //
//////////////////////////////////////////////////////////////////////////
using static VirtualNes.MMU;
using static VirtualNes.Core.CPU;
using INT = System.Int32;
using BYTE = System.Byte;
using Codice.CM.Client.Differences;
namespace VirtualNes.Core
{
public class Mapper009 : Mapper
{
BYTE[] reg = new byte[4];
BYTE latch_a, latch_b;
public Mapper009(NES parent) : base(parent) { }
public override void Reset()
{
SetPROM_32K_Bank(0, PROM_8K_SIZE - 3, PROM_8K_SIZE - 2, PROM_8K_SIZE - 1);
reg[0] = 0; reg[1] = 4;
reg[2] = 0; reg[3] = 0;
latch_a = 0xFE;
latch_b = 0xFE;
SetVROM_4K_Bank(0, 4);
SetVROM_4K_Bank(4, 0);
nes.ppu.SetChrLatchMode(true);
}
//void Mapper009::Write(WORD addr, BYTE data)
public override void Write(ushort addr, byte data)
{
switch (addr & 0xF000)
{
case 0xA000:
SetPROM_8K_Bank(4, data);
break;
case 0xB000:
reg[0] = data;
if (latch_a == 0xFD)
{
SetVROM_4K_Bank(0, reg[0]);
}
break;
case 0xC000:
reg[1] = data;
if (latch_a == 0xFE)
{
SetVROM_4K_Bank(0, reg[1]);
}
break;
case 0xD000:
reg[2] = data;
if (latch_b == 0xFD)
{
SetVROM_4K_Bank(4, reg[2]);
}
break;
case 0xE000:
reg[3] = data;
if (latch_b == 0xFE)
{
SetVROM_4K_Bank(4, reg[3]);
}
break;
case 0xF000:
if ((data & 0x01) != 0) SetVRAM_Mirror(VRAM_HMIRROR);
else SetVRAM_Mirror(VRAM_VMIRROR);
break;
}
}
//void Mapper009::PPU_ChrLatch(WORD addr)
public override void PPU_ChrLatch(ushort addr)
{
if ((addr & 0x1FF0) == 0x0FD0 && latch_a != 0xFD)
{
latch_a = 0xFD;
SetVROM_4K_Bank(0, reg[0]);
}
else if ((addr & 0x1FF0) == 0x0FE0 && latch_a != 0xFE)
{
latch_a = 0xFE;
SetVROM_4K_Bank(0, reg[1]);
}
else if ((addr & 0x1FF0) == 0x1FD0 && latch_b != 0xFD)
{
latch_b = 0xFD;
SetVROM_4K_Bank(4, reg[2]);
}
else if ((addr & 0x1FF0) == 0x1FE0 && latch_b != 0xFE)
{
latch_b = 0xFE;
SetVROM_4K_Bank(4, reg[3]);
}
}
//void Mapper009::SaveState(LPBYTE p)
public override void SaveState(byte[] p)
{
p[0] = reg[0];
p[1] = reg[1];
p[2] = reg[2];
p[3] = reg[3];
p[4] = latch_a;
p[5] = latch_b;
}
//void Mapper009::LoadState(LPBYTE p)
public override void LoadState(byte[] p)
{
reg[0] = p[0];
reg[1] = p[1];
reg[2] = p[2];
reg[3] = p[3];
latch_a = p[4];
latch_b = p[5];
}
public override bool IsStateSave()
{
return true;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 60942642eeee2e04fbe2fad967c2400d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,129 @@
//////////////////////////////////////////////////////////////////////////
// Mapper010 Nintendo MMC4 //
//////////////////////////////////////////////////////////////////////////
using static VirtualNes.MMU;
using static VirtualNes.Core.CPU;
using INT = System.Int32;
using BYTE = System.Byte;
using Codice.CM.Client.Differences;
namespace VirtualNes.Core
{
public class Mapper010 : Mapper
{
BYTE[] reg = new byte[4];
BYTE latch_a, latch_b;
public Mapper010(NES parent) : base(parent) { }
public override void Reset()
{
SetPROM_32K_Bank(0, 1, PROM_8K_SIZE - 2, PROM_8K_SIZE - 1);
reg[0] = 0; reg[1] = 4;
reg[2] = 0; reg[3] = 0;
latch_a = 0xFE;
latch_b = 0xFE;
SetVROM_4K_Bank(0, 4);
SetVROM_4K_Bank(4, 0);
nes.ppu.SetChrLatchMode(true);
}
//void Mapper010::Write(WORD addr, BYTE data)
public override void Write(ushort addr, byte data)
{
switch (addr & 0xF000)
{
case 0xA000:
SetPROM_16K_Bank(4, data);
break;
case 0xB000:
reg[0] = data;
if (latch_a == 0xFD)
{
SetVROM_4K_Bank(0, reg[0]);
}
break;
case 0xC000:
reg[1] = data;
if (latch_a == 0xFE)
{
SetVROM_4K_Bank(0, reg[1]);
}
break;
case 0xD000:
reg[2] = data;
if (latch_b == 0xFD)
{
SetVROM_4K_Bank(4, reg[2]);
}
break;
case 0xE000:
reg[3] = data;
if (latch_b == 0xFE)
{
SetVROM_4K_Bank(4, reg[3]);
}
break;
case 0xF000:
if ((data & 0x01) != 0)
SetVRAM_Mirror(VRAM_HMIRROR);
else SetVRAM_Mirror(VRAM_VMIRROR);
break;
}
}
//void Mapper010::PPU_ChrLatch(WORD addr)
public override void PPU_ChrLatch(ushort addr)
{
if ((addr & 0x1FF0) == 0x0FD0 && latch_a != 0xFD)
{
latch_a = 0xFD;
SetVROM_4K_Bank(0, reg[0]);
}
else if ((addr & 0x1FF0) == 0x0FE0 && latch_a != 0xFE)
{
latch_a = 0xFE;
SetVROM_4K_Bank(0, reg[1]);
}
else if ((addr & 0x1FF0) == 0x1FD0 && latch_b != 0xFD)
{
latch_b = 0xFD;
SetVROM_4K_Bank(4, reg[2]);
}
else if ((addr & 0x1FF0) == 0x1FE0 && latch_b != 0xFE)
{
latch_b = 0xFE;
SetVROM_4K_Bank(4, reg[3]);
}
}
//void Mapper010::SaveState(LPBYTE p)
public override void SaveState(byte[] p)
{
p[0] = reg[0];
p[1] = reg[1];
p[2] = reg[2];
p[3] = reg[3];
p[4] = latch_a;
p[5] = latch_b;
}
//void Mapper010::LoadState(LPBYTE p)
public override void LoadState(byte[] p)
{
reg[0] = p[0];
reg[1] = p[1];
reg[2] = p[2];
reg[3] = p[3];
latch_a = p[4];
latch_b = p[5];
}
public override bool IsStateSave()
{
return true;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0beeffcb64a5c124c9ef8d2b428f723e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,42 @@
//////////////////////////////////////////////////////////////////////////
// Mapper011 Color Dreams //
//////////////////////////////////////////////////////////////////////////
using static VirtualNes.MMU;
using static VirtualNes.Core.CPU;
using INT = System.Int32;
using BYTE = System.Byte;
using Codice.CM.Client.Differences;
namespace VirtualNes.Core
{
public class Mapper011 : Mapper
{
public Mapper011(NES parent) : base(parent) { }
public override void Reset()
{
SetPROM_32K_Bank(0);
if (VROM_1K_SIZE != 0)
{
SetVROM_8K_Bank(0);
// SetVROM_8K_Bank( 1 );
}
SetVRAM_Mirror(VRAM_VMIRROR);
}
//void Mapper011::Write(WORD addr, BYTE data)
public override void Write(ushort addr, byte data)
{
//DEBUGOUT("WR A:%04X D:%02X\n", addr, data);
SetPROM_32K_Bank(data);
if (VROM_1K_SIZE != 0)
{
SetVROM_8K_Bank(data >> 4);
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1d46cb68121988e498159e8a53b0cb90
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,331 @@
using static VirtualNes.MMU;
using static VirtualNes.Core.CPU;
using INT = System.Int32;
using BYTE = System.Byte;
using Codice.CM.Client.Differences;
namespace VirtualNes.Core
{
public class Mapper012 : Mapper
{
uint vb0, vb1;
BYTE[] reg = new byte[8];
BYTE prg0, prg1;
BYTE chr01, chr23, chr4, chr5, chr6, chr7;
BYTE we_sram;
BYTE irq_enable;
BYTE irq_counter;
BYTE irq_latch;
BYTE irq_request;
BYTE irq_preset;
BYTE irq_preset_vbl;
public Mapper012(NES parent) : base(parent) { }
public override void Reset()
{
for (INT i = 0; i < 8; i++)
{
reg[i] = 0x00;
}
prg0 = 0;
prg1 = 1;
SetBank_CPU();
vb0 = 0;
vb1 = 0;
chr01 = 0;
chr23 = 2;
chr4 = 4;
chr5 = 5;
chr6 = 6;
chr7 = 7;
SetBank_PPU();
we_sram = 0; // Disable
irq_enable = 0; // Disable
irq_counter = 0;
irq_latch = 0xFF;
irq_request = 0;
irq_preset = 0;
irq_preset_vbl = 0;
}
//void Mapper012::WriteLow(WORD addr, BYTE data)
public override void WriteLow(ushort addr, byte data)
{
if (addr > 0x4100 && addr < 0x6000)
{
vb0 = (byte)((data & 0x01) << 8);
vb1 = (byte)((data & 0x10) << 4);
SetBank_PPU();
}
else
{
base.WriteLow(addr, data);
}
}
//BYTE Mapper012::ReadLow(WORD addr)
public override byte ReadLow(ushort addr)
{
return 0x01;
}
//void Mapper012::Write(WORD addr, BYTE data)
public override void Write(ushort addr, byte data)
{
//DEBUGOUT( "MPRWR A=%04X D=%02X L=%3d CYC=%d\n", addr&0xFFFF, data&0xFF, nes.GetScanline(), nes.cpu.GetTotalCycles() );
switch (addr & 0xE001)
{
case 0x8000:
reg[0] = data;
SetBank_CPU();
SetBank_PPU();
break;
case 0x8001:
reg[1] = data;
switch (reg[0] & 0x07)
{
case 0x00:
chr01 = (byte)(data & 0xFE);
SetBank_PPU();
break;
case 0x01:
chr23 = (byte)(data & 0xFE);
SetBank_PPU();
break;
case 0x02:
chr4 = data;
SetBank_PPU();
break;
case 0x03:
chr5 = data;
SetBank_PPU();
break;
case 0x04:
chr6 = data;
SetBank_PPU();
break;
case 0x05:
chr7 = data;
SetBank_PPU();
break;
case 0x06:
prg0 = data;
SetBank_CPU();
break;
case 0x07:
prg1 = data;
SetBank_CPU();
break;
}
break;
case 0xA000:
reg[2] = data;
if (!nes.rom.Is4SCREEN())
{
if ((data & 0x01) != 0) SetVRAM_Mirror(VRAM_HMIRROR);
else SetVRAM_Mirror(VRAM_VMIRROR);
}
break;
case 0xA001:
reg[3] = data;
break;
case 0xC000:
reg[4] = data;
irq_latch = data;
break;
case 0xC001:
reg[5] = data;
if (nes.GetScanline() < 240)
{
irq_counter |= 0x80;
irq_preset = 0xFF;
}
else
{
irq_counter |= 0x80;
irq_preset_vbl = 0xFF;
irq_preset = 0;
}
break;
case 0xE000:
reg[6] = data;
irq_enable = 0;
irq_request = 0;
nes.cpu.ClrIRQ(IRQ_MAPPER);
break;
case 0xE001:
reg[7] = data;
irq_enable = 1;
irq_request = 0;
break;
}
}
//void Mapper012::HSync(INT scanline)
public override void HSync(int scanline)
{
if ((scanline >= 0 && scanline <= 239) && nes.ppu.IsDispON())
{
if (irq_preset_vbl != 0)
{
irq_counter = irq_latch;
irq_preset_vbl = 0;
}
if (irq_preset != 0)
{
irq_counter = irq_latch;
irq_preset = 0;
}
else if (irq_counter > 0)
{
irq_counter--;
}
if (irq_counter == 0)
{
// Some game set irq_latch to zero to disable irq. So check it here.
if (irq_enable != 0 && irq_latch != 0)
{
irq_request = 0xFF;
nes.cpu.SetIRQ(IRQ_MAPPER);
}
irq_preset = 0xFF;
}
}
}
void SetBank_CPU()
{
if ((reg[0] & 0x40) != 0)
{
SetPROM_32K_Bank(PROM_8K_SIZE - 2, prg1, prg0, PROM_8K_SIZE - 1);
}
else
{
SetPROM_32K_Bank(prg0, prg1, PROM_8K_SIZE - 2, PROM_8K_SIZE - 1);
}
}
void SetBank_PPU()
{
if (VROM_1K_SIZE != 0)
{
if ((reg[0] & 0x80) != 0)
{
SetVROM_8K_Bank(
(int)(vb0 + chr4),
(int)(vb0 + chr5),
(int)(vb0 + chr6),
(int)(vb0 + chr7),
(int)(vb1 + chr01),
(int)(vb1 + chr01 + 1),
(int)(vb1 + chr23),
(int)(vb1 + chr23 + 1)
);
}
else
{
SetVROM_8K_Bank(
(int)(vb0 + chr01),
(int)(vb0 + chr01 + 1),
(int)(vb0 + chr23),
(int)(vb0 + chr23 + 1),
(int)(vb1 + chr4),
(int)(vb1 + chr5),
(int)(vb1 + chr6),
(int)(vb1 + chr7))
;
}
}
else
{
if ((reg[0] & 0x80) != 0)
{
SetCRAM_1K_Bank(4, (chr01 + 0) & 0x07);
SetCRAM_1K_Bank(5, (chr01 + 1) & 0x07);
SetCRAM_1K_Bank(6, (chr23 + 0) & 0x07);
SetCRAM_1K_Bank(7, (chr23 + 1) & 0x07);
SetCRAM_1K_Bank(0, chr4 & 0x07);
SetCRAM_1K_Bank(1, chr5 & 0x07);
SetCRAM_1K_Bank(2, chr6 & 0x07);
SetCRAM_1K_Bank(3, chr7 & 0x07);
}
else
{
SetCRAM_1K_Bank(0, (chr01 + 0) & 0x07);
SetCRAM_1K_Bank(1, (chr01 + 1) & 0x07);
SetCRAM_1K_Bank(2, (chr23 + 0) & 0x07);
SetCRAM_1K_Bank(3, (chr23 + 1) & 0x07);
SetCRAM_1K_Bank(4, chr4 & 0x07);
SetCRAM_1K_Bank(5, chr5 & 0x07);
SetCRAM_1K_Bank(6, chr6 & 0x07);
SetCRAM_1K_Bank(7, chr7 & 0x07);
}
}
}
//void Mapper012::SaveState(LPBYTE p)
public override void SaveState(byte[] p)
{
//for (INT i = 0; i < 8; i++)
//{
// p[i] = reg[i];
//}
//p[8] = prg0;
//p[9] = prg1;
//p[10] = chr01;
//p[11] = chr23;
//p[12] = chr4;
//p[13] = chr5;
//p[14] = chr6;
//p[15] = chr7;
//p[16] = irq_enable;
//p[17] = (BYTE)irq_counter;
//p[18] = irq_latch;
//p[19] = irq_request;
//p[20] = irq_preset;
//p[21] = irq_preset_vbl;
//*((DWORD*)&p[22]) = vb0;
//*((DWORD*)&p[26]) = vb1;
}
//void Mapper012::LoadState(LPBYTE p)
public override void LoadState(byte[] p)
{
//for (INT i = 0; i < 8; i++)
//{
// reg[i] = p[i];
//}
//prg0 = p[8];
//prg1 = p[9];
//chr01 = p[10];
//chr23 = p[11];
//chr4 = p[12];
//chr5 = p[13];
//chr6 = p[14];
//chr7 = p[15];
//irq_enable = p[16];
//irq_counter = (INT)p[17];
//irq_latch = p[18];
//irq_request = p[19];
//irq_preset = p[20];
//irq_preset_vbl = p[21];
//vb0 = *((DWORD*)&p[22]);
//vb1 = *((DWORD*)&p[26]);
}
public override bool IsStateSave()
{
return true;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a0d9dccfbd35bbf458c8f5d100e2f89b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,33 @@
//////////////////////////////////////////////////////////////////////////
// Mapper013 CPROM //
//////////////////////////////////////////////////////////////////////////
using static VirtualNes.MMU;
using static VirtualNes.Core.CPU;
using INT = System.Int32;
using BYTE = System.Byte;
using Codice.CM.Client.Differences;
namespace VirtualNes.Core
{
public class Mapper013 : Mapper
{
public Mapper013(NES parent) : base(parent) { }
public override void Reset()
{
SetPROM_32K_Bank(0, 1, 2, 3);
SetCRAM_4K_Bank(0, 0);
SetCRAM_4K_Bank(4, 0);
}
//void Mapper013::Write(WORD addr, BYTE data)
public override void Write(ushort addr, byte data)
{
SetPROM_32K_Bank((data & 0x30) >> 4);
SetCRAM_4K_Bank(4, data & 0x03);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 660200e3200da7d4eb9925d2b63afef5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,93 @@
//////////////////////////////////////////////////////////////////////////
// Mapper015 100-in-1 chip //
//////////////////////////////////////////////////////////////////////////
using static VirtualNes.MMU;
using static VirtualNes.Core.CPU;
using INT = System.Int32;
using BYTE = System.Byte;
using Codice.CM.Client.Differences;
namespace VirtualNes.Core
{
public class Mapper015 : Mapper
{
public Mapper015(NES parent) : base(parent) { }
public override void Reset()
{
SetPROM_32K_Bank(0, 1, 2, 3);
}
//void Mapper015::Write(WORD addr, BYTE data)
public override void Write(ushort addr, byte data)
{
switch (addr)
{
case 0x8000:
if ((data & 0x80) != 0)
{
SetPROM_8K_Bank(4, (data & 0x3F) * 2 + 1);
SetPROM_8K_Bank(5, (data & 0x3F) * 2 + 0);
SetPROM_8K_Bank(6, (data & 0x3F) * 2 + 3);
SetPROM_8K_Bank(7, (data & 0x3F) * 2 + 2);
}
else
{
SetPROM_8K_Bank(4, (data & 0x3F) * 2 + 0);
SetPROM_8K_Bank(5, (data & 0x3F) * 2 + 1);
SetPROM_8K_Bank(6, (data & 0x3F) * 2 + 2);
SetPROM_8K_Bank(7, (data & 0x3F) * 2 + 3);
}
if ((data & 0x40) != 0)
SetVRAM_Mirror(VRAM_HMIRROR);
else SetVRAM_Mirror(VRAM_VMIRROR);
break;
case 0x8001:
if ((data & 0x80) != 0)
{
SetPROM_8K_Bank(6, (data & 0x3F) * 2 + 1);
SetPROM_8K_Bank(7, (data & 0x3F) * 2 + 0);
}
else
{
SetPROM_8K_Bank(6, (data & 0x3F) * 2 + 0);
SetPROM_8K_Bank(7, (data & 0x3F) * 2 + 1);
}
break;
case 0x8002:
if ((data & 0x80) != 0)
{
SetPROM_8K_Bank(4, (data & 0x3F) * 2 + 1);
SetPROM_8K_Bank(5, (data & 0x3F) * 2 + 1);
SetPROM_8K_Bank(6, (data & 0x3F) * 2 + 1);
SetPROM_8K_Bank(7, (data & 0x3F) * 2 + 1);
}
else
{
SetPROM_8K_Bank(4, (data & 0x3F) * 2 + 0);
SetPROM_8K_Bank(5, (data & 0x3F) * 2 + 0);
SetPROM_8K_Bank(6, (data & 0x3F) * 2 + 0);
SetPROM_8K_Bank(7, (data & 0x3F) * 2 + 0);
}
break;
case 0x8003:
if ((data & 0x80) != 0)
{
SetPROM_8K_Bank(6, (data & 0x3F) * 2 + 1);
SetPROM_8K_Bank(7, (data & 0x3F) * 2 + 0);
}
else
{
SetPROM_8K_Bank(6, (data & 0x3F) * 2 + 0);
SetPROM_8K_Bank(7, (data & 0x3F) * 2 + 1);
}
if ((data & 0x40) != 0) SetVRAM_Mirror(VRAM_HMIRROR);
else SetVRAM_Mirror(VRAM_VMIRROR);
break;
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9a00ec8072aa26648bcd7bef203e9a39
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -22,6 +22,7 @@ namespace VirtualNes.Core
BYTE irq_latch;
BYTE irq_request;
int MMC4prg, MMC4chr;
public Mapper245(NES parent) : base(parent)
{
}
@ -30,92 +31,92 @@ namespace VirtualNes.Core
//void Mapper245::Reset()
public override void Reset()
{
for (INT i = 0; i < 8; i++)
{
reg[i] = 0x00;
}
prg0 = 0;
prg1 = 1;
SetPROM_32K_Bank(0, 1, PROM_8K_SIZE - 2, PROM_8K_SIZE - 1);
if (VROM_1K_SIZE != 0)
{
SetVROM_8K_Bank(0);
}
we_sram = 0; // Disable
irq_enable = 0; // Disable
irq_counter = 0;
irq_latch = 0;
irq_request = 0;
for (INT i = 0; i < 8; i++)
{
reg[i] = 0x00;
}
prg0 = 0;
prg1 = 1;
SetPROM_32K_Bank(0, 1, PROM_8K_SIZE - 2, PROM_8K_SIZE - 1);
if (VROM_1K_SIZE != 0)
{
SetVROM_8K_Bank(0);
}
we_sram = 0; // Disable
irq_enable = 0; // Disable
irq_counter = 0;
irq_latch = 0;
irq_request = 0;
nes.SetIrqType(NES.IRQMETHOD.IRQ_CLOCK);
}
//void Mapper245::Write(WORD addr, BYTE data)
public override void Write(ushort addr, byte data)
{
switch (addr & 0xF7FF)
{
case 0x8000:
reg[0] = data;
break;
case 0x8001:
reg[1] = data;
switch (reg[0])
{
case 0x00:
reg[3] = (byte)((data & 2) << 5);
SetPROM_8K_Bank(6, 0x3E | reg[3]);
SetPROM_8K_Bank(7, 0x3F | reg[3]);
break;
case 0x06:
prg0 = data;
break;
case 0x07:
prg1 = data;
break;
}
SetPROM_8K_Bank(4, prg0 | reg[3]);
SetPROM_8K_Bank(5, prg1 | reg[3]);
break;
case 0xA000:
reg[2] = data;
if (!nes.rom.Is4SCREEN())
{
if ((data & 0x01) != 0) SetVRAM_Mirror(VRAM_HMIRROR);
else SetVRAM_Mirror(VRAM_VMIRROR);
}
break;
case 0xA001:
break;
case 0xC000:
reg[4] = data;
irq_counter = data;
irq_request = 0;
nes.cpu.ClrIRQ(IRQ_MAPPER);
break;
case 0xC001:
reg[5] = data;
irq_latch = data;
irq_request = 0;
nes.cpu.ClrIRQ(IRQ_MAPPER);
break;
case 0xE000:
reg[6] = data;
irq_enable = 0;
irq_request = 0;
nes.cpu.ClrIRQ(IRQ_MAPPER);
break;
case 0xE001:
reg[7] = data;
irq_enable = 1;
irq_request = 0;
nes.cpu.ClrIRQ(IRQ_MAPPER);
break;
switch (addr & 0xF7FF)
{
case 0x8000:
reg[0] = data;
break;
case 0x8001:
reg[1] = data;
switch (reg[0])
{
case 0x00:
reg[3] = (byte)((data & 2) << 5);
SetPROM_8K_Bank(6, 0x3E | reg[3]);
SetPROM_8K_Bank(7, 0x3F | reg[3]);
break;
case 0x06:
prg0 = data;
break;
case 0x07:
prg1 = data;
break;
}
SetPROM_8K_Bank(4, prg0 | reg[3]);
SetPROM_8K_Bank(5, prg1 | reg[3]);
break;
case 0xA000:
reg[2] = data;
if (!nes.rom.Is4SCREEN())
{
if ((data & 0x01) != 0) SetVRAM_Mirror(VRAM_HMIRROR);
else SetVRAM_Mirror(VRAM_VMIRROR);
}
break;
case 0xA001:
break;
case 0xC000:
reg[4] = data;
irq_counter = data;
irq_request = 0;
nes.cpu.ClrIRQ(IRQ_MAPPER);
break;
case 0xC001:
reg[5] = data;
irq_latch = data;
irq_request = 0;
nes.cpu.ClrIRQ(IRQ_MAPPER);
break;
case 0xE000:
reg[6] = data;
irq_enable = 0;
irq_request = 0;
nes.cpu.ClrIRQ(IRQ_MAPPER);
break;
case 0xE001:
reg[7] = data;
irq_enable = 1;
irq_request = 0;
nes.cpu.ClrIRQ(IRQ_MAPPER);
break;
}
}
@ -130,27 +131,27 @@ namespace VirtualNes.Core
//void Mapper245::HSync(INT scanline)
public override void HSync(int scanline)
{
if ((scanline >= 0 && scanline <= 239))
{
if (nes.ppu.IsDispON())
{
if (irq_enable != 0 && irq_request == 0)
{
if (scanline == 0)
{
if (irq_counter != 0)
{
irq_counter--;
}
}
if ((irq_counter--) == 0)
{
irq_request = 0xFF;
irq_counter = irq_latch;
nes.cpu.SetIRQ(IRQ_MAPPER);
}
}
}
if ((scanline >= 0 && scanline <= 239))
{
if (nes.ppu.IsDispON())
{
if (irq_enable != 0 && irq_request == 0)
{
if (scanline == 0)
{
if (irq_counter != 0)
{
irq_counter--;
}
}
if ((irq_counter--) == 0)
{
irq_request = 0xFF;
irq_counter = irq_latch;
nes.cpu.SetIRQ(IRQ_MAPPER);
}
}
}
}
// if( irq_request && (nes.GetIrqType() == NES::IRQ_HSYNC) ) {
// nes.cpu.IRQ_NotPending();
@ -164,43 +165,43 @@ namespace VirtualNes.Core
void SetBank_PPU()
{
if ((VROM_1K_SIZE) != 0)
{
if (((reg[0] & 0x80)! + 0) != 0)
{
SetVROM_8K_Bank(chr4, chr5, chr6, chr7,
chr23 + 1, chr23, chr01 + 1, chr01);
}
else
{
SetVROM_8K_Bank(chr01, chr01 + 1, chr23, chr23 + 1,
chr4, chr5, chr6, chr7);
}
}
else
{
if ((reg[0] & 0x80) != 0)
{
SetCRAM_1K_Bank(4, (chr01 + 0) & 0x07);
SetCRAM_1K_Bank(5, (chr01 + 1) & 0x07);
SetCRAM_1K_Bank(6, (chr23 + 0) & 0x07);
SetCRAM_1K_Bank(7, (chr23 + 1) & 0x07);
SetCRAM_1K_Bank(0, chr4 & 0x07);
SetCRAM_1K_Bank(1, chr5 & 0x07);
SetCRAM_1K_Bank(2, chr6 & 0x07);
SetCRAM_1K_Bank(3, chr7 & 0x07);
}
else
{
SetCRAM_1K_Bank(0, (chr01 + 0) & 0x07);
SetCRAM_1K_Bank(1, (chr01 + 1) & 0x07);
SetCRAM_1K_Bank(2, (chr23 + 0) & 0x07);
SetCRAM_1K_Bank(3, (chr23 + 1) & 0x07);
SetCRAM_1K_Bank(4, chr4 & 0x07);
SetCRAM_1K_Bank(5, chr5 & 0x07);
SetCRAM_1K_Bank(6, chr6 & 0x07);
SetCRAM_1K_Bank(7, chr7 & 0x07);
}
if (VROM_1K_SIZE != 0)
{
if ((reg[0] & 0x80) != 0)
{
SetVROM_8K_Bank(chr4, chr5, chr6, chr7,
chr23 + 1, chr23, chr01 + 1, chr01);
}
else
{
SetVROM_8K_Bank(chr01, chr01 + 1, chr23, chr23 + 1,
chr4, chr5, chr6, chr7);
}
}
else
{
if ((reg[0] & 0x80) != 0)
{
SetCRAM_1K_Bank(4, (chr01 + 0) & 0x07);
SetCRAM_1K_Bank(5, (chr01 + 1) & 0x07);
SetCRAM_1K_Bank(6, (chr23 + 0) & 0x07);
SetCRAM_1K_Bank(7, (chr23 + 1) & 0x07);
SetCRAM_1K_Bank(0, chr4 & 0x07);
SetCRAM_1K_Bank(1, chr5 & 0x07);
SetCRAM_1K_Bank(2, chr6 & 0x07);
SetCRAM_1K_Bank(3, chr7 & 0x07);
}
else
{
SetCRAM_1K_Bank(0, (chr01 + 0) & 0x07);
SetCRAM_1K_Bank(1, (chr01 + 1) & 0x07);
SetCRAM_1K_Bank(2, (chr23 + 0) & 0x07);
SetCRAM_1K_Bank(3, (chr23 + 1) & 0x07);
SetCRAM_1K_Bank(4, chr4 & 0x07);
SetCRAM_1K_Bank(5, chr5 & 0x07);
SetCRAM_1K_Bank(6, chr6 & 0x07);
SetCRAM_1K_Bank(7, chr7 & 0x07);
}
}
}

View File

@ -1147,6 +1147,16 @@ namespace VirtualNes.Core
bChrLatch = bMode;
}
internal void SetExtNameTableMode(bool bMode)
{
bExtNameTable = bMode;
}
internal void SetExtMonoMode(bool bMode)
{
bExtMono = bMode;
}
public struct Sprite
{
public byte y

View File

@ -91,7 +91,9 @@ Mapper支持越多通俗讲就是支持更多卡带。
我们的项目也必须支持上! 咱们也同步要进行一个补充
追加了特殊的失传Mapper 162,163,175,176,178,192,195,199,216 (from https://github.com/yamanyandakure/VirtuaNES097)
追加了特殊的失传Mapper 35,111,162,163,175,176,178,192,195,199,216 (from https://github.com/yamanyandakure/VirtuaNES097)
后续补充二次,修正 Mapper199 参照叶枫VirtuaNESex_src(20191105)

View File

@ -0,0 +1,203 @@
/* 7z.h -- 7z interface
2010-03-11 : Igor Pavlov : Public domain */
#ifndef __7Z_H
#define __7Z_H
#include "7zBuf.h"
EXTERN_C_BEGIN
#define k7zStartHeaderSize 0x20
#define k7zSignatureSize 6
extern Byte k7zSignature[k7zSignatureSize];
#define k7zMajorVersion 0
enum EIdEnum
{
k7zIdEnd,
k7zIdHeader,
k7zIdArchiveProperties,
k7zIdAdditionalStreamsInfo,
k7zIdMainStreamsInfo,
k7zIdFilesInfo,
k7zIdPackInfo,
k7zIdUnpackInfo,
k7zIdSubStreamsInfo,
k7zIdSize,
k7zIdCRC,
k7zIdFolder,
k7zIdCodersUnpackSize,
k7zIdNumUnpackStream,
k7zIdEmptyStream,
k7zIdEmptyFile,
k7zIdAnti,
k7zIdName,
k7zIdCTime,
k7zIdATime,
k7zIdMTime,
k7zIdWinAttributes,
k7zIdComment,
k7zIdEncodedHeader,
k7zIdStartPos,
k7zIdDummy
};
typedef struct
{
UInt32 NumInStreams;
UInt32 NumOutStreams;
UInt64 MethodID;
CBuf Props;
} CSzCoderInfo;
void SzCoderInfo_Init(CSzCoderInfo *p);
void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc);
typedef struct
{
UInt32 InIndex;
UInt32 OutIndex;
} CSzBindPair;
typedef struct
{
CSzCoderInfo *Coders;
CSzBindPair *BindPairs;
UInt32 *PackStreams;
UInt64 *UnpackSizes;
UInt32 NumCoders;
UInt32 NumBindPairs;
UInt32 NumPackStreams;
int UnpackCRCDefined;
UInt32 UnpackCRC;
UInt32 NumUnpackStreams;
} CSzFolder;
void SzFolder_Init(CSzFolder *p);
UInt64 SzFolder_GetUnpackSize(CSzFolder *p);
int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex);
UInt32 SzFolder_GetNumOutStreams(CSzFolder *p);
UInt64 SzFolder_GetUnpackSize(CSzFolder *p);
SRes SzFolder_Decode(const CSzFolder *folder, const UInt64 *packSizes,
ILookInStream *stream, UInt64 startPos,
Byte *outBuffer, size_t outSize, ISzAlloc *allocMain);
typedef struct
{
UInt32 Low;
UInt32 High;
} CNtfsFileTime;
typedef struct
{
CNtfsFileTime MTime;
UInt64 Size;
UInt32 Crc;
UInt32 Attrib;
Byte HasStream;
Byte IsDir;
Byte IsAnti;
Byte CrcDefined;
Byte MTimeDefined;
Byte AttribDefined;
} CSzFileItem;
void SzFile_Init(CSzFileItem *p);
typedef struct
{
UInt64 *PackSizes;
Byte *PackCRCsDefined;
UInt32 *PackCRCs;
CSzFolder *Folders;
CSzFileItem *Files;
UInt32 NumPackStreams;
UInt32 NumFolders;
UInt32 NumFiles;
} CSzAr;
void SzAr_Init(CSzAr *p);
void SzAr_Free(CSzAr *p, ISzAlloc *alloc);
/*
SzExtract extracts file from archive
*outBuffer must be 0 before first call for each new archive.
Extracting cache:
If you need to decompress more than one file, you can send
these values from previous call:
*blockIndex,
*outBuffer,
*outBufferSize
You can consider "*outBuffer" as cache of solid block. If your archive is solid,
it will increase decompression speed.
If you use external function, you can declare these 3 cache variables
(blockIndex, outBuffer, outBufferSize) as static in that external function.
Free *outBuffer and set *outBuffer to 0, if you want to flush cache.
*/
typedef struct
{
CSzAr db;
UInt64 startPosAfterHeader;
UInt64 dataPos;
UInt32 *FolderStartPackStreamIndex;
UInt64 *PackStreamStartPositions;
UInt32 *FolderStartFileIndex;
UInt32 *FileIndexToFolderIndexMap;
size_t *FileNameOffsets; /* in 2-byte steps */
CBuf FileNames; /* UTF-16-LE */
} CSzArEx;
void SzArEx_Init(CSzArEx *p);
void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc);
UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder);
int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize);
/*
if dest == NULL, the return value specifies the required size of the buffer,
in 16-bit characters, including the null-terminating character.
if dest != NULL, the return value specifies the number of 16-bit characters that
are written to the dest, including the null-terminating character. */
size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, UInt16 *dest);
SRes SzArEx_Extract(
const CSzArEx *db,
ILookInStream *inStream,
UInt32 fileIndex, /* index of file */
UInt32 *blockIndex, /* index of solid block */
Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */
size_t *outBufferSize, /* buffer size for output buffer */
size_t *offset, /* offset of stream for required file in *outBuffer */
size_t *outSizeProcessed, /* size of file in *outBuffer */
ISzAlloc *allocMain,
ISzAlloc *allocTemp);
/*
SzArEx_Open Errors:
SZ_ERROR_NO_ARCHIVE
SZ_ERROR_ARCHIVE
SZ_ERROR_UNSUPPORTED
SZ_ERROR_MEM
SZ_ERROR_CRC
SZ_ERROR_INPUT_EOF
SZ_ERROR_FAIL
*/
SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp);
EXTERN_C_END
#endif

View File

@ -0,0 +1,76 @@
/* 7zAlloc.c -- Allocation functions
2010-10-29 : Igor Pavlov : Public domain */
#include "7zAlloc.h"
/* #define _SZ_ALLOC_DEBUG */
/* use _SZ_ALLOC_DEBUG to debug alloc/free operations */
#ifdef _SZ_ALLOC_DEBUG
#ifdef _WIN32
#include <windows.h>
#endif
#include <stdio.h>
int g_allocCount = 0;
int g_allocCountTemp = 0;
#endif
void *SzAlloc(void *p, size_t size)
{
p = p;
if (size == 0)
return 0;
#ifdef _SZ_ALLOC_DEBUG
fprintf(stderr, "\nAlloc %10d bytes; count = %10d", size, g_allocCount);
g_allocCount++;
#endif
return malloc(size);
}
void SzFree(void *p, void *address)
{
p = p;
#ifdef _SZ_ALLOC_DEBUG
if (address != 0)
{
g_allocCount--;
fprintf(stderr, "\nFree; count = %10d", g_allocCount);
}
#endif
free(address);
}
void *SzAllocTemp(void *p, size_t size)
{
p = p;
if (size == 0)
return 0;
#ifdef _SZ_ALLOC_DEBUG
fprintf(stderr, "\nAlloc_temp %10d bytes; count = %10d", size, g_allocCountTemp);
g_allocCountTemp++;
#ifdef _WIN32
return HeapAlloc(GetProcessHeap(), 0, size);
#endif
#endif
return malloc(size);
}
void SzFreeTemp(void *p, void *address)
{
p = p;
#ifdef _SZ_ALLOC_DEBUG
if (address != 0)
{
g_allocCountTemp--;
fprintf(stderr, "\nFree_temp; count = %10d", g_allocCountTemp);
}
#ifdef _WIN32
HeapFree(GetProcessHeap(), 0, address);
return;
#endif
#endif
free(address);
}

View File

@ -0,0 +1,15 @@
/* 7zAlloc.h -- Allocation functions
2010-10-29 : Igor Pavlov : Public domain */
#ifndef __7Z_ALLOC_H
#define __7Z_ALLOC_H
#include <stdlib.h>
void *SzAlloc(void *p, size_t size);
void SzFree(void *p, void *address);
void *SzAllocTemp(void *p, size_t size);
void SzFreeTemp(void *p, void *address);
#endif

View File

@ -0,0 +1,36 @@
/* 7zBuf.c -- Byte Buffer
2008-03-28
Igor Pavlov
Public domain */
#include "7zBuf.h"
void Buf_Init(CBuf *p)
{
p->data = 0;
p->size = 0;
}
int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc)
{
p->size = 0;
if (size == 0)
{
p->data = 0;
return 1;
}
p->data = (Byte *)alloc->Alloc(alloc, size);
if (p->data != 0)
{
p->size = size;
return 1;
}
return 0;
}
void Buf_Free(CBuf *p, ISzAlloc *alloc)
{
alloc->Free(alloc, p->data);
p->data = 0;
p->size = 0;
}

View File

@ -0,0 +1,39 @@
/* 7zBuf.h -- Byte Buffer
2009-02-07 : Igor Pavlov : Public domain */
#ifndef __7Z_BUF_H
#define __7Z_BUF_H
#include "Types.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct
{
Byte *data;
size_t size;
} CBuf;
void Buf_Init(CBuf *p);
int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc);
void Buf_Free(CBuf *p, ISzAlloc *alloc);
typedef struct
{
Byte *data;
size_t size;
size_t pos;
} CDynBuf;
void DynBuf_Construct(CDynBuf *p);
void DynBuf_SeekToBeg(CDynBuf *p);
int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAlloc *alloc);
void DynBuf_Free(CDynBuf *p, ISzAlloc *alloc);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,74 @@
/* 7zCrc.c -- CRC32 calculation
2009-11-23 : Igor Pavlov : Public domain */
#include "7zCrc.h"
#include "CpuArch.h"
#define kCrcPoly 0xEDB88320
#ifdef MY_CPU_LE
#define CRC_NUM_TABLES 8
#else
#define CRC_NUM_TABLES 1
#endif
typedef UInt32 (MY_FAST_CALL *CRC_FUNC)(UInt32 v, const void *data, size_t size, const UInt32 *table);
static CRC_FUNC g_CrcUpdate;
UInt32 g_CrcTable[256 * CRC_NUM_TABLES];
#if CRC_NUM_TABLES == 1
#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
static UInt32 MY_FAST_CALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const UInt32 *table)
{
const Byte *p = (const Byte *)data;
for (; size > 0; size--, p++)
v = CRC_UPDATE_BYTE_2(v, *p);
return v;
}
#else
UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table);
UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table);
#endif
UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size)
{
return g_CrcUpdate(v, data, size, g_CrcTable);
}
UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size)
{
return g_CrcUpdate(CRC_INIT_VAL, data, size, g_CrcTable) ^ CRC_INIT_VAL;
}
void MY_FAST_CALL CrcGenerateTable()
{
UInt32 i;
for (i = 0; i < 256; i++)
{
UInt32 r = i;
unsigned j;
for (j = 0; j < 8; j++)
r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1));
g_CrcTable[i] = r;
}
#if CRC_NUM_TABLES == 1
g_CrcUpdate = CrcUpdateT1;
#else
for (; i < 256 * CRC_NUM_TABLES; i++)
{
UInt32 r = g_CrcTable[i - 256];
g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8);
}
g_CrcUpdate = CrcUpdateT4;
#ifdef MY_CPU_X86_OR_AMD64
if (!CPU_Is_InOrder())
g_CrcUpdate = CrcUpdateT8;
#endif
#endif
}

View File

@ -0,0 +1,25 @@
/* 7zCrc.h -- CRC32 calculation
2009-11-21 : Igor Pavlov : Public domain */
#ifndef __7Z_CRC_H
#define __7Z_CRC_H
#include "Types.h"
EXTERN_C_BEGIN
extern UInt32 g_CrcTable[];
/* Call CrcGenerateTable one time before other CRC functions */
void MY_FAST_CALL CrcGenerateTable(void);
#define CRC_INIT_VAL 0xFFFFFFFF
#define CRC_GET_DIGEST(crc) ((crc) ^ CRC_INIT_VAL)
#define CRC_UPDATE_BYTE(crc, b) (g_CrcTable[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
UInt32 MY_FAST_CALL CrcUpdate(UInt32 crc, const void *data, size_t size);
UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size);
EXTERN_C_END
#endif

View File

@ -0,0 +1,34 @@
/* 7zCrcOpt.c -- CRC32 calculation : optimized version
2009-11-23 : Igor Pavlov : Public domain */
#include "CpuArch.h"
#ifdef MY_CPU_LE
#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table)
{
const Byte *p = (const Byte *)data;
for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++)
v = CRC_UPDATE_BYTE_2(v, *p);
for (; size >= 4; size -= 4, p += 4)
{
v ^= *(const UInt32 *)p;
v =
table[0x300 + (v & 0xFF)] ^
table[0x200 + ((v >> 8) & 0xFF)] ^
table[0x100 + ((v >> 16) & 0xFF)] ^
table[0x000 + ((v >> 24))];
}
for (; size > 0; size--, p++)
v = CRC_UPDATE_BYTE_2(v, *p);
return v;
}
UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table)
{
return CrcUpdateT4(v, data, size, table);
}
#endif

View File

@ -0,0 +1,470 @@
/* 7zDec.c -- Decoding from 7z folder
2010-11-02 : Igor Pavlov : Public domain */
#include <string.h>
/* #define _7ZIP_PPMD_SUPPPORT */
#include "7z.h"
#include "Bcj2.h"
#include "Bra.h"
#include "CpuArch.h"
#include "LzmaDec.h"
#include "Lzma2Dec.h"
#ifdef _7ZIP_PPMD_SUPPPORT
#include "Ppmd7.h"
#endif
#define k_Copy 0
#define k_LZMA2 0x21
#define k_LZMA 0x30101
#define k_BCJ 0x03030103
#define k_PPC 0x03030205
#define k_ARM 0x03030501
#define k_ARMT 0x03030701
#define k_SPARC 0x03030805
#define k_BCJ2 0x0303011B
#ifdef _7ZIP_PPMD_SUPPPORT
#define k_PPMD 0x30401
typedef struct
{
IByteIn p;
const Byte *cur;
const Byte *end;
const Byte *begin;
UInt64 processed;
Bool extra;
SRes res;
ILookInStream *inStream;
} CByteInToLook;
static Byte ReadByte(void *pp)
{
CByteInToLook *p = (CByteInToLook *)pp;
if (p->cur != p->end)
return *p->cur++;
if (p->res == SZ_OK)
{
size_t size = p->cur - p->begin;
p->processed += size;
p->res = p->inStream->Skip(p->inStream, size);
size = (1 << 25);
p->res = p->inStream->Look(p->inStream, (const void **)&p->begin, &size);
p->cur = p->begin;
p->end = p->begin + size;
if (size != 0)
return *p->cur++;;
}
p->extra = True;
return 0;
}
static SRes SzDecodePpmd(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream,
Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain)
{
CPpmd7 ppmd;
CByteInToLook s;
SRes res = SZ_OK;
s.p.Read = ReadByte;
s.inStream = inStream;
s.begin = s.end = s.cur = NULL;
s.extra = False;
s.res = SZ_OK;
s.processed = 0;
if (coder->Props.size != 5)
return SZ_ERROR_UNSUPPORTED;
{
unsigned order = coder->Props.data[0];
UInt32 memSize = GetUi32(coder->Props.data + 1);
if (order < PPMD7_MIN_ORDER ||
order > PPMD7_MAX_ORDER ||
memSize < PPMD7_MIN_MEM_SIZE ||
memSize > PPMD7_MAX_MEM_SIZE)
return SZ_ERROR_UNSUPPORTED;
Ppmd7_Construct(&ppmd);
if (!Ppmd7_Alloc(&ppmd, memSize, allocMain))
return SZ_ERROR_MEM;
Ppmd7_Init(&ppmd, order);
}
{
CPpmd7z_RangeDec rc;
Ppmd7z_RangeDec_CreateVTable(&rc);
rc.Stream = &s.p;
if (!Ppmd7z_RangeDec_Init(&rc))
res = SZ_ERROR_DATA;
else if (s.extra)
res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA);
else
{
SizeT i;
for (i = 0; i < outSize; i++)
{
int sym = Ppmd7_DecodeSymbol(&ppmd, &rc.p);
if (s.extra || sym < 0)
break;
outBuffer[i] = (Byte)sym;
}
if (i != outSize)
res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA);
else if (s.processed + (s.cur - s.begin) != inSize || !Ppmd7z_RangeDec_IsFinishedOK(&rc))
res = SZ_ERROR_DATA;
}
}
Ppmd7_Free(&ppmd, allocMain);
return res;
}
#endif
static SRes SzDecodeLzma(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream,
Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain)
{
CLzmaDec state;
SRes res = SZ_OK;
LzmaDec_Construct(&state);
RINOK(LzmaDec_AllocateProbs(&state, coder->Props.data, (unsigned)coder->Props.size, allocMain));
state.dic = outBuffer;
state.dicBufSize = outSize;
LzmaDec_Init(&state);
for (;;)
{
Byte *inBuf = NULL;
size_t lookahead = (1 << 18);
if (lookahead > inSize)
lookahead = (size_t)inSize;
res = inStream->Look((void *)inStream, (const void **)&inBuf, &lookahead);
if (res != SZ_OK)
break;
{
SizeT inProcessed = (SizeT)lookahead, dicPos = state.dicPos;
ELzmaStatus status;
res = LzmaDec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status);
lookahead -= inProcessed;
inSize -= inProcessed;
if (res != SZ_OK)
break;
if (state.dicPos == state.dicBufSize || (inProcessed == 0 && dicPos == state.dicPos))
{
if (state.dicBufSize != outSize || lookahead != 0 ||
(status != LZMA_STATUS_FINISHED_WITH_MARK &&
status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK))
res = SZ_ERROR_DATA;
break;
}
res = inStream->Skip((void *)inStream, inProcessed);
if (res != SZ_OK)
break;
}
}
LzmaDec_FreeProbs(&state, allocMain);
return res;
}
static SRes SzDecodeLzma2(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream,
Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain)
{
CLzma2Dec state;
SRes res = SZ_OK;
Lzma2Dec_Construct(&state);
if (coder->Props.size != 1)
return SZ_ERROR_DATA;
RINOK(Lzma2Dec_AllocateProbs(&state, coder->Props.data[0], allocMain));
state.decoder.dic = outBuffer;
state.decoder.dicBufSize = outSize;
Lzma2Dec_Init(&state);
for (;;)
{
Byte *inBuf = NULL;
size_t lookahead = (1 << 18);
if (lookahead > inSize)
lookahead = (size_t)inSize;
res = inStream->Look((void *)inStream, (const void **)&inBuf, &lookahead);
if (res != SZ_OK)
break;
{
SizeT inProcessed = (SizeT)lookahead, dicPos = state.decoder.dicPos;
ELzmaStatus status;
res = Lzma2Dec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status);
lookahead -= inProcessed;
inSize -= inProcessed;
if (res != SZ_OK)
break;
if (state.decoder.dicPos == state.decoder.dicBufSize || (inProcessed == 0 && dicPos == state.decoder.dicPos))
{
if (state.decoder.dicBufSize != outSize || lookahead != 0 ||
(status != LZMA_STATUS_FINISHED_WITH_MARK))
res = SZ_ERROR_DATA;
break;
}
res = inStream->Skip((void *)inStream, inProcessed);
if (res != SZ_OK)
break;
}
}
Lzma2Dec_FreeProbs(&state, allocMain);
return res;
}
static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer)
{
while (inSize > 0)
{
void *inBuf;
size_t curSize = (1 << 18);
if (curSize > inSize)
curSize = (size_t)inSize;
RINOK(inStream->Look((void *)inStream, (const void **)&inBuf, &curSize));
if (curSize == 0)
return SZ_ERROR_INPUT_EOF;
memcpy(outBuffer, inBuf, curSize);
outBuffer += curSize;
inSize -= curSize;
RINOK(inStream->Skip((void *)inStream, curSize));
}
return SZ_OK;
}
static Bool IS_MAIN_METHOD(UInt32 m)
{
switch(m)
{
case k_Copy:
case k_LZMA:
case k_LZMA2:
#ifdef _7ZIP_PPMD_SUPPPORT
case k_PPMD:
#endif
return True;
}
return False;
}
static Bool IS_SUPPORTED_CODER(const CSzCoderInfo *c)
{
return
c->NumInStreams == 1 &&
c->NumOutStreams == 1 &&
c->MethodID <= (UInt32)0xFFFFFFFF &&
IS_MAIN_METHOD((UInt32)c->MethodID);
}
#define IS_BCJ2(c) ((c)->MethodID == k_BCJ2 && (c)->NumInStreams == 4 && (c)->NumOutStreams == 1)
static SRes CheckSupportedFolder(const CSzFolder *f)
{
if (f->NumCoders < 1 || f->NumCoders > 4)
return SZ_ERROR_UNSUPPORTED;
if (!IS_SUPPORTED_CODER(&f->Coders[0]))
return SZ_ERROR_UNSUPPORTED;
if (f->NumCoders == 1)
{
if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBindPairs != 0)
return SZ_ERROR_UNSUPPORTED;
return SZ_OK;
}
if (f->NumCoders == 2)
{
CSzCoderInfo *c = &f->Coders[1];
if (c->MethodID > (UInt32)0xFFFFFFFF ||
c->NumInStreams != 1 ||
c->NumOutStreams != 1 ||
f->NumPackStreams != 1 ||
f->PackStreams[0] != 0 ||
f->NumBindPairs != 1 ||
f->BindPairs[0].InIndex != 1 ||
f->BindPairs[0].OutIndex != 0)
return SZ_ERROR_UNSUPPORTED;
switch ((UInt32)c->MethodID)
{
case k_BCJ:
case k_ARM:
break;
default:
return SZ_ERROR_UNSUPPORTED;
}
return SZ_OK;
}
if (f->NumCoders == 4)
{
if (!IS_SUPPORTED_CODER(&f->Coders[1]) ||
!IS_SUPPORTED_CODER(&f->Coders[2]) ||
!IS_BCJ2(&f->Coders[3]))
return SZ_ERROR_UNSUPPORTED;
if (f->NumPackStreams != 4 ||
f->PackStreams[0] != 2 ||
f->PackStreams[1] != 6 ||
f->PackStreams[2] != 1 ||
f->PackStreams[3] != 0 ||
f->NumBindPairs != 3 ||
f->BindPairs[0].InIndex != 5 || f->BindPairs[0].OutIndex != 0 ||
f->BindPairs[1].InIndex != 4 || f->BindPairs[1].OutIndex != 1 ||
f->BindPairs[2].InIndex != 3 || f->BindPairs[2].OutIndex != 2)
return SZ_ERROR_UNSUPPORTED;
return SZ_OK;
}
return SZ_ERROR_UNSUPPORTED;
}
static UInt64 GetSum(const UInt64 *values, UInt32 index)
{
UInt64 sum = 0;
UInt32 i;
for (i = 0; i < index; i++)
sum += values[i];
return sum;
}
#define CASE_BRA_CONV(isa) case k_ ## isa: isa ## _Convert(outBuffer, outSize, 0, 0); break;
static SRes SzFolder_Decode2(const CSzFolder *folder, const UInt64 *packSizes,
ILookInStream *inStream, UInt64 startPos,
Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain,
Byte *tempBuf[])
{
UInt32 ci;
SizeT tempSizes[3] = { 0, 0, 0};
SizeT tempSize3 = 0;
Byte *tempBuf3 = 0;
RINOK(CheckSupportedFolder(folder));
for (ci = 0; ci < folder->NumCoders; ci++)
{
CSzCoderInfo *coder = &folder->Coders[ci];
if (IS_MAIN_METHOD((UInt32)coder->MethodID))
{
UInt32 si = 0;
UInt64 offset;
UInt64 inSize;
Byte *outBufCur = outBuffer;
SizeT outSizeCur = outSize;
if (folder->NumCoders == 4)
{
UInt32 indices[] = { 3, 2, 0 };
UInt64 unpackSize = folder->UnpackSizes[ci];
si = indices[ci];
if (ci < 2)
{
Byte *temp;
outSizeCur = (SizeT)unpackSize;
if (outSizeCur != unpackSize)
return SZ_ERROR_MEM;
temp = (Byte *)IAlloc_Alloc(allocMain, outSizeCur);
if (temp == 0 && outSizeCur != 0)
return SZ_ERROR_MEM;
outBufCur = tempBuf[1 - ci] = temp;
tempSizes[1 - ci] = outSizeCur;
}
else if (ci == 2)
{
if (unpackSize > outSize) /* check it */
return SZ_ERROR_PARAM;
tempBuf3 = outBufCur = outBuffer + (outSize - (size_t)unpackSize);
tempSize3 = outSizeCur = (SizeT)unpackSize;
}
else
return SZ_ERROR_UNSUPPORTED;
}
offset = GetSum(packSizes, si);
inSize = packSizes[si];
RINOK(LookInStream_SeekTo(inStream, startPos + offset));
if (coder->MethodID == k_Copy)
{
if (inSize != outSizeCur) /* check it */
return SZ_ERROR_DATA;
RINOK(SzDecodeCopy(inSize, inStream, outBufCur));
}
else if (coder->MethodID == k_LZMA)
{
RINOK(SzDecodeLzma(coder, inSize, inStream, outBufCur, outSizeCur, allocMain));
}
else if (coder->MethodID == k_LZMA2)
{
RINOK(SzDecodeLzma2(coder, inSize, inStream, outBufCur, outSizeCur, allocMain));
}
else
{
#ifdef _7ZIP_PPMD_SUPPPORT
RINOK(SzDecodePpmd(coder, inSize, inStream, outBufCur, outSizeCur, allocMain));
#else
return SZ_ERROR_UNSUPPORTED;
#endif
}
}
else if (coder->MethodID == k_BCJ2)
{
UInt64 offset = GetSum(packSizes, 1);
UInt64 s3Size = packSizes[1];
SRes res;
if (ci != 3)
return SZ_ERROR_UNSUPPORTED;
RINOK(LookInStream_SeekTo(inStream, startPos + offset));
tempSizes[2] = (SizeT)s3Size;
if (tempSizes[2] != s3Size)
return SZ_ERROR_MEM;
tempBuf[2] = (Byte *)IAlloc_Alloc(allocMain, tempSizes[2]);
if (tempBuf[2] == 0 && tempSizes[2] != 0)
return SZ_ERROR_MEM;
res = SzDecodeCopy(s3Size, inStream, tempBuf[2]);
RINOK(res)
res = Bcj2_Decode(
tempBuf3, tempSize3,
tempBuf[0], tempSizes[0],
tempBuf[1], tempSizes[1],
tempBuf[2], tempSizes[2],
outBuffer, outSize);
RINOK(res)
}
else
{
if (ci != 1)
return SZ_ERROR_UNSUPPORTED;
switch(coder->MethodID)
{
case k_BCJ:
{
UInt32 state;
x86_Convert_Init(state);
x86_Convert(outBuffer, outSize, 0, &state, 0);
break;
}
CASE_BRA_CONV(ARM)
default:
return SZ_ERROR_UNSUPPORTED;
}
}
}
return SZ_OK;
}
SRes SzFolder_Decode(const CSzFolder *folder, const UInt64 *packSizes,
ILookInStream *inStream, UInt64 startPos,
Byte *outBuffer, size_t outSize, ISzAlloc *allocMain)
{
Byte *tempBuf[3] = { 0, 0, 0};
int i;
SRes res = SzFolder_Decode2(folder, packSizes, inStream, startPos,
outBuffer, (SizeT)outSize, allocMain, tempBuf);
for (i = 0; i < 3; i++)
IAlloc_Free(allocMain, tempBuf[i]);
return res;
}

View File

@ -0,0 +1,284 @@
/* 7zFile.c -- File IO
2009-11-24 : Igor Pavlov : Public domain */
#include "7zFile.h"
#ifndef USE_WINDOWS_FILE
#ifndef UNDER_CE
#include <errno.h>
#endif
#else
/*
ReadFile and WriteFile functions in Windows have BUG:
If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1)
from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES
(Insufficient system resources exist to complete the requested service).
Probably in some version of Windows there are problems with other sizes:
for 32 MB (maybe also for 16 MB).
And message can be "Network connection was lost"
*/
#define kChunkSizeMax (1 << 22)
#endif
void File_Construct(CSzFile *p)
{
#ifdef USE_WINDOWS_FILE
p->handle = INVALID_HANDLE_VALUE;
#else
p->file = NULL;
#endif
}
#if !defined(UNDER_CE) || !defined(USE_WINDOWS_FILE)
static WRes File_Open(CSzFile *p, const char *name, int writeMode)
{
#ifdef USE_WINDOWS_FILE
p->handle = CreateFileA(name,
writeMode ? GENERIC_WRITE : GENERIC_READ,
FILE_SHARE_READ, NULL,
writeMode ? CREATE_ALWAYS : OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
return (p->handle != INVALID_HANDLE_VALUE) ? 0 : GetLastError();
#else
p->file = fopen(name, writeMode ? "wb+" : "rb");
return (p->file != 0) ? 0 :
#ifdef UNDER_CE
2; /* ENOENT */
#else
errno;
#endif
#endif
}
WRes InFile_Open(CSzFile *p, const char *name) { return File_Open(p, name, 0); }
WRes OutFile_Open(CSzFile *p, const char *name) { return File_Open(p, name, 1); }
#endif
#ifdef USE_WINDOWS_FILE
static WRes File_OpenW(CSzFile *p, const WCHAR *name, int writeMode)
{
p->handle = CreateFileW(name,
writeMode ? GENERIC_WRITE : GENERIC_READ,
FILE_SHARE_READ, NULL,
writeMode ? CREATE_ALWAYS : OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
return (p->handle != INVALID_HANDLE_VALUE) ? 0 : GetLastError();
}
WRes InFile_OpenW(CSzFile *p, const WCHAR *name) { return File_OpenW(p, name, 0); }
WRes OutFile_OpenW(CSzFile *p, const WCHAR *name) { return File_OpenW(p, name, 1); }
#endif
WRes File_Close(CSzFile *p)
{
#ifdef USE_WINDOWS_FILE
if (p->handle != INVALID_HANDLE_VALUE)
{
if (!CloseHandle(p->handle))
return GetLastError();
p->handle = INVALID_HANDLE_VALUE;
}
#else
if (p->file != NULL)
{
int res = fclose(p->file);
if (res != 0)
return res;
p->file = NULL;
}
#endif
return 0;
}
WRes File_Read(CSzFile *p, void *data, size_t *size)
{
size_t originalSize = *size;
if (originalSize == 0)
return 0;
#ifdef USE_WINDOWS_FILE
*size = 0;
do
{
DWORD curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : (DWORD)originalSize;
DWORD processed = 0;
BOOL res = ReadFile(p->handle, data, curSize, &processed, NULL);
data = (void *)((Byte *)data + processed);
originalSize -= processed;
*size += processed;
if (!res)
return GetLastError();
if (processed == 0)
break;
}
while (originalSize > 0);
return 0;
#else
*size = fread(data, 1, originalSize, p->file);
if (*size == originalSize)
return 0;
return ferror(p->file);
#endif
}
WRes File_Write(CSzFile *p, const void *data, size_t *size)
{
size_t originalSize = *size;
if (originalSize == 0)
return 0;
#ifdef USE_WINDOWS_FILE
*size = 0;
do
{
DWORD curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : (DWORD)originalSize;
DWORD processed = 0;
BOOL res = WriteFile(p->handle, data, curSize, &processed, NULL);
data = (void *)((Byte *)data + processed);
originalSize -= processed;
*size += processed;
if (!res)
return GetLastError();
if (processed == 0)
break;
}
while (originalSize > 0);
return 0;
#else
*size = fwrite(data, 1, originalSize, p->file);
if (*size == originalSize)
return 0;
return ferror(p->file);
#endif
}
WRes File_Seek(CSzFile *p, Int64 *pos, ESzSeek origin)
{
#ifdef USE_WINDOWS_FILE
LARGE_INTEGER value;
DWORD moveMethod;
value.LowPart = (DWORD)*pos;
value.HighPart = (LONG)((UInt64)*pos >> 16 >> 16); /* for case when UInt64 is 32-bit only */
switch (origin)
{
case SZ_SEEK_SET: moveMethod = FILE_BEGIN; break;
case SZ_SEEK_CUR: moveMethod = FILE_CURRENT; break;
case SZ_SEEK_END: moveMethod = FILE_END; break;
default: return ERROR_INVALID_PARAMETER;
}
value.LowPart = SetFilePointer(p->handle, value.LowPart, &value.HighPart, moveMethod);
if (value.LowPart == 0xFFFFFFFF)
{
WRes res = GetLastError();
if (res != NO_ERROR)
return res;
}
*pos = ((Int64)value.HighPart << 32) | value.LowPart;
return 0;
#else
int moveMethod;
int res;
switch (origin)
{
case SZ_SEEK_SET: moveMethod = SEEK_SET; break;
case SZ_SEEK_CUR: moveMethod = SEEK_CUR; break;
case SZ_SEEK_END: moveMethod = SEEK_END; break;
default: return 1;
}
res = fseek(p->file, (long)*pos, moveMethod);
*pos = ftell(p->file);
return res;
#endif
}
WRes File_GetLength(CSzFile *p, UInt64 *length)
{
#ifdef USE_WINDOWS_FILE
DWORD sizeHigh;
DWORD sizeLow = GetFileSize(p->handle, &sizeHigh);
if (sizeLow == 0xFFFFFFFF)
{
DWORD res = GetLastError();
if (res != NO_ERROR)
return res;
}
*length = (((UInt64)sizeHigh) << 32) + sizeLow;
return 0;
#else
long pos = ftell(p->file);
int res = fseek(p->file, 0, SEEK_END);
*length = ftell(p->file);
fseek(p->file, pos, SEEK_SET);
return res;
#endif
}
/* ---------- FileSeqInStream ---------- */
static SRes FileSeqInStream_Read(void *pp, void *buf, size_t *size)
{
CFileSeqInStream *p = (CFileSeqInStream *)pp;
return File_Read(&p->file, buf, size) == 0 ? SZ_OK : SZ_ERROR_READ;
}
void FileSeqInStream_CreateVTable(CFileSeqInStream *p)
{
p->s.Read = FileSeqInStream_Read;
}
/* ---------- FileInStream ---------- */
static SRes FileInStream_Read(void *pp, void *buf, size_t *size)
{
CFileInStream *p = (CFileInStream *)pp;
return (File_Read(&p->file, buf, size) == 0) ? SZ_OK : SZ_ERROR_READ;
}
static SRes FileInStream_Seek(void *pp, Int64 *pos, ESzSeek origin)
{
CFileInStream *p = (CFileInStream *)pp;
return File_Seek(&p->file, pos, origin);
}
void FileInStream_CreateVTable(CFileInStream *p)
{
p->s.Read = FileInStream_Read;
p->s.Seek = FileInStream_Seek;
}
/* ---------- FileOutStream ---------- */
static size_t FileOutStream_Write(void *pp, const void *data, size_t size)
{
CFileOutStream *p = (CFileOutStream *)pp;
File_Write(&p->file, data, &size);
return size;
}
void FileOutStream_CreateVTable(CFileOutStream *p)
{
p->s.Write = FileOutStream_Write;
}

View File

@ -0,0 +1,83 @@
/* 7zFile.h -- File IO
2009-11-24 : Igor Pavlov : Public domain */
#ifndef __7Z_FILE_H
#define __7Z_FILE_H
#ifdef _WIN32
#define USE_WINDOWS_FILE
#endif
#ifdef USE_WINDOWS_FILE
#include <windows.h>
#else
#include <stdio.h>
#endif
#include "Types.h"
EXTERN_C_BEGIN
/* ---------- File ---------- */
typedef struct
{
#ifdef USE_WINDOWS_FILE
HANDLE handle;
#else
FILE *file;
#endif
} CSzFile;
void File_Construct(CSzFile *p);
#if !defined(UNDER_CE) || !defined(USE_WINDOWS_FILE)
WRes InFile_Open(CSzFile *p, const char *name);
WRes OutFile_Open(CSzFile *p, const char *name);
#endif
#ifdef USE_WINDOWS_FILE
WRes InFile_OpenW(CSzFile *p, const WCHAR *name);
WRes OutFile_OpenW(CSzFile *p, const WCHAR *name);
#endif
WRes File_Close(CSzFile *p);
/* reads max(*size, remain file's size) bytes */
WRes File_Read(CSzFile *p, void *data, size_t *size);
/* writes *size bytes */
WRes File_Write(CSzFile *p, const void *data, size_t *size);
WRes File_Seek(CSzFile *p, Int64 *pos, ESzSeek origin);
WRes File_GetLength(CSzFile *p, UInt64 *length);
/* ---------- FileInStream ---------- */
typedef struct
{
ISeqInStream s;
CSzFile file;
} CFileSeqInStream;
void FileSeqInStream_CreateVTable(CFileSeqInStream *p);
typedef struct
{
ISeekInStream s;
CSzFile file;
} CFileInStream;
void FileInStream_CreateVTable(CFileInStream *p);
typedef struct
{
ISeqOutStream s;
CSzFile file;
} CFileOutStream;
void FileOutStream_CreateVTable(CFileOutStream *p);
EXTERN_C_END
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,438 @@
/* 7zMain.c - Test application for 7z Decoder
2010-10-28 : Igor Pavlov : Public domain */
#include <stdio.h>
#include <string.h>
#include "7z/7z.h"
#include "7z/7zAlloc.h"
#include "7z/7zCrc.h"
#include "7z/7zFile.h"
#include "7z/7zVersion.h"
/*
#ifndef UNICODE
#define UNICODE
#endif
*/
#ifndef USE_WINDOWS_FILE
/* for mkdir */
#ifdef _WIN32
#include <direct.h>
#else
#include <sys/stat.h>
#include <errno.h>
#endif
#endif
static ISzAlloc g_Alloc = { SzAlloc, SzFree };
static int Buf_EnsureSize(CBuf *dest, size_t size)
{
if (dest->size >= size)
return 1;
Buf_Free(dest, &g_Alloc);
return Buf_Create(dest, size, &g_Alloc);
}
#ifndef _WIN32
static Byte kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
static Bool Utf16_To_Utf8(Byte *dest, size_t *destLen, const UInt16 *src, size_t srcLen)
{
size_t destPos = 0, srcPos = 0;
for (;;)
{
unsigned numAdds;
UInt32 value;
if (srcPos == srcLen)
{
*destLen = destPos;
return True;
}
value = src[srcPos++];
if (value < 0x80)
{
if (dest)
dest[destPos] = (char)value;
destPos++;
continue;
}
if (value >= 0xD800 && value < 0xE000)
{
UInt32 c2;
if (value >= 0xDC00 || srcPos == srcLen)
break;
c2 = src[srcPos++];
if (c2 < 0xDC00 || c2 >= 0xE000)
break;
value = (((value - 0xD800) << 10) | (c2 - 0xDC00)) + 0x10000;
}
for (numAdds = 1; numAdds < 5; numAdds++)
if (value < (((UInt32)1) << (numAdds * 5 + 6)))
break;
if (dest)
dest[destPos] = (char)(kUtf8Limits[numAdds - 1] + (value >> (6 * numAdds)));
destPos++;
do
{
numAdds--;
if (dest)
dest[destPos] = (char)(0x80 + ((value >> (6 * numAdds)) & 0x3F));
destPos++;
}
while (numAdds != 0);
}
*destLen = destPos;
return False;
}
static SRes Utf16_To_Utf8Buf(CBuf *dest, const UInt16 *src, size_t srcLen)
{
size_t destLen = 0;
Bool res;
Utf16_To_Utf8(NULL, &destLen, src, srcLen);
destLen += 1;
if (!Buf_EnsureSize(dest, destLen))
return SZ_ERROR_MEM;
res = Utf16_To_Utf8(dest->data, &destLen, src, srcLen);
dest->data[destLen] = 0;
return res ? SZ_OK : SZ_ERROR_FAIL;
}
#endif
static SRes Utf16_To_Char(CBuf *buf, const UInt16 *s, int fileMode)
{
int len = 0;
for (len = 0; s[len] != '\0'; len++);
#ifdef _WIN32
{
int size = len * 3 + 100;
if (!Buf_EnsureSize(buf, size))
return SZ_ERROR_MEM;
{
char defaultChar = '_';
BOOL defUsed;
int numChars = WideCharToMultiByte(fileMode ?
(
#ifdef UNDER_CE
CP_ACP
#else
AreFileApisANSI() ? CP_ACP : CP_OEMCP
#endif
) : CP_OEMCP,
0, s, len, (char *)buf->data, size, &defaultChar, &defUsed);
if (numChars == 0 || numChars >= size)
return SZ_ERROR_FAIL;
buf->data[numChars] = 0;
return SZ_OK;
}
}
#else
fileMode = fileMode;
return Utf16_To_Utf8Buf(buf, s, len);
#endif
}
static WRes MyCreateDir(const UInt16 *name)
{
#ifdef USE_WINDOWS_FILE
return CreateDirectoryW(name, NULL) ? 0 : GetLastError();
#else
CBuf buf;
WRes res;
Buf_Init(&buf);
RINOK(Utf16_To_Char(&buf, name, 1));
res =
#ifdef _WIN32
_mkdir((const char *)buf.data)
#else
mkdir((const char *)buf.data, 0777)
#endif
== 0 ? 0 : errno;
Buf_Free(&buf, &g_Alloc);
return res;
#endif
}
static WRes OutFile_OpenUtf16(CSzFile *p, const UInt16 *name)
{
#ifdef USE_WINDOWS_FILE
return OutFile_OpenW(p, name);
#else
CBuf buf;
WRes res;
Buf_Init(&buf);
RINOK(Utf16_To_Char(&buf, name, 1));
res = OutFile_Open(p, (const char *)buf.data);
Buf_Free(&buf, &g_Alloc);
return res;
#endif
}
static SRes PrintString(const UInt16 *s)
{
CBuf buf;
SRes res;
Buf_Init(&buf);
res = Utf16_To_Char(&buf, s, 0);
if (res == SZ_OK)
fputs((const char *)buf.data, stdout);
Buf_Free(&buf, &g_Alloc);
return res;
}
static void UInt64ToStr(UInt64 value, char *s)
{
char temp[32];
int pos = 0;
do
{
temp[pos++] = (char)('0' + (unsigned)(value % 10));
value /= 10;
}
while (value != 0);
do
*s++ = temp[--pos];
while (pos);
*s = '\0';
}
static char *UIntToStr(char *s, unsigned value, int numDigits)
{
char temp[16];
int pos = 0;
do
temp[pos++] = (char)('0' + (value % 10));
while (value /= 10);
for (numDigits -= pos; numDigits > 0; numDigits--)
*s++ = '0';
do
*s++ = temp[--pos];
while (pos);
*s = '\0';
return s;
}
#define PERIOD_4 (4 * 365 + 1)
#define PERIOD_100 (PERIOD_4 * 25 - 1)
#define PERIOD_400 (PERIOD_100 * 4 + 1)
static void ConvertFileTimeToString(const CNtfsFileTime *ft, char *s)
{
unsigned year, mon, day, hour, min, sec;
UInt64 v64 = (ft->Low | ((UInt64)ft->High << 32)) / 10000000;
Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
unsigned t;
UInt32 v;
sec = (unsigned)(v64 % 60); v64 /= 60;
min = (unsigned)(v64 % 60); v64 /= 60;
hour = (unsigned)(v64 % 24); v64 /= 24;
v = (UInt32)v64;
year = (unsigned)(1601 + v / PERIOD_400 * 400);
v %= PERIOD_400;
t = v / PERIOD_100; if (t == 4) t = 3; year += t * 100; v -= t * PERIOD_100;
t = v / PERIOD_4; if (t == 25) t = 24; year += t * 4; v -= t * PERIOD_4;
t = v / 365; if (t == 4) t = 3; year += t; v -= t * 365;
if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))
ms[1] = 29;
for (mon = 1; mon <= 12; mon++)
{
unsigned s = ms[mon - 1];
if (v < s)
break;
v -= s;
}
day = (unsigned)v + 1;
s = UIntToStr(s, year, 4); *s++ = '-';
s = UIntToStr(s, mon, 2); *s++ = '-';
s = UIntToStr(s, day, 2); *s++ = ' ';
s = UIntToStr(s, hour, 2); *s++ = ':';
s = UIntToStr(s, min, 2); *s++ = ':';
s = UIntToStr(s, sec, 2);
}
void PrintError(char *sz)
{
printf("\nERROR: %s\n", sz);
}
#ifdef USE_WINDOWS_FILE
#define kEmptyAttribChar '.'
static void GetAttribString(UInt32 wa, Bool isDir, char *s)
{
s[0] = (char)(((wa & FILE_ATTRIBUTE_DIRECTORY) != 0 || isDir) ? 'D' : kEmptyAttribChar);
s[1] = (char)(((wa & FILE_ATTRIBUTE_READONLY) != 0) ? 'R': kEmptyAttribChar);
s[2] = (char)(((wa & FILE_ATTRIBUTE_HIDDEN) != 0) ? 'H': kEmptyAttribChar);
s[3] = (char)(((wa & FILE_ATTRIBUTE_SYSTEM) != 0) ? 'S': kEmptyAttribChar);
s[4] = (char)(((wa & FILE_ATTRIBUTE_ARCHIVE) != 0) ? 'A': kEmptyAttribChar);
s[5] = '\0';
}
#else
static void GetAttribString(UInt32, Bool, char *s)
{
s[0] = '\0';
}
#endif
int SevenZipUnCompress( char *fname, unsigned char ** ppBuf,size_t * lpdwSize)
{
CFileInStream archiveStream;
CLookToRead lookStream;
CSzArEx db;
SRes res;
ISzAlloc allocImp;
ISzAlloc allocTempImp;
UInt16 *temp = NULL;
size_t tempSize = 0;
int bHasRomFile = 0;
int bExtractRomOK = 0;
//枚举文件找到NES或者UNF文件找不到直接返回
allocImp.Alloc = SzAlloc;
allocImp.Free = SzFree;
allocTempImp.Alloc = SzAllocTemp;
allocTempImp.Free = SzFreeTemp;
if (InFile_Open(&archiveStream.file, fname))
{
return FALSE;
}
FileInStream_CreateVTable(&archiveStream);
LookToRead_CreateVTable(&lookStream, False);
lookStream.realStream = &archiveStream.s;
LookToRead_Init(&lookStream);
CrcGenerateTable();
SzArEx_Init(&db);
res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp);
if (res == SZ_OK)
{
UInt32 i;
UInt32 blockIndex = 0xFFFFFFFF; /* it can have any value before first call (if outBuffer = 0) */
Byte *outBuffer = 0; /* it must be 0 before first call for each new archive. */
for (i = 0; i < db.db.NumFiles; i++)
{
size_t offset = 0;
size_t outSizeProcessed = 0;
const CSzFileItem *f = db.db.Files + i;
size_t len;
len = SzArEx_GetFileNameUtf16(&db, i, NULL);
if (len > tempSize)
{
SzFree(NULL, temp);
tempSize = len;
temp = (UInt16 *)SzAlloc(NULL, tempSize * sizeof(temp[0]));
if (temp == 0)
{
res = SZ_ERROR_MEM;
break;
}
}
SzArEx_GetFileNameUtf16(&db, i, temp);
//获取文件信息
{
char attr[8];
GetAttribString(f->AttribDefined ? f->Attrib : 0, f->IsDir, attr);// f->IsDir 文件是否是目录
//UInt64ToStr(f->Size, s);//f->Size 文件大小
if(f->IsDir!=1)
{
//检测扩展名
if(len>5)
{
//"*.nes",
//"*.unf",
//"*.fds",
//"*.nsf",
if(wcsicmp(L".nes",&temp[len-5])==0)
{
bHasRomFile =1;
}
else if(wcsicmp(L".unf",&temp[len-5])==0)
{
bHasRomFile =1;
}
else if(wcsicmp(L".fds",&temp[len-5])==0)
{
bHasRomFile =1;
}
else if(wcsicmp(L".nsf",&temp[len-5])==0)
{
bHasRomFile =1;
}
}
//if( (f->Size>16000)&&(f->Size<10000000) )
//bHasRomFile =1;
}
if(bHasRomFile==0)
continue;
}
if (bHasRomFile)
{
res = SzArEx_Extract(&db, &lookStream.s, i,&blockIndex, ppBuf, lpdwSize,&offset, &outSizeProcessed,&allocImp, &allocTempImp);
if (res != SZ_OK)
continue;
else
{
bExtractRomOK = 1;
if(offset!=0)
{//重组
void *pRom = malloc(f->Size);
memcpy(pRom,*ppBuf+offset,f->Size);
*lpdwSize = f->Size;
free(*ppBuf);
*ppBuf = pRom;
}
}
}
if(bExtractRomOK)
break;
}//结束文件枚举循环
IAlloc_Free(&allocImp, outBuffer);
}
SzArEx_Free(&db, &allocImp);
SzFree(NULL, temp);
File_Close(&archiveStream.file);
/*if (res == SZ_OK)
{
printf("\nEverything is Ok\n");
return 0;
}*/
return bExtractRomOK;
}
/*
int MY_CDECL main(int c, char *v[])
{
unsigned char *pBuf = 0;
size_t fileLen;
int i = SevenZipUnCompress(v[1],&pBuf,&fileLen);
free(pBuf); pBuf = 0;
printf("%d",i);
}
*/

View File

@ -0,0 +1,169 @@
/* 7zStream.c -- 7z Stream functions
2010-03-11 : Igor Pavlov : Public domain */
#include <string.h>
#include "Types.h"
SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType)
{
while (size != 0)
{
size_t processed = size;
RINOK(stream->Read(stream, buf, &processed));
if (processed == 0)
return errorType;
buf = (void *)((Byte *)buf + processed);
size -= processed;
}
return SZ_OK;
}
SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size)
{
return SeqInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF);
}
SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf)
{
size_t processed = 1;
RINOK(stream->Read(stream, buf, &processed));
return (processed == 1) ? SZ_OK : SZ_ERROR_INPUT_EOF;
}
SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset)
{
Int64 t = offset;
return stream->Seek(stream, &t, SZ_SEEK_SET);
}
SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size)
{
const void *lookBuf;
if (*size == 0)
return SZ_OK;
RINOK(stream->Look(stream, &lookBuf, size));
memcpy(buf, lookBuf, *size);
return stream->Skip(stream, *size);
}
SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType)
{
while (size != 0)
{
size_t processed = size;
RINOK(stream->Read(stream, buf, &processed));
if (processed == 0)
return errorType;
buf = (void *)((Byte *)buf + processed);
size -= processed;
}
return SZ_OK;
}
SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size)
{
return LookInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF);
}
static SRes LookToRead_Look_Lookahead(void *pp, const void **buf, size_t *size)
{
SRes res = SZ_OK;
CLookToRead *p = (CLookToRead *)pp;
size_t size2 = p->size - p->pos;
if (size2 == 0 && *size > 0)
{
p->pos = 0;
size2 = LookToRead_BUF_SIZE;
res = p->realStream->Read(p->realStream, p->buf, &size2);
p->size = size2;
}
if (size2 < *size)
*size = size2;
*buf = p->buf + p->pos;
return res;
}
static SRes LookToRead_Look_Exact(void *pp, const void **buf, size_t *size)
{
SRes res = SZ_OK;
CLookToRead *p = (CLookToRead *)pp;
size_t size2 = p->size - p->pos;
if (size2 == 0 && *size > 0)
{
p->pos = 0;
if (*size > LookToRead_BUF_SIZE)
*size = LookToRead_BUF_SIZE;
res = p->realStream->Read(p->realStream, p->buf, size);
size2 = p->size = *size;
}
if (size2 < *size)
*size = size2;
*buf = p->buf + p->pos;
return res;
}
static SRes LookToRead_Skip(void *pp, size_t offset)
{
CLookToRead *p = (CLookToRead *)pp;
p->pos += offset;
return SZ_OK;
}
static SRes LookToRead_Read(void *pp, void *buf, size_t *size)
{
CLookToRead *p = (CLookToRead *)pp;
size_t rem = p->size - p->pos;
if (rem == 0)
return p->realStream->Read(p->realStream, buf, size);
if (rem > *size)
rem = *size;
memcpy(buf, p->buf + p->pos, rem);
p->pos += rem;
*size = rem;
return SZ_OK;
}
static SRes LookToRead_Seek(void *pp, Int64 *pos, ESzSeek origin)
{
CLookToRead *p = (CLookToRead *)pp;
p->pos = p->size = 0;
return p->realStream->Seek(p->realStream, pos, origin);
}
void LookToRead_CreateVTable(CLookToRead *p, int lookahead)
{
p->s.Look = lookahead ?
LookToRead_Look_Lookahead :
LookToRead_Look_Exact;
p->s.Skip = LookToRead_Skip;
p->s.Read = LookToRead_Read;
p->s.Seek = LookToRead_Seek;
}
void LookToRead_Init(CLookToRead *p)
{
p->pos = p->size = 0;
}
static SRes SecToLook_Read(void *pp, void *buf, size_t *size)
{
CSecToLook *p = (CSecToLook *)pp;
return LookInStream_LookRead(p->realStream, buf, size);
}
void SecToLook_CreateVTable(CSecToLook *p)
{
p->s.Read = SecToLook_Read;
}
static SRes SecToRead_Read(void *pp, void *buf, size_t *size)
{
CSecToRead *p = (CSecToRead *)pp;
return p->realStream->Read(p->realStream, buf, size);
}
void SecToRead_CreateVTable(CSecToRead *p)
{
p->s.Read = SecToRead_Read;
}

View File

@ -0,0 +1,7 @@
#define MY_VER_MAJOR 9
#define MY_VER_MINOR 20
#define MY_VER_BUILD 0
#define MY_VERSION "9.20"
#define MY_DATE "2010-11-18"
#define MY_COPYRIGHT ": Igor Pavlov : Public domain"
#define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " : " MY_DATE

View File

@ -0,0 +1,132 @@
/* Bcj2.c -- Converter for x86 code (BCJ2)
2008-10-04 : Igor Pavlov : Public domain */
#include "Bcj2.h"
#ifdef _LZMA_PROB32
#define CProb UInt32
#else
#define CProb UInt16
#endif
#define IsJcc(b0, b1) ((b0) == 0x0F && ((b1) & 0xF0) == 0x80)
#define IsJ(b0, b1) ((b1 & 0xFE) == 0xE8 || IsJcc(b0, b1))
#define kNumTopBits 24
#define kTopValue ((UInt32)1 << kNumTopBits)
#define kNumBitModelTotalBits 11
#define kBitModelTotal (1 << kNumBitModelTotalBits)
#define kNumMoveBits 5
#define RC_READ_BYTE (*buffer++)
#define RC_TEST { if (buffer == bufferLim) return SZ_ERROR_DATA; }
#define RC_INIT2 code = 0; range = 0xFFFFFFFF; \
{ int i; for (i = 0; i < 5; i++) { RC_TEST; code = (code << 8) | RC_READ_BYTE; }}
#define NORMALIZE if (range < kTopValue) { RC_TEST; range <<= 8; code = (code << 8) | RC_READ_BYTE; }
#define IF_BIT_0(p) ttt = *(p); bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
#define UPDATE_0(p) range = bound; *(p) = (CProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); NORMALIZE;
#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CProb)(ttt - (ttt >> kNumMoveBits)); NORMALIZE;
int Bcj2_Decode(
const Byte *buf0, SizeT size0,
const Byte *buf1, SizeT size1,
const Byte *buf2, SizeT size2,
const Byte *buf3, SizeT size3,
Byte *outBuf, SizeT outSize)
{
CProb p[256 + 2];
SizeT inPos = 0, outPos = 0;
const Byte *buffer, *bufferLim;
UInt32 range, code;
Byte prevByte = 0;
unsigned int i;
for (i = 0; i < sizeof(p) / sizeof(p[0]); i++)
p[i] = kBitModelTotal >> 1;
buffer = buf3;
bufferLim = buffer + size3;
RC_INIT2
if (outSize == 0)
return SZ_OK;
for (;;)
{
Byte b;
CProb *prob;
UInt32 bound;
UInt32 ttt;
SizeT limit = size0 - inPos;
if (outSize - outPos < limit)
limit = outSize - outPos;
while (limit != 0)
{
Byte b = buf0[inPos];
outBuf[outPos++] = b;
if (IsJ(prevByte, b))
break;
inPos++;
prevByte = b;
limit--;
}
if (limit == 0 || outPos == outSize)
break;
b = buf0[inPos++];
if (b == 0xE8)
prob = p + prevByte;
else if (b == 0xE9)
prob = p + 256;
else
prob = p + 257;
IF_BIT_0(prob)
{
UPDATE_0(prob)
prevByte = b;
}
else
{
UInt32 dest;
const Byte *v;
UPDATE_1(prob)
if (b == 0xE8)
{
v = buf1;
if (size1 < 4)
return SZ_ERROR_DATA;
buf1 += 4;
size1 -= 4;
}
else
{
v = buf2;
if (size2 < 4)
return SZ_ERROR_DATA;
buf2 += 4;
size2 -= 4;
}
dest = (((UInt32)v[0] << 24) | ((UInt32)v[1] << 16) |
((UInt32)v[2] << 8) | ((UInt32)v[3])) - ((UInt32)outPos + 4);
outBuf[outPos++] = (Byte)dest;
if (outPos == outSize)
break;
outBuf[outPos++] = (Byte)(dest >> 8);
if (outPos == outSize)
break;
outBuf[outPos++] = (Byte)(dest >> 16);
if (outPos == outSize)
break;
outBuf[outPos++] = prevByte = (Byte)(dest >> 24);
}
}
return (outPos == outSize) ? SZ_OK : SZ_ERROR_DATA;
}

View File

@ -0,0 +1,38 @@
/* Bcj2.h -- Converter for x86 code (BCJ2)
2009-02-07 : Igor Pavlov : Public domain */
#ifndef __BCJ2_H
#define __BCJ2_H
#include "Types.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
Conditions:
outSize <= FullOutputSize,
where FullOutputSize is full size of output stream of x86_2 filter.
If buf0 overlaps outBuf, there are two required conditions:
1) (buf0 >= outBuf)
2) (buf0 + size0 >= outBuf + FullOutputSize).
Returns:
SZ_OK
SZ_ERROR_DATA - Data error
*/
int Bcj2_Decode(
const Byte *buf0, SizeT size0,
const Byte *buf1, SizeT size1,
const Byte *buf2, SizeT size2,
const Byte *buf3, SizeT size3,
Byte *outBuf, SizeT outSize);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,133 @@
/* Bra.c -- Converters for RISC code
2010-04-16 : Igor Pavlov : Public domain */
#include "Bra.h"
SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
{
SizeT i;
if (size < 4)
return 0;
size -= 4;
ip += 8;
for (i = 0; i <= size; i += 4)
{
if (data[i + 3] == 0xEB)
{
UInt32 dest;
UInt32 src = ((UInt32)data[i + 2] << 16) | ((UInt32)data[i + 1] << 8) | (data[i + 0]);
src <<= 2;
if (encoding)
dest = ip + (UInt32)i + src;
else
dest = src - (ip + (UInt32)i);
dest >>= 2;
data[i + 2] = (Byte)(dest >> 16);
data[i + 1] = (Byte)(dest >> 8);
data[i + 0] = (Byte)dest;
}
}
return i;
}
SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
{
SizeT i;
if (size < 4)
return 0;
size -= 4;
ip += 4;
for (i = 0; i <= size; i += 2)
{
if ((data[i + 1] & 0xF8) == 0xF0 &&
(data[i + 3] & 0xF8) == 0xF8)
{
UInt32 dest;
UInt32 src =
(((UInt32)data[i + 1] & 0x7) << 19) |
((UInt32)data[i + 0] << 11) |
(((UInt32)data[i + 3] & 0x7) << 8) |
(data[i + 2]);
src <<= 1;
if (encoding)
dest = ip + (UInt32)i + src;
else
dest = src - (ip + (UInt32)i);
dest >>= 1;
data[i + 1] = (Byte)(0xF0 | ((dest >> 19) & 0x7));
data[i + 0] = (Byte)(dest >> 11);
data[i + 3] = (Byte)(0xF8 | ((dest >> 8) & 0x7));
data[i + 2] = (Byte)dest;
i += 2;
}
}
return i;
}
SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
{
SizeT i;
if (size < 4)
return 0;
size -= 4;
for (i = 0; i <= size; i += 4)
{
if ((data[i] >> 2) == 0x12 && (data[i + 3] & 3) == 1)
{
UInt32 src = ((UInt32)(data[i + 0] & 3) << 24) |
((UInt32)data[i + 1] << 16) |
((UInt32)data[i + 2] << 8) |
((UInt32)data[i + 3] & (~3));
UInt32 dest;
if (encoding)
dest = ip + (UInt32)i + src;
else
dest = src - (ip + (UInt32)i);
data[i + 0] = (Byte)(0x48 | ((dest >> 24) & 0x3));
data[i + 1] = (Byte)(dest >> 16);
data[i + 2] = (Byte)(dest >> 8);
data[i + 3] &= 0x3;
data[i + 3] |= dest;
}
}
return i;
}
SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
{
UInt32 i;
if (size < 4)
return 0;
size -= 4;
for (i = 0; i <= size; i += 4)
{
if ((data[i] == 0x40 && (data[i + 1] & 0xC0) == 0x00) ||
(data[i] == 0x7F && (data[i + 1] & 0xC0) == 0xC0))
{
UInt32 src =
((UInt32)data[i + 0] << 24) |
((UInt32)data[i + 1] << 16) |
((UInt32)data[i + 2] << 8) |
((UInt32)data[i + 3]);
UInt32 dest;
src <<= 2;
if (encoding)
dest = ip + i + src;
else
dest = src - (ip + i);
dest >>= 2;
dest = (((0 - ((dest >> 22) & 1)) << 22) & 0x3FFFFFFF) | (dest & 0x3FFFFF) | 0x40000000;
data[i + 0] = (Byte)(dest >> 24);
data[i + 1] = (Byte)(dest >> 16);
data[i + 2] = (Byte)(dest >> 8);
data[i + 3] = (Byte)dest;
}
}
return i;
}

View File

@ -0,0 +1,68 @@
/* Bra.h -- Branch converters for executables
2009-02-07 : Igor Pavlov : Public domain */
#ifndef __BRA_H
#define __BRA_H
#include "Types.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
These functions convert relative addresses to absolute addresses
in CALL instructions to increase the compression ratio.
In:
data - data buffer
size - size of data
ip - current virtual Instruction Pinter (IP) value
state - state variable for x86 converter
encoding - 0 (for decoding), 1 (for encoding)
Out:
state - state variable for x86 converter
Returns:
The number of processed bytes. If you call these functions with multiple calls,
you must start next call with first byte after block of processed bytes.
Type Endian Alignment LookAhead
x86 little 1 4
ARMT little 2 2
ARM little 4 0
PPC big 4 0
SPARC big 4 0
IA64 little 16 0
size must be >= Alignment + LookAhead, if it's not last block.
If (size < Alignment + LookAhead), converter returns 0.
Example:
UInt32 ip = 0;
for ()
{
; size must be >= Alignment + LookAhead, if it's not last block
SizeT processed = Convert(data, size, ip, 1);
data += processed;
size -= processed;
ip += processed;
}
*/
#define x86_Convert_Init(state) { state = 0; }
SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding);
SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,85 @@
/* Bra86.c -- Converter for x86 code (BCJ)
2008-10-04 : Igor Pavlov : Public domain */
#include "Bra.h"
#define Test86MSByte(b) ((b) == 0 || (b) == 0xFF)
const Byte kMaskToAllowedStatus[8] = {1, 1, 1, 0, 1, 0, 0, 0};
const Byte kMaskToBitNumber[8] = {0, 1, 2, 2, 3, 3, 3, 3};
SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding)
{
SizeT bufferPos = 0, prevPosT;
UInt32 prevMask = *state & 0x7;
if (size < 5)
return 0;
ip += 5;
prevPosT = (SizeT)0 - 1;
for (;;)
{
Byte *p = data + bufferPos;
Byte *limit = data + size - 4;
for (; p < limit; p++)
if ((*p & 0xFE) == 0xE8)
break;
bufferPos = (SizeT)(p - data);
if (p >= limit)
break;
prevPosT = bufferPos - prevPosT;
if (prevPosT > 3)
prevMask = 0;
else
{
prevMask = (prevMask << ((int)prevPosT - 1)) & 0x7;
if (prevMask != 0)
{
Byte b = p[4 - kMaskToBitNumber[prevMask]];
if (!kMaskToAllowedStatus[prevMask] || Test86MSByte(b))
{
prevPosT = bufferPos;
prevMask = ((prevMask << 1) & 0x7) | 1;
bufferPos++;
continue;
}
}
}
prevPosT = bufferPos;
if (Test86MSByte(p[4]))
{
UInt32 src = ((UInt32)p[4] << 24) | ((UInt32)p[3] << 16) | ((UInt32)p[2] << 8) | ((UInt32)p[1]);
UInt32 dest;
for (;;)
{
Byte b;
int index;
if (encoding)
dest = (ip + (UInt32)bufferPos) + src;
else
dest = src - (ip + (UInt32)bufferPos);
if (prevMask == 0)
break;
index = kMaskToBitNumber[prevMask] * 8;
b = (Byte)(dest >> (24 - index));
if (!Test86MSByte(b))
break;
src = dest ^ ((1 << (32 - index)) - 1);
}
p[4] = (Byte)(~(((dest >> 24) & 1) - 1));
p[3] = (Byte)(dest >> 16);
p[2] = (Byte)(dest >> 8);
p[1] = (Byte)dest;
bufferPos += 5;
}
else
{
prevMask = ((prevMask << 1) & 0x7) | 1;
bufferPos++;
}
}
prevPosT = bufferPos - prevPosT;
*state = ((prevPosT > 3) ? 0 : ((prevMask << ((int)prevPosT - 1)) & 0x7));
return bufferPos;
}

View File

@ -0,0 +1,168 @@
/* CpuArch.c -- CPU specific code
2010-10-26: Igor Pavlov : Public domain */
#include "CpuArch.h"
#ifdef MY_CPU_X86_OR_AMD64
#if (defined(_MSC_VER) && !defined(MY_CPU_AMD64)) || defined(__GNUC__)
#define USE_ASM
#endif
#if defined(USE_ASM) && !defined(MY_CPU_AMD64)
static UInt32 CheckFlag(UInt32 flag)
{
#ifdef _MSC_VER
__asm pushfd;
__asm pop EAX;
__asm mov EDX, EAX;
__asm xor EAX, flag;
__asm push EAX;
__asm popfd;
__asm pushfd;
__asm pop EAX;
__asm xor EAX, EDX;
__asm push EDX;
__asm popfd;
__asm and flag, EAX;
#else
__asm__ __volatile__ (
"pushf\n\t"
"pop %%EAX\n\t"
"movl %%EAX,%%EDX\n\t"
"xorl %0,%%EAX\n\t"
"push %%EAX\n\t"
"popf\n\t"
"pushf\n\t"
"pop %%EAX\n\t"
"xorl %%EDX,%%EAX\n\t"
"push %%EDX\n\t"
"popf\n\t"
"andl %%EAX, %0\n\t":
"=c" (flag) : "c" (flag));
#endif
return flag;
}
#define CHECK_CPUID_IS_SUPPORTED if (CheckFlag(1 << 18) == 0 || CheckFlag(1 << 21) == 0) return False;
#else
#define CHECK_CPUID_IS_SUPPORTED
#endif
static void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d)
{
#ifdef USE_ASM
#ifdef _MSC_VER
UInt32 a2, b2, c2, d2;
__asm xor EBX, EBX;
__asm xor ECX, ECX;
__asm xor EDX, EDX;
__asm mov EAX, function;
__asm cpuid;
__asm mov a2, EAX;
__asm mov b2, EBX;
__asm mov c2, ECX;
__asm mov d2, EDX;
*a = a2;
*b = b2;
*c = c2;
*d = d2;
#else
__asm__ __volatile__ (
"cpuid"
: "=a" (*a) ,
"=b" (*b) ,
"=c" (*c) ,
"=d" (*d)
: "0" (function)) ;
#endif
#else
int CPUInfo[4];
__cpuid(CPUInfo, function);
*a = CPUInfo[0];
*b = CPUInfo[1];
*c = CPUInfo[2];
*d = CPUInfo[3];
#endif
}
Bool x86cpuid_CheckAndRead(Cx86cpuid *p)
{
CHECK_CPUID_IS_SUPPORTED
MyCPUID(0, &p->maxFunc, &p->vendor[0], &p->vendor[2], &p->vendor[1]);
MyCPUID(1, &p->ver, &p->b, &p->c, &p->d);
return True;
}
static UInt32 kVendors[][3] =
{
{ 0x756E6547, 0x49656E69, 0x6C65746E},
{ 0x68747541, 0x69746E65, 0x444D4163},
{ 0x746E6543, 0x48727561, 0x736C7561}
};
int x86cpuid_GetFirm(const Cx86cpuid *p)
{
unsigned i;
for (i = 0; i < sizeof(kVendors) / sizeof(kVendors[i]); i++)
{
const UInt32 *v = kVendors[i];
if (v[0] == p->vendor[0] &&
v[1] == p->vendor[1] &&
v[2] == p->vendor[2])
return (int)i;
}
return -1;
}
Bool CPU_Is_InOrder()
{
Cx86cpuid p;
int firm;
UInt32 family, model;
if (!x86cpuid_CheckAndRead(&p))
return True;
family = x86cpuid_GetFamily(&p);
model = x86cpuid_GetModel(&p);
firm = x86cpuid_GetFirm(&p);
switch (firm)
{
case CPU_FIRM_INTEL: return (family < 6 || (family == 6 && model == 0x100C));
case CPU_FIRM_AMD: return (family < 5 || (family == 5 && (model < 6 || model == 0xA)));
case CPU_FIRM_VIA: return (family < 6 || (family == 6 && model < 0xF));
}
return True;
}
#if !defined(MY_CPU_AMD64) && defined(_WIN32)
static Bool CPU_Sys_Is_SSE_Supported()
{
OSVERSIONINFO vi;
vi.dwOSVersionInfoSize = sizeof(vi);
if (!GetVersionEx(&vi))
return False;
return (vi.dwMajorVersion >= 5);
}
#define CHECK_SYS_SSE_SUPPORT if (!CPU_Sys_Is_SSE_Supported()) return False;
#else
#define CHECK_SYS_SSE_SUPPORT
#endif
Bool CPU_Is_Aes_Supported()
{
Cx86cpuid p;
CHECK_SYS_SSE_SUPPORT
if (!x86cpuid_CheckAndRead(&p))
return False;
return (p.c >> 25) & 1;
}
#endif

View File

@ -0,0 +1,155 @@
/* CpuArch.h -- CPU specific code
2010-10-26: Igor Pavlov : Public domain */
#ifndef __CPU_ARCH_H
#define __CPU_ARCH_H
#include "Types.h"
EXTERN_C_BEGIN
/*
MY_CPU_LE means that CPU is LITTLE ENDIAN.
If MY_CPU_LE is not defined, we don't know about that property of platform (it can be LITTLE ENDIAN).
MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned memory accesses.
If MY_CPU_LE_UNALIGN is not defined, we don't know about these properties of platform.
*/
#if defined(_M_X64) || defined(_M_AMD64) || defined(__x86_64__)
#define MY_CPU_AMD64
#endif
#if defined(MY_CPU_AMD64) || defined(_M_IA64)
#define MY_CPU_64BIT
#endif
#if defined(_M_IX86) || defined(__i386__)
#define MY_CPU_X86
#endif
#if defined(MY_CPU_X86) || defined(MY_CPU_AMD64)
#define MY_CPU_X86_OR_AMD64
#endif
#if defined(MY_CPU_X86) || defined(_M_ARM)
#define MY_CPU_32BIT
#endif
#if defined(_WIN32) && defined(_M_ARM)
#define MY_CPU_ARM_LE
#endif
#if defined(_WIN32) && defined(_M_IA64)
#define MY_CPU_IA64_LE
#endif
#if defined(MY_CPU_X86_OR_AMD64)
#define MY_CPU_LE_UNALIGN
#endif
#if defined(MY_CPU_X86_OR_AMD64) || defined(MY_CPU_ARM_LE) || defined(MY_CPU_IA64_LE) || defined(__ARMEL__) || defined(__MIPSEL__) || defined(__LITTLE_ENDIAN__)
#define MY_CPU_LE
#endif
#if defined(__BIG_ENDIAN__)
#define MY_CPU_BE
#endif
#if defined(MY_CPU_LE) && defined(MY_CPU_BE)
Stop_Compiling_Bad_Endian
#endif
#ifdef MY_CPU_LE_UNALIGN
#define GetUi16(p) (*(const UInt16 *)(p))
#define GetUi32(p) (*(const UInt32 *)(p))
#define GetUi64(p) (*(const UInt64 *)(p))
#define SetUi16(p, d) *(UInt16 *)(p) = (d);
#define SetUi32(p, d) *(UInt32 *)(p) = (d);
#define SetUi64(p, d) *(UInt64 *)(p) = (d);
#else
#define GetUi16(p) (((const Byte *)(p))[0] | ((UInt16)((const Byte *)(p))[1] << 8))
#define GetUi32(p) ( \
((const Byte *)(p))[0] | \
((UInt32)((const Byte *)(p))[1] << 8) | \
((UInt32)((const Byte *)(p))[2] << 16) | \
((UInt32)((const Byte *)(p))[3] << 24))
#define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32))
#define SetUi16(p, d) { UInt32 _x_ = (d); \
((Byte *)(p))[0] = (Byte)_x_; \
((Byte *)(p))[1] = (Byte)(_x_ >> 8); }
#define SetUi32(p, d) { UInt32 _x_ = (d); \
((Byte *)(p))[0] = (Byte)_x_; \
((Byte *)(p))[1] = (Byte)(_x_ >> 8); \
((Byte *)(p))[2] = (Byte)(_x_ >> 16); \
((Byte *)(p))[3] = (Byte)(_x_ >> 24); }
#define SetUi64(p, d) { UInt64 _x64_ = (d); \
SetUi32(p, (UInt32)_x64_); \
SetUi32(((Byte *)(p)) + 4, (UInt32)(_x64_ >> 32)); }
#endif
#if defined(MY_CPU_LE_UNALIGN) && defined(_WIN64) && (_MSC_VER >= 1300)
#pragma intrinsic(_byteswap_ulong)
#pragma intrinsic(_byteswap_uint64)
#define GetBe32(p) _byteswap_ulong(*(const UInt32 *)(const Byte *)(p))
#define GetBe64(p) _byteswap_uint64(*(const UInt64 *)(const Byte *)(p))
#else
#define GetBe32(p) ( \
((UInt32)((const Byte *)(p))[0] << 24) | \
((UInt32)((const Byte *)(p))[1] << 16) | \
((UInt32)((const Byte *)(p))[2] << 8) | \
((const Byte *)(p))[3] )
#define GetBe64(p) (((UInt64)GetBe32(p) << 32) | GetBe32(((const Byte *)(p)) + 4))
#endif
#define GetBe16(p) (((UInt16)((const Byte *)(p))[0] << 8) | ((const Byte *)(p))[1])
#ifdef MY_CPU_X86_OR_AMD64
typedef struct
{
UInt32 maxFunc;
UInt32 vendor[3];
UInt32 ver;
UInt32 b;
UInt32 c;
UInt32 d;
} Cx86cpuid;
enum
{
CPU_FIRM_INTEL,
CPU_FIRM_AMD,
CPU_FIRM_VIA
};
Bool x86cpuid_CheckAndRead(Cx86cpuid *p);
int x86cpuid_GetFirm(const Cx86cpuid *p);
#define x86cpuid_GetFamily(p) (((p)->ver >> 8) & 0xFF00F)
#define x86cpuid_GetModel(p) (((p)->ver >> 4) & 0xF00F)
#define x86cpuid_GetStepping(p) ((p)->ver & 0xF)
Bool CPU_Is_InOrder();
Bool CPU_Is_Aes_Supported();
#endif
EXTERN_C_END
#endif

View File

@ -0,0 +1,356 @@
/* Lzma2Dec.c -- LZMA2 Decoder
2009-05-03 : Igor Pavlov : Public domain */
/* #define SHOW_DEBUG_INFO */
#ifdef SHOW_DEBUG_INFO
#include <stdio.h>
#endif
#include <string.h>
#include "Lzma2Dec.h"
/*
00000000 - EOS
00000001 U U - Uncompressed Reset Dic
00000010 U U - Uncompressed No Reset
100uuuuu U U P P - LZMA no reset
101uuuuu U U P P - LZMA reset state
110uuuuu U U P P S - LZMA reset state + new prop
111uuuuu U U P P S - LZMA reset state + new prop + reset dic
u, U - Unpack Size
P - Pack Size
S - Props
*/
#define LZMA2_CONTROL_LZMA (1 << 7)
#define LZMA2_CONTROL_COPY_NO_RESET 2
#define LZMA2_CONTROL_COPY_RESET_DIC 1
#define LZMA2_CONTROL_EOF 0
#define LZMA2_IS_UNCOMPRESSED_STATE(p) (((p)->control & LZMA2_CONTROL_LZMA) == 0)
#define LZMA2_GET_LZMA_MODE(p) (((p)->control >> 5) & 3)
#define LZMA2_IS_THERE_PROP(mode) ((mode) >= 2)
#define LZMA2_LCLP_MAX 4
#define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11))
#ifdef SHOW_DEBUG_INFO
#define PRF(x) x
#else
#define PRF(x)
#endif
typedef enum
{
LZMA2_STATE_CONTROL,
LZMA2_STATE_UNPACK0,
LZMA2_STATE_UNPACK1,
LZMA2_STATE_PACK0,
LZMA2_STATE_PACK1,
LZMA2_STATE_PROP,
LZMA2_STATE_DATA,
LZMA2_STATE_DATA_CONT,
LZMA2_STATE_FINISHED,
LZMA2_STATE_ERROR
} ELzma2State;
static SRes Lzma2Dec_GetOldProps(Byte prop, Byte *props)
{
UInt32 dicSize;
if (prop > 40)
return SZ_ERROR_UNSUPPORTED;
dicSize = (prop == 40) ? 0xFFFFFFFF : LZMA2_DIC_SIZE_FROM_PROP(prop);
props[0] = (Byte)LZMA2_LCLP_MAX;
props[1] = (Byte)(dicSize);
props[2] = (Byte)(dicSize >> 8);
props[3] = (Byte)(dicSize >> 16);
props[4] = (Byte)(dicSize >> 24);
return SZ_OK;
}
SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAlloc *alloc)
{
Byte props[LZMA_PROPS_SIZE];
RINOK(Lzma2Dec_GetOldProps(prop, props));
return LzmaDec_AllocateProbs(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
}
SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAlloc *alloc)
{
Byte props[LZMA_PROPS_SIZE];
RINOK(Lzma2Dec_GetOldProps(prop, props));
return LzmaDec_Allocate(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
}
void Lzma2Dec_Init(CLzma2Dec *p)
{
p->state = LZMA2_STATE_CONTROL;
p->needInitDic = True;
p->needInitState = True;
p->needInitProp = True;
LzmaDec_Init(&p->decoder);
}
static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)
{
switch(p->state)
{
case LZMA2_STATE_CONTROL:
p->control = b;
PRF(printf("\n %4X ", p->decoder.dicPos));
PRF(printf(" %2X", b));
if (p->control == 0)
return LZMA2_STATE_FINISHED;
if (LZMA2_IS_UNCOMPRESSED_STATE(p))
{
if ((p->control & 0x7F) > 2)
return LZMA2_STATE_ERROR;
p->unpackSize = 0;
}
else
p->unpackSize = (UInt32)(p->control & 0x1F) << 16;
return LZMA2_STATE_UNPACK0;
case LZMA2_STATE_UNPACK0:
p->unpackSize |= (UInt32)b << 8;
return LZMA2_STATE_UNPACK1;
case LZMA2_STATE_UNPACK1:
p->unpackSize |= (UInt32)b;
p->unpackSize++;
PRF(printf(" %8d", p->unpackSize));
return (LZMA2_IS_UNCOMPRESSED_STATE(p)) ? LZMA2_STATE_DATA : LZMA2_STATE_PACK0;
case LZMA2_STATE_PACK0:
p->packSize = (UInt32)b << 8;
return LZMA2_STATE_PACK1;
case LZMA2_STATE_PACK1:
p->packSize |= (UInt32)b;
p->packSize++;
PRF(printf(" %8d", p->packSize));
return LZMA2_IS_THERE_PROP(LZMA2_GET_LZMA_MODE(p)) ? LZMA2_STATE_PROP:
(p->needInitProp ? LZMA2_STATE_ERROR : LZMA2_STATE_DATA);
case LZMA2_STATE_PROP:
{
int lc, lp;
if (b >= (9 * 5 * 5))
return LZMA2_STATE_ERROR;
lc = b % 9;
b /= 9;
p->decoder.prop.pb = b / 5;
lp = b % 5;
if (lc + lp > LZMA2_LCLP_MAX)
return LZMA2_STATE_ERROR;
p->decoder.prop.lc = lc;
p->decoder.prop.lp = lp;
p->needInitProp = False;
return LZMA2_STATE_DATA;
}
}
return LZMA2_STATE_ERROR;
}
static void LzmaDec_UpdateWithUncompressed(CLzmaDec *p, const Byte *src, SizeT size)
{
memcpy(p->dic + p->dicPos, src, size);
p->dicPos += size;
if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= size)
p->checkDicSize = p->prop.dicSize;
p->processedPos += (UInt32)size;
}
void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState);
SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
{
SizeT inSize = *srcLen;
*srcLen = 0;
*status = LZMA_STATUS_NOT_SPECIFIED;
while (p->state != LZMA2_STATE_FINISHED)
{
SizeT dicPos = p->decoder.dicPos;
if (p->state == LZMA2_STATE_ERROR)
return SZ_ERROR_DATA;
if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY)
{
*status = LZMA_STATUS_NOT_FINISHED;
return SZ_OK;
}
if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT)
{
if (*srcLen == inSize)
{
*status = LZMA_STATUS_NEEDS_MORE_INPUT;
return SZ_OK;
}
(*srcLen)++;
p->state = Lzma2Dec_UpdateState(p, *src++);
continue;
}
{
SizeT destSizeCur = dicLimit - dicPos;
SizeT srcSizeCur = inSize - *srcLen;
ELzmaFinishMode curFinishMode = LZMA_FINISH_ANY;
if (p->unpackSize <= destSizeCur)
{
destSizeCur = (SizeT)p->unpackSize;
curFinishMode = LZMA_FINISH_END;
}
if (LZMA2_IS_UNCOMPRESSED_STATE(p))
{
if (*srcLen == inSize)
{
*status = LZMA_STATUS_NEEDS_MORE_INPUT;
return SZ_OK;
}
if (p->state == LZMA2_STATE_DATA)
{
Bool initDic = (p->control == LZMA2_CONTROL_COPY_RESET_DIC);
if (initDic)
p->needInitProp = p->needInitState = True;
else if (p->needInitDic)
return SZ_ERROR_DATA;
p->needInitDic = False;
LzmaDec_InitDicAndState(&p->decoder, initDic, False);
}
if (srcSizeCur > destSizeCur)
srcSizeCur = destSizeCur;
if (srcSizeCur == 0)
return SZ_ERROR_DATA;
LzmaDec_UpdateWithUncompressed(&p->decoder, src, srcSizeCur);
src += srcSizeCur;
*srcLen += srcSizeCur;
p->unpackSize -= (UInt32)srcSizeCur;
p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT;
}
else
{
SizeT outSizeProcessed;
SRes res;
if (p->state == LZMA2_STATE_DATA)
{
int mode = LZMA2_GET_LZMA_MODE(p);
Bool initDic = (mode == 3);
Bool initState = (mode > 0);
if ((!initDic && p->needInitDic) || (!initState && p->needInitState))
return SZ_ERROR_DATA;
LzmaDec_InitDicAndState(&p->decoder, initDic, initState);
p->needInitDic = False;
p->needInitState = False;
p->state = LZMA2_STATE_DATA_CONT;
}
if (srcSizeCur > p->packSize)
srcSizeCur = (SizeT)p->packSize;
res = LzmaDec_DecodeToDic(&p->decoder, dicPos + destSizeCur, src, &srcSizeCur, curFinishMode, status);
src += srcSizeCur;
*srcLen += srcSizeCur;
p->packSize -= (UInt32)srcSizeCur;
outSizeProcessed = p->decoder.dicPos - dicPos;
p->unpackSize -= (UInt32)outSizeProcessed;
RINOK(res);
if (*status == LZMA_STATUS_NEEDS_MORE_INPUT)
return res;
if (srcSizeCur == 0 && outSizeProcessed == 0)
{
if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK ||
p->unpackSize != 0 || p->packSize != 0)
return SZ_ERROR_DATA;
p->state = LZMA2_STATE_CONTROL;
}
if (*status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)
*status = LZMA_STATUS_NOT_FINISHED;
}
}
}
*status = LZMA_STATUS_FINISHED_WITH_MARK;
return SZ_OK;
}
SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
{
SizeT outSize = *destLen, inSize = *srcLen;
*srcLen = *destLen = 0;
for (;;)
{
SizeT srcSizeCur = inSize, outSizeCur, dicPos;
ELzmaFinishMode curFinishMode;
SRes res;
if (p->decoder.dicPos == p->decoder.dicBufSize)
p->decoder.dicPos = 0;
dicPos = p->decoder.dicPos;
if (outSize > p->decoder.dicBufSize - dicPos)
{
outSizeCur = p->decoder.dicBufSize;
curFinishMode = LZMA_FINISH_ANY;
}
else
{
outSizeCur = dicPos + outSize;
curFinishMode = finishMode;
}
res = Lzma2Dec_DecodeToDic(p, outSizeCur, src, &srcSizeCur, curFinishMode, status);
src += srcSizeCur;
inSize -= srcSizeCur;
*srcLen += srcSizeCur;
outSizeCur = p->decoder.dicPos - dicPos;
memcpy(dest, p->decoder.dic + dicPos, outSizeCur);
dest += outSizeCur;
outSize -= outSizeCur;
*destLen += outSizeCur;
if (res != 0)
return res;
if (outSizeCur == 0 || outSize == 0)
return SZ_OK;
}
}
SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc)
{
CLzma2Dec decoder;
SRes res;
SizeT outSize = *destLen, inSize = *srcLen;
Byte props[LZMA_PROPS_SIZE];
Lzma2Dec_Construct(&decoder);
*destLen = *srcLen = 0;
*status = LZMA_STATUS_NOT_SPECIFIED;
decoder.decoder.dic = dest;
decoder.decoder.dicBufSize = outSize;
RINOK(Lzma2Dec_GetOldProps(prop, props));
RINOK(LzmaDec_AllocateProbs(&decoder.decoder, props, LZMA_PROPS_SIZE, alloc));
*srcLen = inSize;
res = Lzma2Dec_DecodeToDic(&decoder, outSize, src, srcLen, finishMode, status);
*destLen = decoder.decoder.dicPos;
if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)
res = SZ_ERROR_INPUT_EOF;
LzmaDec_FreeProbs(&decoder.decoder, alloc);
return res;
}

View File

@ -0,0 +1,84 @@
/* Lzma2Dec.h -- LZMA2 Decoder
2009-05-03 : Igor Pavlov : Public domain */
#ifndef __LZMA2_DEC_H
#define __LZMA2_DEC_H
#include "LzmaDec.h"
#ifdef __cplusplus
extern "C" {
#endif
/* ---------- State Interface ---------- */
typedef struct
{
CLzmaDec decoder;
UInt32 packSize;
UInt32 unpackSize;
int state;
Byte control;
Bool needInitDic;
Bool needInitState;
Bool needInitProp;
} CLzma2Dec;
#define Lzma2Dec_Construct(p) LzmaDec_Construct(&(p)->decoder)
#define Lzma2Dec_FreeProbs(p, alloc) LzmaDec_FreeProbs(&(p)->decoder, alloc);
#define Lzma2Dec_Free(p, alloc) LzmaDec_Free(&(p)->decoder, alloc);
SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAlloc *alloc);
SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAlloc *alloc);
void Lzma2Dec_Init(CLzma2Dec *p);
/*
finishMode:
It has meaning only if the decoding reaches output limit (*destLen or dicLimit).
LZMA_FINISH_ANY - use smallest number of input bytes
LZMA_FINISH_END - read EndOfStream marker after decoding
Returns:
SZ_OK
status:
LZMA_STATUS_FINISHED_WITH_MARK
LZMA_STATUS_NOT_FINISHED
LZMA_STATUS_NEEDS_MORE_INPUT
SZ_ERROR_DATA - Data error
*/
SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen,
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
/* ---------- One Call Interface ---------- */
/*
finishMode:
It has meaning only if the decoding reaches output limit (*destLen).
LZMA_FINISH_ANY - use smallest number of input bytes
LZMA_FINISH_END - read EndOfStream marker after decoding
Returns:
SZ_OK
status:
LZMA_STATUS_FINISHED_WITH_MARK
LZMA_STATUS_NOT_FINISHED
SZ_ERROR_DATA - Data error
SZ_ERROR_MEM - Memory allocation error
SZ_ERROR_UNSUPPORTED - Unsupported properties
SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
*/
SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,999 @@
/* LzmaDec.c -- LZMA Decoder
2009-09-20 : Igor Pavlov : Public domain */
#include "LzmaDec.h"
#include <string.h>
#define kNumTopBits 24
#define kTopValue ((UInt32)1 << kNumTopBits)
#define kNumBitModelTotalBits 11
#define kBitModelTotal (1 << kNumBitModelTotalBits)
#define kNumMoveBits 5
#define RC_INIT_SIZE 5
#define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); }
#define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
#define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));
#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits));
#define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \
{ UPDATE_0(p); i = (i + i); A0; } else \
{ UPDATE_1(p); i = (i + i) + 1; A1; }
#define GET_BIT(p, i) GET_BIT2(p, i, ; , ;)
#define TREE_GET_BIT(probs, i) { GET_BIT((probs + i), i); }
#define TREE_DECODE(probs, limit, i) \
{ i = 1; do { TREE_GET_BIT(probs, i); } while (i < limit); i -= limit; }
/* #define _LZMA_SIZE_OPT */
#ifdef _LZMA_SIZE_OPT
#define TREE_6_DECODE(probs, i) TREE_DECODE(probs, (1 << 6), i)
#else
#define TREE_6_DECODE(probs, i) \
{ i = 1; \
TREE_GET_BIT(probs, i); \
TREE_GET_BIT(probs, i); \
TREE_GET_BIT(probs, i); \
TREE_GET_BIT(probs, i); \
TREE_GET_BIT(probs, i); \
TREE_GET_BIT(probs, i); \
i -= 0x40; }
#endif
#define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); }
#define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
#define UPDATE_0_CHECK range = bound;
#define UPDATE_1_CHECK range -= bound; code -= bound;
#define GET_BIT2_CHECK(p, i, A0, A1) IF_BIT_0_CHECK(p) \
{ UPDATE_0_CHECK; i = (i + i); A0; } else \
{ UPDATE_1_CHECK; i = (i + i) + 1; A1; }
#define GET_BIT_CHECK(p, i) GET_BIT2_CHECK(p, i, ; , ;)
#define TREE_DECODE_CHECK(probs, limit, i) \
{ i = 1; do { GET_BIT_CHECK(probs + i, i) } while (i < limit); i -= limit; }
#define kNumPosBitsMax 4
#define kNumPosStatesMax (1 << kNumPosBitsMax)
#define kLenNumLowBits 3
#define kLenNumLowSymbols (1 << kLenNumLowBits)
#define kLenNumMidBits 3
#define kLenNumMidSymbols (1 << kLenNumMidBits)
#define kLenNumHighBits 8
#define kLenNumHighSymbols (1 << kLenNumHighBits)
#define LenChoice 0
#define LenChoice2 (LenChoice + 1)
#define LenLow (LenChoice2 + 1)
#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
#define kNumStates 12
#define kNumLitStates 7
#define kStartPosModelIndex 4
#define kEndPosModelIndex 14
#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
#define kNumPosSlotBits 6
#define kNumLenToPosStates 4
#define kNumAlignBits 4
#define kAlignTableSize (1 << kNumAlignBits)
#define kMatchMinLen 2
#define kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols)
#define IsMatch 0
#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
#define IsRepG0 (IsRep + kNumStates)
#define IsRepG1 (IsRepG0 + kNumStates)
#define IsRepG2 (IsRepG1 + kNumStates)
#define IsRep0Long (IsRepG2 + kNumStates)
#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
#define LenCoder (Align + kAlignTableSize)
#define RepLenCoder (LenCoder + kNumLenProbs)
#define Literal (RepLenCoder + kNumLenProbs)
#define LZMA_BASE_SIZE 1846
#define LZMA_LIT_SIZE 768
#define LzmaProps_GetNumProbs(p) ((UInt32)LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((p)->lc + (p)->lp)))
#if Literal != LZMA_BASE_SIZE
StopCompilingDueBUG
#endif
#define LZMA_DIC_MIN (1 << 12)
/* First LZMA-symbol is always decoded.
And it decodes new LZMA-symbols while (buf < bufLimit), but "buf" is without last normalization
Out:
Result:
SZ_OK - OK
SZ_ERROR_DATA - Error
p->remainLen:
< kMatchSpecLenStart : normal remain
= kMatchSpecLenStart : finished
= kMatchSpecLenStart + 1 : Flush marker
= kMatchSpecLenStart + 2 : State Init Marker
*/
static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte *bufLimit)
{
CLzmaProb *probs = p->probs;
unsigned state = p->state;
UInt32 rep0 = p->reps[0], rep1 = p->reps[1], rep2 = p->reps[2], rep3 = p->reps[3];
unsigned pbMask = ((unsigned)1 << (p->prop.pb)) - 1;
unsigned lpMask = ((unsigned)1 << (p->prop.lp)) - 1;
unsigned lc = p->prop.lc;
Byte *dic = p->dic;
SizeT dicBufSize = p->dicBufSize;
SizeT dicPos = p->dicPos;
UInt32 processedPos = p->processedPos;
UInt32 checkDicSize = p->checkDicSize;
unsigned len = 0;
const Byte *buf = p->buf;
UInt32 range = p->range;
UInt32 code = p->code;
do
{
CLzmaProb *prob;
UInt32 bound;
unsigned ttt;
unsigned posState = processedPos & pbMask;
prob = probs + IsMatch + (state << kNumPosBitsMax) + posState;
IF_BIT_0(prob)
{
unsigned symbol;
UPDATE_0(prob);
prob = probs + Literal;
if (checkDicSize != 0 || processedPos != 0)
prob += (LZMA_LIT_SIZE * (((processedPos & lpMask) << lc) +
(dic[(dicPos == 0 ? dicBufSize : dicPos) - 1] >> (8 - lc))));
if (state < kNumLitStates)
{
state -= (state < 4) ? state : 3;
symbol = 1;
do { GET_BIT(prob + symbol, symbol) } while (symbol < 0x100);
}
else
{
unsigned matchByte = p->dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];
unsigned offs = 0x100;
state -= (state < 10) ? 3 : 6;
symbol = 1;
do
{
unsigned bit;
CLzmaProb *probLit;
matchByte <<= 1;
bit = (matchByte & offs);
probLit = prob + offs + bit + symbol;
GET_BIT2(probLit, symbol, offs &= ~bit, offs &= bit)
}
while (symbol < 0x100);
}
dic[dicPos++] = (Byte)symbol;
processedPos++;
continue;
}
else
{
UPDATE_1(prob);
prob = probs + IsRep + state;
IF_BIT_0(prob)
{
UPDATE_0(prob);
state += kNumStates;
prob = probs + LenCoder;
}
else
{
UPDATE_1(prob);
if (checkDicSize == 0 && processedPos == 0)
return SZ_ERROR_DATA;
prob = probs + IsRepG0 + state;
IF_BIT_0(prob)
{
UPDATE_0(prob);
prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState;
IF_BIT_0(prob)
{
UPDATE_0(prob);
dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];
dicPos++;
processedPos++;
state = state < kNumLitStates ? 9 : 11;
continue;
}
UPDATE_1(prob);
}
else
{
UInt32 distance;
UPDATE_1(prob);
prob = probs + IsRepG1 + state;
IF_BIT_0(prob)
{
UPDATE_0(prob);
distance = rep1;
}
else
{
UPDATE_1(prob);
prob = probs + IsRepG2 + state;
IF_BIT_0(prob)
{
UPDATE_0(prob);
distance = rep2;
}
else
{
UPDATE_1(prob);
distance = rep3;
rep3 = rep2;
}
rep2 = rep1;
}
rep1 = rep0;
rep0 = distance;
}
state = state < kNumLitStates ? 8 : 11;
prob = probs + RepLenCoder;
}
{
unsigned limit, offset;
CLzmaProb *probLen = prob + LenChoice;
IF_BIT_0(probLen)
{
UPDATE_0(probLen);
probLen = prob + LenLow + (posState << kLenNumLowBits);
offset = 0;
limit = (1 << kLenNumLowBits);
}
else
{
UPDATE_1(probLen);
probLen = prob + LenChoice2;
IF_BIT_0(probLen)
{
UPDATE_0(probLen);
probLen = prob + LenMid + (posState << kLenNumMidBits);
offset = kLenNumLowSymbols;
limit = (1 << kLenNumMidBits);
}
else
{
UPDATE_1(probLen);
probLen = prob + LenHigh;
offset = kLenNumLowSymbols + kLenNumMidSymbols;
limit = (1 << kLenNumHighBits);
}
}
TREE_DECODE(probLen, limit, len);
len += offset;
}
if (state >= kNumStates)
{
UInt32 distance;
prob = probs + PosSlot +
((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits);
TREE_6_DECODE(prob, distance);
if (distance >= kStartPosModelIndex)
{
unsigned posSlot = (unsigned)distance;
int numDirectBits = (int)(((distance >> 1) - 1));
distance = (2 | (distance & 1));
if (posSlot < kEndPosModelIndex)
{
distance <<= numDirectBits;
prob = probs + SpecPos + distance - posSlot - 1;
{
UInt32 mask = 1;
unsigned i = 1;
do
{
GET_BIT2(prob + i, i, ; , distance |= mask);
mask <<= 1;
}
while (--numDirectBits != 0);
}
}
else
{
numDirectBits -= kNumAlignBits;
do
{
NORMALIZE
range >>= 1;
{
UInt32 t;
code -= range;
t = (0 - ((UInt32)code >> 31)); /* (UInt32)((Int32)code >> 31) */
distance = (distance << 1) + (t + 1);
code += range & t;
}
/*
distance <<= 1;
if (code >= range)
{
code -= range;
distance |= 1;
}
*/
}
while (--numDirectBits != 0);
prob = probs + Align;
distance <<= kNumAlignBits;
{
unsigned i = 1;
GET_BIT2(prob + i, i, ; , distance |= 1);
GET_BIT2(prob + i, i, ; , distance |= 2);
GET_BIT2(prob + i, i, ; , distance |= 4);
GET_BIT2(prob + i, i, ; , distance |= 8);
}
if (distance == (UInt32)0xFFFFFFFF)
{
len += kMatchSpecLenStart;
state -= kNumStates;
break;
}
}
}
rep3 = rep2;
rep2 = rep1;
rep1 = rep0;
rep0 = distance + 1;
if (checkDicSize == 0)
{
if (distance >= processedPos)
return SZ_ERROR_DATA;
}
else if (distance >= checkDicSize)
return SZ_ERROR_DATA;
state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3;
}
len += kMatchMinLen;
if (limit == dicPos)
return SZ_ERROR_DATA;
{
SizeT rem = limit - dicPos;
unsigned curLen = ((rem < len) ? (unsigned)rem : len);
SizeT pos = (dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0);
processedPos += curLen;
len -= curLen;
if (pos + curLen <= dicBufSize)
{
Byte *dest = dic + dicPos;
ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos;
const Byte *lim = dest + curLen;
dicPos += curLen;
do
*(dest) = (Byte)*(dest + src);
while (++dest != lim);
}
else
{
do
{
dic[dicPos++] = dic[pos];
if (++pos == dicBufSize)
pos = 0;
}
while (--curLen != 0);
}
}
}
}
while (dicPos < limit && buf < bufLimit);
NORMALIZE;
p->buf = buf;
p->range = range;
p->code = code;
p->remainLen = len;
p->dicPos = dicPos;
p->processedPos = processedPos;
p->reps[0] = rep0;
p->reps[1] = rep1;
p->reps[2] = rep2;
p->reps[3] = rep3;
p->state = state;
return SZ_OK;
}
static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit)
{
if (p->remainLen != 0 && p->remainLen < kMatchSpecLenStart)
{
Byte *dic = p->dic;
SizeT dicPos = p->dicPos;
SizeT dicBufSize = p->dicBufSize;
unsigned len = p->remainLen;
UInt32 rep0 = p->reps[0];
if (limit - dicPos < len)
len = (unsigned)(limit - dicPos);
if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len)
p->checkDicSize = p->prop.dicSize;
p->processedPos += len;
p->remainLen -= len;
while (len-- != 0)
{
dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];
dicPos++;
}
p->dicPos = dicPos;
}
}
static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit)
{
do
{
SizeT limit2 = limit;
if (p->checkDicSize == 0)
{
UInt32 rem = p->prop.dicSize - p->processedPos;
if (limit - p->dicPos > rem)
limit2 = p->dicPos + rem;
}
RINOK(LzmaDec_DecodeReal(p, limit2, bufLimit));
if (p->processedPos >= p->prop.dicSize)
p->checkDicSize = p->prop.dicSize;
LzmaDec_WriteRem(p, limit);
}
while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart);
if (p->remainLen > kMatchSpecLenStart)
{
p->remainLen = kMatchSpecLenStart;
}
return 0;
}
typedef enum
{
DUMMY_ERROR, /* unexpected end of input stream */
DUMMY_LIT,
DUMMY_MATCH,
DUMMY_REP
} ELzmaDummy;
static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inSize)
{
UInt32 range = p->range;
UInt32 code = p->code;
const Byte *bufLimit = buf + inSize;
CLzmaProb *probs = p->probs;
unsigned state = p->state;
ELzmaDummy res;
{
CLzmaProb *prob;
UInt32 bound;
unsigned ttt;
unsigned posState = (p->processedPos) & ((1 << p->prop.pb) - 1);
prob = probs + IsMatch + (state << kNumPosBitsMax) + posState;
IF_BIT_0_CHECK(prob)
{
UPDATE_0_CHECK
/* if (bufLimit - buf >= 7) return DUMMY_LIT; */
prob = probs + Literal;
if (p->checkDicSize != 0 || p->processedPos != 0)
prob += (LZMA_LIT_SIZE *
((((p->processedPos) & ((1 << (p->prop.lp)) - 1)) << p->prop.lc) +
(p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc))));
if (state < kNumLitStates)
{
unsigned symbol = 1;
do { GET_BIT_CHECK(prob + symbol, symbol) } while (symbol < 0x100);
}
else
{
unsigned matchByte = p->dic[p->dicPos - p->reps[0] +
((p->dicPos < p->reps[0]) ? p->dicBufSize : 0)];
unsigned offs = 0x100;
unsigned symbol = 1;
do
{
unsigned bit;
CLzmaProb *probLit;
matchByte <<= 1;
bit = (matchByte & offs);
probLit = prob + offs + bit + symbol;
GET_BIT2_CHECK(probLit, symbol, offs &= ~bit, offs &= bit)
}
while (symbol < 0x100);
}
res = DUMMY_LIT;
}
else
{
unsigned len;
UPDATE_1_CHECK;
prob = probs + IsRep + state;
IF_BIT_0_CHECK(prob)
{
UPDATE_0_CHECK;
state = 0;
prob = probs + LenCoder;
res = DUMMY_MATCH;
}
else
{
UPDATE_1_CHECK;
res = DUMMY_REP;
prob = probs + IsRepG0 + state;
IF_BIT_0_CHECK(prob)
{
UPDATE_0_CHECK;
prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState;
IF_BIT_0_CHECK(prob)
{
UPDATE_0_CHECK;
NORMALIZE_CHECK;
return DUMMY_REP;
}
else
{
UPDATE_1_CHECK;
}
}
else
{
UPDATE_1_CHECK;
prob = probs + IsRepG1 + state;
IF_BIT_0_CHECK(prob)
{
UPDATE_0_CHECK;
}
else
{
UPDATE_1_CHECK;
prob = probs + IsRepG2 + state;
IF_BIT_0_CHECK(prob)
{
UPDATE_0_CHECK;
}
else
{
UPDATE_1_CHECK;
}
}
}
state = kNumStates;
prob = probs + RepLenCoder;
}
{
unsigned limit, offset;
CLzmaProb *probLen = prob + LenChoice;
IF_BIT_0_CHECK(probLen)
{
UPDATE_0_CHECK;
probLen = prob + LenLow + (posState << kLenNumLowBits);
offset = 0;
limit = 1 << kLenNumLowBits;
}
else
{
UPDATE_1_CHECK;
probLen = prob + LenChoice2;
IF_BIT_0_CHECK(probLen)
{
UPDATE_0_CHECK;
probLen = prob + LenMid + (posState << kLenNumMidBits);
offset = kLenNumLowSymbols;
limit = 1 << kLenNumMidBits;
}
else
{
UPDATE_1_CHECK;
probLen = prob + LenHigh;
offset = kLenNumLowSymbols + kLenNumMidSymbols;
limit = 1 << kLenNumHighBits;
}
}
TREE_DECODE_CHECK(probLen, limit, len);
len += offset;
}
if (state < 4)
{
unsigned posSlot;
prob = probs + PosSlot +
((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
kNumPosSlotBits);
TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot);
if (posSlot >= kStartPosModelIndex)
{
int numDirectBits = ((posSlot >> 1) - 1);
/* if (bufLimit - buf >= 8) return DUMMY_MATCH; */
if (posSlot < kEndPosModelIndex)
{
prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits) - posSlot - 1;
}
else
{
numDirectBits -= kNumAlignBits;
do
{
NORMALIZE_CHECK
range >>= 1;
code -= range & (((code - range) >> 31) - 1);
/* if (code >= range) code -= range; */
}
while (--numDirectBits != 0);
prob = probs + Align;
numDirectBits = kNumAlignBits;
}
{
unsigned i = 1;
do
{
GET_BIT_CHECK(prob + i, i);
}
while (--numDirectBits != 0);
}
}
}
}
}
NORMALIZE_CHECK;
return res;
}
static void LzmaDec_InitRc(CLzmaDec *p, const Byte *data)
{
p->code = ((UInt32)data[1] << 24) | ((UInt32)data[2] << 16) | ((UInt32)data[3] << 8) | ((UInt32)data[4]);
p->range = 0xFFFFFFFF;
p->needFlush = 0;
}
void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState)
{
p->needFlush = 1;
p->remainLen = 0;
p->tempBufSize = 0;
if (initDic)
{
p->processedPos = 0;
p->checkDicSize = 0;
p->needInitState = 1;
}
if (initState)
p->needInitState = 1;
}
void LzmaDec_Init(CLzmaDec *p)
{
p->dicPos = 0;
LzmaDec_InitDicAndState(p, True, True);
}
static void LzmaDec_InitStateReal(CLzmaDec *p)
{
UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (p->prop.lc + p->prop.lp));
UInt32 i;
CLzmaProb *probs = p->probs;
for (i = 0; i < numProbs; i++)
probs[i] = kBitModelTotal >> 1;
p->reps[0] = p->reps[1] = p->reps[2] = p->reps[3] = 1;
p->state = 0;
p->needInitState = 0;
}
SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen,
ELzmaFinishMode finishMode, ELzmaStatus *status)
{
SizeT inSize = *srcLen;
(*srcLen) = 0;
LzmaDec_WriteRem(p, dicLimit);
*status = LZMA_STATUS_NOT_SPECIFIED;
while (p->remainLen != kMatchSpecLenStart)
{
int checkEndMarkNow;
if (p->needFlush != 0)
{
for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--)
p->tempBuf[p->tempBufSize++] = *src++;
if (p->tempBufSize < RC_INIT_SIZE)
{
*status = LZMA_STATUS_NEEDS_MORE_INPUT;
return SZ_OK;
}
if (p->tempBuf[0] != 0)
return SZ_ERROR_DATA;
LzmaDec_InitRc(p, p->tempBuf);
p->tempBufSize = 0;
}
checkEndMarkNow = 0;
if (p->dicPos >= dicLimit)
{
if (p->remainLen == 0 && p->code == 0)
{
*status = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK;
return SZ_OK;
}
if (finishMode == LZMA_FINISH_ANY)
{
*status = LZMA_STATUS_NOT_FINISHED;
return SZ_OK;
}
if (p->remainLen != 0)
{
*status = LZMA_STATUS_NOT_FINISHED;
return SZ_ERROR_DATA;
}
checkEndMarkNow = 1;
}
if (p->needInitState)
LzmaDec_InitStateReal(p);
if (p->tempBufSize == 0)
{
SizeT processed;
const Byte *bufLimit;
if (inSize < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)
{
int dummyRes = LzmaDec_TryDummy(p, src, inSize);
if (dummyRes == DUMMY_ERROR)
{
memcpy(p->tempBuf, src, inSize);
p->tempBufSize = (unsigned)inSize;
(*srcLen) += inSize;
*status = LZMA_STATUS_NEEDS_MORE_INPUT;
return SZ_OK;
}
if (checkEndMarkNow && dummyRes != DUMMY_MATCH)
{
*status = LZMA_STATUS_NOT_FINISHED;
return SZ_ERROR_DATA;
}
bufLimit = src;
}
else
bufLimit = src + inSize - LZMA_REQUIRED_INPUT_MAX;
p->buf = src;
if (LzmaDec_DecodeReal2(p, dicLimit, bufLimit) != 0)
return SZ_ERROR_DATA;
processed = (SizeT)(p->buf - src);
(*srcLen) += processed;
src += processed;
inSize -= processed;
}
else
{
unsigned rem = p->tempBufSize, lookAhead = 0;
while (rem < LZMA_REQUIRED_INPUT_MAX && lookAhead < inSize)
p->tempBuf[rem++] = src[lookAhead++];
p->tempBufSize = rem;
if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)
{
int dummyRes = LzmaDec_TryDummy(p, p->tempBuf, rem);
if (dummyRes == DUMMY_ERROR)
{
(*srcLen) += lookAhead;
*status = LZMA_STATUS_NEEDS_MORE_INPUT;
return SZ_OK;
}
if (checkEndMarkNow && dummyRes != DUMMY_MATCH)
{
*status = LZMA_STATUS_NOT_FINISHED;
return SZ_ERROR_DATA;
}
}
p->buf = p->tempBuf;
if (LzmaDec_DecodeReal2(p, dicLimit, p->buf) != 0)
return SZ_ERROR_DATA;
lookAhead -= (rem - (unsigned)(p->buf - p->tempBuf));
(*srcLen) += lookAhead;
src += lookAhead;
inSize -= lookAhead;
p->tempBufSize = 0;
}
}
if (p->code == 0)
*status = LZMA_STATUS_FINISHED_WITH_MARK;
return (p->code == 0) ? SZ_OK : SZ_ERROR_DATA;
}
SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
{
SizeT outSize = *destLen;
SizeT inSize = *srcLen;
*srcLen = *destLen = 0;
for (;;)
{
SizeT inSizeCur = inSize, outSizeCur, dicPos;
ELzmaFinishMode curFinishMode;
SRes res;
if (p->dicPos == p->dicBufSize)
p->dicPos = 0;
dicPos = p->dicPos;
if (outSize > p->dicBufSize - dicPos)
{
outSizeCur = p->dicBufSize;
curFinishMode = LZMA_FINISH_ANY;
}
else
{
outSizeCur = dicPos + outSize;
curFinishMode = finishMode;
}
res = LzmaDec_DecodeToDic(p, outSizeCur, src, &inSizeCur, curFinishMode, status);
src += inSizeCur;
inSize -= inSizeCur;
*srcLen += inSizeCur;
outSizeCur = p->dicPos - dicPos;
memcpy(dest, p->dic + dicPos, outSizeCur);
dest += outSizeCur;
outSize -= outSizeCur;
*destLen += outSizeCur;
if (res != 0)
return res;
if (outSizeCur == 0 || outSize == 0)
return SZ_OK;
}
}
void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc)
{
alloc->Free(alloc, p->probs);
p->probs = 0;
}
static void LzmaDec_FreeDict(CLzmaDec *p, ISzAlloc *alloc)
{
alloc->Free(alloc, p->dic);
p->dic = 0;
}
void LzmaDec_Free(CLzmaDec *p, ISzAlloc *alloc)
{
LzmaDec_FreeProbs(p, alloc);
LzmaDec_FreeDict(p, alloc);
}
SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size)
{
UInt32 dicSize;
Byte d;
if (size < LZMA_PROPS_SIZE)
return SZ_ERROR_UNSUPPORTED;
else
dicSize = data[1] | ((UInt32)data[2] << 8) | ((UInt32)data[3] << 16) | ((UInt32)data[4] << 24);
if (dicSize < LZMA_DIC_MIN)
dicSize = LZMA_DIC_MIN;
p->dicSize = dicSize;
d = data[0];
if (d >= (9 * 5 * 5))
return SZ_ERROR_UNSUPPORTED;
p->lc = d % 9;
d /= 9;
p->pb = d / 5;
p->lp = d % 5;
return SZ_OK;
}
static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAlloc *alloc)
{
UInt32 numProbs = LzmaProps_GetNumProbs(propNew);
if (p->probs == 0 || numProbs != p->numProbs)
{
LzmaDec_FreeProbs(p, alloc);
p->probs = (CLzmaProb *)alloc->Alloc(alloc, numProbs * sizeof(CLzmaProb));
p->numProbs = numProbs;
if (p->probs == 0)
return SZ_ERROR_MEM;
}
return SZ_OK;
}
SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc)
{
CLzmaProps propNew;
RINOK(LzmaProps_Decode(&propNew, props, propsSize));
RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc));
p->prop = propNew;
return SZ_OK;
}
SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc)
{
CLzmaProps propNew;
SizeT dicBufSize;
RINOK(LzmaProps_Decode(&propNew, props, propsSize));
RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc));
dicBufSize = propNew.dicSize;
if (p->dic == 0 || dicBufSize != p->dicBufSize)
{
LzmaDec_FreeDict(p, alloc);
p->dic = (Byte *)alloc->Alloc(alloc, dicBufSize);
if (p->dic == 0)
{
LzmaDec_FreeProbs(p, alloc);
return SZ_ERROR_MEM;
}
}
p->dicBufSize = dicBufSize;
p->prop = propNew;
return SZ_OK;
}
SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,
ELzmaStatus *status, ISzAlloc *alloc)
{
CLzmaDec p;
SRes res;
SizeT inSize = *srcLen;
SizeT outSize = *destLen;
*srcLen = *destLen = 0;
if (inSize < RC_INIT_SIZE)
return SZ_ERROR_INPUT_EOF;
LzmaDec_Construct(&p);
res = LzmaDec_AllocateProbs(&p, propData, propSize, alloc);
if (res != 0)
return res;
p.dic = dest;
p.dicBufSize = outSize;
LzmaDec_Init(&p);
*srcLen = inSize;
res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status);
if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)
res = SZ_ERROR_INPUT_EOF;
(*destLen) = p.dicPos;
LzmaDec_FreeProbs(&p, alloc);
return res;
}

View File

@ -0,0 +1,231 @@
/* LzmaDec.h -- LZMA Decoder
2009-02-07 : Igor Pavlov : Public domain */
#ifndef __LZMA_DEC_H
#define __LZMA_DEC_H
#include "Types.h"
#ifdef __cplusplus
extern "C" {
#endif
/* #define _LZMA_PROB32 */
/* _LZMA_PROB32 can increase the speed on some CPUs,
but memory usage for CLzmaDec::probs will be doubled in that case */
#ifdef _LZMA_PROB32
#define CLzmaProb UInt32
#else
#define CLzmaProb UInt16
#endif
/* ---------- LZMA Properties ---------- */
#define LZMA_PROPS_SIZE 5
typedef struct _CLzmaProps
{
unsigned lc, lp, pb;
UInt32 dicSize;
} CLzmaProps;
/* LzmaProps_Decode - decodes properties
Returns:
SZ_OK
SZ_ERROR_UNSUPPORTED - Unsupported properties
*/
SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size);
/* ---------- LZMA Decoder state ---------- */
/* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case.
Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */
#define LZMA_REQUIRED_INPUT_MAX 20
typedef struct
{
CLzmaProps prop;
CLzmaProb *probs;
Byte *dic;
const Byte *buf;
UInt32 range, code;
SizeT dicPos;
SizeT dicBufSize;
UInt32 processedPos;
UInt32 checkDicSize;
unsigned state;
UInt32 reps[4];
unsigned remainLen;
int needFlush;
int needInitState;
UInt32 numProbs;
unsigned tempBufSize;
Byte tempBuf[LZMA_REQUIRED_INPUT_MAX];
} CLzmaDec;
#define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; }
void LzmaDec_Init(CLzmaDec *p);
/* There are two types of LZMA streams:
0) Stream with end mark. That end mark adds about 6 bytes to compressed size.
1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */
typedef enum
{
LZMA_FINISH_ANY, /* finish at any point */
LZMA_FINISH_END /* block must be finished at the end */
} ELzmaFinishMode;
/* ELzmaFinishMode has meaning only if the decoding reaches output limit !!!
You must use LZMA_FINISH_END, when you know that current output buffer
covers last bytes of block. In other cases you must use LZMA_FINISH_ANY.
If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK,
and output value of destLen will be less than output buffer size limit.
You can check status result also.
You can use multiple checks to test data integrity after full decompression:
1) Check Result and "status" variable.
2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize.
3) Check that output(srcLen) = compressedSize, if you know real compressedSize.
You must use correct finish mode in that case. */
typedef enum
{
LZMA_STATUS_NOT_SPECIFIED, /* use main error code instead */
LZMA_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */
LZMA_STATUS_NOT_FINISHED, /* stream was not finished */
LZMA_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK /* there is probability that stream was finished without end mark */
} ELzmaStatus;
/* ELzmaStatus is used only as output value for function call */
/* ---------- Interfaces ---------- */
/* There are 3 levels of interfaces:
1) Dictionary Interface
2) Buffer Interface
3) One Call Interface
You can select any of these interfaces, but don't mix functions from different
groups for same object. */
/* There are two variants to allocate state for Dictionary Interface:
1) LzmaDec_Allocate / LzmaDec_Free
2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs
You can use variant 2, if you set dictionary buffer manually.
For Buffer Interface you must always use variant 1.
LzmaDec_Allocate* can return:
SZ_OK
SZ_ERROR_MEM - Memory allocation error
SZ_ERROR_UNSUPPORTED - Unsupported properties
*/
SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc);
void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc);
SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc);
void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc);
/* ---------- Dictionary Interface ---------- */
/* You can use it, if you want to eliminate the overhead for data copying from
dictionary to some other external buffer.
You must work with CLzmaDec variables directly in this interface.
STEPS:
LzmaDec_Constr()
LzmaDec_Allocate()
for (each new stream)
{
LzmaDec_Init()
while (it needs more decompression)
{
LzmaDec_DecodeToDic()
use data from CLzmaDec::dic and update CLzmaDec::dicPos
}
}
LzmaDec_Free()
*/
/* LzmaDec_DecodeToDic
The decoding to internal dictionary buffer (CLzmaDec::dic).
You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!!
finishMode:
It has meaning only if the decoding reaches output limit (dicLimit).
LZMA_FINISH_ANY - Decode just dicLimit bytes.
LZMA_FINISH_END - Stream must be finished after dicLimit.
Returns:
SZ_OK
status:
LZMA_STATUS_FINISHED_WITH_MARK
LZMA_STATUS_NOT_FINISHED
LZMA_STATUS_NEEDS_MORE_INPUT
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
SZ_ERROR_DATA - Data error
*/
SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit,
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
/* ---------- Buffer Interface ---------- */
/* It's zlib-like interface.
See LzmaDec_DecodeToDic description for information about STEPS and return results,
but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need
to work with CLzmaDec variables manually.
finishMode:
It has meaning only if the decoding reaches output limit (*destLen).
LZMA_FINISH_ANY - Decode just destLen bytes.
LZMA_FINISH_END - Stream must be finished after (*destLen).
*/
SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen,
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
/* ---------- One Call Interface ---------- */
/* LzmaDecode
finishMode:
It has meaning only if the decoding reaches output limit (*destLen).
LZMA_FINISH_ANY - Decode just destLen bytes.
LZMA_FINISH_END - Stream must be finished after (*destLen).
Returns:
SZ_OK
status:
LZMA_STATUS_FINISHED_WITH_MARK
LZMA_STATUS_NOT_FINISHED
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
SZ_ERROR_DATA - Data error
SZ_ERROR_MEM - Memory allocation error
SZ_ERROR_UNSUPPORTED - Unsupported properties
SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
*/
SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,
ELzmaStatus *status, ISzAlloc *alloc);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,81 @@
/* Ppmd.h -- PPMD codec common code
2010-03-12 : Igor Pavlov : Public domain
This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
#ifndef __PPMD_H
#define __PPMD_H
#include "Types.h"
#include "CpuArch.h"
EXTERN_C_BEGIN
#ifdef MY_CPU_32BIT
#define PPMD_32BIT
#endif
#define PPMD_INT_BITS 7
#define PPMD_PERIOD_BITS 7
#define PPMD_BIN_SCALE (1 << (PPMD_INT_BITS + PPMD_PERIOD_BITS))
#define PPMD_GET_MEAN_SPEC(summ, shift, round) (((summ) + (1 << ((shift) - (round)))) >> (shift))
#define PPMD_GET_MEAN(summ) PPMD_GET_MEAN_SPEC((summ), PPMD_PERIOD_BITS, 2)
#define PPMD_UPDATE_PROB_0(prob) ((prob) + (1 << PPMD_INT_BITS) - PPMD_GET_MEAN(prob))
#define PPMD_UPDATE_PROB_1(prob) ((prob) - PPMD_GET_MEAN(prob))
#define PPMD_N1 4
#define PPMD_N2 4
#define PPMD_N3 4
#define PPMD_N4 ((128 + 3 - 1 * PPMD_N1 - 2 * PPMD_N2 - 3 * PPMD_N3) / 4)
#define PPMD_NUM_INDEXES (PPMD_N1 + PPMD_N2 + PPMD_N3 + PPMD_N4)
/* SEE-contexts for PPM-contexts with masked symbols */
typedef struct
{
UInt16 Summ; /* Freq */
Byte Shift; /* Speed of Freq change; low Shift is for fast change */
Byte Count; /* Count to next change of Shift */
} CPpmd_See;
#define Ppmd_See_Update(p) if ((p)->Shift < PPMD_PERIOD_BITS && --(p)->Count == 0) \
{ (p)->Summ <<= 1; (p)->Count = (Byte)(3 << (p)->Shift++); }
typedef struct
{
Byte Symbol;
Byte Freq;
UInt16 SuccessorLow;
UInt16 SuccessorHigh;
} CPpmd_State;
typedef
#ifdef PPMD_32BIT
CPpmd_State *
#else
UInt32
#endif
CPpmd_State_Ref;
typedef
#ifdef PPMD_32BIT
void *
#else
UInt32
#endif
CPpmd_Void_Ref;
typedef
#ifdef PPMD_32BIT
Byte *
#else
UInt32
#endif
CPpmd_Byte_Ref;
#define PPMD_SetAllBitsIn256Bytes(p) \
{ unsigned i; for (i = 0; i < 256 / sizeof(p[0]); i += 8) { \
p[i+7] = p[i+6] = p[i+5] = p[i+4] = p[i+3] = p[i+2] = p[i+1] = p[i+0] = ~(size_t)0; }}
EXTERN_C_END
#endif

View File

@ -0,0 +1,708 @@
/* Ppmd7.c -- PPMdH codec
2010-03-12 : Igor Pavlov : Public domain
This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
#include <memory.h>
#include "Ppmd7.h"
const Byte PPMD7_kExpEscape[16] = { 25, 14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 };
static const UInt16 kInitBinEsc[] = { 0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x5ABC, 0x6632, 0x6051};
#define MAX_FREQ 124
#define UNIT_SIZE 12
#define U2B(nu) ((UInt32)(nu) * UNIT_SIZE)
#define U2I(nu) (p->Units2Indx[(nu) - 1])
#define I2U(indx) (p->Indx2Units[indx])
#ifdef PPMD_32BIT
#define REF(ptr) (ptr)
#else
#define REF(ptr) ((UInt32)((Byte *)(ptr) - (p)->Base))
#endif
#define STATS_REF(ptr) ((CPpmd_State_Ref)REF(ptr))
#define CTX(ref) ((CPpmd7_Context *)Ppmd7_GetContext(p, ref))
#define STATS(ctx) Ppmd7_GetStats(p, ctx)
#define ONE_STATE(ctx) Ppmd7Context_OneState(ctx)
#define SUFFIX(ctx) CTX((ctx)->Suffix)
typedef CPpmd7_Context * CTX_PTR;
struct CPpmd7_Node_;
typedef
#ifdef PPMD_32BIT
struct CPpmd7_Node_ *
#else
UInt32
#endif
CPpmd7_Node_Ref;
typedef struct CPpmd7_Node_
{
UInt16 Stamp; /* must be at offset 0 as CPpmd7_Context::NumStats. Stamp=0 means free */
UInt16 NU;
CPpmd7_Node_Ref Next; /* must be at offset >= 4 */
CPpmd7_Node_Ref Prev;
} CPpmd7_Node;
#ifdef PPMD_32BIT
#define NODE(ptr) (ptr)
#else
#define NODE(offs) ((CPpmd7_Node *)(p->Base + (offs)))
#endif
void Ppmd7_Construct(CPpmd7 *p)
{
unsigned i, k, m;
p->Base = 0;
for (i = 0, k = 0; i < PPMD_NUM_INDEXES; i++)
{
unsigned step = (i >= 12 ? 4 : (i >> 2) + 1);
do { p->Units2Indx[k++] = (Byte)i; } while(--step);
p->Indx2Units[i] = (Byte)k;
}
p->NS2BSIndx[0] = (0 << 1);
p->NS2BSIndx[1] = (1 << 1);
memset(p->NS2BSIndx + 2, (2 << 1), 9);
memset(p->NS2BSIndx + 11, (3 << 1), 256 - 11);
for (i = 0; i < 3; i++)
p->NS2Indx[i] = (Byte)i;
for (m = i, k = 1; i < 256; i++)
{
p->NS2Indx[i] = (Byte)m;
if (--k == 0)
k = (++m) - 2;
}
memset(p->HB2Flag, 0, 0x40);
memset(p->HB2Flag + 0x40, 8, 0x100 - 0x40);
}
void Ppmd7_Free(CPpmd7 *p, ISzAlloc *alloc)
{
alloc->Free(alloc, p->Base);
p->Size = 0;
p->Base = 0;
}
Bool Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAlloc *alloc)
{
if (p->Base == 0 || p->Size != size)
{
Ppmd7_Free(p, alloc);
p->AlignOffset =
#ifdef PPMD_32BIT
(4 - size) & 3;
#else
4 - (size & 3);
#endif
if ((p->Base = (Byte *)alloc->Alloc(alloc, p->AlignOffset + size
#ifndef PPMD_32BIT
+ UNIT_SIZE
#endif
)) == 0)
return False;
p->Size = size;
}
return True;
}
static void InsertNode(CPpmd7 *p, void *node, unsigned indx)
{
*((CPpmd_Void_Ref *)node) = p->FreeList[indx];
p->FreeList[indx] = REF(node);
}
static void *RemoveNode(CPpmd7 *p, unsigned indx)
{
CPpmd_Void_Ref *node = (CPpmd_Void_Ref *)Ppmd7_GetPtr(p, p->FreeList[indx]);
p->FreeList[indx] = *node;
return node;
}
static void SplitBlock(CPpmd7 *p, void *ptr, unsigned oldIndx, unsigned newIndx)
{
unsigned i, nu = I2U(oldIndx) - I2U(newIndx);
ptr = (Byte *)ptr + U2B(I2U(newIndx));
if (I2U(i = U2I(nu)) != nu)
{
unsigned k = I2U(--i);
InsertNode(p, ((Byte *)ptr) + U2B(k), nu - k - 1);
}
InsertNode(p, ptr, i);
}
static void GlueFreeBlocks(CPpmd7 *p)
{
#ifdef PPMD_32BIT
CPpmd7_Node headItem;
CPpmd7_Node_Ref head = &headItem;
#else
CPpmd7_Node_Ref head = p->AlignOffset + p->Size;
#endif
CPpmd7_Node_Ref n = head;
unsigned i;
p->GlueCount = 255;
/* create doubly-linked list of free blocks */
for (i = 0; i < PPMD_NUM_INDEXES; i++)
{
UInt16 nu = I2U(i);
CPpmd7_Node_Ref next = (CPpmd7_Node_Ref)p->FreeList[i];
p->FreeList[i] = 0;
while (next != 0)
{
CPpmd7_Node *node = NODE(next);
node->Next = n;
n = NODE(n)->Prev = next;
next = *(const CPpmd7_Node_Ref *)node;
node->Stamp = 0;
node->NU = (UInt16)nu;
}
}
NODE(head)->Stamp = 1;
NODE(head)->Next = n;
NODE(n)->Prev = head;
if (p->LoUnit != p->HiUnit)
((CPpmd7_Node *)p->LoUnit)->Stamp = 1;
/* Glue free blocks */
while (n != head)
{
CPpmd7_Node *node = NODE(n);
UInt32 nu = (UInt32)node->NU;
for (;;)
{
CPpmd7_Node *node2 = NODE(n) + nu;
nu += node2->NU;
if (node2->Stamp != 0 || nu >= 0x10000)
break;
NODE(node2->Prev)->Next = node2->Next;
NODE(node2->Next)->Prev = node2->Prev;
node->NU = (UInt16)nu;
}
n = node->Next;
}
/* Fill lists of free blocks */
for (n = NODE(head)->Next; n != head;)
{
CPpmd7_Node *node = NODE(n);
unsigned nu;
CPpmd7_Node_Ref next = node->Next;
for (nu = node->NU; nu > 128; nu -= 128, node += 128)
InsertNode(p, node, PPMD_NUM_INDEXES - 1);
if (I2U(i = U2I(nu)) != nu)
{
unsigned k = I2U(--i);
InsertNode(p, node + k, nu - k - 1);
}
InsertNode(p, node, i);
n = next;
}
}
static void *AllocUnitsRare(CPpmd7 *p, unsigned indx)
{
unsigned i;
void *retVal;
if (p->GlueCount == 0)
{
GlueFreeBlocks(p);
if (p->FreeList[indx] != 0)
return RemoveNode(p, indx);
}
i = indx;
do
{
if (++i == PPMD_NUM_INDEXES)
{
UInt32 numBytes = U2B(I2U(indx));
p->GlueCount--;
return ((UInt32)(p->UnitsStart - p->Text) > numBytes) ? (p->UnitsStart -= numBytes) : (NULL);
}
}
while (p->FreeList[i] == 0);
retVal = RemoveNode(p, i);
SplitBlock(p, retVal, i, indx);
return retVal;
}
static void *AllocUnits(CPpmd7 *p, unsigned indx)
{
UInt32 numBytes;
if (p->FreeList[indx] != 0)
return RemoveNode(p, indx);
numBytes = U2B(I2U(indx));
if (numBytes <= (UInt32)(p->HiUnit - p->LoUnit))
{
void *retVal = p->LoUnit;
p->LoUnit += numBytes;
return retVal;
}
return AllocUnitsRare(p, indx);
}
#define MyMem12Cpy(dest, src, num) \
{ UInt32 *d = (UInt32 *)dest; const UInt32 *s = (const UInt32 *)src; UInt32 n = num; \
do { d[0] = s[0]; d[1] = s[1]; d[2] = s[2]; s += 3; d += 3; } while(--n); }
static void *ShrinkUnits(CPpmd7 *p, void *oldPtr, unsigned oldNU, unsigned newNU)
{
unsigned i0 = U2I(oldNU);
unsigned i1 = U2I(newNU);
if (i0 == i1)
return oldPtr;
if (p->FreeList[i1] != 0)
{
void *ptr = RemoveNode(p, i1);
MyMem12Cpy(ptr, oldPtr, newNU);
InsertNode(p, oldPtr, i0);
return ptr;
}
SplitBlock(p, oldPtr, i0, i1);
return oldPtr;
}
#define SUCCESSOR(p) ((CPpmd_Void_Ref)((p)->SuccessorLow | ((UInt32)(p)->SuccessorHigh << 16)))
static void SetSuccessor(CPpmd_State *p, CPpmd_Void_Ref v)
{
(p)->SuccessorLow = (UInt16)((UInt32)(v) & 0xFFFF);
(p)->SuccessorHigh = (UInt16)(((UInt32)(v) >> 16) & 0xFFFF);
}
static void RestartModel(CPpmd7 *p)
{
unsigned i, k, m;
memset(p->FreeList, 0, sizeof(p->FreeList));
p->Text = p->Base + p->AlignOffset;
p->HiUnit = p->Text + p->Size;
p->LoUnit = p->UnitsStart = p->HiUnit - p->Size / 8 / UNIT_SIZE * 7 * UNIT_SIZE;
p->GlueCount = 0;
p->OrderFall = p->MaxOrder;
p->RunLength = p->InitRL = -(Int32)((p->MaxOrder < 12) ? p->MaxOrder : 12) - 1;
p->PrevSuccess = 0;
p->MinContext = p->MaxContext = (CTX_PTR)(p->HiUnit -= UNIT_SIZE); /* AllocContext(p); */
p->MinContext->Suffix = 0;
p->MinContext->NumStats = 256;
p->MinContext->SummFreq = 256 + 1;
p->FoundState = (CPpmd_State *)p->LoUnit; /* AllocUnits(p, PPMD_NUM_INDEXES - 1); */
p->LoUnit += U2B(256 / 2);
p->MinContext->Stats = REF(p->FoundState);
for (i = 0; i < 256; i++)
{
CPpmd_State *s = &p->FoundState[i];
s->Symbol = (Byte)i;
s->Freq = 1;
SetSuccessor(s, 0);
}
for (i = 0; i < 128; i++)
for (k = 0; k < 8; k++)
{
UInt16 *dest = p->BinSumm[i] + k;
UInt16 val = (UInt16)(PPMD_BIN_SCALE - kInitBinEsc[k] / (i + 2));
for (m = 0; m < 64; m += 8)
dest[m] = val;
}
for (i = 0; i < 25; i++)
for (k = 0; k < 16; k++)
{
CPpmd_See *s = &p->See[i][k];
s->Summ = (UInt16)((5 * i + 10) << (s->Shift = PPMD_PERIOD_BITS - 4));
s->Count = 4;
}
}
void Ppmd7_Init(CPpmd7 *p, unsigned maxOrder)
{
p->MaxOrder = maxOrder;
RestartModel(p);
p->DummySee.Shift = PPMD_PERIOD_BITS;
p->DummySee.Summ = 0; /* unused */
p->DummySee.Count = 64; /* unused */
}
static CTX_PTR CreateSuccessors(CPpmd7 *p, Bool skip)
{
CPpmd_State upState;
CTX_PTR c = p->MinContext;
CPpmd_Byte_Ref upBranch = (CPpmd_Byte_Ref)SUCCESSOR(p->FoundState);
CPpmd_State *ps[PPMD7_MAX_ORDER];
unsigned numPs = 0;
if (!skip)
ps[numPs++] = p->FoundState;
while (c->Suffix)
{
CPpmd_Void_Ref successor;
CPpmd_State *s;
c = SUFFIX(c);
if (c->NumStats != 1)
{
for (s = STATS(c); s->Symbol != p->FoundState->Symbol; s++);
}
else
s = ONE_STATE(c);
successor = SUCCESSOR(s);
if (successor != upBranch)
{
c = CTX(successor);
if (numPs == 0)
return c;
break;
}
ps[numPs++] = s;
}
upState.Symbol = *(const Byte *)Ppmd7_GetPtr(p, upBranch);
SetSuccessor(&upState, upBranch + 1);
if (c->NumStats == 1)
upState.Freq = ONE_STATE(c)->Freq;
else
{
UInt32 cf, s0;
CPpmd_State *s;
for (s = STATS(c); s->Symbol != upState.Symbol; s++);
cf = s->Freq - 1;
s0 = c->SummFreq - c->NumStats - cf;
upState.Freq = (Byte)(1 + ((2 * cf <= s0) ? (5 * cf > s0) : ((2 * cf + 3 * s0 - 1) / (2 * s0))));
}
do
{
/* Create Child */
CTX_PTR c1; /* = AllocContext(p); */
if (p->HiUnit != p->LoUnit)
c1 = (CTX_PTR)(p->HiUnit -= UNIT_SIZE);
else if (p->FreeList[0] != 0)
c1 = (CTX_PTR)RemoveNode(p, 0);
else
{
c1 = (CTX_PTR)AllocUnitsRare(p, 0);
if (!c1)
return NULL;
}
c1->NumStats = 1;
*ONE_STATE(c1) = upState;
c1->Suffix = REF(c);
SetSuccessor(ps[--numPs], REF(c1));
c = c1;
}
while (numPs != 0);
return c;
}
static void SwapStates(CPpmd_State *t1, CPpmd_State *t2)
{
CPpmd_State tmp = *t1;
*t1 = *t2;
*t2 = tmp;
}
static void UpdateModel(CPpmd7 *p)
{
CPpmd_Void_Ref successor, fSuccessor = SUCCESSOR(p->FoundState);
CTX_PTR c;
unsigned s0, ns;
if (p->FoundState->Freq < MAX_FREQ / 4 && p->MinContext->Suffix != 0)
{
c = SUFFIX(p->MinContext);
if (c->NumStats == 1)
{
CPpmd_State *s = ONE_STATE(c);
if (s->Freq < 32)
s->Freq++;
}
else
{
CPpmd_State *s = STATS(c);
if (s->Symbol != p->FoundState->Symbol)
{
do { s++; } while (s->Symbol != p->FoundState->Symbol);
if (s[0].Freq >= s[-1].Freq)
{
SwapStates(&s[0], &s[-1]);
s--;
}
}
if (s->Freq < MAX_FREQ - 9)
{
s->Freq += 2;
c->SummFreq += 2;
}
}
}
if (p->OrderFall == 0)
{
p->MinContext = p->MaxContext = CreateSuccessors(p, True);
if (p->MinContext == 0)
{
RestartModel(p);
return;
}
SetSuccessor(p->FoundState, REF(p->MinContext));
return;
}
*p->Text++ = p->FoundState->Symbol;
successor = REF(p->Text);
if (p->Text >= p->UnitsStart)
{
RestartModel(p);
return;
}
if (fSuccessor)
{
if (fSuccessor <= successor)
{
CTX_PTR cs = CreateSuccessors(p, False);
if (cs == NULL)
{
RestartModel(p);
return;
}
fSuccessor = REF(cs);
}
if (--p->OrderFall == 0)
{
successor = fSuccessor;
p->Text -= (p->MaxContext != p->MinContext);
}
}
else
{
SetSuccessor(p->FoundState, successor);
fSuccessor = REF(p->MinContext);
}
s0 = p->MinContext->SummFreq - (ns = p->MinContext->NumStats) - (p->FoundState->Freq - 1);
for (c = p->MaxContext; c != p->MinContext; c = SUFFIX(c))
{
unsigned ns1;
UInt32 cf, sf;
if ((ns1 = c->NumStats) != 1)
{
if ((ns1 & 1) == 0)
{
/* Expand for one UNIT */
unsigned oldNU = ns1 >> 1;
unsigned i = U2I(oldNU);
if (i != U2I(oldNU + 1))
{
void *ptr = AllocUnits(p, i + 1);
void *oldPtr;
if (!ptr)
{
RestartModel(p);
return;
}
oldPtr = STATS(c);
MyMem12Cpy(ptr, oldPtr, oldNU);
InsertNode(p, oldPtr, i);
c->Stats = STATS_REF(ptr);
}
}
c->SummFreq = (UInt16)(c->SummFreq + (2 * ns1 < ns) + 2 * ((4 * ns1 <= ns) & (c->SummFreq <= 8 * ns1)));
}
else
{
CPpmd_State *s = (CPpmd_State*)AllocUnits(p, 0);
if (!s)
{
RestartModel(p);
return;
}
*s = *ONE_STATE(c);
c->Stats = REF(s);
if (s->Freq < MAX_FREQ / 4 - 1)
s->Freq <<= 1;
else
s->Freq = MAX_FREQ - 4;
c->SummFreq = (UInt16)(s->Freq + p->InitEsc + (ns > 3));
}
cf = 2 * (UInt32)p->FoundState->Freq * (c->SummFreq + 6);
sf = (UInt32)s0 + c->SummFreq;
if (cf < 6 * sf)
{
cf = 1 + (cf > sf) + (cf >= 4 * sf);
c->SummFreq += 3;
}
else
{
cf = 4 + (cf >= 9 * sf) + (cf >= 12 * sf) + (cf >= 15 * sf);
c->SummFreq = (UInt16)(c->SummFreq + cf);
}
{
CPpmd_State *s = STATS(c) + ns1;
SetSuccessor(s, successor);
s->Symbol = p->FoundState->Symbol;
s->Freq = (Byte)cf;
c->NumStats = (UInt16)(ns1 + 1);
}
}
p->MaxContext = p->MinContext = CTX(fSuccessor);
}
static void Rescale(CPpmd7 *p)
{
unsigned i, adder, sumFreq, escFreq;
CPpmd_State *stats = STATS(p->MinContext);
CPpmd_State *s = p->FoundState;
{
CPpmd_State tmp = *s;
for (; s != stats; s--)
s[0] = s[-1];
*s = tmp;
}
escFreq = p->MinContext->SummFreq - s->Freq;
s->Freq += 4;
adder = (p->OrderFall != 0);
s->Freq = (Byte)((s->Freq + adder) >> 1);
sumFreq = s->Freq;
i = p->MinContext->NumStats - 1;
do
{
escFreq -= (++s)->Freq;
s->Freq = (Byte)((s->Freq + adder) >> 1);
sumFreq += s->Freq;
if (s[0].Freq > s[-1].Freq)
{
CPpmd_State *s1 = s;
CPpmd_State tmp = *s1;
do
s1[0] = s1[-1];
while (--s1 != stats && tmp.Freq > s1[-1].Freq);
*s1 = tmp;
}
}
while (--i);
if (s->Freq == 0)
{
unsigned numStats = p->MinContext->NumStats;
unsigned n0, n1;
do { i++; } while ((--s)->Freq == 0);
escFreq += i;
p->MinContext->NumStats = (UInt16)(p->MinContext->NumStats - i);
if (p->MinContext->NumStats == 1)
{
CPpmd_State tmp = *stats;
do
{
tmp.Freq = (Byte)(tmp.Freq - (tmp.Freq >> 1));
escFreq >>= 1;
}
while (escFreq > 1);
InsertNode(p, stats, U2I(((numStats + 1) >> 1)));
*(p->FoundState = ONE_STATE(p->MinContext)) = tmp;
return;
}
n0 = (numStats + 1) >> 1;
n1 = (p->MinContext->NumStats + 1) >> 1;
if (n0 != n1)
p->MinContext->Stats = STATS_REF(ShrinkUnits(p, stats, n0, n1));
}
p->MinContext->SummFreq = (UInt16)(sumFreq + escFreq - (escFreq >> 1));
p->FoundState = STATS(p->MinContext);
}
CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *escFreq)
{
CPpmd_See *see;
unsigned nonMasked = p->MinContext->NumStats - numMasked;
if (p->MinContext->NumStats != 256)
{
see = p->See[p->NS2Indx[nonMasked - 1]] +
(nonMasked < (unsigned)SUFFIX(p->MinContext)->NumStats - p->MinContext->NumStats) +
2 * (p->MinContext->SummFreq < 11 * p->MinContext->NumStats) +
4 * (numMasked > nonMasked) +
p->HiBitsFlag;
{
unsigned r = (see->Summ >> see->Shift);
see->Summ = (UInt16)(see->Summ - r);
*escFreq = r + (r == 0);
}
}
else
{
see = &p->DummySee;
*escFreq = 1;
}
return see;
}
static void NextContext(CPpmd7 *p)
{
CTX_PTR c = CTX(SUCCESSOR(p->FoundState));
if (p->OrderFall == 0 && (Byte *)c > p->Text)
p->MinContext = p->MaxContext = c;
else
UpdateModel(p);
}
void Ppmd7_Update1(CPpmd7 *p)
{
CPpmd_State *s = p->FoundState;
s->Freq += 4;
p->MinContext->SummFreq += 4;
if (s[0].Freq > s[-1].Freq)
{
SwapStates(&s[0], &s[-1]);
p->FoundState = --s;
if (s->Freq > MAX_FREQ)
Rescale(p);
}
NextContext(p);
}
void Ppmd7_Update1_0(CPpmd7 *p)
{
p->PrevSuccess = (2 * p->FoundState->Freq > p->MinContext->SummFreq);
p->RunLength += p->PrevSuccess;
p->MinContext->SummFreq += 4;
if ((p->FoundState->Freq += 4) > MAX_FREQ)
Rescale(p);
NextContext(p);
}
void Ppmd7_UpdateBin(CPpmd7 *p)
{
p->FoundState->Freq = (Byte)(p->FoundState->Freq + (p->FoundState->Freq < 128 ? 1: 0));
p->PrevSuccess = 1;
p->RunLength++;
NextContext(p);
}
void Ppmd7_Update2(CPpmd7 *p)
{
p->MinContext->SummFreq += 4;
if ((p->FoundState->Freq += 4) > MAX_FREQ)
Rescale(p);
p->RunLength = p->InitRL;
UpdateModel(p);
}

View File

@ -0,0 +1,140 @@
/* Ppmd7.h -- PPMdH compression codec
2010-03-12 : Igor Pavlov : Public domain
This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
/* This code supports virtual RangeDecoder and includes the implementation
of RangeCoder from 7z, instead of RangeCoder from original PPMd var.H.
If you need the compatibility with original PPMd var.H, you can use external RangeDecoder */
#ifndef __PPMD7_H
#define __PPMD7_H
#include "Ppmd.h"
EXTERN_C_BEGIN
#define PPMD7_MIN_ORDER 2
#define PPMD7_MAX_ORDER 64
#define PPMD7_MIN_MEM_SIZE (1 << 11)
#define PPMD7_MAX_MEM_SIZE (0xFFFFFFFF - 12 * 3)
struct CPpmd7_Context_;
typedef
#ifdef PPMD_32BIT
struct CPpmd7_Context_ *
#else
UInt32
#endif
CPpmd7_Context_Ref;
typedef struct CPpmd7_Context_
{
UInt16 NumStats;
UInt16 SummFreq;
CPpmd_State_Ref Stats;
CPpmd7_Context_Ref Suffix;
} CPpmd7_Context;
#define Ppmd7Context_OneState(p) ((CPpmd_State *)&(p)->SummFreq)
typedef struct
{
CPpmd7_Context *MinContext, *MaxContext;
CPpmd_State *FoundState;
unsigned OrderFall, InitEsc, PrevSuccess, MaxOrder, HiBitsFlag;
Int32 RunLength, InitRL; /* must be 32-bit at least */
UInt32 Size;
UInt32 GlueCount;
Byte *Base, *LoUnit, *HiUnit, *Text, *UnitsStart;
UInt32 AlignOffset;
Byte Indx2Units[PPMD_NUM_INDEXES];
Byte Units2Indx[128];
CPpmd_Void_Ref FreeList[PPMD_NUM_INDEXES];
Byte NS2Indx[256], NS2BSIndx[256], HB2Flag[256];
CPpmd_See DummySee, See[25][16];
UInt16 BinSumm[128][64];
} CPpmd7;
void Ppmd7_Construct(CPpmd7 *p);
Bool Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAlloc *alloc);
void Ppmd7_Free(CPpmd7 *p, ISzAlloc *alloc);
void Ppmd7_Init(CPpmd7 *p, unsigned maxOrder);
#define Ppmd7_WasAllocated(p) ((p)->Base != NULL)
/* ---------- Internal Functions ---------- */
extern const Byte PPMD7_kExpEscape[16];
#ifdef PPMD_32BIT
#define Ppmd7_GetPtr(p, ptr) (ptr)
#define Ppmd7_GetContext(p, ptr) (ptr)
#define Ppmd7_GetStats(p, ctx) ((ctx)->Stats)
#else
#define Ppmd7_GetPtr(p, offs) ((void *)((p)->Base + (offs)))
#define Ppmd7_GetContext(p, offs) ((CPpmd7_Context *)Ppmd7_GetPtr((p), (offs)))
#define Ppmd7_GetStats(p, ctx) ((CPpmd_State *)Ppmd7_GetPtr((p), ((ctx)->Stats)))
#endif
void Ppmd7_Update1(CPpmd7 *p);
void Ppmd7_Update1_0(CPpmd7 *p);
void Ppmd7_Update2(CPpmd7 *p);
void Ppmd7_UpdateBin(CPpmd7 *p);
#define Ppmd7_GetBinSumm(p) \
&p->BinSumm[Ppmd7Context_OneState(p->MinContext)->Freq - 1][p->PrevSuccess + \
p->NS2BSIndx[Ppmd7_GetContext(p, p->MinContext->Suffix)->NumStats - 1] + \
(p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol]) + \
2 * p->HB2Flag[Ppmd7Context_OneState(p->MinContext)->Symbol] + \
((p->RunLength >> 26) & 0x20)]
CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *scale);
/* ---------- Decode ---------- */
typedef struct
{
UInt32 (*GetThreshold)(void *p, UInt32 total);
void (*Decode)(void *p, UInt32 start, UInt32 size);
UInt32 (*DecodeBit)(void *p, UInt32 size0);
} IPpmd7_RangeDec;
typedef struct
{
IPpmd7_RangeDec p;
UInt32 Range;
UInt32 Code;
IByteIn *Stream;
} CPpmd7z_RangeDec;
void Ppmd7z_RangeDec_CreateVTable(CPpmd7z_RangeDec *p);
Bool Ppmd7z_RangeDec_Init(CPpmd7z_RangeDec *p);
#define Ppmd7z_RangeDec_IsFinishedOK(p) ((p)->Code == 0)
int Ppmd7_DecodeSymbol(CPpmd7 *p, IPpmd7_RangeDec *rc);
/* ---------- Encode ---------- */
typedef struct
{
UInt64 Low;
UInt32 Range;
Byte Cache;
UInt64 CacheSize;
IByteOut *Stream;
} CPpmd7z_RangeEnc;
void Ppmd7z_RangeEnc_Init(CPpmd7z_RangeEnc *p);
void Ppmd7z_RangeEnc_FlushData(CPpmd7z_RangeEnc *p);
void Ppmd7_EncodeSymbol(CPpmd7 *p, CPpmd7z_RangeEnc *rc, int symbol);
EXTERN_C_END
#endif

View File

@ -0,0 +1,187 @@
/* Ppmd7Dec.c -- PPMdH Decoder
2010-03-12 : Igor Pavlov : Public domain
This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
#include "Ppmd7.h"
#define kTopValue (1 << 24)
Bool Ppmd7z_RangeDec_Init(CPpmd7z_RangeDec *p)
{
unsigned i;
p->Code = 0;
p->Range = 0xFFFFFFFF;
if (p->Stream->Read((void *)p->Stream) != 0)
return False;
for (i = 0; i < 4; i++)
p->Code = (p->Code << 8) | p->Stream->Read((void *)p->Stream);
return (p->Code < 0xFFFFFFFF);
}
static UInt32 Range_GetThreshold(void *pp, UInt32 total)
{
CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp;
return (p->Code) / (p->Range /= total);
}
static void Range_Normalize(CPpmd7z_RangeDec *p)
{
if (p->Range < kTopValue)
{
p->Code = (p->Code << 8) | p->Stream->Read((void *)p->Stream);
p->Range <<= 8;
if (p->Range < kTopValue)
{
p->Code = (p->Code << 8) | p->Stream->Read((void *)p->Stream);
p->Range <<= 8;
}
}
}
static void Range_Decode(void *pp, UInt32 start, UInt32 size)
{
CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp;
p->Code -= start * p->Range;
p->Range *= size;
Range_Normalize(p);
}
static UInt32 Range_DecodeBit(void *pp, UInt32 size0)
{
CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp;
UInt32 newBound = (p->Range >> 14) * size0;
UInt32 symbol;
if (p->Code < newBound)
{
symbol = 0;
p->Range = newBound;
}
else
{
symbol = 1;
p->Code -= newBound;
p->Range -= newBound;
}
Range_Normalize(p);
return symbol;
}
void Ppmd7z_RangeDec_CreateVTable(CPpmd7z_RangeDec *p)
{
p->p.GetThreshold = Range_GetThreshold;
p->p.Decode = Range_Decode;
p->p.DecodeBit = Range_DecodeBit;
}
#define MASK(sym) ((signed char *)charMask)[sym]
int Ppmd7_DecodeSymbol(CPpmd7 *p, IPpmd7_RangeDec *rc)
{
size_t charMask[256 / sizeof(size_t)];
if (p->MinContext->NumStats != 1)
{
CPpmd_State *s = Ppmd7_GetStats(p, p->MinContext);
unsigned i;
UInt32 count, hiCnt;
if ((count = rc->GetThreshold(rc, p->MinContext->SummFreq)) < (hiCnt = s->Freq))
{
Byte symbol;
rc->Decode(rc, 0, s->Freq);
p->FoundState = s;
symbol = s->Symbol;
Ppmd7_Update1_0(p);
return symbol;
}
p->PrevSuccess = 0;
i = p->MinContext->NumStats - 1;
do
{
if ((hiCnt += (++s)->Freq) > count)
{
Byte symbol;
rc->Decode(rc, hiCnt - s->Freq, s->Freq);
p->FoundState = s;
symbol = s->Symbol;
Ppmd7_Update1(p);
return symbol;
}
}
while (--i);
if (count >= p->MinContext->SummFreq)
return -2;
p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol];
rc->Decode(rc, hiCnt, p->MinContext->SummFreq - hiCnt);
PPMD_SetAllBitsIn256Bytes(charMask);
MASK(s->Symbol) = 0;
i = p->MinContext->NumStats - 1;
do { MASK((--s)->Symbol) = 0; } while (--i);
}
else
{
UInt16 *prob = Ppmd7_GetBinSumm(p);
if (rc->DecodeBit(rc, *prob) == 0)
{
Byte symbol;
*prob = (UInt16)PPMD_UPDATE_PROB_0(*prob);
symbol = (p->FoundState = Ppmd7Context_OneState(p->MinContext))->Symbol;
Ppmd7_UpdateBin(p);
return symbol;
}
*prob = (UInt16)PPMD_UPDATE_PROB_1(*prob);
p->InitEsc = PPMD7_kExpEscape[*prob >> 10];
PPMD_SetAllBitsIn256Bytes(charMask);
MASK(Ppmd7Context_OneState(p->MinContext)->Symbol) = 0;
p->PrevSuccess = 0;
}
for (;;)
{
CPpmd_State *ps[256], *s;
UInt32 freqSum, count, hiCnt;
CPpmd_See *see;
unsigned i, num, numMasked = p->MinContext->NumStats;
do
{
p->OrderFall++;
if (!p->MinContext->Suffix)
return -1;
p->MinContext = Ppmd7_GetContext(p, p->MinContext->Suffix);
}
while (p->MinContext->NumStats == numMasked);
hiCnt = 0;
s = Ppmd7_GetStats(p, p->MinContext);
i = 0;
num = p->MinContext->NumStats - numMasked;
do
{
int k = (int)(MASK(s->Symbol));
hiCnt += (s->Freq & k);
ps[i] = s++;
i -= k;
}
while (i != num);
see = Ppmd7_MakeEscFreq(p, numMasked, &freqSum);
freqSum += hiCnt;
count = rc->GetThreshold(rc, freqSum);
if (count < hiCnt)
{
Byte symbol;
CPpmd_State **pps = ps;
for (hiCnt = 0; (hiCnt += (*pps)->Freq) <= count; pps++);
s = *pps;
rc->Decode(rc, hiCnt - s->Freq, s->Freq);
Ppmd_See_Update(see);
p->FoundState = s;
symbol = s->Symbol;
Ppmd7_Update2(p);
return symbol;
}
if (count >= freqSum)
return -2;
rc->Decode(rc, hiCnt, freqSum - hiCnt);
see->Summ = (UInt16)(see->Summ + freqSum);
do { MASK(ps[--i]->Symbol) = 0; } while (i != 0);
}
}

View File

@ -0,0 +1,254 @@
/* Types.h -- Basic types
2010-10-09 : Igor Pavlov : Public domain */
#ifndef __7Z_TYPES_H
#define __7Z_TYPES_H
#include <stddef.h>
#ifdef _WIN32
#include <windows.h>
#endif
#ifndef EXTERN_C_BEGIN
#ifdef __cplusplus
#define EXTERN_C_BEGIN extern "C" {
#define EXTERN_C_END }
#else
#define EXTERN_C_BEGIN
#define EXTERN_C_END
#endif
#endif
EXTERN_C_BEGIN
#define SZ_OK 0
#define SZ_ERROR_DATA 1
#define SZ_ERROR_MEM 2
#define SZ_ERROR_CRC 3
#define SZ_ERROR_UNSUPPORTED 4
#define SZ_ERROR_PARAM 5
#define SZ_ERROR_INPUT_EOF 6
#define SZ_ERROR_OUTPUT_EOF 7
#define SZ_ERROR_READ 8
#define SZ_ERROR_WRITE 9
#define SZ_ERROR_PROGRESS 10
#define SZ_ERROR_FAIL 11
#define SZ_ERROR_THREAD 12
#define SZ_ERROR_ARCHIVE 16
#define SZ_ERROR_NO_ARCHIVE 17
typedef int SRes;
#ifdef _WIN32
typedef DWORD WRes;
#else
typedef int WRes;
#endif
#ifndef RINOK
#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; }
#endif
typedef unsigned char Byte;
typedef short Int16;
typedef unsigned short UInt16;
#ifdef _LZMA_UINT32_IS_ULONG
typedef long Int32;
typedef unsigned long UInt32;
#else
typedef int Int32;
typedef unsigned int UInt32;
#endif
#ifdef _SZ_NO_INT_64
/* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers.
NOTES: Some code will work incorrectly in that case! */
typedef long Int64;
typedef unsigned long UInt64;
#else
#if defined(_MSC_VER) || defined(__BORLANDC__)
typedef __int64 Int64;
typedef unsigned __int64 UInt64;
#define UINT64_CONST(n) n
#else
typedef long long int Int64;
typedef unsigned long long int UInt64;
#define UINT64_CONST(n) n ## ULL
#endif
#endif
#ifdef _LZMA_NO_SYSTEM_SIZE_T
typedef UInt32 SizeT;
#else
typedef size_t SizeT;
#endif
typedef int Bool;
#define True 1
#define False 0
#ifdef _WIN32
#define MY_STD_CALL __stdcall
#else
#define MY_STD_CALL
#endif
#ifdef _MSC_VER
#if _MSC_VER >= 1300
#define MY_NO_INLINE __declspec(noinline)
#else
#define MY_NO_INLINE
#endif
#define MY_CDECL __cdecl
#define MY_FAST_CALL __fastcall
#else
#define MY_CDECL
#define MY_FAST_CALL
#endif
/* The following interfaces use first parameter as pointer to structure */
typedef struct
{
Byte (*Read)(void *p); /* reads one byte, returns 0 in case of EOF or error */
} IByteIn;
typedef struct
{
void (*Write)(void *p, Byte b);
} IByteOut;
typedef struct
{
SRes (*Read)(void *p, void *buf, size_t *size);
/* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
(output(*size) < input(*size)) is allowed */
} ISeqInStream;
/* it can return SZ_ERROR_INPUT_EOF */
SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size);
SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType);
SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf);
typedef struct
{
size_t (*Write)(void *p, const void *buf, size_t size);
/* Returns: result - the number of actually written bytes.
(result < size) means error */
} ISeqOutStream;
typedef enum
{
SZ_SEEK_SET = 0,
SZ_SEEK_CUR = 1,
SZ_SEEK_END = 2
} ESzSeek;
typedef struct
{
SRes (*Read)(void *p, void *buf, size_t *size); /* same as ISeqInStream::Read */
SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin);
} ISeekInStream;
typedef struct
{
SRes (*Look)(void *p, const void **buf, size_t *size);
/* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
(output(*size) > input(*size)) is not allowed
(output(*size) < input(*size)) is allowed */
SRes (*Skip)(void *p, size_t offset);
/* offset must be <= output(*size) of Look */
SRes (*Read)(void *p, void *buf, size_t *size);
/* reads directly (without buffer). It's same as ISeqInStream::Read */
SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin);
} ILookInStream;
SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size);
SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset);
/* reads via ILookInStream::Read */
SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType);
SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size);
#define LookToRead_BUF_SIZE (1 << 14)
typedef struct
{
ILookInStream s;
ISeekInStream *realStream;
size_t pos;
size_t size;
Byte buf[LookToRead_BUF_SIZE];
} CLookToRead;
void LookToRead_CreateVTable(CLookToRead *p, int lookahead);
void LookToRead_Init(CLookToRead *p);
typedef struct
{
ISeqInStream s;
ILookInStream *realStream;
} CSecToLook;
void SecToLook_CreateVTable(CSecToLook *p);
typedef struct
{
ISeqInStream s;
ILookInStream *realStream;
} CSecToRead;
void SecToRead_CreateVTable(CSecToRead *p);
typedef struct
{
SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize);
/* Returns: result. (result != SZ_OK) means break.
Value (UInt64)(Int64)-1 for size means unknown value. */
} ICompressProgress;
typedef struct
{
void *(*Alloc)(void *p, size_t size);
void (*Free)(void *p, void *address); /* address can be 0 */
} ISzAlloc;
#define IAlloc_Alloc(p, size) (p)->Alloc((p), size)
#define IAlloc_Free(p, a) (p)->Free((p), a)
#ifdef _WIN32
#define CHAR_PATH_SEPARATOR '\\'
#define WCHAR_PATH_SEPARATOR L'\\'
#define STRING_PATH_SEPARATOR "\\"
#define WSTRING_PATH_SEPARATOR L"\\"
#else
#define CHAR_PATH_SEPARATOR '/'
#define WCHAR_PATH_SEPARATOR L'/'
#define STRING_PATH_SEPARATOR "/"
#define WSTRING_PATH_SEPARATOR L"/"
#endif
EXTERN_C_END
#endif

View File

@ -0,0 +1,106 @@
//
// 僶乕僕儑儞僟僀傾儘僌僋儔僗
//
//
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <shellapi.h>
#include <string>
using namespace std;
#include "VirtuaNESres.h"
#include "DebugOut.h"
#include "App.h"
#include "Pathlib.h"
#include "Wnd.h"
#include "AboutDlg.h"
DLG_MESSAGE_BEGIN(CAboutDlg)
DLG_ON_MESSAGE( WM_INITDIALOG, OnInitDialog )
DLG_COMMAND_BEGIN()
DLG_ON_COMMAND( IDOK, OnOK )
DLG_ON_COMMAND( IDCANCEL, OnCancel )
DLG_ON_COMMAND( IDC_VER_WEBSITE, OnWebsite )
DLG_COMMAND_END()
DLG_MESSAGE_END()
INT CAboutDlg::DoModal( HWND hWndParent )
{
return ::DialogBoxParam( CApp::GetPlugin(), MAKEINTRESOURCE(IDD_VERSION),
hWndParent, g_DlgProc, (LPARAM)this );
}
DLGMSG CAboutDlg::OnInitDialog( DLGMSGPARAM )
{
// DEBUGOUT( "CAboutDlg::OnInitDialog\n" );
::SendDlgItemMessage( m_hWnd, IDC_VER_ICON, STM_SETICON,
(WPARAM)CApp::LoadIcon( IDI_ICON ), 0 );
TCHAR str[256];
::wsprintf( str, "VirtuaNESex version %01d.%01d%01d%s",
(VIRTUANES_VERSION&0xF00)>>8,
(VIRTUANES_VERSION&0x0F0)>>4,
(VIRTUANES_VERSION&0x00F),
VIRTUANES_FIXVERSION );
::SetDlgItemText( m_hWnd, IDC_VER_VERSION, str );
::wsprintf( str,
"编译时间:\r\n\
%s %s\r\n\r\n\
\r\n\
tpu \r\n\
temryu \r\n\
byemu \r\n\
\r\n\
",
__DATE__,__TIME__);
::SetDlgItemText( m_hWnd, IDC_VER_CONTRIBUTOR, str );
// ::SetDlgItemText( m_hWnd, IDC_VER_WEBSITE, VIRTUANES_WEBSITE );
m_Website.Attach( ::GetDlgItem( m_hWnd, IDC_VER_WEBSITE ), VIRTUANES_WEBSITE );
string email, mailto;
email = VIRTUANES_EMAILNAME;
email += "@";
email += VIRTUANES_EMAILDOMAIN;
mailto = "mailto:" + email;
m_Email.Attach( ::GetDlgItem( m_hWnd, IDC_VER_EMAIL ), email.c_str(), mailto.c_str() );
return TRUE;
}
DLGCMD CAboutDlg::OnOK( DLGCMDPARAM )
{
// DEBUGOUT( "CAboutDlg::OnOK\n" );
// m_Website.Detach();
// m_Email.Detach();
::EndDialog( m_hWnd, IDOK );
}
DLGCMD CAboutDlg::OnCancel( DLGCMDPARAM )
{
// DEBUGOUT( "CAboutDlg::OnCancel\n" );
// m_Website.Detach();
// m_Email.Detach();
::EndDialog( m_hWnd, IDCANCEL );
}
DLGCMD CAboutDlg::OnWebsite( DLGCMDPARAM )
{
// DEBUGOUT( "CAboutDlg::OnCancel\n" );
::ShellExecute( HWND_DESKTOP, "open", VIRTUANES_WEBSITE, NULL, NULL, SW_SHOWNORMAL );
// ::ShellExecute( m_hWnd, "open", VIRTUANES_WEBSITE, NULL, NULL, SW_SHOWNORMAL );
}

View File

@ -0,0 +1,36 @@
//
// バージョンダイアログクラス
//
#ifndef __CABOUTDLG_INCLUDED__
#define __CABOUTDLG_INCLUDED__
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <string>
using namespace std;
#include "Wnd.h"
#include "CHyperLink.h"
class CAboutDlg : public CWnd
{
public:
// Override from CWnd
INT DoModal( HWND hWndParent );
protected:
// Message map
DLG_MESSAGE_MAP()
DLGMSG OnInitDialog( DLGMSGPARAM );
DLGCMD OnOK( DLGCMDPARAM );
DLGCMD OnCancel( DLGCMDPARAM );
DLGCMD OnWebsite( DLGCMDPARAM );
//
CHyperLink m_Website;
CHyperLink m_Email;
private:
};
#endif // !__CABOUTDLG_INCLUDED__

View File

@ -0,0 +1,81 @@
//
// アプリケーションサポートクラス
//
#include "VirtuaNESres.h"
#include "App.h"
// _tWinMainからの引数そのまま
HINSTANCE CApp::m_hInstance = NULL;
HINSTANCE CApp::m_hPrevInstance = NULL;
LPTSTR CApp::m_lpCmdLine = NULL;
INT CApp::m_nCmdShow = 0;
// 言語リソースプラグインのインスタンスハンドル
HINSTANCE CApp::m_hPlugin = NULL;
// メインウインドウのウインドウハンドル
HWND CApp::m_hWnd = NULL;
// メインウインドウのメニューハンドル
HMENU CApp::m_hMenu = NULL;
// プログラムのパス(起動時のパス)
CHAR CApp::m_szModulePath[_MAX_PATH];
// エラーストリング(テンポラリ)
CHAR szErrorString[256];
// エラー処理用
INT CApp::m_ErrorStringTableID[] = {
IDS_ERROR,
IDS_ERROR_STARTUP,
IDS_ERROR_UNKNOWN,
IDS_ERROR_OPEN,
IDS_ERROR_READ,
IDS_ERROR_WRITE,
IDS_ERROR_OUTOFMEMORY,
IDS_ERROR_ILLEGALOPCODE,
IDS_ERROR_UNSUPPORTFORMAT,
IDS_ERROR_INVALIDNESHEADER,
IDS_ERROR_SMALLFILE,
IDS_ERROR_UNSUPPORTMAPPER,
IDS_ERROR_NODISKBIOS,
IDS_ERROR_UNSUPPORTDISK,
IDS_ERROR_ILLEGALDISKSIZE,
IDS_ERROR_ILLEGALMAPPERNO,
IDS_ERROR_ILLEGALHEADER,
IDS_ERROR_ILLEGALSTATECRC,
IDS_ERROR_ILLEGALMOVIEOLD,
IDS_ERROR_ILLEGALMOVIEVER,
IDS_ERROR_ILLEGALMOVIECRC,
IDS_ERROR_ILLEGALMOVIEOLD_A,
IDS_ERROR_ILLEGALMOVIEVER_A,
IDS_ERROR_ILLEGALMOVIECRC_A,
IDS_ERROR_NETWORKDISCONNECT,
IDS_ERROR_NETWORKERROR,
0,
};
CHAR CApp::m_ErrorString[ERRORSTRING_MAX][256];
void CApp::LoadErrorString()
{
if( !m_hPlugin )
return;
for( INT i = 0; m_ErrorStringTableID[i]; i++ ) {
LoadString( m_ErrorStringTableID[i], m_ErrorString[i], sizeof(m_ErrorString[i]) );
}
}
CHAR* CApp::GetErrorString( INT nID )
{
for( INT i = 0; m_ErrorStringTableID[i]; i++ ) {
if( m_ErrorStringTableID[i] == nID )
return m_ErrorString[i];
}
return ""; // NULL ストリングとして渡す
}

View File

@ -0,0 +1,76 @@
//
// アプリケーションサポートクラス
//
#ifndef __CAPP_INCLUDED__
#define __CAPP_INCLUDED__
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#define ERRORSTRING_MAX 32
class CApp {
public:
// 起動時に設定する
static void SetInstance( HINSTANCE hInstance ) { m_hInstance = hInstance; }
static void SetPrevInstance( HINSTANCE hInstance ) { m_hPrevInstance = hInstance; }
static void SetCmdLine( LPSTR lpCmdLine ) { m_lpCmdLine = lpCmdLine; }
static void SetCmdShow( INT nCmdShow ) { m_nCmdShow = nCmdShow; }
static void SetHWnd( HWND hWnd ) { m_hWnd = hWnd; }
static void SetMenu( HMENU hMenu ) { m_hMenu = hMenu; }
static void SetPlugin( HINSTANCE hPlugin ) { m_hPlugin = hPlugin; LoadErrorString(); }
static void SetModulePath( LPCSTR lpModulePath ) { ::strcpy( m_szModulePath, lpModulePath ); }
// アプリ内部で使用する
static HINSTANCE GetInstance() { return m_hInstance; }
static HINSTANCE GetPrevInstance() { return m_hPrevInstance; }
static LPTSTR GetCmdLine() { return m_lpCmdLine; }
static INT GetCmdShow() { return m_nCmdShow; }
static HWND GetHWnd() { return m_hWnd; }
static HMENU GetMenu() { return m_hMenu; }
static HINSTANCE GetPlugin() { return m_hPlugin; }
static LPCSTR GetModulePath() { return m_szModulePath; }
static HMENU LoadMenu( UINT uID ) { return ::LoadMenu( m_hPlugin, MAKEINTRESOURCE(uID) ); }
static HICON LoadIcon( UINT uID ) { return ::LoadIcon( m_hInstance, MAKEINTRESOURCE(uID) ); }
static INT LoadString( UINT uID, LPTSTR lpBuffer, INT nBufferMax ) {
return ::LoadString( m_hPlugin, uID, lpBuffer, nBufferMax ); }
// エラー処理用
static void LoadErrorString();
static CHAR* GetErrorString( INT nID );
protected:
// WinMain からの引数そのまま
static HINSTANCE m_hInstance;
static HINSTANCE m_hPrevInstance;
static LPSTR m_lpCmdLine;
static INT m_nCmdShow;
// 言語リソースプラグインのインスタンスハンドル
static HINSTANCE m_hPlugin;
// メインウインドウのウインドウハンドル
static HWND m_hWnd;
// メインウインドウのメニューハンドル
static HMENU m_hMenu;
// プログラムのパス(起動時のパス)
static CHAR m_szModulePath[_MAX_PATH];
// エラー処理用
static INT m_ErrorStringTableID[ERRORSTRING_MAX];
static CHAR m_ErrorString[ERRORSTRING_MAX][256];
private:
};
// エラーメッセージ用テンポラリ
extern CHAR szErrorString[256];
#endif // !__CAPP_INCLUDED__

View File

@ -0,0 +1,332 @@
//
// アーカイブファイル操作
//
// Original:NesterJ arc.cpp arc.h by Mikami Kana
// Original:NNNesterJ ulunzip.cpp
//
// Zlib use!
// Reprogrammed by Norix
//
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <shlwapi.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mbstring.h>
#include <time.h>
#include "typedef.h"
#include "macro.h"
#include "DebugOut.h"
#include "App.h"
#include "Pathlib.h"
#include "VirtuaNESres.h"
#define UNZ_BUFSIZE (65536)
#include "unzip.h"
#ifdef __cplusplus
extern "C" {
#endif
int SevenZipUnCompress( char *fname, unsigned char ** ppBuf,size_t * lpdwSize);
#ifdef __cplusplus
}
#endif
#pragma pack(1)
#define FNAME_MAX32 512
typedef struct {
DWORD dwOriginalSize;
DWORD dwCompressedSize;
DWORD dwCRC;
UINT uFlag;
UINT uOSType;
WORD wRatio;
WORD wDate;
WORD wTime;
char szFileName[FNAME_MAX32 + 1];
char dummy1[3];
char szAttribute[8];
char szMode[8];
} INDIVIDUALINFO, *LPINDIVIDUALINFO;
#pragma pack()
// Un??? use function
typedef int(WINAPI *EXECUTECOMMAND)(HWND,LPCSTR,LPSTR,const DWORD);
typedef BOOL(WINAPI *CHECKARCHIVE)(LPCSTR,const int);
typedef int(WINAPI *EXTRACTMEM)(HWND,LPCSTR,LPBYTE,const DWORD,time_t,LPWORD,LPDWORD);
typedef HGLOBAL(WINAPI *OPENARCHIVE)(HWND,LPCSTR,const DWORD);
typedef int(WINAPI *CLOSEARCHIVE)(HGLOBAL);
typedef int(WINAPI *FINDFIRST)(HGLOBAL,LPCSTR,INDIVIDUALINFO*);
static LPCSTR pszArchiver[] = {
"UNLHA32",
"UNZIP32",
"UNRAR32",
"CAB32",
NULL
};
static LPCSTR pszFuncPrefix[] = {
"Unlha",
"UnZip",
"Unrar",
"Cab",
};
static LPCSTR pszCommand[] = {
NULL,
NULL,
"-e -u \"%s\" \"%s\" \"%s\"",
"-x -j \"%s\" \"%s\" \"%s\"",
};
static LPCSTR pszExtension[] = {
"*.nes",
"*.fds",
"*.nsf",
NULL
};
static BOOL bFileMatching[] = {
FALSE,
TRUE,
FALSE,
FALSE,
};
#define FREEDLL(h) if( h ) { FreeLibrary(h);h=NULL; }
#define M_ERROR_MESSAGE_OFF 0x00800000L
// zlibを使用したZIP解凍ルーチン
BOOL ZlibUnZip( LPCSTR fname, LPBYTE* ppBuf, LPDWORD lpdwSize )
{
unzFile unzipFile = NULL;
unz_global_info unzipGlobalInfo;
unz_file_info unzipFileInfo;
char fname_buf[256];
*ppBuf = NULL;
*lpdwSize = 0;
if( !(unzipFile = unzOpen( (const char*)fname )) )
return FALSE;
if( unzGetGlobalInfo( unzipFile, &unzipGlobalInfo ) != UNZ_OK ) {
unzClose( unzipFile );
return FALSE;
}
for( uLong i = 0; i < unzipGlobalInfo.number_entry; i++ ) {
if( unzGetCurrentFileInfo( unzipFile, &unzipFileInfo, fname_buf, sizeof(fname_buf), NULL, 0, NULL, 0 ) != UNZ_OK )
break;
char* pExt = ::PathFindExtension( fname_buf );
if( _stricmp( pExt, ".nes" ) == 0 || _stricmp( pExt, ".fds" ) == 0 || _stricmp( pExt, ".nsf" ) == 0 ) {
if( unzipFileInfo.uncompressed_size ) {
if( unzOpenCurrentFile( unzipFile ) != UNZ_OK )
break;
if( unzipFileInfo.uncompressed_size > 0 ) {
if( !(*ppBuf = (LPBYTE)::malloc( unzipFileInfo.uncompressed_size )) )
break;
uInt size = unzReadCurrentFile( unzipFile, *ppBuf, unzipFileInfo.uncompressed_size );
if( size != unzipFileInfo.uncompressed_size )
break;
}
*lpdwSize = unzipFileInfo.uncompressed_size;
if( unzCloseCurrentFile( unzipFile ) != UNZ_OK )
break;
unzClose( unzipFile );
return TRUE;
}
}
// Next file
if( (i+1) < unzipGlobalInfo.number_entry ) {
if( unzGoToNextFile( unzipFile ) != UNZ_OK ) {
break;
}
}
}
FREE( *ppBuf );
if( unzipFile ) {
unzCloseCurrentFile( unzipFile );
unzClose( unzipFile );
}
return FALSE;
}
BOOL UnCompress( LPCSTR fname, LPBYTE* ppBuf, LPDWORD lpdwSize )
{
HMODULE hDLL;
INDIVIDUALINFO idvinfo;
char* pExt = ::PathFindExtension( fname );
if( _stricmp( pExt, ".zip" ) == 0 ) {
// ZIPならまずzlibライブラリの解凍を使ってみる
if( ZlibUnZip( fname, ppBuf, lpdwSize ) ) {
// DEBUGOUT( "zlib unzip ok! [%s]\n", fname );
return TRUE;
}
} else if( _stricmp( pExt, ".7z" ) == 0 ) {
return SevenZipUnCompress((char*)fname, ppBuf, (size_t*)lpdwSize);
}
hDLL = NULL;
for( INT i = 0; pszArchiver[i]; i++ ) {
// DLLアンロード
FREEDLL( hDLL );
// DLLロード
if( !(hDLL = LoadLibrary( pszArchiver[i] )) )
continue;
CHAR szTemp[256];
sprintf( szTemp, "%sCheckArchive", pszFuncPrefix[i] );
CHECKARCHIVE CheckArchive;
if( !(CheckArchive = (CHECKARCHIVE)GetProcAddress( hDLL, szTemp )) )
continue;
// 対応するアーカイブかチェックする
if( !CheckArchive( fname, 1 ) )
continue;
// アーカイブ内に対応するファイルがあるかのチェック
OPENARCHIVE OpenArchive;
CLOSEARCHIVE CloseArchive;
FINDFIRST FindFirst;
sprintf( szTemp, "%sOpenArchive", pszFuncPrefix[i] );
OpenArchive = (OPENARCHIVE)GetProcAddress( hDLL, szTemp );
sprintf( szTemp, "%sFindFirst", pszFuncPrefix[i] );
FindFirst = (FINDFIRST)GetProcAddress( hDLL, szTemp );
sprintf( szTemp, "%sCloseArchive", pszFuncPrefix[i] );
CloseArchive = (CLOSEARCHIVE)GetProcAddress( hDLL, szTemp );
HGLOBAL hARC;
BOOL bFound = FALSE;
for( INT j = 0; pszExtension[j]; j++ ) {
if( !(hARC = OpenArchive( NULL, fname, M_ERROR_MESSAGE_OFF ) ) ) {
CloseArchive( hARC );
break;
}
INT ret = FindFirst( hARC, pszExtension[j], &idvinfo );
CloseArchive( hARC );
if( ret == 0 ) { // Found!!
bFound = TRUE;
break;
} else if( ret == -1 ) { // Not found.
} else { // 異常終了
break;
}
}
if( !bFound )
continue;
if( !pszCommand[i] ) {
// メモリ解凍あり(UNLHA32,UNZIP32)
*lpdwSize = idvinfo.dwOriginalSize;
*ppBuf = (LPBYTE)malloc( *lpdwSize );
CHAR szCmd [256];
CHAR szFunc[256];
if( !bFileMatching[i] ) {
sprintf( szCmd, "\"%s\" \"%s\"", fname, idvinfo.szFileName );
} else {
// UNZIP32 only
BYTE szFile[FNAME_MAX32+1];
LPBYTE lpF0, lpF1;
// 正規表現を切るオプションが欲しかった....
lpF0 = (LPBYTE)idvinfo.szFileName;
lpF1 = szFile;
while( *lpF0 ) {
if( *lpF0 == '[' || *lpF0 == ']' ) {
*lpF1++ = '\\';
}
_mbsncpy( lpF1, lpF0, 1 );
lpF0 = _mbsinc( lpF0 );
lpF1 = _mbsinc( lpF1 );
}
*lpF1 = '\0';
sprintf( szCmd, "\"%s\" \"%s\"", fname, szFile );
}
sprintf( szFunc, "%sExtractMem", pszFuncPrefix[i] );
EXTRACTMEM ExtractMem;
ExtractMem = (EXTRACTMEM)GetProcAddress( hDLL, szFunc );
INT ret = ExtractMem( NULL, szCmd, (LPBYTE)(*ppBuf), *lpdwSize, NULL, NULL, NULL );
FREEDLL( hDLL );
if( ret == 0 )
return TRUE;
} else {
// メモリ解凍が無い場合
CHAR szCmd [256];
CHAR szTempPath[_MAX_PATH];
EXECUTECOMMAND ExecuteCommand;
GetTempPath( _MAX_PATH, szTempPath );
//DEBUGOUT( "TempPath:%s\n", szTempPath );
sprintf( szCmd, pszCommand[i], fname, szTempPath, idvinfo.szFileName );
ExecuteCommand = (EXECUTECOMMAND)GetProcAddress( hDLL, pszFuncPrefix[i] );
ExecuteCommand( NULL, szCmd, NULL, 0 );
FREEDLL( hDLL );
string FileName = CPathlib::MakePath( szTempPath, idvinfo.szFileName );
FILE *fp = NULL;
if( (fp = fopen( FileName.c_str(), "rb" )) ) {
// ファイルサイズ取得
fseek( fp, 0, SEEK_END );
*lpdwSize = ftell( fp );
fseek( fp, 0, SEEK_SET );
if( *lpdwSize < 17 ) {
// ファイルサイズが小さすぎます
throw CApp::GetErrorString( IDS_ERROR_SMALLFILE );
}
// テンポラリメモリ確保
if( !(*ppBuf = (LPBYTE)malloc( *lpdwSize )) ) {
FCLOSE( fp );
// メモリを確保出来ません
throw CApp::GetErrorString( IDS_ERROR_OUTOFMEMORY );
}
// サイズ分読み込み
if( fread( *ppBuf, *lpdwSize, 1, fp ) != 1 ) {
FCLOSE( fp );
FREE( *ppBuf );
// ファイルの読み込みに失敗しました
throw CApp::GetErrorString( IDS_ERROR_READ );
}
FCLOSE( fp );
DeleteFile( FileName.c_str() );
} else {
// xxx ファイルを開けません
LPCSTR szErrStr = CApp::GetErrorString( IDS_ERROR_OPEN );
sprintf( szErrorString, szErrStr, fname );
throw szErrorString;
}
return TRUE;
}
}
FREEDLL( hDLL );
return FALSE;
}
// Archive

View File

@ -0,0 +1,12 @@
//
// アーカイブファイル操作
//
#ifndef __CARCHIVEFILE_INCLUDED__
#define __CARCHIVEFILE_INCLUDED__
#include "typedef.h"
extern BOOL UnCompress( LPCSTR fname, LPBYTE* ppBuf, LPDWORD lpdwSize );
#endif // !__CARCHIVEFILE_INCLUDED__

View File

@ -0,0 +1,250 @@
#ifndef __CHYPERLINK_INCLUDED__
#define __CHYPERLINK_INCLUDED__
//
// スタティックコントロールをSubclass化してハイパーリンクをサポート
//
// Usage: CHyperLink hyperlink;
// hyperlink.Attach( GetDlgItem( hWnd, IDC_URL ) );
//
class CHyperLink
{
public:
CHyperLink() : m_hWnd(NULL), m_lpLabel(NULL),
m_hCursor(NULL), m_hFont(NULL),
m_lpHyperLink(NULL), m_lpfnOldWndProc(NULL)
{
}
~CHyperLink()
{
Detach();
}
// コントロールにアタッチする
BOOL Attach( HWND hWnd, LPCSTR lpLabel = NULL, LPCSTR lpHyperLink = NULL )
{
if( m_hWnd )
return FALSE; // 既にAttach済み
m_hWnd = hWnd;
// 文字列をコピー
if( lpLabel ) {
m_lpLabel = new CHAR[::lstrlen(lpLabel)+1];
::lstrcpy( m_lpLabel, lpLabel );
::SendMessage( m_hWnd, WM_SETTEXT, 0, (LPARAM)m_lpLabel );
}
// 表示とハイパーリンクが同じ場合はハイパーリンクはラベルと同じに
if( lpLabel && !lpHyperLink ) {
m_lpHyperLink = new CHAR[::lstrlen(lpLabel)+1];
::lstrcpy( m_lpHyperLink, lpLabel );
}
// ハイパーリンクが別の場合
if( lpHyperLink ) {
m_lpHyperLink = new CHAR[::lstrlen(lpHyperLink)+1];
::lstrcpy( m_lpHyperLink, lpHyperLink );
}
// ポイントカーソル(無ければデフォルト)
m_hCursor = ::LoadCursor( NULL, MAKEINTRESOURCE(32649) );
// アンダーラインフォントの作成
HFONT m_hOldFont = (HFONT)::SendMessage( hWnd, WM_GETFONT, 0, 0 );
LOGFONT lFont;
::GetObject( m_hOldFont, sizeof(LOGFONT), &lFont );
lFont.lfUnderline = TRUE;
m_hFont = ::CreateFontIndirect( &lFont );
// ラベルの表示領域を計算
CalcLabelRectangle();
// スタイルの変更(通知をイネーブルにする)
DWORD dwStyle = ::GetWindowLong( hWnd, GWL_STYLE );
dwStyle |= SS_NOTIFY;
::SetWindowLong( hWnd, GWL_STYLE, (LONG)dwStyle );
// コントロールのサブクラス化
m_lpfnOldWndProc = (WNDPROC)::SetWindowLong( hWnd, GWL_WNDPROC, (LONG)HyperLinkProc );
// Thisを埋め込む
::SetWindowLong( hWnd, GWL_USERDATA, (LONG)this );
return TRUE;
}
BOOL Detach()
{
if( m_hWnd ) {
// サブクラス化を解除
if( m_lpfnOldWndProc ) {
::SetWindowLong( m_hWnd, GWL_WNDPROC, (LONG)m_lpfnOldWndProc );
m_lpfnOldWndProc = NULL;
}
// フォントを削除
if( m_hFont ) {
::DeleteObject( (HGDIOBJ)m_hFont );
m_hFont = NULL;
}
// 文字列を削除
if( m_lpLabel ) {
delete[] m_lpLabel;
m_lpLabel = NULL;
}
if( m_lpHyperLink ) {
delete[] m_lpHyperLink;
m_lpHyperLink = NULL;
}
}
m_hWnd = NULL;
return TRUE;
}
BOOL SetLabel( LPCSTR lpLabel )
{
if( m_lpLabel ) {
delete[] m_lpLabel;
}
m_lpLabel = new CHAR[::lstrlen(lpLabel)+1];
::lstrcpy( m_lpLabel, lpLabel );
// コントロールに文字列を設定
::SendMessage( m_hWnd, WM_SETTEXT, 0, (LPARAM)m_lpLabel );
// ラベルの表示領域を計算
CalcLabelRectangle();
}
BOOL SetHyperLink( LPCSTR lpHyperLink )
{
if( m_lpHyperLink ) {
delete[] m_lpHyperLink;
}
m_lpHyperLink = new CHAR[::lstrlen(lpHyperLink)+1];
::lstrcpy( m_lpHyperLink, lpHyperLink );
}
protected:
BOOL CalcLabelRectangle()
{
if( !::IsWindow(m_hWnd) )
return FALSE;
if( !m_lpLabel )
return FALSE;
RECT rcClient;
::GetClientRect( m_hWnd, &rcClient );
m_rcLabel = rcClient;
HDC hDC = ::GetDC( m_hWnd );
HFONT hOldFont = (HFONT)::SelectObject( hDC, m_hFont );
// スタイル
DWORD dwStyle = ::GetWindowLong( m_hWnd, GWL_STYLE );
INT nDrawStyle = DT_LEFT;
if( dwStyle && SS_CENTER ) {
nDrawStyle = DT_CENTER;
} else if( dwStyle && SS_RIGHT ) {
nDrawStyle = DT_RIGHT;
}
// 文字列表示と描画領域の計算
::DrawText( hDC, m_lpLabel, -1, &m_rcLabel, nDrawStyle | DT_WORDBREAK | DT_CALCRECT );
::SelectObject( hDC, hOldFont );
// スタイルによってオフセットを計算
if( dwStyle & SS_CENTER ) {
::OffsetRect( &m_rcLabel, (rcClient.right - m_rcLabel.right) / 2, 0 );
} else if (dwStyle & SS_RIGHT) {
::OffsetRect( &m_rcLabel, rcClient.right - m_rcLabel.right, 0 );
}
return true;
}
static LRESULT CALLBACK HyperLinkProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
CHyperLink* pHyperLink = reinterpret_cast<CHyperLink*>(::GetWindowLong( hWnd, GWL_USERDATA));
switch( msg ) {
case WM_DESTROY:
{
// 2003/10/11 リリース後にfix...
WNDPROC pWndProcOld = pHyperLink->m_lpfnOldWndProc;
pHyperLink->Detach();
return CallWindowProc( pWndProcOld, hWnd, msg, wParam, lParam );
}
break;
case WM_LBUTTONDOWN: {
POINT pt = { LOWORD(lParam), HIWORD(lParam) };
if( pHyperLink->m_lpLabel && pHyperLink->m_lpHyperLink ) {
if( ::PtInRect( &pHyperLink->m_rcLabel, pt ) ) {
::ShellExecute( hWnd, NULL, pHyperLink->m_lpHyperLink, NULL, NULL, SW_SHOWNORMAL );
return TRUE;
}
}
}
break;
case WM_MOUSEMOVE: {
POINT pt = { LOWORD(lParam), HIWORD(lParam) };
if( pHyperLink->m_lpLabel && pHyperLink->m_lpHyperLink ) {
if( ::PtInRect( &pHyperLink->m_rcLabel, pt ) ) {
::SetCursor( pHyperLink->m_hCursor );
return TRUE;
}
}
}
break;
case WM_PAINT: {
PAINTSTRUCT ps;
HDC hDC = ::BeginPaint( hWnd, &ps );
DWORD dwStyle = ::GetWindowLong( hWnd, GWL_STYLE );
INT nDrawStyle = DT_LEFT;
if( dwStyle && SS_CENTER ) {
nDrawStyle = DT_CENTER;
} else if( dwStyle && SS_RIGHT ) {
nDrawStyle = DT_RIGHT;
}
// アトリビュート
::SetBkMode( hDC, TRANSPARENT );
::SetTextColor( hDC, 0x00FF0000 );
// 文字列表示
if( pHyperLink->m_lpLabel ) {
HFONT hOldFont = (HFONT)::SelectObject( hDC, pHyperLink->m_hFont );
::DrawText( hDC, pHyperLink->m_lpLabel, -1, &pHyperLink->m_rcLabel, nDrawStyle | DT_WORDBREAK );
::SelectObject( hDC, hOldFont );
}
::EndPaint( hWnd, &ps );
}
return TRUE;
default:
break;
}
return CallWindowProc( pHyperLink->m_lpfnOldWndProc, hWnd, msg, wParam, lParam );
}
HWND m_hWnd;
HFONT m_hFont;
HFONT m_hOldFont;
HCURSOR m_hCursor;
WNDPROC m_lpfnOldWndProc;
RECT m_rcLabel;
LPSTR m_lpLabel;
LPSTR m_lpHyperLink;
private:
};
#endif // !__CHYPERLINK_INCLUDED__

View File

@ -0,0 +1,277 @@
//
// チャットダイアログクラス
//
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <commctrl.h>
#include <stdio.h>
#include <stdlib.h>
#include <mbstring.h>
#include <shlwapi.h>
#include <string>
using namespace std;
#include "typedef.h"
#include "macro.h"
#include "VirtuaNESres.h"
#include "DebugOut.h"
#include "App.h"
#include "Pathlib.h"
#include "Config.h"
#include "NetPlay.h"
#include "Wnd.h"
#include "ChatDlg.h"
// メッセージ
DLG_MESSAGE_BEGIN(CChatDlg)
DLG_ON_MESSAGE( WM_INITDIALOG, OnInitDialog )
DLG_ON_MESSAGE( WM_DESTROY, OnDestroy )
DLG_ON_MESSAGE( WM_CLOSE, OnClose )
DLG_ON_MESSAGE( WM_ACTIVATE, OnActivate )
DLG_ON_MESSAGE( WM_SETCURSOR, OnSetCursor )
DLG_ON_MESSAGE( WM_SIZE, OnSize )
DLG_ON_MESSAGE( WM_CTLCOLORSTATIC, OnControlColorStatic )
DLG_ON_MESSAGE( WM_COPYDATA, OnCopyData )
// コマンド
DLG_COMMAND_BEGIN()
DLG_ON_COMMAND_NOTIFY( IDC_NCT_MESSAGE, EN_SETFOCUS, OnMessageFocus )
DLG_ON_COMMAND( IDOK, OnOK )
DLG_ON_COMMAND( IDCANCEL, OnCancel )
DLG_ON_COMMAND( IDC_NCT_SEND, OnSend )
DLG_COMMAND_END()
// Notify メッセージ
DLG_NOTIFY_BEGIN()
DLG_NOTIFY_END()
DLG_MESSAGE_END()
BOOL CChatDlg::Create( HWND hWndParent )
{
// 親はデスクトップにする
m_hWnd = ::CreateDialogParam( CApp::GetPlugin(), MAKEINTRESOURCE(IDD_NETPLAY_CHAT),
NULL, g_DlgProc, (LPARAM)this );
if( !m_hWnd )
return FALSE;
// モードレスダイアログリストに加える
CWndList::Add( this );
return TRUE;
}
void CChatDlg::Destroy()
{
if( m_hWnd ) {
// モードレスダイアログリストから削除
CWndList::Del( this );
::GetWindowRect( m_hWnd, &Config.netplay.rcChatPos );
::DestroyWindow( m_hWnd );
m_hWnd = NULL;
}
}
void CChatDlg::SetEditText()
{
CHAR szText[256+1];
::GetWindowText( ::GetDlgItem(m_hWnd, IDC_NCT_EDIT), szText, sizeof(szText)-1 );
::SetWindowText( ::GetDlgItem(m_hWnd, IDC_NCT_EDIT), "" );
if( ::strlen(szText) ) {
// clear message window
if( ::StrCmpI( szText, "/clear" ) == 0 ) {
::SendDlgItemMessage( m_hWnd, IDC_NCT_MESSAGE, EM_SETSEL, 0, -1 );
::SendDlgItemMessage( m_hWnd, IDC_NCT_MESSAGE, EM_REPLACESEL, FALSE, (WPARAM)"" );
return;
}
string str;
if( NetPlay.IsConnect() ) {
str = "(";
str = str + Config.netplay.szNick;
str = str + ") ";
}
str = str + szText;
str = str + "\r\n";
// 相手に送信
if( NetPlay.IsConnect() ) {
NetPlay.ChatSend( (LPSTR)str.c_str() );
}
// 自分自身のメッセージを表示
INT n = GetWindowTextLength( GetDlgItem( m_hWnd, IDC_NCT_MESSAGE ) );
::SendDlgItemMessage( m_hWnd, IDC_NCT_MESSAGE, EM_SETSEL, (WPARAM)n, (LPARAM)n );
::SendDlgItemMessage( m_hWnd, IDC_NCT_MESSAGE, EM_REPLACESEL, (WPARAM)TRUE, (LPARAM)str.c_str() );
}
}
DLGMSG CChatDlg::OnCopyData( DLGMSGPARAM )
{
COPYDATASTRUCT* pcds = (COPYDATASTRUCT*)lParam;
CHAR* lpStr = (CHAR*)pcds->lpData;
INT n = GetWindowTextLength( GetDlgItem( hWnd, IDC_NCT_MESSAGE ) );
::SendDlgItemMessage( hWnd, IDC_NCT_MESSAGE, EM_SETSEL, (WPARAM)n, (LPARAM)n );
::SendDlgItemMessage( hWnd, IDC_NCT_MESSAGE, EM_REPLACESEL, (WPARAM)TRUE, (LPARAM)lpStr );
if( ::GetFocus() != m_hWnd && ::strlen( lpStr ) > 0 ) {
::MessageBeep( MB_OK );
// ::PlaySound( "MailBeep", NULL, SND_ALIAS|SND_ASYNC );
}
// メッセージが来たらポップアップさせるため
::SendMessage( CApp::GetHWnd(), WM_VNS_CHATPOPUP, 0, 0 );
return TRUE;
}
DLGMSG CChatDlg::OnInitDialog( DLGMSGPARAM )
{
// DEBUGOUT( "CChatDlg::OnInitDialog\n" );
NetPlay.SetChatWnd( m_hWnd );
// 位置情報を保存
::GetClientRect( m_hWnd, &m_rcClient );
::GetWindowRect( ::GetDlgItem(m_hWnd, IDC_NCT_MESSAGE), &m_rcMessage );
::GetWindowRect( ::GetDlgItem(m_hWnd, IDC_NCT_EDIT), &m_rcEdit );
::GetWindowRect( ::GetDlgItem(m_hWnd, IDC_NCT_SEND), &m_rcButton );
// クライアント座標への変換
::ScreenToClient( m_hWnd, (POINT*)&m_rcMessage.left );
::ScreenToClient( m_hWnd, (POINT*)&m_rcMessage.right );
::ScreenToClient( m_hWnd, (POINT*)&m_rcEdit.left );
::ScreenToClient( m_hWnd, (POINT*)&m_rcEdit.right );
::ScreenToClient( m_hWnd, (POINT*)&m_rcButton.left );
::ScreenToClient( m_hWnd, (POINT*)&m_rcButton.right );
// ウインドウ位置/サイズの設定
// RECT rc = Config.launcher.rcWindowPos;
// if( (rc.right-rc.left) && (rc.bottom-rc.top) ) {
// ::SetWindowPos( m_hWnd, NULL, rc.left, rc.top, RCWIDTH(rc), RCHEIGHT(rc), SWP_NOZORDER );
// }
// ウインドウ位置/サイズの設定
RECT rc = Config.netplay.rcChatPos;
if( (rc.right-rc.left) && (rc.bottom-rc.top) ) {
::SetWindowPos( m_hWnd, NULL, rc.left, rc.top, RCWIDTH(rc), RCHEIGHT(rc), SWP_NOZORDER );
}
// 表示
::ShowWindow( m_hWnd, SW_SHOW );
return TRUE;
}
DLGMSG CChatDlg::OnDestroy( DLGMSGPARAM )
{
return TRUE;
}
DLGMSG CChatDlg::OnClose( DLGMSGPARAM )
{
::ShowWindow( m_hWnd, SW_HIDE ); // 非表示にするだけ
return TRUE;
}
DLGMSG CChatDlg::OnActivate( DLGMSGPARAM )
{
if( LOWORD(wParam) == WA_INACTIVE ) {
// DEBUGOUT( "CChatDlg::OnActivate:Inactive\n" );
::PostMessage( CApp::GetHWnd(), WM_VNS_SHORTCUTENABLE, (WPARAM)TRUE, 0 );
Config.InputKeyboardDisable( FALSE );
} else {
// DEBUGOUT( "CChatDlg::OnActivate:Active\n" );
::PostMessage( CApp::GetHWnd(), WM_VNS_SHORTCUTENABLE, (WPARAM)FALSE, 0 );
Config.InputKeyboardDisable( TRUE );
}
return TRUE;
}
DLGMSG CChatDlg::OnSetCursor( DLGMSGPARAM )
{
// DEBUGOUT( "CChatDlg::OnSetCursor\n" );
return FALSE;
}
DLGMSG CChatDlg::OnSize( DLGMSGPARAM )
{
// DEBUGOUT( "CChatDlg::OnSize\n" );
HWND hWndCtrl;
RECT rcC, rcT;
::GetClientRect( m_hWnd, &rcC );
// メッセージ枠
if( (hWndCtrl = ::GetDlgItem( m_hWnd, IDC_NCT_MESSAGE )) ) {
rcT.left = rcC.left;
rcT.right = rcC.right;
rcT.top = rcC.top;
rcT.bottom = rcC.bottom - (m_rcClient.bottom-m_rcMessage.bottom);
::MoveWindow( hWndCtrl, rcT.left, rcT.top, RCWIDTH(rcT), RCHEIGHT(rcT), TRUE );
}
if( (hWndCtrl = ::GetDlgItem( m_hWnd, IDC_NCT_EDIT )) ) {
rcT.left = rcC.left;
rcT.right = rcC.right - (m_rcClient.right-m_rcEdit.right);
rcT.top = rcC.bottom - (m_rcClient.bottom-m_rcEdit.top);
rcT.bottom = rcC.bottom - (m_rcClient.bottom-m_rcEdit.bottom);
::MoveWindow( hWndCtrl, rcT.left, rcT.top, RCWIDTH(rcT), RCHEIGHT(rcT), TRUE );
}
if( (hWndCtrl = ::GetDlgItem( m_hWnd, IDC_NCT_SEND )) ) {
rcT.left = rcC.right - (m_rcClient.right-m_rcButton.left);
rcT.right = rcT.left + RCWIDTH(m_rcButton);
rcT.top = rcC.bottom - (m_rcClient.bottom-m_rcButton.top);
rcT.bottom = rcT.top + RCHEIGHT(m_rcButton);
::MoveWindow( hWndCtrl, rcT.left, rcT.top, RCWIDTH(rcT), RCHEIGHT(rcT), TRUE );
}
return FALSE;
}
DLGMSG CChatDlg::OnControlColorStatic( DLGMSGPARAM )
{
if( (HWND)lParam == ::GetDlgItem( m_hWnd, IDC_NCT_MESSAGE ) ) {
SetBkColor( (HDC)wParam, (COLORREF)0x00FFFFFF );
bResult = (LRESULT)GetStockObject( WHITE_BRUSH );
return TRUE;
}
return FALSE;
}
DLGCMD CChatDlg::OnMessageFocus( DLGCMDPARAM )
{
DEBUGOUT( "CChatDlg::OnMessageFocus\n" );
// ::SetFocus( ::GetDlgItem( m_hWnd, IDC_NCT_EDIT ) );
::SetFocus( m_hWnd );
}
DLGCMD CChatDlg::OnOK( DLGCMDPARAM )
{
// DEBUGOUT( "CChatDlg::OnOK\n" );
SetEditText();
}
DLGCMD CChatDlg::OnCancel( DLGCMDPARAM )
{
// DEBUGOUT( "CChatDlg::OnCancel\n" );
::ShowWindow( m_hWnd, SW_HIDE ); // 非表示にするだけ
}
DLGCMD CChatDlg::OnSend( DLGCMDPARAM )
{
// DEBUGOUT( "CChatDlg::OnSend\n" );
SetEditText();
::SetFocus( ::GetDlgItem( m_hWnd, IDC_NCT_EDIT ) );
}

View File

@ -0,0 +1,55 @@
//
// チャットダイアログクラス
//
#ifndef __CCHATDLG_INCLUDED__
#define __CCHATDLG_INCLUDED__
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <string>
using namespace std;
#include "Wnd.h"
class CChatDlg : public CWnd
{
public:
// Override from CWnd
BOOL Create( HWND hWndParent );
void Destroy();
// Set Message
void SetEditText();
protected:
// Message map
DLG_MESSAGE_MAP()
DLGMSG OnInitDialog( DLGMSGPARAM );
DLGMSG OnDestroy( DLGMSGPARAM );
DLGMSG OnClose( DLGMSGPARAM );
DLGMSG OnActivate( DLGMSGPARAM );
DLGMSG OnSetCursor( DLGMSGPARAM );
DLGMSG OnSize( DLGMSGPARAM );
DLGMSG OnControlColorStatic( DLGMSGPARAM );
DLGMSG OnCopyData( DLGMSGPARAM );
DLGCMD OnMessageFocus( DLGCMDPARAM );
DLGCMD OnOK( DLGCMDPARAM );
DLGCMD OnCancel( DLGCMDPARAM );
DLGCMD OnSend( DLGCMDPARAM );
//
// 位置
RECT m_rcClient; // クライアントエリア
RECT m_rcMessage; // メッセージ枠
RECT m_rcEdit; // エディット枠
RECT m_rcButton; // 送信ボタン
private:
};
#endif // !__CCHATDLG_INCLUDED__

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,175 @@
//
// チートダイアログクラス
//
#ifndef __CCHEATDLG_INCLUDED__
#define __CCHEATDLG_INCLUDED__
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <list>
#include <vector>
#include <string>
using namespace std;
#include "Wnd.h"
#include "cheat.h"
// サーチダイアログ
class CSearchDlg : public CWnd
{
public:
// Override from CWnd
BOOL Create( HWND hWndParent );
void Destroy();
protected:
void OnListUpdate();
// Utils
DWORD GetNesMemory( INT length, DWORD addr );
DWORD GetSearchMemory( INT length, DWORD addr );
DWORD GetSearchMemoryOld( INT length, DWORD addr );
BOOL CompareData( INT type, DWORD dataA, DWORD dataB );
BOOL CompareRange( INT length, DWORD dataA, DWORD dataB, DWORD range );
// Message map
DLG_MESSAGE_MAP()
DLGMSG OnInitDialog( DLGMSGPARAM );
DLGMSG OnActivate( DLGMSGPARAM );
DLGMSG OnClose( DLGMSGPARAM );
DLGMSG OnContextMenu( DLGMSGPARAM );
DLGCMD OnOK( DLGCMDPARAM );
DLGCMD OnCancel( DLGCMDPARAM );
DLGCMD OnRadixCommand( DLGCMDPARAM );
DLGCMD OnLengthCommand( DLGCMDPARAM );
DLGCMD OnStart( DLGCMDPARAM );
DLGCMD OnUpdate( DLGCMDPARAM );
DLGCMD OnUndo( DLGCMDPARAM );
DLGCMD OnSearchCommand( DLGCMDPARAM );
DLGCMD OnSearchData( DLGCMDPARAM );
DLGCMD OnWriteData( DLGCMDPARAM );
DLGCMD OnCodeAppend( DLGCMDPARAM );
//
DLGNOTIFY OnDoubleClickListView( DLGNOTIFYPARAM );
private:
HMENU m_hMenu;
HMENU m_hSubMenu;
BOOL m_bShortCutDisable;
WORD m_Address;
INT m_nRadix;
INT m_nLength;
struct RESULT {
BYTE RAM_N[0x0800]; // RAM New value
BYTE RAM_O[0x0800]; // RAM Old value
BYTE RAM_F[0x0800]; // RAM Flag
BYTE SRAM_N[0x2000]; // RAM New value
BYTE SRAM_O[0x2000]; // RAM Old value
BYTE SRAM_F[0x2000]; // RAM Flag
};
struct RESULT m_Result; // 今回データ
struct RESULT m_ResultOld; // 1回前
};
// チートコード編集ダイアログ
class CCheatCodeEditDlg : public CWnd
{
public:
// Override from CWnd
INT DoModal( HWND hWndParent );
//
CHEATCODE m_Code;
INT m_nRadix;
protected:
// Message map
DLG_MESSAGE_MAP()
DLGMSG OnInitDialog( DLGMSGPARAM );
DLGCMD OnOK( DLGCMDPARAM );
DLGCMD OnCancel( DLGCMDPARAM );
//
private:
};
// チートコード入力ダイアログ
class CCheatCodeInputDlg : public CWnd
{
public:
// Override from CWnd
INT DoModal( HWND hWndParent );
string m_Codes;
string m_Comment;
protected:
// Message map
DLG_MESSAGE_MAP()
DLGMSG OnInitDialog( DLGMSGPARAM );
DLGCMD OnOK( DLGCMDPARAM );
DLGCMD OnCancel( DLGCMDPARAM );
//
private:
};
// チートコードダイアログ
class CCheatCodeDlg : public CWnd
{
public:
// Override from CWnd
INT DoModal( HWND hWndParent );
protected:
void OnListUpdate();
// Message map
DLG_MESSAGE_MAP()
DLGMSG OnInitDialog( DLGMSGPARAM );
DLGMSG OnDestroy( DLGMSGPARAM );
DLGMSG OnTimer( DLGMSGPARAM );
DLGNOTIFY OnKeyDownListView( DLGNOTIFYPARAM );
DLGNOTIFY OnClickListView( DLGNOTIFYPARAM );
DLGNOTIFY OnDblClkListView( DLGNOTIFYPARAM );
DLGCMD OnOK( DLGCMDPARAM );
DLGCMD OnCancel( DLGCMDPARAM );
DLGCMD OnEnable( DLGCMDPARAM );
DLGCMD OnDisable( DLGCMDPARAM );
DLGCMD OnClear( DLGCMDPARAM );
DLGCMD OnRemove( DLGCMDPARAM );
DLGCMD OnInput( DLGCMDPARAM );
DLGCMD OnEdit( DLGCMDPARAM );
DLGCMD OnLoad( DLGCMDPARAM );
DLGCMD OnSave( DLGCMDPARAM );
// Image List
HIMAGELIST m_hImageList;
// Timer
UINT m_uTimerID;
// Temp buffer
vector<CHEATCODE> m_CheatCode;
private:
};
#endif // !__CCHEATDLG_INCLUDED__

View File

@ -0,0 +1,35 @@
//
// COM—˜—pƒTƒ|<7C>[ƒgƒNƒ‰ƒX
//
#include <objbase.h>
#include "DebugOut.h"
#include "Com.h"
INT COM::m_nRefCount = 0;
LRESULT COM::AddRef()
{
if( !m_nRefCount ) {
HRESULT hr;
if( (hr = ::CoInitialize( NULL )) != S_OK ) {
DEBUGOUT( "COM::AddRef() CoInitialize failed.\n" );
return hr;
}
DEBUGOUT( "COM::AddRef() CoInitialize.\n" );
}
m_nRefCount++;
return 0L;
}
void COM::Release()
{
if( !m_nRefCount ) {
DEBUGOUT( "COM::Release() too many released.\n" );
return;
}
if( !(--m_nRefCount) ) {
::CoUninitialize();
DEBUGOUT( "COM::AddRef() CoUninitialize.\n" );
}
}

View File

@ -0,0 +1,21 @@
//
// COM利用サポートクラス
//
#ifndef __CCOM_INCLUDED__
#define __CCOM_INCLUDED__
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
class COM
{
public:
static LRESULT AddRef();
static void Release();
protected:
static INT m_nRefCount;
};
#endif // !__CCOM_INCLUDED__

View File

@ -0,0 +1,817 @@
//
// 設定保存クラス
//
#include "VirtuaNESres.h"
#include "DebugOut.h"
#include "Config.h"
#include "Registry.h"
#include "DirectInput.h"
#include "extsoundfile.h"
// Global instance
CConfig Config;
// Sampling rate table
INT CConfig::SamplingRateTable[] = {
11025, 8, 11025, 16, 22050, 8, 22050, 16,
44100, 8, 44100, 16, 48000, 8, 48000, 16,
};
// Shortcut key IDs table
INT CConfig::ShortcutKeyID[] = {
// Main controls
ID_OPEN, IDS_CUT_OPEN, 0,
ID_CLOSE, IDS_CUT_CLOSE, 1,
ID_LAUNCHER, IDS_CUT_LAUNCHER, 2,
ID_NETPLAY_CONNECT, IDS_CUT_NETPLAY_CONNECT, 3,
ID_NETPLAY_DISCONNECT, IDS_CUT_NETPLAY_DISCONNECT, 4,
ID_NETPLAY_CHAT, IDS_CUT_NETPLAY_CHAT, 5,
ID_ROMINFO, IDS_CUT_ROMINFO, 8,
ID_WAVERECORD, IDS_CUT_WAVERECORD, 9,
ID_EXIT, IDS_CUT_EXIT, 15,
// Emulation controls
ID_HWRESET, IDS_CUT_HWRESET, 16,
ID_SWRESET, IDS_CUT_SWRESET, 17,
ID_PAUSE, IDS_CUT_PAUSE, 18,
ID_ONEFRAME, IDS_CUT_ONEFRAME, 23,
ID_THROTTLE, IDS_CUT_THROTTLE, 19,
ID_KEYTHROTTLE, IDS_CUT_KEYTHROTTLE, 24,
ID_FRAMESKIP_AUTO, IDS_CUT_FRAMESKIP_AUTO, 20,
ID_FRAMESKIP_UP, IDS_CUT_FRAMESKIP_UP, 21,
ID_FRAMESKIP_DOWN, IDS_CUT_FRAMESKIP_DOWN, 22,
// State controls
ID_STATE_LOAD, IDS_CUT_STATE_LOAD, 32,
ID_STATE_SAVE, IDS_CUT_STATE_SAVE, 33,
ID_STATE_UP, IDS_CUT_STATE_UP, 34,
ID_STATE_DOWN, IDS_CUT_STATE_DOWN, 35,
ID_STATE_SLOT0, IDS_CUT_STATE_SLOT0, 36,
ID_STATE_SLOT1, IDS_CUT_STATE_SLOT1, 37,
ID_STATE_SLOT2, IDS_CUT_STATE_SLOT2, 38,
ID_STATE_SLOT3, IDS_CUT_STATE_SLOT3, 39,
ID_STATE_SLOT4, IDS_CUT_STATE_SLOT4, 40,
ID_STATE_SLOT5, IDS_CUT_STATE_SLOT5, 41,
ID_STATE_SLOT6, IDS_CUT_STATE_SLOT6, 42,
ID_STATE_SLOT7, IDS_CUT_STATE_SLOT7, 43,
ID_STATE_SLOT8, IDS_CUT_STATE_SLOT8, 44,
ID_STATE_SLOT9, IDS_CUT_STATE_SLOT9, 45,
// QuickLoad
ID_QUICKLOAD_SLOT0, IDS_CUT_QUICKLOAD_SLOT0, 256,
ID_QUICKLOAD_SLOT1, IDS_CUT_QUICKLOAD_SLOT1, 257,
ID_QUICKLOAD_SLOT2, IDS_CUT_QUICKLOAD_SLOT2, 258,
ID_QUICKLOAD_SLOT3, IDS_CUT_QUICKLOAD_SLOT3, 259,
ID_QUICKLOAD_SLOT4, IDS_CUT_QUICKLOAD_SLOT4, 260,
ID_QUICKLOAD_SLOT5, IDS_CUT_QUICKLOAD_SLOT5, 261,
ID_QUICKLOAD_SLOT6, IDS_CUT_QUICKLOAD_SLOT6, 262,
ID_QUICKLOAD_SLOT7, IDS_CUT_QUICKLOAD_SLOT7, 263,
ID_QUICKLOAD_SLOT8, IDS_CUT_QUICKLOAD_SLOT8, 264,
ID_QUICKLOAD_SLOT9, IDS_CUT_QUICKLOAD_SLOT9, 265,
// QuickSave
ID_QUICKSAVE_SLOT0, IDS_CUT_QUICKSAVE_SLOT0, 266,
ID_QUICKSAVE_SLOT1, IDS_CUT_QUICKSAVE_SLOT1, 267,
ID_QUICKSAVE_SLOT2, IDS_CUT_QUICKSAVE_SLOT2, 268,
ID_QUICKSAVE_SLOT3, IDS_CUT_QUICKSAVE_SLOT3, 269,
ID_QUICKSAVE_SLOT4, IDS_CUT_QUICKSAVE_SLOT4, 270,
ID_QUICKSAVE_SLOT5, IDS_CUT_QUICKSAVE_SLOT5, 271,
ID_QUICKSAVE_SLOT6, IDS_CUT_QUICKSAVE_SLOT6, 272,
ID_QUICKSAVE_SLOT7, IDS_CUT_QUICKSAVE_SLOT7, 273,
ID_QUICKSAVE_SLOT8, IDS_CUT_QUICKSAVE_SLOT8, 274,
ID_QUICKSAVE_SLOT9, IDS_CUT_QUICKSAVE_SLOT9, 275,
// Disk controls
ID_DISK_EJECT, IDS_CUT_DISK_EJECT, 48,
ID_DISK_0A, IDS_CUT_DISK_0A, 49,
ID_DISK_0B, IDS_CUT_DISK_0B, 50,
ID_DISK_1A, IDS_CUT_DISK_1A, 51,
ID_DISK_1B, IDS_CUT_DISK_1B, 52,
// Movie controls
ID_MOVIE_PLAY, IDS_CUT_MOVIE_PLAY, 56,
ID_MOVIE_REC, IDS_CUT_MOVIE_REC, 57,
ID_MOVIE_REC_APPEND, IDS_CUT_MOVIE_REC_APPEND, 58,
ID_MOVIE_STOP, IDS_CUT_MOVIE_STOP, 59,
ID_MOVIE_INFO, IDS_CUT_MOVIE_INFO, 60,
// Screen controls
ID_ZOOMx1, IDS_CUT_ZOOMx1, 64,
ID_ZOOMx2, IDS_CUT_ZOOMx2, 65,
ID_ZOOMx3, IDS_CUT_ZOOMx3, 66,
ID_ZOOMx4, IDS_CUT_ZOOMx4, 67,
ID_FULLSCREEN, IDS_CUT_FULLSCREEN, 68,
// Sound controls
ID_MUTE_0, IDS_CUT_MUTE_MASTER, 72,
ID_MUTE_1, IDS_CUT_MUTE_RECTANGLE1, 73,
ID_MUTE_2, IDS_CUT_MUTE_RECTANGLE2, 74,
ID_MUTE_3, IDS_CUT_MUTE_TRIANGLE, 75,
ID_MUTE_4, IDS_CUT_MUTE_NOISE, 76,
ID_MUTE_5, IDS_CUT_MUTE_DPCM, 77,
ID_MUTE_6, IDS_CUT_MUTE_EXTERNAL1, 78,
ID_MUTE_7, IDS_CUT_MUTE_EXTERNAL2, 79,
ID_MUTE_8, IDS_CUT_MUTE_EXTERNAL3, 80,
ID_MUTE_9, IDS_CUT_MUTE_EXTERNAL4, 81,
ID_MUTE_A, IDS_CUT_MUTE_EXTERNAL5, 82,
ID_MUTE_B, IDS_CUT_MUTE_EXTERNAL6, 83,
ID_MUTE_C, IDS_CUT_MUTE_EXTERNAL7, 84,
ID_MUTE_D, IDS_CUT_MUTE_EXTERNAL8, 85,
// Tape controls
ID_TAPE_PLAY, IDS_CUT_TAPE_PLAY, 90,
ID_TAPE_REC, IDS_CUT_TAPE_REC, 91,
ID_TAPE_STOP, IDS_CUT_TAPE_STOP, 92,
// Other controls
ID_SNAPSHOT, IDS_CUT_SNAPSHOT, 96,
ID_FPSDISP, IDS_CUT_FPSDISP, 97,
ID_TVASPECT, IDS_CUT_TVASPECT, 98,
ID_TVFRAME, IDS_CUT_TVFRAME, 99,
ID_SCANLINE, IDS_CUT_SCANLINE, 100,
ID_ALLLINE, IDS_CUT_ALLLINE, 101,
ID_ALLSPRITE, IDS_CUT_ALLSPRITE, 102,
ID_LEFTCLIP, IDS_CUT_LEFTCLIP, 105,
ID_SYNCDRAW, IDS_CUT_SYNCDRAW, 103,
ID_FITSCREEN, IDS_CUT_FITSCREEN, 104,
// Tool controls
ID_SEARCH, IDS_CUT_SEARCH, 110,
ID_CHEAT, IDS_CUT_CHEAT, 111,
ID_CHEAT_ENABLE, IDS_CUT_CHEAT_ENABLE, 112,
ID_CHEAT_DISABLE, IDS_CUT_CHEAT_DISABLE, 113,
ID_GENIE, IDS_CUT_GENIE, 114,
ID_VIEW_PATTERN, IDS_CUT_VIEW_PATTERN, 116,
ID_VIEW_NAMETABLE, IDS_CUT_VIEW_NAMETABLE, 117,
ID_VIEW_PALETTE, IDS_CUT_VIEW_PALETTE, 118,
ID_VIEW_MEMORY, IDS_CUT_VIEW_MEMORY, 119,
0, 0, 0
};
void CConfig::Load()
{
INT i, j;
string ret;
string section;
CHAR keys[64];
CHAR szTemp[MAX_PATH];
WORD szKeyTemp[64];
// General
section = "General";
general.bDoubleExecute = (BOOL)CRegistry::GetProfileInt( section.c_str(), "DoubleExecute", general.bDoubleExecute );
general.bStartupLauncher = (BOOL)CRegistry::GetProfileInt( section.c_str(), "StartupLauncher", general.bStartupLauncher );
// general.bWindowSave = CRegistry::GetProfileInt( section.c_str(), "WindowPosSave", general.bWindowSave );
general.bWindowZoom = CRegistry::GetProfileInt( section.c_str(), "WindowZoom", general.bWindowZoom );
RECT rc;
if( CRegistry::GetProfileBinary( section.c_str(), "WindowPos", (LPBYTE)&rc, sizeof(RECT) ) ) {
general.rcWindowPos = rc;
}
if( CRegistry::GetProfileBinary( section.c_str(), "SearchDialogPos", (LPBYTE)&rc, sizeof(RECT) ) ) {
general.rcSearchDlgPos = rc;
}
if( CRegistry::GetProfileBinary( section.c_str(), "PatternViewPos", (LPBYTE)&rc, sizeof(RECT) ) ) {
general.rcPatternViewPos = rc;
}
if( CRegistry::GetProfileBinary( section.c_str(), "NameTableViewPos", (LPBYTE)&rc, sizeof(RECT) ) ) {
general.rcNameTableViewPos = rc;
}
if( CRegistry::GetProfileBinary( section.c_str(), "PaletteViewPos", (LPBYTE)&rc, sizeof(RECT) ) ) {
general.rcPaletteViewPos = rc;
}
if( CRegistry::GetProfileBinary( section.c_str(), "MemoryViewPos", (LPBYTE)&rc, sizeof(RECT) ) ) {
general.rcMemoryViewPos = rc;
}
if( CRegistry::GetProfileBinary( section.c_str(), "BarcodePos", (LPBYTE)&rc, sizeof(RECT) ) ) {
general.rcBarcodePos = rc;
}
if( CRegistry::GetProfileBinary( section.c_str(), "PaletteEditPos", (LPBYTE)&rc, sizeof(RECT) ) ) {
general.rcPaletteEditPos = rc;
}
general.nScreenZoom = CRegistry::GetProfileInt( section.c_str(), "ScreenZoom", general.nScreenZoom );
general.bNoJoystickID = (BOOL)CRegistry::GetProfileInt( section.c_str(), "NoJoystickID", general.bNoJoystickID );
general.nJoyAxisDisable = CRegistry::GetProfileInt( section.c_str(), "JoyAxisDisable", general.nJoyAxisDisable );
if( general.nJoyAxisDisable ) {
// 以前の設定を引き継ぐ為
WORD bits = 0;
switch( general.nJoyAxisDisable ) {
case 1:
bits = (1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<4)|(1<<5);
break;
case 2:
bits = (1<<1)|(1<<2)|(1<<3)|(1<<4)|(1<<5);
break;
case 3:
bits = (1<<2)|(1<<3)|(1<<4)|(1<<5);
break;
case 4:
bits = (1<<3)|(1<<4)|(1<<5);
break;
case 5:
bits = (1<<4)|(1<<5);
break;
case 6:
bits = (1<<5);
break;
}
for( i = 0; i < 16; i++ ) {
general.JoyAxisSetting[i] = bits;
}
general.nJoyAxisDisable = 0;
} else {
if( CRegistry::GetProfileBinary( section.c_str(), "JoyAxisSetting", szKeyTemp, 16*sizeof(WORD) ) ) {
::memcpy( general.JoyAxisSetting, szKeyTemp, 16*sizeof(WORD) );
}
}
// Paths
section = "Path";
path.bRomAutoRunPath = (BOOL)CRegistry::GetProfileInt( section.c_str(), "RomAutoRunPathUse", path.bRomAutoRunPath );
path.bRomPath = (BOOL)CRegistry::GetProfileInt( section.c_str(), "RomPathUse", path.bRomPath );
path.bSavePath = (BOOL)CRegistry::GetProfileInt( section.c_str(), "SavePathUse", path.bSavePath );
path.bStatePath = (BOOL)CRegistry::GetProfileInt( section.c_str(), "StatePathUse", path.bStatePath );
path.bSnapshotPath = (BOOL)CRegistry::GetProfileInt( section.c_str(), "SnapshotPathUse", path.bSnapshotPath );
path.bMoviePath = (BOOL)CRegistry::GetProfileInt( section.c_str(), "MoviePathUse", path.bMoviePath );
path.bWavePath = (BOOL)CRegistry::GetProfileInt( section.c_str(), "WavePathUse", path.bWavePath );
path.bCheatPath = (BOOL)CRegistry::GetProfileInt( section.c_str(), "CheatPathUse", path.bCheatPath );
if( CRegistry::GetProfileString(section.c_str(), "RomAutoRunPath", szTemp, sizeof(szTemp))) {
::strcpy(path.szRomAutoRunPath, szTemp);
DEBUGOUT("RomAutoRunPath = %s\n", szTemp);
} else {
DEBUGOUT("RomAutoRunPath get failed! write default path\n");
CRegistry::WriteProfileString( section.c_str(), "RomAutoRunPath", path.szRomAutoRunPath );
}
if( CRegistry::GetProfileString( section.c_str(), "RomPath", szTemp, sizeof(szTemp) ) )
::strcpy( path.szRomPath, szTemp );
if( CRegistry::GetProfileString( section.c_str(), "SavePath", szTemp, sizeof(szTemp) ) )
::strcpy( path.szSavePath, szTemp );
if( CRegistry::GetProfileString( section.c_str(), "StatePath", szTemp, sizeof(szTemp) ) )
::strcpy( path.szStatePath, szTemp );
if( CRegistry::GetProfileString( section.c_str(), "SnapshotPath", szTemp, sizeof(szTemp) ) )
::strcpy( path.szSnapshotPath, szTemp );
if( CRegistry::GetProfileString( section.c_str(), "MoviePath", szTemp, sizeof(szTemp) ) )
::strcpy( path.szMoviePath, szTemp );
if( CRegistry::GetProfileString( section.c_str(), "WavePath", szTemp, sizeof(szTemp) ) )
::strcpy( path.szWavePath, szTemp );
if( CRegistry::GetProfileString( section.c_str(), "CheatPath", szTemp, sizeof(szTemp) ) )
::strcpy( path.szCheatPath, szTemp );
// Emulator
section = "Emulation";
emulator.bIllegalOp = (BOOL)CRegistry::GetProfileInt( section.c_str(), "IllegalOp", emulator.bIllegalOp );
emulator.bAutoFrameSkip = (BOOL)CRegistry::GetProfileInt( section.c_str(), "AutoFrameSkip", emulator.bAutoFrameSkip );
emulator.bThrottle = (BOOL)CRegistry::GetProfileInt( section.c_str(), "Throttle", emulator.bThrottle );
emulator.nThrottleFPS = CRegistry::GetProfileInt( section.c_str(), "ThrottleFPS", emulator.nThrottleFPS );
emulator.bBackground = (BOOL)CRegistry::GetProfileInt( section.c_str(), "Background", emulator.bBackground );
emulator.nPriority = CRegistry::GetProfileInt( section.c_str(), "Priority", emulator.nPriority );
emulator.bFourPlayer = (BOOL)CRegistry::GetProfileInt( section.c_str(), "FourPlayer", emulator.bFourPlayer );
emulator.bCrcCheck = (BOOL)CRegistry::GetProfileInt( section.c_str(), "CrcCheck", emulator.bCrcCheck );
emulator.bDiskThrottle = (BOOL)CRegistry::GetProfileInt( section.c_str(), "DiskThrottle", emulator.bDiskThrottle );
emulator.bLoadFullscreen= (BOOL)CRegistry::GetProfileInt( section.c_str(), "LoadFullscreen",emulator.bLoadFullscreen );
emulator.bPNGsnapshot = (BOOL)CRegistry::GetProfileInt( section.c_str(), "PNGsnapshot", emulator.bPNGsnapshot );
// Graphic
section = "Graphics";
graphics.bAspect = (BOOL)CRegistry::GetProfileInt( section.c_str(), "Aspect", graphics.bAspect );
graphics.bAllSprite = (BOOL)CRegistry::GetProfileInt( section.c_str(), "SpriteMax", graphics.bAllSprite );
graphics.bAllLine = (BOOL)CRegistry::GetProfileInt( section.c_str(), "AllLine", graphics.bAllLine );
graphics.bFPSDisp = (BOOL)CRegistry::GetProfileInt( section.c_str(), "FPSDisp", graphics.bFPSDisp );
graphics.bTVFrame = (BOOL)CRegistry::GetProfileInt( section.c_str(), "TVFrameMode", graphics.bTVFrame );
graphics.bScanline = (BOOL)CRegistry::GetProfileInt( section.c_str(), "ScanlineMode", graphics.bScanline );
graphics.nScanlineColor = CRegistry::GetProfileInt( section.c_str(), "ScanlineColor", graphics.nScanlineColor );
graphics.bSyncDraw = (BOOL)CRegistry::GetProfileInt( section.c_str(), "SyncDraw", graphics.bSyncDraw );
graphics.bFitZoom = (BOOL)CRegistry::GetProfileInt( section.c_str(), "MaxZoom", graphics.bFitZoom );
graphics.bLeftClip = (BOOL)CRegistry::GetProfileInt( section.c_str(), "LeftClip", graphics.bLeftClip );
graphics.bWindowVSync = (BOOL)CRegistry::GetProfileInt( section.c_str(), "WindowVSync", graphics.bWindowVSync );
graphics.bSyncNoSleep = (BOOL)CRegistry::GetProfileInt( section.c_str(), "SyncNoSleep", graphics.bSyncNoSleep );
graphics.bDiskAccessLamp= (BOOL)CRegistry::GetProfileInt( section.c_str(), "DiskAccessLamp",graphics.bDiskAccessLamp );
graphics.bDoubleSize = (BOOL)CRegistry::GetProfileInt( section.c_str(), "DoubleSize", graphics.bDoubleSize );
graphics.bSystemMemory = (BOOL)CRegistry::GetProfileInt( section.c_str(), "SystemMemory", graphics.bSystemMemory );
graphics.bUseHEL = (BOOL)CRegistry::GetProfileInt( section.c_str(), "UseHEL", graphics.bUseHEL );
graphics.bNoSquareList = (BOOL)CRegistry::GetProfileInt( section.c_str(), "NoSquareList", graphics.bNoSquareList );
graphics.nGraphicsFilter= CRegistry::GetProfileInt( section.c_str(), "GraphicsFilter",graphics.nGraphicsFilter );
graphics.dwDisplayWidth = (DWORD)CRegistry::GetProfileInt( section.c_str(), "DisplayWidth", graphics.dwDisplayWidth );
graphics.dwDisplayHeight = (DWORD)CRegistry::GetProfileInt( section.c_str(), "DisplayHeight", graphics.dwDisplayHeight );
graphics.dwDisplayDepth = (DWORD)CRegistry::GetProfileInt( section.c_str(), "DisplayDepth", graphics.dwDisplayDepth );
graphics.dwDisplayRate = (DWORD)CRegistry::GetProfileInt( section.c_str(), "DisplayRate", graphics.dwDisplayRate );
graphics.bPaletteFile = (BOOL)CRegistry::GetProfileInt( section.c_str(), "PaletteUse", graphics.bPaletteFile );
if( CRegistry::GetProfileString( section.c_str(), "PaletteFile", szTemp, sizeof(szTemp) ) )
::strcpy( graphics.szPaletteFile, szTemp );
// Sound
section = "Sound";
sound.bEnable = (BOOL)CRegistry::GetProfileInt( section.c_str(), "Enable", sound.bEnable );
sound.nRate = CRegistry::GetProfileInt( section.c_str(), "SamplingRate", sound.nRate );
sound.nBits = CRegistry::GetProfileInt( section.c_str(), "SamplingBits", sound.nBits );
sound.nBufferSize = CRegistry::GetProfileInt( section.c_str(), "BufferSize", sound.nBufferSize );
sound.nFilterType = CRegistry::GetProfileInt( section.c_str(), "FilterType", sound.nFilterType );
sound.bChangeTone = (BOOL)CRegistry::GetProfileInt( section.c_str(), "ChangeTone", sound.bChangeTone );
sound.bDisableVolumeEffect = (BOOL)CRegistry::GetProfileInt( section.c_str(), "DisableVolumeEffect", sound.bDisableVolumeEffect );
sound.bExtraSoundEnable = (BOOL)CRegistry::GetProfileInt( section.c_str(), "ExtraSoundEnable", sound.bExtraSoundEnable );
if( CRegistry::GetProfileBinary( section.c_str(), "Volume", szTemp, sizeof(sound.nVolume) ) )
::memcpy( sound.nVolume, szTemp, sizeof(sound.nVolume) );
// ShortCuts
section = "ShortCut";
for( i = 0; i < sizeof(shortcut.nShortCut)/(16*sizeof(WORD)); i++ ) {
::wsprintf( keys, "Tbl%02d", i );
if( CRegistry::GetProfileBinary( section.c_str(), keys, szTemp, 16*sizeof(WORD) ) )
::memcpy( &shortcut.nShortCut[i*16], szTemp, 16*sizeof(WORD) );
}
// Controllers
for( i = 0; i < 4; i++ ) {
::wsprintf( keys, "Controller %d", i+1 );
if( CRegistry::GetProfileBinary( keys, "Keys", szKeyTemp, 64*sizeof(WORD) ) ) {
::memcpy( controller.nButton[i], szKeyTemp, 64*sizeof(WORD) );
} else if( CRegistry::GetProfileBinary( keys, "Keys", szKeyTemp, 32*sizeof(WORD) ) ) {
// 古い設定を引き継ぐ為の措置
::memcpy( &controller.nButton[i][ 0], &szKeyTemp[ 0], 16*sizeof(WORD) );
::memcpy( &controller.nButton[i][32], &szKeyTemp[16], 16*sizeof(WORD) );
::memcpy( controller.nButton[i], szKeyTemp, 32*sizeof(WORD) );
} else if( CRegistry::GetProfileBinary( keys, "Keys", szKeyTemp, 20*sizeof(WORD) ) ) {
// 古い設定を引き継ぐ為の措置
::memcpy( &controller.nButton[i][ 0], &szKeyTemp[ 0], 10*sizeof(WORD) );
::memcpy( &controller.nButton[i][32], &szKeyTemp[10], 10*sizeof(WORD) );
// Micの変更
if( i == 1 ) {
controller.nButton[i][10] = szKeyTemp[ 8];
controller.nButton[i][ 8] = 0;
controller.nButton[i][42] = szKeyTemp[18];
controller.nButton[i][40] = 0;
}
} else if( CRegistry::GetProfileBinary( keys, "Keys", szKeyTemp, 10*sizeof(WORD) ) ) {
// 古い設定を引き継ぐ為の措置
::memcpy( controller.nButton[i], szKeyTemp, 10*sizeof(WORD) );
// Micの変更
if( i == 1 ) {
controller.nButton[i][10] = szKeyTemp[ 8];
controller.nButton[i][ 8] = 0;
}
}
if( CRegistry::GetProfileBinary( keys, "Rapid", szTemp, 2*sizeof(WORD) ) )
::memcpy( controller.nRapid[i], szTemp, 2*sizeof(WORD) );
}
// ExControllers
for( i = 0; i < 4; i++ ) {
if( i == 0 ) section = "Crazy Climber";
if( i == 1 ) section = "Family Trainer";
if( i == 2 ) section = "Exciting Boxing";
if( i == 3 ) section = "Mahjang";
if( CRegistry::GetProfileBinary( section.c_str(), "Keys", szKeyTemp, 64*sizeof(WORD) ) ) {
::memcpy( controller.nExButton[i], szKeyTemp, 64*sizeof(WORD) );
} else if( CRegistry::GetProfileBinary( section.c_str(), "Keys", szKeyTemp, 32*sizeof(WORD) ) ) {
::memcpy( &controller.nExButton[i][ 0], &szKeyTemp[ 0], 16*sizeof(WORD) );
::memcpy( &controller.nExButton[i][32], &szKeyTemp[16], 16*sizeof(WORD) );
} else if( CRegistry::GetProfileBinary( section.c_str(), "Keys", szKeyTemp, 20*sizeof(WORD) ) ) {
// 古い設定を引き継ぐ為の措置
::memcpy( &controller.nExButton[i][ 0], &szKeyTemp[ 0], 10*sizeof(WORD) );
::memcpy( &controller.nExButton[i][32], &szKeyTemp[10], 10*sizeof(WORD) );
} else if( CRegistry::GetProfileBinary( section.c_str(), "Keys", szKeyTemp, 10*sizeof(WORD) ) ) {
// 古い設定を引き継ぐ為の措置
::memcpy( controller.nExButton[i], szKeyTemp, 10*sizeof(WORD) );
}
}
// NSF Contoller
section = "NSF controller";
if( CRegistry::GetProfileBinary( section.c_str(), "Keys", szKeyTemp, 64*sizeof(WORD) ) ) {
::memcpy( controller.nNsfButton, szKeyTemp, 64*sizeof(WORD) );
} else if( CRegistry::GetProfileBinary( section.c_str(), "Keys", szKeyTemp, 32*sizeof(WORD) ) ) {
::memcpy( &controller.nNsfButton[ 0], &szKeyTemp[ 0], 16*sizeof(WORD) );
::memcpy( &controller.nNsfButton[32], &szKeyTemp[16], 16*sizeof(WORD) );
} else if( CRegistry::GetProfileBinary( section.c_str(), "Keys", szKeyTemp, 20*sizeof(WORD) ) ) {
// 古い設定を引き継ぐ為の措置
::memcpy( &controller.nNsfButton[ 0], &szKeyTemp[ 0], 10*sizeof(WORD) );
::memcpy( &controller.nNsfButton[32], &szKeyTemp[10], 10*sizeof(WORD) );
}
// VS-Unisystem
section = "VS-Unisystem";
if( CRegistry::GetProfileBinary( section.c_str(), "Keys", szKeyTemp, 64*sizeof(WORD) ) ) {
::memcpy( controller.nVSUnisystem, szKeyTemp, 64*sizeof(WORD) );
}
// Movie
section = "Movie";
if( CRegistry::GetProfileBinary( section.c_str(), "UsePlayer", szTemp, sizeof(movie.bUsePlayer) ) )
::memcpy( movie.bUsePlayer, szTemp, sizeof(movie.bUsePlayer) );
movie.bResetRec = (BOOL)CRegistry::GetProfileInt( section.c_str(), "ResetRec", movie.bResetRec );
movie.bRerecord = (BOOL)CRegistry::GetProfileInt( section.c_str(), "Rerecord", movie.bRerecord );
movie.bLoopPlay = (BOOL)CRegistry::GetProfileInt( section.c_str(), "LoopPlay", movie.bLoopPlay );
movie.bPadDisplay = (BOOL)CRegistry::GetProfileInt( section.c_str(), "PadDisplay", movie.bPadDisplay );
// Launcher
section = "Launcher";
if( CRegistry::GetProfileBinary( section.c_str(), "WindowPos", (LPBYTE)&rc, sizeof(RECT) ) )
launcher.rcWindowPos = rc;
if( CRegistry::GetProfileBinary( section.c_str(), "ColumnView", szTemp, sizeof(launcher.bHeaderView) ) )
::memcpy( launcher.bHeaderView, szTemp, sizeof(launcher.bHeaderView) );
if( CRegistry::GetProfileBinary( section.c_str(), "ColumnOrder", szTemp, sizeof(launcher.nHeaderOrder) ) )
::memcpy( launcher.nHeaderOrder, szTemp, sizeof(launcher.nHeaderOrder) );
if( CRegistry::GetProfileBinary( section.c_str(), "ColumnWidth", szTemp, sizeof(launcher.nHeaderWidth) ) )
::memcpy( launcher.nHeaderWidth, szTemp, sizeof(launcher.nHeaderWidth) );
launcher.nListSelect = CRegistry::GetProfileInt( section.c_str(), "ListSelect", launcher.nListSelect );
launcher.bSortDir = (BOOL)CRegistry::GetProfileInt( section.c_str(), "SortDir", launcher.bSortDir );
launcher.nSortType = CRegistry::GetProfileInt( section.c_str(), "SortType", launcher.nSortType );
if( CRegistry::GetProfileBinary( section.c_str(), "ColumnSort", szTemp, sizeof(launcher.nHeaderWidth) ) )
::memcpy( launcher.nHeaderWidth, szTemp, sizeof(launcher.nHeaderWidth) );
if( CRegistry::GetProfileBinary( section.c_str(), "FolderUse", szTemp, sizeof(launcher.bFolderUse) ) )
::memcpy( launcher.bFolderUse, szTemp, sizeof(launcher.bFolderUse) );
for( i = 0; i < 16; i++ ) {
::wsprintf( keys, "Folder%02d", i );
if( CRegistry::GetProfileString( section.c_str(), keys, szTemp, sizeof(szTemp) ) )
::strcpy( launcher.szFolder[i], szTemp );
}
if( CRegistry::GetProfileString( section.c_str(), "LastSelect", szTemp, sizeof(szTemp) ) )
::strcpy( launcher.szLastSelect, szTemp );
launcher.bActivePause = (BOOL)CRegistry::GetProfileInt( section.c_str(), "ActivePause", launcher.bActivePause );
// ExtraSound
section = "ExtraSound";
for( i = ESF_MOEPRO_STRIKE; i <= ESF_MOEPRO_WA; i++ ) {
::wsprintf( keys, "Moepro%02d", i );
if( CRegistry::GetProfileString( section.c_str(), keys, szTemp, sizeof(szTemp) ) )
::strcpy( extsound.szExtSoundFile[i], szTemp );
}
for( i = ESF_DISKSYSTEM_BOOT, j = 0; i <= ESF_DISKSYSTEM_SEEKEND; i++, j++ ) {
::wsprintf( keys, "DiskSound%02d", j );
if( CRegistry::GetProfileString( section.c_str(), keys, szTemp, sizeof(szTemp) ) )
::strcpy( extsound.szExtSoundFile[i], szTemp );
}
// NetPlay
section = "Netplay";
if( CRegistry::GetProfileBinary( section.c_str(), "ChatPos", (LPBYTE)&rc, sizeof(RECT) ) )
netplay.rcChatPos = rc;
if( CRegistry::GetProfileString( section.c_str(), "NickName", szTemp, sizeof(szTemp) ) )
::strcpy( netplay.szNick, szTemp );
netplay.nRecentPort = CRegistry::GetProfileInt( section.c_str(), "RecnetPortNum", netplay.nRecentPort );
for( i = 0; i < netplay.nRecentPort; i++ ) {
::wsprintf( keys, "RecentPort%02d", i );
if( CRegistry::GetProfileString( section.c_str(), keys, szTemp, sizeof(szTemp) ) )
::strcpy( netplay.szRecentPort[i], szTemp );
}
netplay.nRecentHost = CRegistry::GetProfileInt( section.c_str(), "RecnetHostNum", netplay.nRecentHost );
for( i = 0; i < netplay.nRecentHost; i++ ) {
::wsprintf( keys, "RecentHost%02d", i );
if( CRegistry::GetProfileString( section.c_str(), keys, szTemp, sizeof(szTemp) ) )
::strcpy( netplay.szRecentHost[i], szTemp );
}
}
void CConfig::Save()
{
INT i;
string section;
CHAR keys[64];
// General
section = "General";
CRegistry::WriteProfileInt ( section.c_str(), "DoubleExecute", general.bDoubleExecute );
CRegistry::WriteProfileInt ( section.c_str(), "StartupLauncher", general.bStartupLauncher );
// CRegistry::WriteProfileInt( section.c_str(), "WindowPosSave", general.bWindowSave );
CRegistry::WriteProfileInt ( section.c_str(), "WindowZoom", general.bWindowZoom );
CRegistry::WriteProfileBinary( section.c_str(), "WindowPos", (LPBYTE)&general.rcWindowPos, sizeof(RECT) );
CRegistry::WriteProfileInt ( section.c_str(), "ScreenZoom", general.nScreenZoom );
CRegistry::WriteProfileBinary( section.c_str(), "SearchDialogPos", (LPBYTE)&general.rcSearchDlgPos, sizeof(RECT) );
CRegistry::WriteProfileBinary( section.c_str(), "PatternViewPos", (LPBYTE)&general.rcPatternViewPos, sizeof(RECT) );
CRegistry::WriteProfileBinary( section.c_str(), "NameTableViewPos", (LPBYTE)&general.rcNameTableViewPos, sizeof(RECT) );
CRegistry::WriteProfileBinary( section.c_str(), "PaletteViewPos", (LPBYTE)&general.rcPaletteViewPos, sizeof(RECT) );
CRegistry::WriteProfileBinary( section.c_str(), "MemoryViewPos", (LPBYTE)&general.rcMemoryViewPos, sizeof(RECT) );
CRegistry::WriteProfileBinary( section.c_str(), "BarcodePos", (LPBYTE)&general.rcBarcodePos, sizeof(RECT) );
CRegistry::WriteProfileBinary( section.c_str(), "PaletteEditPos", (LPBYTE)&general.rcPaletteEditPos, sizeof(RECT) );
CRegistry::WriteProfileInt ( section.c_str(), "JoyAxisDisable", general.nJoyAxisDisable );
CRegistry::WriteProfileBinary( section.c_str(), "JoyAxisSetting", (LPBYTE)general.JoyAxisSetting, 16*sizeof(WORD) );
// Paths
section = "Path";
CRegistry::WriteProfileInt( section.c_str(), "RomPathUse", path.bRomPath );
CRegistry::WriteProfileInt( section.c_str(), "SavePathUse", path.bSavePath );
CRegistry::WriteProfileInt( section.c_str(), "StatePathUse", path.bStatePath );
CRegistry::WriteProfileInt( section.c_str(), "SnapshotPathUse", path.bSnapshotPath );
CRegistry::WriteProfileInt( section.c_str(), "MoviePathUse", path.bMoviePath );
CRegistry::WriteProfileInt( section.c_str(), "WavePathUse", path.bWavePath );
CRegistry::WriteProfileInt( section.c_str(), "CheatPathUse", path.bCheatPath );
CRegistry::WriteProfileString( section.c_str(), "RomAutoRunPath", path.szRomAutoRunPath );
CRegistry::WriteProfileString( section.c_str(), "RomPath", path.szRomPath );
CRegistry::WriteProfileString( section.c_str(), "SavePath", path.szSavePath );
CRegistry::WriteProfileString( section.c_str(), "StatePath", path.szStatePath );
CRegistry::WriteProfileString( section.c_str(), "SnapshotPath", path.szSnapshotPath );
CRegistry::WriteProfileString( section.c_str(), "MoviePath", path.szMoviePath );
CRegistry::WriteProfileString( section.c_str(), "WavePath", path.szWavePath );
CRegistry::WriteProfileString( section.c_str(), "CheatPath", path.szCheatPath );
// Emulation
section = "Emulation";
CRegistry::WriteProfileInt( section.c_str(), "IllegalOp", emulator.bIllegalOp );
CRegistry::WriteProfileInt( section.c_str(), "AutoFrameSkip", emulator.bAutoFrameSkip );
CRegistry::WriteProfileInt( section.c_str(), "Throttle", emulator.bThrottle );
CRegistry::WriteProfileInt( section.c_str(), "ThrottleFPS", emulator.nThrottleFPS );
CRegistry::WriteProfileInt( section.c_str(), "Background", emulator.bBackground );
CRegistry::WriteProfileInt( section.c_str(), "Priority", emulator.nPriority );
CRegistry::WriteProfileInt( section.c_str(), "FourPlayer", emulator.bFourPlayer );
CRegistry::WriteProfileInt( section.c_str(), "CrcCheck", emulator.bCrcCheck );
CRegistry::WriteProfileInt( section.c_str(), "DiskThrottle", emulator.bDiskThrottle );
CRegistry::WriteProfileInt( section.c_str(), "LoadFullscreen",emulator.bLoadFullscreen );
CRegistry::WriteProfileInt( section.c_str(), "PNGsnapshot", emulator.bPNGsnapshot );
// Graphic
section = "Graphics";
CRegistry::WriteProfileInt( section.c_str(), "Aspect", graphics.bAspect );
CRegistry::WriteProfileInt( section.c_str(), "SpriteMax", graphics.bAllSprite );
CRegistry::WriteProfileInt( section.c_str(), "AllLine", graphics.bAllLine );
CRegistry::WriteProfileInt( section.c_str(), "FPSDisp", graphics.bFPSDisp );
CRegistry::WriteProfileInt( section.c_str(), "TVFrameMode", graphics.bTVFrame );
CRegistry::WriteProfileInt( section.c_str(), "ScanlineMode", graphics.bScanline );
CRegistry::WriteProfileInt( section.c_str(), "ScanlineColor", graphics.nScanlineColor );
CRegistry::WriteProfileInt( section.c_str(), "SyncDraw", graphics.bSyncDraw );
CRegistry::WriteProfileInt( section.c_str(), "MaxZoom", graphics.bFitZoom );
CRegistry::WriteProfileInt( section.c_str(), "LeftClip", graphics.bLeftClip );
CRegistry::WriteProfileInt( section.c_str(), "WindowVSync", graphics.bWindowVSync );
CRegistry::WriteProfileInt( section.c_str(), "DiskAccessLamp",graphics.bDiskAccessLamp );
CRegistry::WriteProfileInt( section.c_str(), "DoubleSize", graphics.bDoubleSize );
CRegistry::WriteProfileInt( section.c_str(), "SystemMemory", graphics.bSystemMemory );
CRegistry::WriteProfileInt( section.c_str(), "UseHEL", graphics.bUseHEL );
CRegistry::WriteProfileInt( section.c_str(), "NoSquareList", graphics.bNoSquareList );
CRegistry::WriteProfileInt( section.c_str(), "GraphicsFilter",graphics.nGraphicsFilter );
CRegistry::WriteProfileInt( section.c_str(), "DisplayWidth", graphics.dwDisplayWidth );
CRegistry::WriteProfileInt( section.c_str(), "DisplayHeight", graphics.dwDisplayHeight );
CRegistry::WriteProfileInt( section.c_str(), "DisplayDepth", graphics.dwDisplayDepth );
CRegistry::WriteProfileInt( section.c_str(), "DisplayRate", graphics.dwDisplayRate );
CRegistry::WriteProfileInt( section.c_str(), "PaletteUse", graphics.bPaletteFile );
CRegistry::WriteProfileString( section.c_str(), "PaletteFile", graphics.szPaletteFile );
// Sound
section = "Sound";
CRegistry::WriteProfileInt( section.c_str(), "Enable", sound.bEnable );
CRegistry::WriteProfileInt( section.c_str(), "DisableVolumeEffect", sound.bDisableVolumeEffect );
CRegistry::WriteProfileInt( section.c_str(), "ExtraSoundEnable", sound.bExtraSoundEnable );
CRegistry::WriteProfileInt( section.c_str(), "SamplingRate", sound.nRate );
CRegistry::WriteProfileInt( section.c_str(), "SamplingBits", sound.nBits );
CRegistry::WriteProfileInt( section.c_str(), "BufferSize", sound.nBufferSize );
CRegistry::WriteProfileInt( section.c_str(), "FilterType", sound.nFilterType );
CRegistry::WriteProfileBinary( section.c_str(), "Volume", (LPBYTE)sound.nVolume, sizeof(sound.nVolume) );
// ShortCut
section = "ShortCut";
for( i = 0; i < sizeof(shortcut.nShortCut)/(16*sizeof(WORD)); i++ ) {
::wsprintf( keys, "TBL%02d", i );
CRegistry::WriteProfileBinary( section.c_str(), keys, (LPBYTE)&shortcut.nShortCut[i*16], 16*sizeof(WORD) );
}
// Controllers
for( i = 0; i < 4; i++ ) {
::wsprintf( keys, "Controller %01d", i+1 );
CRegistry::WriteProfileBinary( keys, "Keys", (LPBYTE)controller.nButton[i], 64*sizeof(WORD) );
CRegistry::WriteProfileBinary( keys, "Rapid", (LPBYTE)controller.nRapid[i], 2*sizeof(WORD) );
}
// ExControllers
section = "Crazy Climber";
CRegistry::WriteProfileBinary( section.c_str(), "Keys", (LPBYTE)controller.nExButton[0], 64*sizeof(WORD) );
section = "Family Trainer";
CRegistry::WriteProfileBinary( section.c_str(), "Keys", (LPBYTE)controller.nExButton[1], 64*sizeof(WORD) );
section = "Exciting Boxing";
CRegistry::WriteProfileBinary( section.c_str(), "Keys", (LPBYTE)controller.nExButton[2], 64*sizeof(WORD) );
section = "Mahjang";
CRegistry::WriteProfileBinary( section.c_str(), "Keys", (LPBYTE)controller.nExButton[3], 64*sizeof(WORD) );
// NSF Contoller
section = "NSF controller";
CRegistry::WriteProfileBinary( section.c_str(), "Keys", (LPBYTE)controller.nNsfButton, 64*sizeof(WORD) );
// VS-Unisystem
section = "VS-Unisystem";
CRegistry::WriteProfileBinary( section.c_str(), "Keys", (LPBYTE)controller.nVSUnisystem, 64*sizeof(WORD) );
// Movie
section = "Movie";
CRegistry::WriteProfileBinary( section.c_str(), "UsePlayer", (LPBYTE)movie.bUsePlayer, sizeof(movie.bUsePlayer) );
CRegistry::WriteProfileInt( section.c_str(), "ResetRec", movie.bResetRec );
CRegistry::WriteProfileInt( section.c_str(), "Rerecord", movie.bRerecord );
CRegistry::WriteProfileInt( section.c_str(), "LoopPlay", movie.bLoopPlay );
CRegistry::WriteProfileInt( section.c_str(), "PadDisplay", movie.bPadDisplay );
// Launcher
section = "Launcher";
CRegistry::WriteProfileBinary( section.c_str(), "WindowPos", (LPBYTE)&launcher.rcWindowPos, sizeof(RECT) );
CRegistry::WriteProfileBinary( section.c_str(), "ColumnView", (LPBYTE)launcher.bHeaderView, sizeof(launcher.bHeaderView) );
CRegistry::WriteProfileBinary( section.c_str(), "ColumnOrder", (LPBYTE)launcher.nHeaderOrder, sizeof(launcher.nHeaderOrder) );
CRegistry::WriteProfileBinary( section.c_str(), "ColumnWidth", (LPBYTE)launcher.nHeaderWidth, sizeof(launcher.nHeaderWidth) );
CRegistry::WriteProfileInt( section.c_str(), "ListSelect", launcher.nListSelect );
CRegistry::WriteProfileInt( section.c_str(), "SortDir", launcher.bSortDir );
CRegistry::WriteProfileInt( section.c_str(), "SortType", launcher.nSortType );
CRegistry::WriteProfileBinary( section.c_str(), "FolderUse", (LPBYTE)launcher.bFolderUse, sizeof(launcher.bFolderUse) );
for( i = 0; i < 16; i++ ) {
::wsprintf( keys, "Folder%02d", i );
CRegistry::WriteProfileString( section.c_str(), keys, launcher.szFolder[i] );
}
CRegistry::WriteProfileString( section.c_str(), "LastSelect", launcher.szLastSelect );
CRegistry::WriteProfileInt( section.c_str(), "ActivePause", launcher.bActivePause );
// NetPlay
section = "Netplay";
CRegistry::WriteProfileBinary( section.c_str(), "ChatPos", (LPBYTE)&netplay.rcChatPos, sizeof(RECT) );
CRegistry::WriteProfileString( section.c_str(), "NickName", netplay.szNick );
CRegistry::WriteProfileInt( section.c_str(), "RecnetPortNum", netplay.nRecentPort );
for( i = 0; i < 16; i++ ) {
::wsprintf( keys, "RecentPort%02d", i );
CRegistry::WriteProfileString( section.c_str(), keys, netplay.szRecentPort[i] );
}
CRegistry::WriteProfileInt( section.c_str(), "RecnetHostNum", netplay.nRecentHost );
for( i = 0; i < 16; i++ ) {
::wsprintf( keys, "RecentHost%02d", i );
CRegistry::WriteProfileString( section.c_str(), keys, netplay.szRecentHost[i] );
}
}
BOOL CConfig::ButtonCheck( INT nNo, INT nID )
{
if( m_bKeyboardDisable ) {
if( (Config.controller.nButton[nNo][nID+ 0] >= 256) && DirectInput.m_Sw[Config.controller.nButton[nNo][nID+ 0]]
|| (Config.controller.nButton[nNo][nID+32] >= 256) && DirectInput.m_Sw[Config.controller.nButton[nNo][nID+32]] )
return TRUE;
} else {
if( Config.controller.nButton[nNo][nID+ 0] && DirectInput.m_Sw[Config.controller.nButton[nNo][nID+ 0]]
|| Config.controller.nButton[nNo][nID+32] && DirectInput.m_Sw[Config.controller.nButton[nNo][nID+32]] )
return TRUE;
}
return FALSE;
}
BOOL CConfig::ExButtonCheck( INT nNo, INT nID )
{
if( Config.controller.nExButton[nNo][nID+ 0] && DirectInput.m_Sw[Config.controller.nExButton[nNo][nID+ 0]]
|| Config.controller.nExButton[nNo][nID+32] && DirectInput.m_Sw[Config.controller.nExButton[nNo][nID+32]] )
return TRUE;
return FALSE;
}
BOOL CConfig::NsfButtonCheck( INT nID )
{
if( Config.controller.nNsfButton[nID+ 0] && DirectInput.m_Sw[Config.controller.nNsfButton[nID+ 0]]
|| Config.controller.nNsfButton[nID+32] && DirectInput.m_Sw[Config.controller.nNsfButton[nID+32]] )
return TRUE;
return FALSE;
}
BOOL CConfig::ButtonCheck( INT nID, WORD* pKey )
{
if( pKey[nID+ 0] && DirectInput.m_Sw[pKey[nID+ 0]]
|| pKey[nID+32] && DirectInput.m_Sw[pKey[nID+32]] )
return TRUE;
return FALSE;
}
string CConfig::ShortcutToKeyName( INT nShortcutKey )
{
string str;
if( nShortcutKey == 0 ) {
str = "----";
} else {
if( nShortcutKey & CCfgShortCut::K_ALT )
str = str + "Alt+";
if( nShortcutKey & CCfgShortCut::K_CTRL )
str = str + "Ctrl+";
if( nShortcutKey & CCfgShortCut::K_SHIFT )
str = str + "Shift+";
str = str + DirectInput.SearchKeyName( nShortcutKey & 0x0FFF );
}
return str;
}
/////////////////////////////////
CGameOption GameOption;
void CGameOption::Load( DWORD crc )
{
CRegistry::SetRegistryKey( "GameOption.ini" );
CHAR szSection[256];
::wsprintf( szSection, "%08X", crc );
nRenderMethod = CRegistry::GetProfileInt( szSection, "RenderMethod", defRenderMethod );
nIRQtype = CRegistry::GetProfileInt( szSection, "IRQtype", defIRQtype );
bFrameIRQ = (BOOL)CRegistry::GetProfileInt( szSection, "FrameIRQ", defFrameIRQ );
bVideoMode = (BOOL)CRegistry::GetProfileInt( szSection, "VideoMode", defVideoMode );
}
void CGameOption::Save( LPCSTR name, DWORD crc )
{
CRegistry::SetRegistryKey( "GameOption.ini" );
CHAR szSection[256];
::wsprintf( szSection, "%08X", crc );
CRegistry::WriteProfileString( szSection, "Title", name );
CRegistry::WriteProfileInt( szSection, "RenderMethod", nRenderMethod );
CRegistry::WriteProfileInt( szSection, "IRQtype", nIRQtype );
CRegistry::WriteProfileInt( szSection, "FrameIRQ", (INT)bFrameIRQ );
CRegistry::WriteProfileInt( szSection, "VideoMode", (INT)bVideoMode );
}
void CGameOption::Load( DWORD gid, DWORD mid )
{
CRegistry::SetRegistryKey( "GameOption.ini" );
CHAR szSection[256];
::wsprintf( szSection, "%08X%08X", gid, mid );
nRenderMethod = CRegistry::GetProfileInt( szSection, "RenderMethod", defRenderMethod );
nIRQtype = CRegistry::GetProfileInt( szSection, "IRQtype", defIRQtype );
bFrameIRQ = (BOOL)CRegistry::GetProfileInt( szSection, "FrameIRQ", defFrameIRQ );
}
void CGameOption::Save( LPCSTR name, DWORD gid, DWORD mid )
{
CRegistry::SetRegistryKey( "GameOption.ini" );
CHAR szSection[256];
::wsprintf( szSection, "%08X%08X", gid, mid );
CRegistry::WriteProfileString( szSection, "Title", name );
CRegistry::WriteProfileInt( szSection, "RenderMethod", nRenderMethod );
CRegistry::WriteProfileInt( szSection, "IRQtype", nIRQtype );
CRegistry::WriteProfileInt( szSection, "FrameIRQ", (INT)bFrameIRQ );
}

View File

@ -0,0 +1,783 @@
//
// 設定保存クラス
//
#ifndef __CCONFIG_INCLUDED__
#define __CCONFIG_INCLUDED__
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdlib.h>
#define DIRECTINPUT_VERSION 0x0700
#include <dinput.h>
#include <string>
using namespace std;
#include "extsoundfile.h"
#include "typedef.h"
#include "macro.h"
class CCfgGeneral
{
public:
BOOL bDoubleExecute;
BOOL bStartupLauncher;
BOOL bWindowSave;
BOOL bWindowZoom;
RECT rcWindowPos;
BOOL bScreenMode;
BOOL nScreenZoom;
RECT rcSearchDlgPos;
RECT rcPatternViewPos;
RECT rcNameTableViewPos;
RECT rcPaletteViewPos;
RECT rcMemoryViewPos;
RECT rcBarcodePos;
RECT rcPaletteEditPos;
BOOL bNoJoystickID;
WORD JoyAxisSetting[16];
// ジョイパッドの軸の無効化
// 0 : All enable
// 1 : X軸以降全て
// 2 : Y軸以降全て
// 3 : Z軸以降全て
// 4 : RX軸以降全て
// 5 : RY軸以降全て
// 6 : RZ軸以降全て
INT nJoyAxisDisable;
void Default() {
bWindowSave = FALSE;
bWindowZoom = FALSE;
rcWindowPos.left = rcWindowPos.right =
rcWindowPos.top = rcWindowPos.bottom = 0;
bDoubleExecute = TRUE;
bStartupLauncher = FALSE;
bScreenMode = FALSE;
nScreenZoom = 0;
rcSearchDlgPos.left = rcSearchDlgPos.right =
rcSearchDlgPos.top = rcSearchDlgPos.bottom = 0;
rcPatternViewPos.left = rcPatternViewPos.right =
rcPatternViewPos.top = rcPatternViewPos.bottom = 0;
rcNameTableViewPos.left = rcNameTableViewPos.right =
rcNameTableViewPos.top = rcNameTableViewPos.bottom = 0;
rcPaletteViewPos.left = rcPaletteViewPos.right =
rcPaletteViewPos.top = rcPaletteViewPos.bottom = 0;
rcMemoryViewPos.left = rcMemoryViewPos.right =
rcMemoryViewPos.top = rcMemoryViewPos.bottom = 0;
rcBarcodePos.left = rcBarcodePos.right =
rcBarcodePos.top = rcBarcodePos.bottom = 0;
rcPaletteEditPos.left = rcPaletteEditPos.right =
rcPaletteEditPos.top = rcPaletteEditPos.bottom = 0;
bNoJoystickID = FALSE;
nJoyAxisDisable = 0;
for( INT i = 0; i < 16; i++ ) {
JoyAxisSetting[i] = 0;
}
}
};
class CCfgPath
{
public:
BOOL bRomAutoRunPath;//ミト<EFBE90>ユlヨェサィ100エ<30><EFBDB4>メメカキ耿<EFBDB7>モオトケヲトワ ト」ト簇<EFBE84>ヒミミハアラヤカッエ<EFBDAF>ェヨクカィホトシ<EFBE84>
BOOL bRomPath;
BOOL bRamPath;
BOOL bSavePath;
BOOL bStatePath;
BOOL bSnapshotPath;
BOOL bMoviePath;
BOOL bWavePath;
BOOL bCheatPath;
CHAR szRomAutoRunPath [_MAX_PATH];
CHAR szRomPath [_MAX_PATH];
CHAR szRamPath [_MAX_PATH];
CHAR szSavePath [_MAX_PATH];
CHAR szStatePath [_MAX_PATH];
CHAR szSnapshotPath[_MAX_PATH];
CHAR szMoviePath [_MAX_PATH];
CHAR szWavePath [_MAX_PATH];
CHAR szCheatPath [_MAX_PATH];
void Default() {
#if 0
bRomPath = bRamPath = bSavePath =
bStatePath = bSnapshotPath =
bMoviePath = bWavePath =
bCheatPath = FALSE;
szRomPath[0] = szRamPath[0] = szSavePath[0] =
szStatePath[0] = szSnapshotPath[0] =
szMoviePath[0] = szWavePath[0] =
szCheatPath[0] = 0;
#endif
bRomPath = bRomPath = bSavePath =
bStatePath = bSnapshotPath =
bMoviePath = bWavePath =
bCheatPath = TRUE;
bRomAutoRunPath = FALSE;
::lstrcpy( szRomAutoRunPath, ".\\" );
::lstrcpy( szRomPath, ".\\roms\\" );
::lstrcpy( szRamPath, ".\\ram\\" );
::lstrcpy( szSavePath, ".\\save\\" );
::lstrcpy( szStatePath, ".\\state\\" );
::lstrcpy( szSnapshotPath, ".\\snapshot\\" );
::lstrcpy( szMoviePath, ".\\movie\\" );
::lstrcpy( szWavePath, ".\\wave\\" );
::lstrcpy( szCheatPath, ".\\cheatcode\\" );
}
};
class CCfgEmulator
{
public:
BOOL bIllegalOp;
BOOL bAutoFrameSkip;
BOOL bThrottle;
INT nThrottleFPS;
BOOL bBackground;
INT nPriority;
BOOL bFourPlayer;
BOOL bCrcCheck;
BOOL bDiskThrottle;
BOOL bLoadFullscreen;
BOOL bPNGsnapshot;
void Default() {
bIllegalOp = FALSE;
bAutoFrameSkip = TRUE;
bThrottle = TRUE;
nThrottleFPS = 120; // 120FPS
bBackground = FALSE;
nPriority = 3; // Normal
bFourPlayer = TRUE; // TRUE:NES FALSE:Famicom
bCrcCheck = TRUE;
bDiskThrottle = TRUE;
bLoadFullscreen = FALSE;
bPNGsnapshot = FALSE;
}
};
class CCfgGraphics
{
public:
BOOL bAspect;
BOOL bAllSprite;
BOOL bAllLine;
BOOL bFPSDisp;
BOOL bTVFrame;
BOOL bScanline;
INT nScanlineColor;
BOOL bSyncDraw;
BOOL bFitZoom;
BOOL bLeftClip;
BOOL bWindowVSync;
BOOL bSyncNoSleep;
BOOL bDiskAccessLamp;
BOOL bDoubleSize;
BOOL bSystemMemory;
BOOL bUseHEL;
BOOL bNoSquareList;
INT nGraphicsFilter;
DWORD dwDisplayWidth;
DWORD dwDisplayHeight;
DWORD dwDisplayDepth;
DWORD dwDisplayRate;
BOOL bPaletteFile;
CHAR szPaletteFile[_MAX_PATH];
void Default() {
bAspect = FALSE;
bAllSprite = TRUE;
bAllLine = FALSE;
bFPSDisp = FALSE;
bTVFrame = FALSE;
bScanline = FALSE;
nScanlineColor = 75;
bSyncDraw = FALSE;
bFitZoom = FALSE;
bLeftClip = TRUE;
bWindowVSync = FALSE;
bSyncNoSleep = FALSE;
bDiskAccessLamp = FALSE;
bDoubleSize = FALSE;
bSystemMemory = FALSE;
bUseHEL = FALSE;
bNoSquareList = FALSE;
nGraphicsFilter = 0;
dwDisplayWidth = 640;
dwDisplayHeight = 480;
dwDisplayDepth = 16;
dwDisplayRate = 0;
bPaletteFile = FALSE;
szPaletteFile[0] = 0;
}
};
class CCfgSound
{
public:
BOOL bEnable;
INT nRate;
INT nBits;
INT nBufferSize;
INT nFilterType;
BOOL bChangeTone;
BOOL bDisableVolumeEffect;
BOOL bExtraSoundEnable;
// 0:Master
// 1:Rectangle 1
// 2:Rectangle 2
// 3:Triangle
// 4:Noise
// 5:DPCM
// 6:VRC6
// 7:VRC7
// 8:FDS
// 9:MMC5
// 10:N106
// 11:FME7
SHORT nVolume[16];
void Default() {
bEnable = TRUE;
nRate = 22050;
nBits = 8;
nBufferSize = 4;
nFilterType = 0;
bChangeTone = FALSE;
bDisableVolumeEffect = FALSE;
bExtraSoundEnable = TRUE;
for( INT i = 0; i < 16; i++ ) {
nVolume[i] = 100;
}
}
};
class CCfgShortCut
{
public:
WORD nShortCut[512];
enum {
K_ALT = 0x8000,
K_CTRL = 0x4000,
K_SHIFT = 0x2000,
};
void Default() {
for( INT i = 0; i < (sizeof(nShortCut)/sizeof(WORD)); i++ ) {
nShortCut[i] = 0;
}
// Main controls
nShortCut[ 0] = DIK_O+K_CTRL; // ID_OPEN
nShortCut[ 1] = DIK_C+K_CTRL; // ID_CLOSE
nShortCut[ 2] = DIK_L+K_CTRL; // ID_LAUNCHER
nShortCut[ 3] = DIK_N+K_CTRL; // ID_NETPLAY_CONNECT
nShortCut[ 4] = DIK_D+K_CTRL; // ID_NETPLAY_DISCONNECT
nShortCut[ 5] = DIK_A+K_CTRL; // ID_NETPLAY_CHAT
nShortCut[ 8] = DIK_I+K_CTRL; // ID_ROMINFO
nShortCut[ 9] = DIK_W+K_CTRL; // ID_WAVERECORD
nShortCut[ 15] = DIK_X+K_CTRL; // ID_EXIT
// Emulation controls
nShortCut[ 16] = DIK_F1; // Hardware reset
nShortCut[ 17] = DIK_F2; // Software reset
nShortCut[ 18] = DIK_P; // Hardware pause
nShortCut[ 19] = DIK_TAB; // Throttle(toggled)
nShortCut[ 20] = DIK_NUMPADENTER; // Frame skip Auto
nShortCut[ 21] = DIK_ADD; // Frame skip +
nShortCut[ 22] = DIK_SUBTRACT; // Frame skip -
nShortCut[ 23] = DIK_SPACE; // One Frame step
nShortCut[ 24] = DIK_BACKSPACE; // Throttle(Not toggle)
// State controls
nShortCut[ 32] = DIK_L; // State Load
nShortCut[ 33] = DIK_S; // State Save
nShortCut[ 34] = DIK_F3; // State Slot +
nShortCut[ 35] = DIK_F4; // State Slot -
// Disk controls
nShortCut[ 48] = DIK_5; // Disk Eject
nShortCut[ 49] = DIK_1; // Disk 0 Side A
nShortCut[ 50] = DIK_2; // Disk 0 Side B
nShortCut[ 51] = DIK_3; // Disk 1 Side A
nShortCut[ 52] = DIK_4; // Disk 1 Side B
// Movie controls
nShortCut[ 56] = DIK_P+K_ALT; // Movie Play
nShortCut[ 57] = DIK_R+K_ALT; // Movie Rec
nShortCut[ 58] = DIK_A+K_ALT; // Movie Rec Append
nShortCut[ 59] = DIK_S+K_ALT; // Movie Stop
nShortCut[ 60] = DIK_M+K_ALT; // Movie Info
// Screen controls
nShortCut[ 64] = DIK_F5; // Zoom x1
nShortCut[ 65] = DIK_F6; // Zoom x2
nShortCut[ 66] = DIK_F7; // Zoom x3
nShortCut[ 67] = DIK_F8; // Zoom x4
nShortCut[ 68] = DIK_RETURN+K_ALT; // Fullscreen
// Sound controls
nShortCut[ 72] = DIK_BACK+K_CTRL; // Mute Master
nShortCut[ 73] = DIK_1+K_CTRL; // Mute Rectangle #1
nShortCut[ 74] = DIK_2+K_CTRL; // Mute Rectangle #2
nShortCut[ 75] = DIK_3+K_CTRL; // Mute Triangle
nShortCut[ 76] = DIK_4+K_CTRL; // Mute Noise
nShortCut[ 77] = DIK_5+K_CTRL; // Mute Dpcm
nShortCut[ 78] = DIK_6+K_CTRL; // Mute External #1
nShortCut[ 79] = DIK_7+K_CTRL; // Mute External #2
nShortCut[ 80] = DIK_8+K_CTRL; // Mute External #3
nShortCut[ 81] = DIK_9+K_CTRL; // Mute External #4
nShortCut[ 82] = DIK_0+K_CTRL; // Mute External #5
nShortCut[ 83] = DIK_MINUS+K_CTRL; // Mute External #6
nShortCut[ 84] = DIK_CIRCUMFLEX+K_CTRL; // Mute External #7
nShortCut[ 85] = DIK_YEN+K_CTRL; // Mute External #8
// Tape controls
nShortCut[ 90] = 0; // Tape Play
nShortCut[ 91] = 0; // Tape Rec
nShortCut[ 92] = 0; // Tape Stop
// Other controls
nShortCut[ 96] = DIK_P+K_CTRL; // Snapshot
nShortCut[ 97] = DIK_F11; // FPSDISP
nShortCut[ 98] = DIK_F12+K_CTRL; // TV Aspect
nShortCut[ 99] = DIK_F11+K_CTRL; // TV frame
nShortCut[100] = DIK_F12; // Scanline
nShortCut[101] = DIK_F9+K_CTRL; // Show 240 lines
nShortCut[102] = DIK_F9; // All sprites
nShortCut[103] = DIK_F10; // Sync draw
nShortCut[104] = DIK_F10+K_CTRL; // Fit screen
nShortCut[105] = 0; // Left clip
// Cheat
nShortCut[110] = DIK_HOME+K_CTRL; // Search
nShortCut[111] = DIK_END+K_CTRL; // Cheat
nShortCut[112] = DIK_INSERT; // Cheat enable
nShortCut[113] = DIK_DELETE; // Cheat disable
nShortCut[114] = 0; // GameGenie
// Tools
nShortCut[116] = 0; // Pattern Viewer
nShortCut[117] = 0; // NameTable Viewer
nShortCut[118] = 0; // Palette Viewer
nShortCut[119] = 0; // Memory Viewer
// Quick Load/Save
nShortCut[256] = DIK_NUMPAD0+K_CTRL; // QuickLoad Slot0
nShortCut[257] = DIK_NUMPAD1+K_CTRL; // QuickLoad Slot1
nShortCut[258] = DIK_NUMPAD2+K_CTRL; // QuickLoad Slot2
nShortCut[259] = DIK_NUMPAD3+K_CTRL; // QuickLoad Slot3
nShortCut[260] = DIK_NUMPAD4+K_CTRL; // QuickLoad Slot4
nShortCut[261] = DIK_NUMPAD5+K_CTRL; // QuickLoad Slot5
nShortCut[262] = DIK_NUMPAD6+K_CTRL; // QuickLoad Slot6
nShortCut[263] = DIK_NUMPAD7+K_CTRL; // QuickLoad Slot7
nShortCut[264] = DIK_NUMPAD8+K_CTRL; // QuickLoad Slot8
nShortCut[265] = DIK_NUMPAD9+K_CTRL; // QuickLoad Slot9
nShortCut[266] = DIK_NUMPAD0+K_ALT; // QuickSave Slot0
nShortCut[267] = DIK_NUMPAD1+K_ALT; // QuickSave Slot1
nShortCut[268] = DIK_NUMPAD2+K_ALT; // QuickSave Slot2
nShortCut[269] = DIK_NUMPAD3+K_ALT; // QuickSave Slot3
nShortCut[270] = DIK_NUMPAD4+K_ALT; // QuickSave Slot4
nShortCut[271] = DIK_NUMPAD5+K_ALT; // QuickSave Slot5
nShortCut[272] = DIK_NUMPAD6+K_ALT; // QuickSave Slot6
nShortCut[273] = DIK_NUMPAD7+K_ALT; // QuickSave Slot7
nShortCut[274] = DIK_NUMPAD8+K_ALT; // QuickSave Slot8
nShortCut[275] = DIK_NUMPAD9+K_ALT; // QuickSave Slot9
}
};
class CCfgLanguage
{
public:
LCID lcID;
CHAR szLanguage[256];
void Default() {
lcID = NULL;
szLanguage[0] = 0;
}
};
class CCfgController
{
public:
WORD nButton[4][64];
WORD nRapid [4][ 2];
// 0:Crazy Climber
// 1:Famly Trainer
// 2:Exciting Boxing
// 3:Mahjang
WORD nExButton[4][64];
WORD nNsfButton[64];
WORD nVSUnisystem[64];
void Default() {
DefaultController1();
DefaultController2();
DefaultController3();
DefaultController4();
DefaultExController0();
DefaultExController1();
DefaultExController2();
DefaultExController3();
DefaultNsfController();
DefaultVSUnisystem();
}
void DefaultController1() {
for( INT i = 0; i < 64; i++ )
nButton[0][i] = 0;
nButton[0][ 0] = DIK_UP;
nButton[0][ 1] = DIK_DOWN;
nButton[0][ 2] = DIK_LEFT;
nButton[0][ 3] = DIK_RIGHT;
nButton[0][ 4] = DIK_X; // A
nButton[0][ 5] = DIK_Z; // B
nButton[0][ 6] = 0; // A Rapid
nButton[0][ 7] = 0; // B Rapid
nButton[0][ 8] = DIK_RSHIFT; // SELECT
nButton[0][ 9] = DIK_RETURN; // START
nRapid[0][0] = 0; // A Rapid speed
nRapid[0][1] = 0; // B Rapid speed
}
void DefaultController2() {
for( INT i = 0; i < 64; i++ )
nButton[1][i] = 0;
nButton[1][ 0] = DIK_NUMPAD8;
nButton[1][ 1] = DIK_NUMPAD2;
nButton[1][ 2] = DIK_NUMPAD4;
nButton[1][ 3] = DIK_NUMPAD6;
nButton[1][ 4] = DIK_N; // A
nButton[1][ 5] = DIK_B; // B
nButton[1][ 6] = 0; // A Rapid
nButton[1][ 7] = 0; // B Rapid
nButton[1][ 8] = 0; // SELECT
nButton[1][ 9] = 0; // START
nButton[1][10] = DIK_M; // Mic
nRapid[1][0] = 0; // A Rapid speed
nRapid[1][1] = 0; // B Rapid speed
}
void DefaultController3() {
for( INT i = 0; i < 64; i++ )
nButton[2][i] = 0;
nRapid[2][0] = 0; // A Rapid speed
nRapid[2][1] = 0; // B Rapid speed
}
void DefaultController4() {
for( INT i = 0; i < 64; i++ )
nButton[3][i] = 0;
nRapid[3][0] = 0; // A Rapid speed
nRapid[3][1] = 0; // B Rapid speed
}
void DefaultExController0() {
// Crazy Climberコントローラ(実際には存在しない)
for( INT i = 0; i < 64; i++ )
nExButton[0][i] = 0;
// nExButton[0][ 0] = 0; // L up
// nExButton[0][ 1] = 0; // L down
// nExButton[0][ 2] = 0; // L left
// nExButton[0][ 3] = 0; // L right
// nExButton[0][ 4] = 0; // R up
// nExButton[0][ 5] = 0; // R down
// nExButton[0][ 6] = 0; // R left
// nExButton[0][ 7] = 0; // R right
}
void DefaultExController1() {
// Famly Trainerコントローラ
for( INT i = 0; i < 64; i++ )
nExButton[1][i] = 0;
}
void DefaultExController2() {
// Exciting Boxingコントローラ
for( INT i = 0; i < 64; i++ )
nExButton[2][i] = 0;
}
void DefaultExController3() {
// Mahjangコントローラ
for( INT i = 0; i < 64; i++ )
nExButton[3][i] = 0;
}
void DefaultNsfController() {
for( INT i = 0; i < 64; i++ )
nNsfButton[i] = 0;
nNsfButton[ 0] = DIK_UP; // Play
nNsfButton[ 1] = DIK_DOWN; // Stop
nNsfButton[ 2] = DIK_LEFT; // Number -1
nNsfButton[ 3] = DIK_RIGHT; // Number +1
nNsfButton[ 4] = DIK_PRIOR; // Number +16
nNsfButton[ 5] = DIK_NEXT; // Number -16
}
void DefaultVSUnisystem() {
for( INT i = 0; i < 64; i++ )
nVSUnisystem[i] = 0;
nVSUnisystem[0] = DIK_C; // Coin
}
};
class CCfgMovie
{
public:
BYTE bUsePlayer[4];
BOOL bRerecord;
BOOL bLoopPlay;
BOOL bResetRec;
BOOL bPadDisplay;
void Default() {
bUsePlayer[0] = 0xFF;
bUsePlayer[1] = 0x00;
bUsePlayer[2] = 0x00;
bUsePlayer[3] = 0x00;
bRerecord = TRUE;
bLoopPlay = FALSE;
bResetRec = FALSE;
bPadDisplay = FALSE;
}
};
class CCfgLauncher
{
public:
RECT rcWindowPos;
BYTE bHeaderView [16];
BYTE nHeaderOrder[16];
SHORT nHeaderWidth[16];
BOOL bActivePause;
INT nListSelect;
BOOL bSortDir;
INT nSortType;
BYTE bFolderUse[16];
CHAR szFolder[16][_MAX_PATH];
CHAR szLastSelect[_MAX_PATH];
void Default() {
rcWindowPos.left = rcWindowPos.right =
rcWindowPos.top = rcWindowPos.bottom = 0;
bActivePause = FALSE;
nListSelect = 0;
bSortDir = FALSE;
nSortType = 0;
INT i;
for( i = 0; i < 16; i++ ) {
bHeaderView [i] = TRUE;
nHeaderOrder[i] = i;
nHeaderWidth[i] = (i==0)?160:48;
}
for( i = 0; i < 16; i++ ) {
bFolderUse[i] = FALSE;
szFolder[i][0] = '\0';
}
szLastSelect[0] = '\0';
}
};
class CCfgExtraSound
{
public:
CHAR szExtSoundFile[ ESF_FILE_MAX ][ MAX_PATH ];
void Default() {
for( INT i = 0; i < ESF_FILE_MAX; i++ ) {
szExtSoundFile[i][0] = '\0';
}
}
};
class CCfgNetPlay
{
public:
RECT rcChatPos;
INT nRecentPort, nRecentHost;
CHAR szRecentPort[16][_MAX_PATH+1];
CHAR szRecentHost[16][_MAX_PATH+1];
CHAR szNick[_MAX_PATH+1];
void Default() {
rcChatPos.left = rcChatPos.right =
rcChatPos.top = rcChatPos.bottom = 0;
::lstrcpy( szNick, "NoName" );
for( INT i = 0; i < 16; i++ ) {
szRecentPort[i][0] = '\0';
szRecentHost[i][0] = '\0';
}
::lstrcpy( szRecentPort[0], "10000" );
::lstrcpy( szRecentHost[0], "localhost:10000" );
nRecentPort = 1;
nRecentHost = 1;
}
};
class CConfig
{
public:
CConfig() {
m_bKeyboardDisable = FALSE;
Default();
}
CCfgGeneral general;
CCfgPath path;
CCfgEmulator emulator;
CCfgGraphics graphics;
CCfgSound sound;
CCfgShortCut shortcut;
CCfgLanguage language;
CCfgController controller;
CCfgMovie movie;
CCfgLauncher launcher;
CCfgExtraSound extsound;
CCfgNetPlay netplay;
void Default() {
general.Default();
path.Default();
emulator.Default();
graphics.Default();
sound.Default();
shortcut.Default();
language.Default();
controller.Default();
movie.Default();
launcher.Default();
extsound.Default();
netplay.Default();
}
void Load();
void Save();
// Checker
void InputKeyboardDisable( BOOL bEnable ) {
m_bKeyboardDisable = bEnable;
}
BOOL ButtonCheck( INT nNo, INT nID );
BOOL ExButtonCheck( INT nNo, INT nID );
BOOL NsfButtonCheck( INT nID );
BOOL ButtonCheck( INT nID, WORD* pKey );
// Converter
string ShortcutToKeyName( INT nShortcut );
// Table
static INT SamplingRateTable[];
static INT ShortcutKeyID[];
protected:
BOOL m_bKeyboardDisable;
private:
};
// 個別ゲームオプション
class CGameOption
{
public:
// for Cartridge
void Load( DWORD crc );
void Save( LPCSTR name, DWORD crc );
// for FDS
void Load( DWORD gid, DWORD mid );
void Save( LPCSTR name, DWORD gid, DWORD mid );
// Default保存
INT defRenderMethod;
INT defIRQtype;
BOOL defFrameIRQ;
BOOL defVideoMode;
// データ
INT nRenderMethod;
INT nIRQtype;
BOOL bFrameIRQ;
BOOL bVideoMode;
protected:
private:
};
extern CConfig Config;
extern CGameOption GameOption;
#endif // !__CCONFIG_INCLUDED__

View File

@ -0,0 +1,516 @@
//
// コントローラダイアログクラス
//
//
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <mmsystem.h>
#include <string>
using namespace std;
#include "VirtuaNESres.h"
#include "DebugOut.h"
#include "App.h"
#include "Pathlib.h"
#include "Wnd.h"
#include "ControllerDlg.h"
#include "DirectInput.h"
///////////////////////////////////////////////////////////////////////////////
DLG_MESSAGE_BEGIN(CControllerPageDlg)
// メッセージ
DLG_ON_MESSAGE( WM_INITDIALOG, OnInitDialog )
// NOTIFYメッセージ
DLG_NOTIFY_BEGIN()
DLG_NOTIFY_END()
// コマンド
DLG_COMMAND_BEGIN()
DLG_ON_COMMAND_NOTIFY_RANGE( IDC_CTR_UP, IDC_CTR_END, STN_CLICKED, OnClicked )
DLG_COMMAND_END()
DLG_MESSAGE_END()
INT CControllerPageDlg::Create( UINT nID, HWND hWndParent )
{
m_nPageID = nID;
m_hWnd = ::CreateDialogParam( CApp::GetPlugin(), MAKEINTRESOURCE(nID),
hWndParent, g_DlgProc, (LPARAM)this );
return (m_hWnd)?TRUE:FALSE;
}
void CControllerPageDlg::Destroy()
{
::DestroyWindow( m_hWnd );
}
DLGCMD CControllerPageDlg::OnClicked( DLGCMDPARAM )
{
// DEBUGOUT( "CControllerPageDlg::OnClicked uID=%d\n", uID );
// 親のタブコントロールをパスしてメッセージを通知:p
HWND hWndParent, hWndOwner;
hWndParent = ::GetParent( m_hWnd );
hWndOwner = ::GetParent( hWndParent );
::SendMessage( hWndOwner, WM_COMMAND, MAKELPARAM(uID,STN_CLICKED), (LPARAM)::GetDlgItem(m_hWnd,uID) );
}
DLGMSG CControllerPageDlg::OnInitDialog( DLGMSGPARAM )
{
// DEBUGOUT( "CControllerPageDlg::OnInitDialog\n" );
return TRUE;
}
///////////////////////////////////////////////////////////////////////////////
UINT CControllerDlg::ControllerPageID[] = {
IDD_CTR_PLAYER1,
IDD_CTR_PLAYER2,
IDD_CTR_PLAYER3,
IDD_CTR_PLAYER4,
IDD_CTR_CRAZYCLIMBER,
IDD_CTR_FAMLYTRAINER,
IDD_CTR_EXCITINGBOXING,
IDD_CTR_MAHJANG,
IDD_CTR_NSFPLAYER,
IDD_CTR_VSUNISYSTEM,
0
};
DLG_MESSAGE_BEGIN(CControllerDlg)
// メッセージ
DLG_ON_MESSAGE( WM_INITDIALOG, OnInitDialog )
DLG_ON_MESSAGE( WM_DESTROY, OnDestroy )
DLG_ON_MESSAGE( WM_TIMER, OnTimer )
// NOTIFYメッセージ
DLG_NOTIFY_BEGIN()
DLG_ON_NOTIFY( IDC_CTR_TAB, TCN_SELCHANGE, OnSelectChange )
DLG_NOTIFY_END()
// コマンド
DLG_COMMAND_BEGIN()
DLG_ON_COMMAND( IDOK, OnOK )
DLG_ON_COMMAND( IDCANCEL, OnCancel )
DLG_ON_COMMAND( IDDEFAULT, OnDefault )
DLG_ON_COMMAND_NOTIFY_RANGE( IDC_CTR_UP, IDC_CTR_END, STN_CLICKED, OnClicked )
DLG_ON_COMMAND_NOTIFY( IDC_CTR_SELECT_COMBO, CBN_SELCHANGE, OnSettingSelectChange )
DLG_COMMAND_END()
DLG_MESSAGE_END()
INT CControllerDlg::DoModal( HWND hWndParent )
{
m_bCancelMode = FALSE;
m_TimerID = 0;
m_SettingSel = 0;
return ::DialogBoxParam( CApp::GetPlugin(), MAKEINTRESOURCE(IDD_CFG_CONTROLLER),
hWndParent, g_DlgProc, (LPARAM)this );
}
BOOL CControllerDlg::PreTranslateMessage( MSG* pMsg )
{
if( pMsg->message >= WM_KEYFIRST && pMsg->message <= WM_KEYLAST ) {
// DEBUGOUT( "CControllerDlg::PreTranslateMessage WM_KEY????\n" );
return m_bCancelMode;
}
return FALSE;
}
void CControllerDlg::OnInitialMember()
{
HWND hWndCtrl = ::GetDlgItem( m_hWnd, IDC_CTR_TAB );
RECT rcT, rcP, rcW;
INT page;
// for( INT page = 0; ControllerPageID[page]; page++ ) {
for( page = 0; ControllerPageID[page]; page++ ) {
m_Page[page].Create( ControllerPageID[page], hWndCtrl );
// 名前の取得
CHAR szTitle[256];
::GetWindowText( m_Page[page].m_hWnd, szTitle, sizeof(szTitle) );
// 名前を取得したらキャプションを消す
LONG style;
style = ::GetWindowLong( m_Page[page].m_hWnd, GWL_STYLE );
style &= ~(WS_CAPTION|WS_BORDER|WS_OVERLAPPED);
::SetWindowLong( m_Page[page].m_hWnd, GWL_STYLE, style );
// サイズ変更
::GetWindowRect( m_Page[page].m_hWnd, &rcW );
rcW.right -= ::GetSystemMetrics( SM_CXSIZEFRAME );
rcW.bottom -= ::GetSystemMetrics( SM_CYCAPTION )+::GetSystemMetrics( SM_CYSIZEFRAME )*2;
::SetWindowPos( m_Page[page].m_hWnd, NULL, 0, 0, RCWIDTH(rcW), RCHEIGHT(rcW), SWP_NOMOVE|SWP_NOZORDER );
// タブに名前を設定する
TCITEM tcitem;
tcitem.mask = TCIF_TEXT;
tcitem.pszText = szTitle;
TabCtrl_InsertItem( hWndCtrl, page, &tcitem );
// // ページ位置の補正
// ::GetClientRect( hWndCtrl, &rcT );
// TabCtrl_AdjustRect( hWndCtrl, FALSE, &rcT );
// ::GetWindowRect( m_Page[page].m_hWnd, &rcP );
// 計算
// rcW.left = rcT.left + (RCWIDTH(rcT)-RCWIDTH(rcP))/2;
// rcW.top = rcT.top + (RCHEIGHT(rcT)-RCHEIGHT(rcP))/2;
// rcW.right = rcW.left + RCWIDTH(rcP);
// rcW.bottom = rcW.top + RCHEIGHT(rcP);
// ::SetWindowPos( m_Page[page].m_hWnd, NULL, rcW.left, rcW.top, RCWIDTH(rcW), RCHEIGHT(rcW), SWP_NOZORDER|SWP_NOACTIVATE );
// 各ページのリストボックスの設定
if( page < 4 ) {
HWND hWndList;
hWndList = ::GetDlgItem( m_Page[page].m_hWnd, IDC_CTR_A_RAPID_LIST );
::SendMessage( hWndList, LB_INSERTSTRING, 0, (LPARAM)" 10FPS" );
::SendMessage( hWndList, LB_INSERTSTRING, 1, (LPARAM)" 15FPS" );
::SendMessage( hWndList, LB_INSERTSTRING, 2, (LPARAM)" 20FPS" );
::SendMessage( hWndList, LB_INSERTSTRING, 3, (LPARAM)" 30FPS" );
hWndList = ::GetDlgItem( m_Page[page].m_hWnd, IDC_CTR_B_RAPID_LIST );
::SendMessage( hWndList, LB_INSERTSTRING, 0, (LPARAM)" 10FPS" );
::SendMessage( hWndList, LB_INSERTSTRING, 1, (LPARAM)" 15FPS" );
::SendMessage( hWndList, LB_INSERTSTRING, 2, (LPARAM)" 20FPS" );
::SendMessage( hWndList, LB_INSERTSTRING, 3, (LPARAM)" 30FPS" );
}
// ボタン名等の設定
OnPageSetup( page );
::ShowWindow( m_Page[page].m_hWnd, (page==0)?SW_SHOW:SW_HIDE );
}
// ページ位置再調整
for( page = 0; ControllerPageID[page]; page++ ) {
// ページ位置の補正
::GetClientRect( hWndCtrl, &rcT );
TabCtrl_AdjustRect( hWndCtrl, FALSE, &rcT );
::GetWindowRect( m_Page[page].m_hWnd, &rcP );
// 計算
rcW.left = rcT.left + (RCWIDTH(rcT)-RCWIDTH(rcP))/2;
rcW.top = rcT.top + (RCHEIGHT(rcT)-RCHEIGHT(rcP))/2;
rcW.right = rcW.left + RCWIDTH(rcP);
rcW.bottom = rcW.top + RCHEIGHT(rcP);
::SetWindowPos( m_Page[page].m_hWnd, NULL, rcW.left, rcW.top, RCWIDTH(rcW), RCHEIGHT(rcW), SWP_NOZORDER|SWP_NOACTIVATE );
}
TabCtrl_SetCurSel( hWndCtrl, 0 );
m_PageSel = 0;
m_PageNum = page;
// 設定コンボボックス
::SendDlgItemMessage( m_hWnd, IDC_CTR_SELECT_COMBO, CB_RESETCONTENT, 0, 0 );
CHAR szStr[64];
for( INT i = IDS_CTR_SELECT1; i <= IDS_CTR_SELECT2; i++ ) {
CApp::LoadString( i, szStr, sizeof(szStr) );
::SendDlgItemMessage( m_hWnd, IDC_CTR_SELECT_COMBO, CB_INSERTSTRING, (WPARAM)i-IDS_CTR_SELECT1, (LPARAM)szStr );
}
::SendDlgItemMessage( m_hWnd, IDC_CTR_SELECT_COMBO, CB_SETCURSEL, 0, 0 );
}
void CControllerDlg::OnPageSetup( UINT nPage )
{
HWND hWnd = m_Page[nPage].m_hWnd;
HWND hWndCtrl;
INT nKey;
LPCSTR lpStr;
INT nOffset = m_SettingSel?32:0;
for( INT nID = IDC_CTR_UP; nID <= IDC_CTR_END; nID++ ) {
if( (hWndCtrl = ::GetDlgItem( hWnd, nID )) ) {
if( nPage < 4 ) {
nKey = Config.controller.nButton[nPage][nID-IDC_CTR_UP+nOffset];
} else if( ControllerPageID[nPage] == IDD_CTR_CRAZYCLIMBER ) {
nKey = Config.controller.nExButton[0][nID-IDC_CTR_UP+nOffset];
} else if( ControllerPageID[nPage] == IDD_CTR_FAMLYTRAINER ) {
nKey = Config.controller.nExButton[1][nID-IDC_CTR_UP+nOffset];
} else if( ControllerPageID[nPage] == IDD_CTR_EXCITINGBOXING ) {
nKey = Config.controller.nExButton[2][nID-IDC_CTR_UP+nOffset];
} else if( ControllerPageID[nPage] == IDD_CTR_MAHJANG ) {
nKey = Config.controller.nExButton[3][nID-IDC_CTR_UP+nOffset];
} else if( ControllerPageID[nPage] == IDD_CTR_NSFPLAYER ) {
nKey = Config.controller.nNsfButton[nID-IDC_CTR_UP+nOffset];
} else if( ControllerPageID[nPage] == IDD_CTR_VSUNISYSTEM ) {
nKey = Config.controller.nVSUnisystem[nID-IDC_CTR_UP+nOffset];
}
if( (lpStr = DirectInput.SearchKeyName(nKey)) ) {
::SetWindowText( hWndCtrl, lpStr );
} else {
::SetWindowText( hWndCtrl, "----" );
}
::InvalidateRect( hWndCtrl, NULL, TRUE );
}
}
if( nPage < 4 ) {
::SendDlgItemMessage( hWnd, IDC_CTR_A_RAPID_LIST, LB_SETCURSEL,
(WPARAM)Config.controller.nRapid[nPage][0], 0 );
::SendDlgItemMessage( hWnd, IDC_CTR_B_RAPID_LIST, LB_SETCURSEL,
(WPARAM)Config.controller.nRapid[nPage][1], 0 );
}
}
DLGMSG CControllerDlg::OnInitDialog( DLGMSGPARAM )
{
// DEBUGOUT( "CControllerDlg::OnInitDialog\n" );
m_ConfigSave = Config.controller;
OnInitialMember();
return TRUE;
}
DLGMSG CControllerDlg::OnDestroy( DLGMSGPARAM )
{
// DEBUGOUT( "CControllerDlg::OnDestroy\n" );
// チャイルドウインドウを破棄
for( INT i = 0; i < m_PageNum; i++ ) {
::DestroyWindow( m_Page[i].m_hWnd );
}
return FALSE;
}
DLGNOTIFY CControllerDlg::OnSelectChange( DLGNOTIFYPARAM )
{
// DEBUGOUT( "CControllerDlg::OnSelectChange\n" );
HWND hWndCtrl = ::GetDlgItem( m_hWnd, IDC_CTR_TAB );
m_PageSel = TabCtrl_GetCurSel( hWndCtrl );
OnPageSetup( m_PageSel );
for( INT i = 0; i < m_PageNum; i++ ) {
if( i == m_PageSel ) {
::ShowWindow( m_Page[i].m_hWnd, SW_SHOW );
} else {
::ShowWindow( m_Page[i].m_hWnd, SW_HIDE );
}
}
if( m_TimerID ) {
::KillTimer( m_hWnd, m_TimerID );
m_TimerID = 0;
m_ControlID = 0;
// ::InvalidateRect( hWndCtrl, NULL, TRUE );
}
m_bCancelMode = FALSE;
}
DLGNOTIFY CControllerDlg::OnSettingSelectChange( DLGCMDPARAM )
{
// DEBUGOUT( "CControllerDlg::OnSettingSelectChange\n" );
if( m_TimerID ) {
::KillTimer( m_hWnd, m_TimerID );
m_TimerID = 0;
m_ControlID = 0;
// ::InvalidateRect( ::GetDlgItem( m_hWnd, IDC_CTR_TAB ), NULL, TRUE );
}
m_bCancelMode = FALSE;
m_SettingSel = ::SendDlgItemMessage( m_hWnd, IDC_CTR_SELECT_COMBO, CB_GETCURSEL, 0, 0 );
OnPageSetup( m_PageSel );
}
DLGCMD CControllerDlg::OnClicked( DLGCMDPARAM )
{
// DEBUGOUT( "CControllerDlg::OnClicked uID=%d\n", uID );
if( !m_TimerID ) {
m_ControlID = uID;
m_TimerCount = 0;
m_TimerID = ::SetTimer( m_hWnd, 1, 50, NULL );
m_bCancelMode = TRUE;
}
}
DLGMSG CControllerDlg::OnTimer( DLGMSGPARAM )
{
HWND hWndCtrl = ::GetDlgItem( m_Page[m_PageSel].m_hWnd, m_ControlID );
INT nID = m_ControlID - IDC_CTR_UP;
INT nOffset = m_SettingSel?32:0;
if( wParam == (WPARAM)m_TimerID ) {
if( m_TimerCount == 0 )
m_TimerStart = ::timeGetTime();
m_TimerCount++;
DirectInput.Poll();
if( m_TimerCount > 60 ) {
// TimeOut
if( m_TimerID ) {
::KillTimer( m_hWnd, m_TimerID );
m_TimerID = 0;
m_ControlID = 0;
::InvalidateRect( hWndCtrl, NULL, TRUE );
}
m_bCancelMode = FALSE;
} else {
// Button push?
BOOL bSet = FALSE;
INT i;
LPCSTR str;
// Set cancel
if( DirectInput.m_Sw[DIK_ESCAPE] ) {
if( m_PageSel < 4 ) {
Config.controller.nButton[m_PageSel][nID+nOffset] = 0;
} else if( ControllerPageID[m_PageSel] == IDD_CTR_CRAZYCLIMBER ) {
Config.controller.nExButton[0][nID+nOffset] = 0;
} else if( ControllerPageID[m_PageSel] == IDD_CTR_FAMLYTRAINER ) {
Config.controller.nExButton[1][nID+nOffset] = 0;
} else if( ControllerPageID[m_PageSel] == IDD_CTR_EXCITINGBOXING ) {
Config.controller.nExButton[2][nID+nOffset] = 0;
} else if( ControllerPageID[m_PageSel] == IDD_CTR_MAHJANG ) {
Config.controller.nExButton[3][nID+nOffset] = 0;
} else if( ControllerPageID[m_PageSel] == IDD_CTR_NSFPLAYER ) {
Config.controller.nNsfButton[nID+nOffset] = 0;
} else if( ControllerPageID[m_PageSel] == IDD_CTR_VSUNISYSTEM ) {
Config.controller.nVSUnisystem[nID+nOffset] = 0;
}
::SetWindowText( hWndCtrl, "----" );
bSet = TRUE;
} else {
for( i = 0; i < 512; i++ ) {
if( DirectInput.m_Sw[i] ) {
if( (str=DirectInput.SearchKeyName( i )) ) {
if( m_PageSel < 4 ) {
Config.controller.nButton[m_PageSel][nID+nOffset] = i;
} else if( ControllerPageID[m_PageSel] == IDD_CTR_CRAZYCLIMBER ) {
Config.controller.nExButton[0][nID+nOffset] = i;
} else if( ControllerPageID[m_PageSel] == IDD_CTR_FAMLYTRAINER ) {
Config.controller.nExButton[1][nID+nOffset] = i;
} else if( ControllerPageID[m_PageSel] == IDD_CTR_EXCITINGBOXING ) {
Config.controller.nExButton[2][nID+nOffset] = i;
} else if( ControllerPageID[m_PageSel] == IDD_CTR_MAHJANG ) {
Config.controller.nExButton[3][nID+nOffset] = i;
} else if( ControllerPageID[m_PageSel] == IDD_CTR_NSFPLAYER ) {
Config.controller.nNsfButton[nID+nOffset] = i;
} else if( ControllerPageID[m_PageSel] == IDD_CTR_VSUNISYSTEM ) {
Config.controller.nVSUnisystem[nID+nOffset] = i;
}
::SetWindowText( hWndCtrl, str );
bSet = TRUE;
}
}
}
}
if( bSet ) {
// Button Pressed
if( m_TimerID ) {
::KillTimer( m_hWnd, m_TimerID );
m_TimerID = 0;
m_ControlID = 0;
::InvalidateRect( hWndCtrl, NULL, TRUE );
}
m_bCancelMode = FALSE;
} else {
// Flashing
HDC hDC = ::GetDC( hWndCtrl );
RECT rc;
::GetClientRect( hWndCtrl, &rc );
DWORD c = ((::timeGetTime()-m_TimerStart)/3)&0xFF;
if( c > 0x7F )
c = 0x80 - (c - 0x7F);
c *= 2;
::SetBkColor( hDC, RGB(c,c,c) );
::ExtTextOut( hDC, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL );
::ReleaseDC( hWndCtrl, hDC );
}
}
}
return FALSE;
}
DLGCMD CControllerDlg::OnOK( DLGCMDPARAM )
{
// DEBUGOUT( "CControllerDlg::OnOK\n" );
if( m_TimerID ) {
::KillTimer( m_hWnd, m_TimerID );
m_TimerID = 0;
m_ControlID = 0;
}
m_bCancelMode = FALSE;
for( INT page = 0; page < 4; page++ ) {
Config.controller.nRapid[page][0] = ::SendDlgItemMessage( m_Page[page].m_hWnd, IDC_CTR_A_RAPID_LIST, LB_GETCURSEL, 0, 0 );
Config.controller.nRapid[page][1] = ::SendDlgItemMessage( m_Page[page].m_hWnd, IDC_CTR_B_RAPID_LIST, LB_GETCURSEL, 0, 0 );
}
::EndDialog( m_hWnd, IDOK );
}
DLGCMD CControllerDlg::OnCancel( DLGCMDPARAM )
{
// DEBUGOUT( "CControllerDlg::OnCancel\n" );
// if( m_bCancelMode )
// return;
if( m_TimerID ) {
::KillTimer( m_hWnd, m_TimerID );
m_TimerID = 0;
m_ControlID = 0;
}
m_bCancelMode = FALSE;
Config.controller = m_ConfigSave;
::EndDialog( m_hWnd, IDCANCEL );
}
DLGCMD CControllerDlg::OnDefault( DLGCMDPARAM )
{
// DEBUGOUT( "CControllerDlg::OnDefault\n" );
if( m_TimerID ) {
::KillTimer( m_hWnd, m_TimerID );
m_TimerID = 0;
m_ControlID = 0;
}
m_bCancelMode = FALSE;
switch( ControllerPageID[m_PageSel] ) {
case IDD_CTR_PLAYER1:
Config.controller.DefaultController1();
break;
case IDD_CTR_PLAYER2:
Config.controller.DefaultController2();
break;
case IDD_CTR_PLAYER3:
Config.controller.DefaultController3();
break;
case IDD_CTR_PLAYER4:
Config.controller.DefaultController4();
break;
case IDD_CTR_CRAZYCLIMBER:
Config.controller.DefaultExController0();
break;
case IDD_CTR_FAMLYTRAINER:
Config.controller.DefaultExController1();
break;
case IDD_CTR_EXCITINGBOXING:
Config.controller.DefaultExController2();
break;
case IDD_CTR_MAHJANG:
Config.controller.DefaultExController3();
break;
case IDD_CTR_NSFPLAYER:
Config.controller.DefaultNsfController();
break;
case IDD_CTR_VSUNISYSTEM:
Config.controller.DefaultVSUnisystem();
break;
default:
break;
}
OnPageSetup( m_PageSel );
}

View File

@ -0,0 +1,81 @@
//
// コントローラダイアログクラス
//
#ifndef __CCONTROLLERDLG_INCLUDED__
#define __CCONTROLLERDLG_INCLUDED__
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <string>
using namespace std;
#include "Wnd.h"
#include "Config.h"
class CControllerPageDlg : public CWnd
{
public:
BOOL Create( UINT nID, HWND hWndParent );
// Override from CWnd
void Destroy();
protected:
// Message map
DLG_MESSAGE_MAP()
DLGMSG OnInitDialog( DLGMSGPARAM );
DLGCMD OnClicked( DLGCMDPARAM );
//
UINT m_nPageID;
private:
};
class CControllerDlg : public CWnd
{
public:
// Override from CWnd
INT DoModal( HWND hWndParent );
// Override from CWnd
BOOL PreTranslateMessage( MSG* pMsg );
protected:
void OnInitialMember();
void OnPageSetup( UINT nPage );
// Message map
DLG_MESSAGE_MAP()
DLGMSG OnInitDialog( DLGMSGPARAM );
DLGMSG OnDestroy( DLGMSGPARAM );
DLGMSG OnTimer( DLGMSGPARAM );
DLGNOTIFY OnSelectChange( DLGNOTIFYPARAM );
DLGNOTIFY OnSettingSelectChange( DLGCMDPARAM );
DLGCMD OnClicked( DLGCMDPARAM );
DLGCMD OnOK( DLGCMDPARAM );
DLGCMD OnCancel( DLGCMDPARAM );
DLGCMD OnDefault( DLGCMDPARAM );
//
enum { PAGE_MAX=12 };
BOOL m_bCancelMode;
INT m_ControlID;
INT m_TimerID;
INT m_TimerStart;
INT m_TimerCount;
INT m_SettingSel;
INT m_PageSel;
INT m_PageNum;
CControllerPageDlg m_Page[PAGE_MAX];
CCfgController m_ConfigSave;
static UINT ControllerPageID[];
private:
};
#endif // !__CCONTROLLERDLG_INCLUDED__

View File

@ -0,0 +1,71 @@
//
// CRCチェック用ライブラリクラス
//
#include "Crclib.h"
BOOL CRC::m_Init = FALSE;
BOOL CRC::m_InitRev = FALSE;
DWORD CRC::m_CrcTable[ UCHAR_MAX+1 ];
DWORD CRC::m_CrcTableRev[ UCHAR_MAX+1 ];
#define CRCPOLY1 0x04C11DB7UL
#define CRCPOLY2 0xEDB88320UL
DWORD CRC::Crc( INT size, LPBYTE c )
{
if( !m_Init ) {
MakeTable();
m_Init = TRUE;
}
DWORD r = 0xFFFFFFFFUL;
while( --size >= 0 ) {
r = (r << CHAR_BIT) ^ m_CrcTable[(BYTE)(r >> (32 - CHAR_BIT)) ^ *c++];
}
return ~r & 0xFFFFFFFFUL;
}
DWORD CRC::CrcRev( INT size, LPBYTE c )
{
if( !m_InitRev ) {
MakeTableRev();
m_InitRev = TRUE;
}
DWORD r = 0xFFFFFFFFUL;
while( --size >= 0 ) {
r = (r >> CHAR_BIT) ^ m_CrcTableRev[(BYTE)r ^ *c++];
}
return r ^ 0xFFFFFFFFUL;
}
void CRC::MakeTable()
{
INT i, j;
DWORD r;
for( i = 0; i <= UCHAR_MAX; i++ ) {
r = (DWORD)i << (32 - CHAR_BIT);
for( j = 0; j < CHAR_BIT; j++ ) {
if( r & 0x80000000UL ) r = (r << 1) ^ CRCPOLY1;
else r <<= 1;
}
m_CrcTable[i] = r & 0xFFFFFFFFUL;
}
}
void CRC::MakeTableRev()
{
INT i, j;
DWORD r;
for( i = 0; i <= UCHAR_MAX; i++ ) {
r = i;
for( j = 0; j < CHAR_BIT; j++ ) {
if( r & 1 ) r = (r >> 1) ^ CRCPOLY2;
else r >>= 1;
}
m_CrcTableRev[i] = r;
}
}

View File

@ -0,0 +1,24 @@
//
// CRCチェック用ライブラリクラス
//
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <limits.h>
class CRC
{
public:
static DWORD Crc( INT size, LPBYTE c );
static DWORD CrcRev( INT size, LPBYTE c ); // 逆順
protected:
static void MakeTable();
static void MakeTableRev(); // 逆順
static BOOL m_Init;
static BOOL m_InitRev;
static DWORD m_CrcTable[ UCHAR_MAX+1 ];
static DWORD m_CrcTableRev[ UCHAR_MAX+1 ];
private:
};

View File

@ -0,0 +1,173 @@
//
// DATACHバーコードバトラーダイアログクラス
//
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <commctrl.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <list>
#include <vector>
#include <string>
using namespace std;
#include "typedef.h"
#include "macro.h"
#include "VirtuaNESres.h"
#include "DebugOut.h"
#include "App.h"
#include "Pathlib.h"
#include "Config.h"
#include "Wnd.h"
#include "DatachBarcodeDlg.h"
#include "EmuThread.h"
#include "nes.h"
#include "mapper.h"
// メッセージ
DLG_MESSAGE_BEGIN(CDatachBarcodeDlg)
DLG_ON_MESSAGE( WM_INITDIALOG, OnInitDialog )
DLG_ON_MESSAGE( WM_ACTIVATE, OnActivate )
DLG_ON_MESSAGE( WM_DESTROY, OnDestroy )
DLG_ON_MESSAGE( WM_CLOSE, OnClose )
// コマンド
DLG_COMMAND_BEGIN()
DLG_ON_COMMAND( IDCANCEL, OnCancel )
//DLG_ON_COMMAND( IDC_EBB_CODE, OnCodeinput )
DLG_ON_COMMAND( IDC_EBB_TRANSFER, OnCodeTransfer )
DLG_ON_COMMAND( IDC_EBB_RANDOM, OnCodeCreate )
DLG_ON_COMMAND_NOTIFY( IDC_EBB_CODE, EN_CHANGE, OnCodeinput )
DLG_COMMAND_END()
// Notify メッセージ
DLG_NOTIFY_BEGIN()
//DLG_ON_NOTIFY( IDC_LCH_LIST, LVN_KEYDOWN, OnKeyDownListView )
DLG_NOTIFY_END()
DLG_MESSAGE_END()
BOOL CDatachBarcodeDlg::Create( HWND hWndParent )
{
// 親はデスクトップにする
m_hWnd = ::CreateDialogParam( CApp::GetPlugin(), MAKEINTRESOURCE(IDD_EXT_BARCODEBATTLER),
NULL, g_DlgProc, (LPARAM)this );
if( !m_hWnd )
return FALSE;
// モードレスダイアログリストに加える
CWndList::Add( this );
return TRUE;
}
void CDatachBarcodeDlg::Destroy()
{
if( m_hWnd ) {
// 位置保存
::GetWindowRect( m_hWnd, &Config.general.rcBarcodePos );
// モードレスダイアログリストから削除
CWndList::Del( this );
::DestroyWindow( m_hWnd );
m_hWnd = NULL;
}
}
DLGMSG CDatachBarcodeDlg::OnInitDialog( DLGMSGPARAM )
{
DEBUGOUT( "CDatachBarcodeDlg::OnInitDialog\n" );
// 位置修正
if( Config.general.rcBarcodePos.right-Config.general.rcBarcodePos.left != 0
&& Config.general.rcBarcodePos.bottom-Config.general.rcBarcodePos.top != 0 ) {
::SetWindowPos( m_hWnd, HWND_NOTOPMOST, Config.general.rcBarcodePos.left, Config.general.rcBarcodePos.top,
0, 0, SWP_NOSIZE | SWP_NOZORDER );
}
::SendDlgItemMessage( m_hWnd, IDC_EBB_CODE, EM_SETLIMITTEXT, 13, 0 );
CTRLENABLE( IDC_EBB_TRANSFER, FALSE );
::srand( (unsigned)::time( NULL ) );
return TRUE;
}
DLGMSG CDatachBarcodeDlg::OnActivate( DLGMSGPARAM )
{
DEBUGOUT( "CDatachBarcodeDlg::OnActivate\n" );
if( LOWORD(wParam) == WA_INACTIVE ) {
DEBUGOUT( "CDatachBarcodeDlg::OnActivate:Inactive\n" );
::PostMessage( CApp::GetHWnd(), WM_VNS_SHORTCUTENABLE, (WPARAM)TRUE, 0 );
} else {
DEBUGOUT( "CDatachBarcodeDlg::OnActivate:Active\n" );
::PostMessage( CApp::GetHWnd(), WM_VNS_SHORTCUTENABLE, (WPARAM)FALSE, 0 );
}
return FALSE;
}
DLGMSG CDatachBarcodeDlg::OnDestroy( DLGMSGPARAM )
{
return TRUE;
}
DLGMSG CDatachBarcodeDlg::OnClose( DLGMSGPARAM )
{
DEBUGOUT( "CDatachBarcodeDlg::OnClose\n" );
::ShowWindow( m_hWnd, SW_HIDE ); // 非表示にするだけ
return TRUE;
}
DLGCMD CDatachBarcodeDlg::OnCancel( DLGCMDPARAM )
{
DEBUGOUT( "CDatachBarcodeDlg::OnCancel\n" );
::ShowWindow( m_hWnd, SW_HIDE ); // 非表示にするだけ
}
DLGCMD CDatachBarcodeDlg::OnCodeinput( DLGCMDPARAM )
{
DEBUGOUT( "CDatachBarcodeDlg::OnCodeinput\n" );
INT len = ::SendDlgItemMessage( m_hWnd, IDC_EBB_CODE, WM_GETTEXTLENGTH, 0, 0 );
CTRLENABLE( IDC_EBB_TRANSFER, ((len==8)||(len==13))?TRUE:FALSE );
}
DLGCMD CDatachBarcodeDlg::OnCodeTransfer( DLGCMDPARAM )
{
DEBUGOUT( "CDatachBarcodeDlg::OnCodeTransfer\n" );
if( !Emu.IsRunning() )
return;
BYTE code[14], *p;
p = code;
INT len = ::GetDlgItemText( m_hWnd, IDC_EBB_CODE, (LPTSTR)code, 14 );
Emu.EventParam2( CEmuThread::EV_BARCODE, (LONG)code, (LONG)len );
}
DLGCMD CDatachBarcodeDlg::OnCodeCreate( DLGCMDPARAM )
{
DEBUGOUT( "CDatachBarcodeDlg::OnCodeCreate\n" );
BYTE code[14];
INT digit, sum;
sum = 0;
for( INT i = 0; i < 12; i++ ) {
digit = ::rand()%10;
code[i] = '0'+digit;
sum += digit*((i&1)?3:1);
}
code[12] = '0'+((10-(sum%10))%10);
code[13] = '\0';
::SetDlgItemText( m_hWnd, IDC_EBB_CODE, (LPCTSTR)code );
}

View File

@ -0,0 +1,40 @@
//
// DATACHバーコードバトラーダイアログクラス
//
#ifndef __CDATACHBARCODEDLG_INCLUDED__
#define __CDATACHBARCODEDLG_INCLUDED__
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <list>
#include <vector>
#include <string>
using namespace std;
#include "Wnd.h"
class CDatachBarcodeDlg : public CWnd
{
public:
// Override from CWnd
BOOL Create( HWND hWndParent );
void Destroy();
protected:
// Message map
DLG_MESSAGE_MAP()
DLGMSG OnInitDialog( DLGMSGPARAM );
DLGMSG OnActivate( DLGMSGPARAM );
DLGMSG OnDestroy( DLGMSGPARAM );
DLGMSG OnClose( DLGMSGPARAM );
DLGCMD OnCancel( DLGCMDPARAM );
DLGCMD OnCodeinput( DLGCMDPARAM );
DLGCMD OnCodeTransfer( DLGCMDPARAM );
DLGCMD OnCodeCreate( DLGCMDPARAM );
//
private:
};
#endif // !__CDATACHBARCODEDLG_INCLUDED__

Binary file not shown.

View File

@ -0,0 +1,211 @@
[Path]
RomAutoRunPath=.\
RomPathUse=1
SavePathUse=1
StatePathUse=1
SnapshotPathUse=1
MoviePathUse=1
WavePathUse=1
CheatPathUse=1
RomPath=.\roms\
SavePath=.\save\
StatePath=.\state\
SnapshotPath=.\snapshot\
MoviePath=.\movie\
WavePath=.\wave\
CheatPath=.\cheatcode\
[General]
DoubleExecute=1
StartupLauncher=0
WindowZoom=0
WindowPos=5B020000C10000006F040000E002000073
ScreenZoom=1
SearchDialogPos=0000000000000000000000000000000000
PatternViewPos=0000000000000000000000000000000000
NameTableViewPos=0000000000000000000000000000000000
PaletteViewPos=0000000000000000000000000000000000
MemoryViewPos=A50000009E00000078020000BC0200007B
BarcodePos=0000000000000000000000000000000000
PaletteEditPos=0000000000000000000000000000000000
JoyAxisDisable=0
JoyAxisSetting=000000000000000000000000000000000000000000000000000000000000000000
[Emulation]
IllegalOp=0
AutoFrameSkip=1
Throttle=1
ThrottleFPS=120
Background=0
Priority=3
FourPlayer=1
CrcCheck=1
DiskThrottle=1
LoadFullscreen=0
PNGsnapshot=0
[Graphics]
Aspect=0
SpriteMax=1
AllLine=1
FPSDisp=0
TVFrameMode=0
ScanlineMode=0
ScanlineColor=75
SyncDraw=0
MaxZoom=0
LeftClip=1
WindowVSync=0
DiskAccessLamp=0
DoubleSize=0
SystemMemory=0
UseHEL=0
NoSquareList=0
GraphicsFilter=0
DisplayWidth=640
DisplayHeight=480
DisplayDepth=32
DisplayRate=56
PaletteUse=0
PaletteFile=
[Sound]
Enable=1
DisableVolumeEffect=0
ExtraSoundEnable=1
SamplingRate=22050
SamplingBits=8
BufferSize=4
FilterType=0
Volume=640064006400640064006400640064006400640064006400640064006400640040
[ShortCut]
TBL00=18402E402640314020401E400000000017401140000000000000000000002D4070
TBL01=3B003C0019000F009C004E004A0039000E0000000000000000000000000000001A
TBL02=0C000D003D003E0000000000000000000000000000000000000000000000000094
TBL03=06000200030004000500000000000000198013801E801F8032800000000000002F
TBL04=3F004000410042001C800000000000000E400240034004400540064007400840CF
TBL05=09400A400B400C4090407D400000000000000000000000000000000000000000B7
TBL06=19405700584057405800434043004400444000000000000000000000C740CF40DB
TBL07=D200D30000000000000000000000000000000000000000000000000000000000A5
TBL08=000000000000000000000000000000000000000000000000000000000000000000
TBL09=000000000000000000000000000000000000000000000000000000000000000000
TBL10=000000000000000000000000000000000000000000000000000000000000000000
TBL11=000000000000000000000000000000000000000000000000000000000000000000
TBL12=000000000000000000000000000000000000000000000000000000000000000000
TBL13=000000000000000000000000000000000000000000000000000000000000000000
TBL14=000000000000000000000000000000000000000000000000000000000000000000
TBL15=000000000000000000000000000000000000000000000000000000000000000000
TBL16=52404F40504051404B404C404D4047404840494052804F80508051804B804C8057
TBL17=4D8047804880498000000000000000000000000000000000000000000000000025
TBL18=000000000000000000000000000000000000000000000000000000000000000000
TBL19=000000000000000000000000000000000000000000000000000000000000000000
TBL20=000000000000000000000000000000000000000000000000000000000000000000
TBL21=000000000000000000000000000000000000000000000000000000000000000000
TBL22=000000000000000000000000000000000000000000000000000000000000000000
TBL23=000000000000000000000000000000000000000000000000000000000000000000
TBL24=000000000000000000000000000000000000000000000000000000000000000000
TBL25=000000000000000000000000000000000000000000000000000000000000000000
TBL26=000000000000000000000000000000000000000000000000000000000000000000
TBL27=000000000000000000000000000000000000000000000000000000000000000000
TBL28=000000000000000000000000000000000000000000000000000000000000000000
TBL29=000000000000000000000000000000000000000000000000000000000000000000
TBL30=000000000000000000000000000000000000000000000000000000000000000000
TBL31=000000000000000000000000000000000000000000000000000000000000000000
[Controller 1]
Keys=120020001F0021002500240017001600220023000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002D
Rapid=0000000000
[Controller 2]
Keys=480050004B004D00310030000000000000000000320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C3
Rapid=0000000000
[Controller 3]
Keys=000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Rapid=0000000000
[Controller 4]
Keys=000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Rapid=0000000000
[Crazy Climber]
Keys=000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
[Family Trainer]
Keys=000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
[Exciting Boxing]
Keys=000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
[Mahjang]
Keys=000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
[NSF controller]
Keys=C800D000CB00CD00C900D1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000CA
[VS-Unisystem]
Keys=2E000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002E
[Movie]
UsePlayer=FF000000FF
ResetRec=0
Rerecord=1
LoopPlay=0
PadDisplay=0
[Launcher]
WindowPos=0000000000000000000000000000000000
ColumnView=0101010101010101010101010101010110
ColumnOrder=000102030405060708090A0B0C0D0E0F78
ColumnWidth=A00030003000300030003000300030003000300030003000300030003000300070
ListSelect=0
SortDir=0
SortType=0
FolderUse=0000000000000000000000000000000000
Folder00=
Folder01=
Folder02=
Folder03=
Folder04=
Folder05=
Folder06=
Folder07=
Folder08=
Folder09=
Folder10=
Folder11=
Folder12=
Folder13=
Folder14=
Folder15=
LastSelect=
ActivePause=0
[Netplay]
ChatPos=0000000000000000000000000000000000
NickName=NoName
RecnetPortNum=1
RecentPort00=10000
RecentPort01=
RecentPort02=
RecentPort03=
RecentPort04=
RecentPort05=
RecentPort06=
RecentPort07=
RecentPort08=
RecentPort09=
RecentPort10=
RecentPort11=
RecentPort12=
RecentPort13=
RecentPort14=
RecentPort15=
RecnetHostNum=1
RecentHost00=localhost:10000
RecentHost01=
RecentHost02=
RecentHost03=
RecentHost04=
RecentHost05=
RecentHost06=
RecentHost07=
RecentHost08=
RecentHost09=
RecentHost10=
RecentHost11=
RecentHost12=
RecentHost13=
RecentHost14=
RecentHost15=
[Recent Path List]
Path1=E:\Game\NES\ProgramStudy\[Subor]Karaoke(C)\
Path2=E:\Game\NES\NSF\
Path3=E:\Game\NES\Rom\
[Recent File List]
File1=E:\Game\NES\ProgramStudy\[Subor]Karaoke(C)\[Subor]Karaoke(C).nsf
File2=E:\Game\NES\NSF\Contra.nsf
File3=E:\Game\NES\Rom\Contra(U).nes

View File

@ -0,0 +1,62 @@
//
// Debug output
//
#include "DebugOut.h"
CDebugOut Dbg;
static const CHAR szClassName[] = "DebugWindow_wndclass";
CDebugOut::CDebugOut()
{
#if defined(_DEBUG) || defined(_DEBUGOUT)
hWndDebugOutput = ::FindWindow( szClassName, NULL );
if( !hWndDebugOutput ) {
::OutputDebugString( "DebugWindow がありません\n" );
}
#endif
}
void CDebugOut::Clear()
{
#if defined(_DEBUG) || defined(_DEBUGOUT)
if( hWndDebugOutput ) {
if( ::IsWindow( hWndDebugOutput ) ) {
::SendMessage( hWndDebugOutput, WM_APP+1, (WPARAM)NULL, (LPARAM)NULL );
}
}
#endif
}
void __cdecl CDebugOut::Out( LPSTR fmt, ... )
{
#if defined(_DEBUG) || defined(_DEBUGOUT)
CHAR buf[1000];
va_list va;
va_start( va, fmt );
::vsprintf( buf, fmt, va );
if( hWndDebugOutput ) {
if( ::IsWindow( hWndDebugOutput ) ) {
COPYDATASTRUCT cds;
cds.dwData = 0;
cds.lpData = (void*)buf;
cds.cbData = ::strlen(buf)+1; // 終端のNULLも送る
// 文字列送信
::SendMessage( hWndDebugOutput, WM_COPYDATA, (WPARAM)NULL, (LPARAM)&cds );
} else {
::OutputDebugString( buf );
}
} else {
::OutputDebugString( buf );
}
#endif
}
void CDebugOut::Out( const string& str )
{
#if defined(_DEBUG) || defined(_DEBUGOUT)
Out( (LPSTR)str.c_str() );
#endif
}

View File

@ -0,0 +1,45 @@
//
// Debug output
//
#ifndef __DEBUGOUT_INCLUDED__
#define __DEBUGOUT_INCLUDED__
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <string>
using namespace std;
typedef void (__cdecl *DEBUGWINDOWOUTPUT)(LPCTSTR);
class CDebugOut {
public:
CDebugOut();
void Clear();
void __cdecl Out( LPSTR fmt, ... );
void Out( const string& str );
protected:
HWND hWndDebugOutput;
private:
};
extern CDebugOut Dbg;
#if defined(_DEBUG) || defined(_DEBUGOUT)
#define DEBUGOUT Dbg.Out
#else
#define DEBUGOUT
#endif // !_DEBUG
#if defined(_DEBUG) || defined(_DEBUGOUT)
#define DEBUGCLR Dbg.Clear
#else
#define DEBUGCLR
#endif // !_DEBUG
#endif // !__DEBUGOUT_INCLUDED__

View File

@ -0,0 +1,130 @@
//
// チャットダイアログクラス
//
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <commctrl.h>
#include <stdio.h>
#include <stdlib.h>
#include <mbstring.h>
#include <shlwapi.h>
#include <string>
using namespace std;
#include "typedef.h"
#include "macro.h"
#include "VirtuaNESres.h"
#include "DebugOut.h"
#include "App.h"
#include "Pathlib.h"
#include "EmuThread.h"
#include "VsUnisystem.h"
#include "Wnd.h"
#include "DipSwitchDlg.h"
// メッセージ
DLG_MESSAGE_BEGIN(CDipSwitchDlg)
DLG_ON_MESSAGE( WM_INITDIALOG, OnInitDialog )
// コマンド
DLG_COMMAND_BEGIN()
DLG_ON_COMMAND( IDOK, OnOK )
DLG_ON_COMMAND( IDCANCEL, OnCancel )
DLG_COMMAND_END()
// Notify メッセージ
DLG_NOTIFY_BEGIN()
DLG_NOTIFY_END()
DLG_MESSAGE_END()
INT CDipSwitchDlg::DoModal( HWND hWndParent )
{
return ::DialogBoxParam( CApp::GetPlugin(), MAKEINTRESOURCE(IDD_EXT_VSUNISYSTEM),
hWndParent, g_DlgProc, (LPARAM)this );
}
DLGMSG CDipSwitchDlg::OnInitDialog( DLGMSGPARAM )
{
// DEBUGOUT( "CDipSwitchDlg::OnInitDialog\n" );
for( INT i = IDC_EVS_DIPCOMBO0; i <= IDC_EVS_DIPCOMBO7; i++ ) {
::SendDlgItemMessage( m_hWnd, i, CB_RESETCONTENT, 0, 0 );
}
BYTE val = Emu.GetNES()->GetVSDipSwitch();
VSDIPSWITCH* dip = Emu.GetNES()->GetVSDipSwitchTable();
DEBUGOUT( "GET DIPSWITCH:%02X\n", val );
BYTE mask;
INT nStatic = IDC_EVS_DIPNAME0;
INT nCombo = IDC_EVS_DIPCOMBO0;
BOOL bFlag;
INT nCount, nSelect;
bFlag = FALSE;
nCount = nSelect = 0;
for(;;) {
if( dip->name == NULL && dip->value == 0x0000 ) {
break;
} else if( dip->value == 0x00FF ) {
bFlag = FALSE;
::SendDlgItemMessage( m_hWnd, nCombo, CB_SETCURSEL, (WPARAM)nSelect, 0 );
nCombo++;
} else if( !bFlag ) {
bFlag = TRUE;
::SetDlgItemText( m_hWnd, nStatic, (LPCTSTR)dip->name );
mask = dip->value>>8;
nCount = 0;
nStatic++;
} else {
if( dip->value == (val & mask) )
nSelect = nCount;
::SendDlgItemMessage( m_hWnd, nCombo, CB_INSERTSTRING, (WPARAM)-1, (LPARAM)dip->name );
::SendDlgItemMessage( m_hWnd, nCombo, CB_SETITEMDATA, (WPARAM)nCount, (LPARAM)(dip->value&0xFF) );
nCount++;
}
dip++;
}
m_nDispCount = nStatic-IDC_EVS_DIPNAME0;
// 使わない奴は非表示にする
for( ; nStatic <= IDC_EVS_DIPNAME7; nStatic++, nCombo++ ) {
::ShowWindow( ::GetDlgItem( m_hWnd, nStatic ), SW_HIDE );
::ShowWindow( ::GetDlgItem( m_hWnd, nCombo ), SW_HIDE );
}
return TRUE;
}
DLGCMD CDipSwitchDlg::OnOK( DLGCMDPARAM )
{
// DEBUGOUT( "CDipSwitchDlg::OnOK\n" );
// 選択されている奴のItemDataを取得してDipSwitchデータを作り直す(OnInitDialogでItemDataを設定済み)
BYTE dipval = 0;
for( INT i = IDC_EVS_DIPCOMBO0; i < IDC_EVS_DIPCOMBO0+m_nDispCount; i++ ) {
INT sel = ::SendDlgItemMessage( m_hWnd, i, CB_GETCURSEL, 0, 0 );
DWORD val = (DWORD)::SendDlgItemMessage( m_hWnd, i, CB_GETITEMDATA, (WPARAM)sel, 0 );
dipval |= val & 0xFF;
}
Emu.GetNES()->SetVSDipSwitch( dipval );
DEBUGOUT( "SET DIPSWITCH:%02X\n", dipval );
::EndDialog( m_hWnd, IDOK );
}
DLGCMD CDipSwitchDlg::OnCancel( DLGCMDPARAM )
{
// DEBUGOUT( "CDipSwitchDlg::OnCancel\n" );
::EndDialog( m_hWnd, IDCANCEL );
}

Some files were not shown because too many files have changed in this diff Show More