CAPCOM YM2151 主要高频函数 unsafe 指针优化 | CPS NeoGeo PGS draw 函数 指针优化
This commit is contained in:
parent
0fc5acac4c
commit
0634207bf0
@ -20,6 +20,14 @@ namespace MAME.Core
|
||||
{
|
||||
Act_Log?.Invoke(msg);
|
||||
}
|
||||
|
||||
|
||||
public static void Assert(bool conditional, string msg)
|
||||
{
|
||||
if (conditional)
|
||||
return;
|
||||
Act_Log?.Invoke(msg);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
417
MAME.Unity/Assets/Plugins/UMAME/ObjectPoolAuto.cs
Normal file
417
MAME.Unity/Assets/Plugins/UMAME/ObjectPoolAuto.cs
Normal file
@ -0,0 +1,417 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MAME.Core
|
||||
{
|
||||
internal static class ObjectPoolAuto
|
||||
{
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>
|
||||
/// 获取或者创建一个新的
|
||||
/// </summary>
|
||||
/// <remarks>Remember to <see cref="Release{T}(T)"/> 需要回收参见这个</remarks>
|
||||
public static T Acquire<T>()
|
||||
where T : class, new()
|
||||
=> ObjectPool<T>.Acquire();
|
||||
|
||||
/// <summary>
|
||||
/// 获取或者创建一个新的
|
||||
/// </summary>
|
||||
/// <remarks>Remember to <see cref="Release{T}(T)"/> 需要回收参见这个</remarks>
|
||||
public static void Acquire<T>(out T item)
|
||||
where T : class, new()
|
||||
=> item = ObjectPool<T>.Acquire();
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>
|
||||
/// 回收对象
|
||||
/// </summary>
|
||||
public static void Release<T>(T item)
|
||||
where T : class, new()
|
||||
=> ObjectPool<T>.Release(item);
|
||||
|
||||
/// <summary>
|
||||
/// 回收对象
|
||||
/// </summary>
|
||||
public static void Release<T>(ref T item) where T : class, new()
|
||||
{
|
||||
if (item != null)
|
||||
{
|
||||
ObjectPool<T>.Release(item);
|
||||
item = null;
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
public const string
|
||||
NotClearError = " They must be cleared before being released to the pool and not modified after that.";
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>
|
||||
/// 获取或创建List
|
||||
/// </summary>
|
||||
/// <remarks>Remember to <see cref="Release{T}(List{T})"/> 回收参见此方法</remarks>
|
||||
public static List<T> AcquireList<T>()
|
||||
{
|
||||
var list = ObjectPool<List<T>>.Acquire();
|
||||
EmuLogger.Assert(list.Count == 0, "A pooled list is not empty." + NotClearError);
|
||||
return list;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 回收List
|
||||
/// </summary>
|
||||
public static void Release<T>(List<T> list)
|
||||
{
|
||||
list.Clear();
|
||||
ObjectPool<List<T>>.Release(list);
|
||||
}
|
||||
/// <summary>
|
||||
/// 回收List内容
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="list"></param>
|
||||
public static void ReleaseListContent<T>(List<T> list) where T : class, new()
|
||||
{
|
||||
foreach (var item in list)
|
||||
{
|
||||
ObjectPool<T>.Release(item);
|
||||
}
|
||||
list.Clear();
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>
|
||||
/// 获取或创建HashSet
|
||||
/// </summary>
|
||||
public static HashSet<T> AcquireSet<T>()
|
||||
{
|
||||
var set = ObjectPool<HashSet<T>>.Acquire();
|
||||
EmuLogger.Assert(set.Count == 0, "A pooled set is not empty." + NotClearError);
|
||||
return set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 释放HashSet
|
||||
/// </summary>
|
||||
public static void Release<T>(HashSet<T> set)
|
||||
{
|
||||
set.Clear();
|
||||
ObjectPool<HashSet<T>>.Release(set);
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>
|
||||
/// 获取一个字符串StringBuilder
|
||||
/// </summary>
|
||||
/// <remarks>Remember to <see cref="Release(StringBuilder)"/>回收参见这个</remarks>
|
||||
public static StringBuilder AcquireStringBuilder()
|
||||
{
|
||||
var builder = ObjectPool<StringBuilder>.Acquire();
|
||||
EmuLogger.Assert(builder.Length == 0, $"A pooled {nameof(StringBuilder)} is not empty." + NotClearError);
|
||||
return builder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 回收 StringBuilder
|
||||
/// </summary>
|
||||
public static void Release(StringBuilder builder)
|
||||
{
|
||||
builder.Length = 0;
|
||||
ObjectPool<StringBuilder>.Release(builder);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 回收 StringBuilder
|
||||
/// </summary>
|
||||
public static string ReleaseToString(this StringBuilder builder)
|
||||
{
|
||||
var result = builder.ToString();
|
||||
Release(builder);
|
||||
return result;
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
private static class Cache<T>
|
||||
{
|
||||
public static readonly Dictionary<MethodInfo, KeyValuePair<Func<T>, T>>
|
||||
Results = new Dictionary<MethodInfo, KeyValuePair<Func<T>, T>>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 此方法主要用于频繁绘制缓存,比如说GUI绘制
|
||||
/// </summary>
|
||||
public static T GetCachedResult<T>(Func<T> function)
|
||||
{
|
||||
var method = function.Method;
|
||||
if (!Cache<T>.Results.TryGetValue(method, out var result))
|
||||
{
|
||||
|
||||
result = new KeyValuePair<Func<T>, T>(function, function());
|
||||
Cache<T>.Results.Add(method, result);
|
||||
}
|
||||
else if (result.Key != function)
|
||||
{
|
||||
EmuLogger.Log(
|
||||
$"{nameof(GetCachedResult)}<{typeof(T).Name}>" +
|
||||
$" was previously called on {method.Name} with a different target." +
|
||||
" This likely means that a new delegate is being passed into every call" +
|
||||
" so it can't actually return the same cached object.");
|
||||
}
|
||||
|
||||
return result.Value;
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
public static class Disposable
|
||||
{
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>
|
||||
/// Calls <see cref="ObjectPool{T}.Disposable.Acquire"/> to get a spare <see cref="List{T}"/> if
|
||||
/// </summary>
|
||||
public static IDisposable Acquire<T>(out T item)
|
||||
where T : class, new()
|
||||
=> ObjectPool<T>.Disposable.Acquire(out item);
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>
|
||||
/// Calls <see cref="ObjectPool{T}.Disposable.Acquire"/> to get a spare <see cref="List{T}"/> if
|
||||
/// </summary>
|
||||
public static IDisposable AcquireList<T>(out List<T> list)
|
||||
{
|
||||
var disposable = ObjectPool<List<T>>.Disposable.Acquire(out list, onRelease: (l) => l.Clear());
|
||||
EmuLogger.Assert(list.Count == 0, "A pooled list is not empty." + NotClearError);
|
||||
return disposable;
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>
|
||||
/// Calls <see cref="ObjectPool{T}.Disposable.Acquire"/> to get a spare <see cref="HashSet{T}"/> if
|
||||
/// </summary>
|
||||
public static IDisposable AcquireSet<T>(out HashSet<T> set)
|
||||
{
|
||||
var disposable = ObjectPool<HashSet<T>>.Disposable.Acquire(out set, onRelease: (s) => s.Clear());
|
||||
EmuLogger.Assert(set.Count == 0, "A pooled set is not empty." + NotClearError);
|
||||
return disposable;
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
}
|
||||
/************************************************************************************************************************/
|
||||
public static class ObjectPool<T> where T : class, new()
|
||||
{
|
||||
/************************************************************************************************************************/
|
||||
|
||||
private static readonly List<T>
|
||||
Items = new List<T>();
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>The number of spare items currently in the pool.</summary>
|
||||
public static int Count
|
||||
{
|
||||
get => Items.Count;
|
||||
set
|
||||
{
|
||||
var count = Items.Count;
|
||||
if (count < value)
|
||||
{
|
||||
if (Items.Capacity < value)
|
||||
Items.Capacity = Mathf.NextPowerOfTwo(value);
|
||||
|
||||
do
|
||||
{
|
||||
Items.Add(new T());
|
||||
count++;
|
||||
}
|
||||
while (count < value);
|
||||
|
||||
}
|
||||
else if (count > value)
|
||||
{
|
||||
Items.RemoveRange(value, count - value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>
|
||||
/// If the <see cref="Count"/> is less than the specified value, this method increases it to that value by
|
||||
/// creating new objects.
|
||||
/// </summary>
|
||||
public static void SetMinCount(int count)
|
||||
{
|
||||
if (Count < count)
|
||||
Count = count;
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>The <see cref="List{T}.Capacity"/> of the internal list of spare items.</summary>
|
||||
public static int Capacity
|
||||
{
|
||||
get => Items.Capacity;
|
||||
set
|
||||
{
|
||||
if (Items.Count > value)
|
||||
Items.RemoveRange(value, Items.Count - value);
|
||||
Items.Capacity = value;
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>Returns a spare item if there are any, or creates a new one.</summary>
|
||||
/// <remarks>Remember to <see cref="Release(T)"/> it when you are done.</remarks>
|
||||
public static T Acquire()
|
||||
{
|
||||
var count = Items.Count;
|
||||
if (count == 0)
|
||||
{
|
||||
return new T();
|
||||
}
|
||||
else
|
||||
{
|
||||
count--;
|
||||
var item = Items[count];
|
||||
Items.RemoveAt(count);
|
||||
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>Adds the `item` to the list of spares so it can be reused.</summary>
|
||||
public static void Release(T item)
|
||||
{
|
||||
Items.Add(item);
|
||||
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>Returns a description of the state of this pool.</summary>
|
||||
public static string GetDetails()
|
||||
{
|
||||
return
|
||||
$"{typeof(T).Name}" +
|
||||
$" ({nameof(Count)} = {Items.Count}" +
|
||||
$", {nameof(Capacity)} = {Items.Capacity}" +
|
||||
")";
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>
|
||||
/// An <see cref="IDisposable"/> system to allow pooled objects to be acquired and released within <c>using</c>
|
||||
/// statements instead of needing to manually release everything.
|
||||
/// </summary>
|
||||
public sealed class Disposable : IDisposable
|
||||
{
|
||||
/************************************************************************************************************************/
|
||||
|
||||
private static readonly List<Disposable> LazyStack = new List<Disposable>();
|
||||
|
||||
private static int _ActiveDisposables;
|
||||
|
||||
private T _Item;
|
||||
private Action<T> _OnRelease;
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
private Disposable() { }
|
||||
|
||||
/// <summary>
|
||||
/// Calls <see cref="ObjectPool{T}.Acquire"/> to set the `item` and returns an <see cref="IDisposable"/>
|
||||
/// that will call <see cref="Release(T)"/> on the `item` when disposed.
|
||||
/// </summary>
|
||||
public static IDisposable Acquire(out T item, Action<T> onRelease = null)
|
||||
{
|
||||
Disposable disposable;
|
||||
|
||||
if (LazyStack.Count <= _ActiveDisposables)
|
||||
{
|
||||
LazyStack.Add(disposable = new Disposable());
|
||||
}
|
||||
else
|
||||
{
|
||||
disposable = LazyStack[_ActiveDisposables];
|
||||
}
|
||||
|
||||
_ActiveDisposables++;
|
||||
|
||||
disposable._Item = item = ObjectPool<T>.Acquire();
|
||||
disposable._OnRelease = onRelease;
|
||||
return disposable;
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
void IDisposable.Dispose()
|
||||
{
|
||||
_OnRelease?.Invoke(_Item);
|
||||
Release(_Item);
|
||||
_ActiveDisposables--;
|
||||
}
|
||||
/************************************************************************************************************************/
|
||||
}
|
||||
}
|
||||
|
||||
#region ExtFunctions
|
||||
public struct PoolHandle<T> : IDisposable
|
||||
where T : class, new()
|
||||
{
|
||||
public T Ins;
|
||||
internal static PoolHandle<T> Create(T poolIns)
|
||||
{
|
||||
return new PoolHandle<T> { Ins = poolIns };
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
ObjectPoolAuto.Release<T>(Ins);
|
||||
}
|
||||
}
|
||||
public struct PoolListHandle<T> : IDisposable
|
||||
{
|
||||
public List<T> Ins;
|
||||
internal static PoolListHandle<T> Create(List<T> poolIns)
|
||||
{
|
||||
return new PoolListHandle<T> { Ins = poolIns };
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
ObjectPoolAuto.Release<T>(Ins);
|
||||
}
|
||||
}
|
||||
|
||||
public static PoolHandle<T> PoolScope<T>()
|
||||
where T : class, new()
|
||||
{
|
||||
return PoolHandle<T>.Create(ObjectPoolAuto.Acquire<T>());
|
||||
}
|
||||
public static PoolListHandle<T> PoolListScope<T>()
|
||||
{
|
||||
return PoolListHandle<T>.Create(ObjectPoolAuto.AcquireList<T>());
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
11
MAME.Unity/Assets/Plugins/UMAME/ObjectPoolAuto.cs.meta
Normal file
11
MAME.Unity/Assets/Plugins/UMAME/ObjectPoolAuto.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f22c2fa157c9e6045ad5307124c8a365
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -61,7 +61,10 @@ namespace cpu.nec
|
||||
{
|
||||
if (line >= 0 && line < 35)
|
||||
{
|
||||
Cpuint.lirq.Add(new irq(cpunum, line, state, vector, EmuTimer.get_current_time()));
|
||||
irq _irq = ObjectPoolAuto.Acquire<irq>();
|
||||
_irq.Init(cpunum, line, state, vector, EmuTimer.get_current_time());
|
||||
Cpuint.lirq.Add(_irq);
|
||||
//Cpuint.lirq.Add(new irq(cpunum, line, state, vector, EmuTimer.get_current_time()));
|
||||
int event_index = Cpuint.input_event_index[cpunum, line]++;
|
||||
if (event_index >= 35)
|
||||
{
|
||||
|
@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Numerics;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace MAME.Core
|
||||
@ -57,7 +58,7 @@ namespace MAME.Core
|
||||
{
|
||||
|
||||
}
|
||||
public irq(int _cpunum, int _line, LineState _state, int _vector, Atime _time)
|
||||
public void Init(int _cpunum, int _line, LineState _state, int _vector, Atime _time)
|
||||
{
|
||||
cpunum = _cpunum;
|
||||
line = _line;
|
||||
@ -134,7 +135,10 @@ namespace MAME.Core
|
||||
public static void cpunum_set_input_line(int cpunum, int line, LineState state)
|
||||
{
|
||||
int vector = (line >= 0 && line < 35) ? interrupt_vector[cpunum, line] : 0xff;
|
||||
lirq.Add(new irq(cpunum, line, state, vector, EmuTimer.get_current_time()));
|
||||
irq _irq = ObjectPoolAuto.Acquire<irq>();
|
||||
_irq.Init(cpunum, line, state, vector, EmuTimer.get_current_time());
|
||||
lirq.Add(_irq);
|
||||
//lirq.Add(new irq(cpunum, line, state, vector, EmuTimer.get_current_time()));
|
||||
Cpuexec.cpu[cpunum].cpunum_set_input_line_and_vector(cpunum, line, state, vector);
|
||||
}
|
||||
public static void cpunum_set_input_line_vector(int cpunum, int line, int vector)
|
||||
@ -149,13 +153,17 @@ namespace MAME.Core
|
||||
{
|
||||
if (line >= 0 && line < 35)
|
||||
{
|
||||
lirq.Add(new irq(cpunum, line, state, vector, EmuTimer.get_current_time()));
|
||||
irq _irq = ObjectPoolAuto.Acquire<irq>();
|
||||
_irq.Init(cpunum, line, state, vector, EmuTimer.get_current_time());
|
||||
lirq.Add(_irq);
|
||||
//lirq.Add(new irq(cpunum, line, state, vector, EmuTimer.get_current_time()));
|
||||
EmuTimer.timer_set_internal(EmuTimer.TIME_ACT.Cpuint_cpunum_empty_event_queue);
|
||||
}
|
||||
}
|
||||
public static void cpunum_empty_event_queue()
|
||||
{
|
||||
List<irq> lsirq = new List<irq>();
|
||||
//List<irq> lsirq = new List<irq>();
|
||||
List<irq> lsirq = ObjectPoolAuto.AcquireList<irq>();
|
||||
if (lirq.Count == 0)
|
||||
{
|
||||
int i1 = 1;
|
||||
@ -219,12 +227,14 @@ namespace MAME.Core
|
||||
foreach (irq irq1 in lsirq)
|
||||
{
|
||||
input_event_index[irq1.cpunum, irq1.line] = 0;
|
||||
ObjectPoolAuto.Release(irq1);
|
||||
lirq.Remove(irq1);
|
||||
}
|
||||
if (lirq.Count > 0)
|
||||
{
|
||||
int i1 = 1;
|
||||
}
|
||||
ObjectPoolAuto.Release(lsirq);
|
||||
}
|
||||
public static int cpu_irq_callback(int cpunum, int line)
|
||||
{
|
||||
@ -348,7 +358,9 @@ namespace MAME.Core
|
||||
lirq = new List<irq>();
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
lirq.Add(new irq());
|
||||
irq _irq = ObjectPoolAuto.Acquire<irq>();
|
||||
lirq.Add(_irq);
|
||||
//lirq.Add(new irq());
|
||||
lirq[i].cpunum = reader.ReadInt32();
|
||||
lirq[i].line = reader.ReadInt32();
|
||||
lirq[i].state = (LineState)reader.ReadInt32();
|
||||
|
@ -25,10 +25,6 @@ namespace MAME.Core
|
||||
public Atime period;
|
||||
public Atime start;
|
||||
public Atime expire;
|
||||
public emu_timer()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
public class emu_timer2
|
||||
{
|
||||
@ -502,16 +498,18 @@ namespace MAME.Core
|
||||
lt.Insert(i, timer1);
|
||||
}
|
||||
}
|
||||
|
||||
static List<emu_timer> timer_list_remove_lt1 = new List<emu_timer>();
|
||||
public static void timer_list_remove(emu_timer timer1)
|
||||
{
|
||||
if (timer1.action == TIME_ACT.Cpuint_cpunum_empty_event_queue || timer1.action == TIME_ACT.setvector)
|
||||
{
|
||||
List<emu_timer> lt1 = new List<emu_timer>();
|
||||
timer_list_remove_lt1.Clear();
|
||||
foreach (emu_timer et in lt)
|
||||
{
|
||||
if (et.action == timer1.action && Attotime.attotime_compare(et.expire, timer1.expire) == 0)
|
||||
{
|
||||
lt1.Add(et);
|
||||
timer_list_remove_lt1.Add(et);
|
||||
//lt.Remove(et);
|
||||
//break;
|
||||
}
|
||||
@ -524,7 +522,7 @@ namespace MAME.Core
|
||||
int i1 = 1;
|
||||
}
|
||||
}
|
||||
foreach (emu_timer et1 in lt1)
|
||||
foreach (emu_timer et1 in timer_list_remove_lt1)
|
||||
{
|
||||
lt.Remove(et1);
|
||||
}
|
||||
|
@ -145,8 +145,195 @@ namespace MAME.Core
|
||||
return (((max_y >= y) && (scanline >= y) && (scanline <= max_y)) ||
|
||||
((max_y < y) && ((scanline >= y) || (scanline <= max_y))));
|
||||
}
|
||||
private static void draw_sprites(int iBitmap, int scanline)
|
||||
|
||||
//private static void draw_sprites(int iBitmap, int scanline)
|
||||
//{
|
||||
// int x_2, code_2;
|
||||
// int x, y, rows, zoom_x, zoom_y, sprite_list_offset, sprite_index, max_sprite_index, sprite_number, sprite_y, tile, attr_and_code_offs, code, zoom_x_table_offset, gfx_offset, line_pens_offset, x_inc, sprite_line, zoom_line;
|
||||
// ushort y_control, zoom_control, attr;
|
||||
// byte sprite_y_and_tile;
|
||||
// bool invert;
|
||||
// y = 0;
|
||||
// x = 0;
|
||||
// rows = 0;
|
||||
// zoom_y = 0;
|
||||
// zoom_x = 0;
|
||||
// if ((scanline & 0x01) != 0)
|
||||
// {
|
||||
// sprite_list_offset = 0x8680;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// sprite_list_offset = 0x8600;
|
||||
// }
|
||||
// Span<ushort> span_neogeo_videoram = neogeo_videoram.AsSpan();
|
||||
// Span<int> span_bitmapbaseN_iBitmap = Video.bitmapbaseN[iBitmap].AsSpan();
|
||||
// Span<byte> span_sprite_gfx = sprite_gfx.AsSpan();
|
||||
// Span<int> span_pens = pens.AsSpan();
|
||||
// for (max_sprite_index = 95; max_sprite_index >= 0; max_sprite_index--)
|
||||
// {
|
||||
// if (span_neogeo_videoram[sprite_list_offset + max_sprite_index] != 0)
|
||||
// {
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// if (max_sprite_index != 95)
|
||||
// {
|
||||
// max_sprite_index = max_sprite_index + 1;
|
||||
// }
|
||||
// for (sprite_index = 0; sprite_index < max_sprite_index; sprite_index++)
|
||||
// {
|
||||
// sprite_number = span_neogeo_videoram[sprite_list_offset + sprite_index] & 0x1ff;
|
||||
// y_control = span_neogeo_videoram[0x8200 | sprite_number];
|
||||
// zoom_control = span_neogeo_videoram[0x8000 | sprite_number];
|
||||
// x_2 = span_neogeo_videoram[0x8400 | sprite_number];
|
||||
// code_2 = span_neogeo_videoram[sprite_number << 6];
|
||||
// if ((y_control & 0x40) != 0)
|
||||
// {
|
||||
// x = (x + zoom_x + 1) & 0x01ff;
|
||||
// zoom_x = (zoom_control >> 8) & 0x0f;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// y = 0x200 - (y_control >> 7);
|
||||
// x = span_neogeo_videoram[0x8400 | sprite_number] >> 7;
|
||||
// zoom_y = zoom_control & 0xff;
|
||||
// zoom_x = (zoom_control >> 8) & 0x0f;
|
||||
// rows = y_control & 0x3f;
|
||||
// }
|
||||
// if ((x >= 0x140) && (x <= 0x1f0))
|
||||
// {
|
||||
// continue;
|
||||
// }
|
||||
// if (sprite_on_scanline(scanline, y, rows))
|
||||
// {
|
||||
// sprite_line = (scanline - y) & 0x1ff;
|
||||
// zoom_line = sprite_line & 0xff;
|
||||
// invert = ((sprite_line & 0x100) != 0) ? true : false;
|
||||
// if (invert)
|
||||
// {
|
||||
// zoom_line ^= 0xff;
|
||||
// }
|
||||
// if (rows > 0x20)
|
||||
// {
|
||||
// zoom_line = zoom_line % ((zoom_y + 1) << 1);
|
||||
// if (zoom_line > zoom_y)
|
||||
// {
|
||||
// zoom_line = ((zoom_y + 1) << 1) - 1 - zoom_line;
|
||||
// invert = !invert;
|
||||
// }
|
||||
// }
|
||||
// sprite_y_and_tile = zoomyrom[(zoom_y << 8) | zoom_line];
|
||||
// sprite_y = sprite_y_and_tile & 0x0f;
|
||||
// tile = sprite_y_and_tile >> 4;
|
||||
// if (invert)
|
||||
// {
|
||||
// sprite_y ^= 0x0f;
|
||||
// tile ^= 0x1f;
|
||||
// }
|
||||
// attr_and_code_offs = (sprite_number << 6) | (tile << 1);
|
||||
// attr = span_neogeo_videoram[attr_and_code_offs + 1];
|
||||
// code = ((attr << 12) & 0x70000) | span_neogeo_videoram[attr_and_code_offs];
|
||||
// if (auto_animation_disabled == 0)
|
||||
// {
|
||||
// if ((attr & 0x0008) != 0)
|
||||
// {
|
||||
// code = (code & ~0x07) | (auto_animation_counter & 0x07);
|
||||
// }
|
||||
// else if ((attr & 0x0004) != 0)
|
||||
// {
|
||||
// code = (code & ~0x03) | (auto_animation_counter & 0x03);
|
||||
// }
|
||||
// }
|
||||
// if ((attr & 0x0002) != 0)
|
||||
// {
|
||||
// sprite_y ^= 0x0f;
|
||||
// }
|
||||
// zoom_x_table_offset = 0;
|
||||
// gfx_offset = (int)(((code << 8) | (sprite_y << 4)) & sprite_gfx_address_mask);
|
||||
// line_pens_offset = attr >> 8 << 4;
|
||||
// if ((attr & 0x0001) != 0)
|
||||
// {
|
||||
// gfx_offset = gfx_offset + 0x0f;
|
||||
// x_inc = -1;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// x_inc = 1;
|
||||
// }
|
||||
// int pixel_addr_offsetx, pixel_addr_offsety;
|
||||
// if (x <= 0x01f0)
|
||||
// {
|
||||
// int i;
|
||||
// pixel_addr_offsetx = x + NEOGEO_HBEND;
|
||||
// pixel_addr_offsety = scanline;
|
||||
// for (i = 0; i < 0x10; i++)
|
||||
// {
|
||||
// if (zoom_x_tables[zoom_x, zoom_x_table_offset] != 0)
|
||||
// {
|
||||
// //if (sprite_gfx[gfx_offset] != 0)
|
||||
// if (span_sprite_gfx[gfx_offset] != 0)
|
||||
// {
|
||||
// //Video.bitmapbaseN[iBitmap][pixel_addr_offsety * 384 + pixel_addr_offsetx] = pens[line_pens_offset + sprite_gfx[gfx_offset]];
|
||||
// span_bitmapbaseN_iBitmap[pixel_addr_offsety * 384 + pixel_addr_offsetx] = span_pens[line_pens_offset + span_sprite_gfx[gfx_offset]];
|
||||
// }
|
||||
// pixel_addr_offsetx++;
|
||||
// }
|
||||
// zoom_x_table_offset++;
|
||||
// gfx_offset += x_inc;
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// int i;
|
||||
// int x_save = x;
|
||||
// pixel_addr_offsetx = NEOGEO_HBEND;
|
||||
// pixel_addr_offsety = scanline;
|
||||
// for (i = 0; i < 0x10; i++)
|
||||
// {
|
||||
// if (zoom_x_tables[zoom_x, zoom_x_table_offset] != 0)
|
||||
// {
|
||||
// if (x >= 0x200)
|
||||
// {
|
||||
// //if (sprite_gfx[gfx_offset] != 0)
|
||||
// if (span_sprite_gfx[gfx_offset] != 0)
|
||||
// {
|
||||
// //Video.bitmapbaseN[iBitmap][pixel_addr_offsety * 384 + pixel_addr_offsetx] = pens[line_pens_offset + sprite_gfx[gfx_offset]];
|
||||
// span_bitmapbaseN_iBitmap[pixel_addr_offsety * 384 + pixel_addr_offsetx] = span_pens[line_pens_offset + span_sprite_gfx[gfx_offset]];
|
||||
// }
|
||||
// pixel_addr_offsetx++;
|
||||
// }
|
||||
// x++;
|
||||
// }
|
||||
// zoom_x_table_offset++;
|
||||
// gfx_offset += x_inc;
|
||||
// }
|
||||
// x = x_save;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
/// <summary>
|
||||
/// draw_sprites (Unsafa 尝试提升效率)
|
||||
/// </summary>
|
||||
/// <param name="iBitmap"></param>
|
||||
/// <param name="scanline"></param>
|
||||
unsafe private static void draw_sprites(int iBitmap, int scanline)
|
||||
{
|
||||
|
||||
fixed (ushort* videoramPtr = &neogeo_videoram[0])
|
||||
fixed (int* bitmapbasePtr = &Video.bitmapbaseN[iBitmap][0])
|
||||
fixed (byte* spriteGfxPtr = &sprite_gfx[0])
|
||||
fixed (int* pensPtr = &pens[0])
|
||||
fixed (byte* zoomyromPtr = &zoomyrom[0])
|
||||
{
|
||||
ushort* neogeo_videoram = videoramPtr;
|
||||
int* bitmapbase = bitmapbasePtr;
|
||||
byte* spriteGfx = spriteGfxPtr;
|
||||
int* pens = pensPtr;
|
||||
byte* zoomyrom = zoomyromPtr;
|
||||
|
||||
int x_2, code_2;
|
||||
int x, y, rows, zoom_x, zoom_y, sprite_list_offset, sprite_index, max_sprite_index, sprite_number, sprite_y, tile, attr_and_code_offs, code, zoom_x_table_offset, gfx_offset, line_pens_offset, x_inc, sprite_line, zoom_line;
|
||||
ushort y_control, zoom_control, attr;
|
||||
@ -183,6 +370,13 @@ namespace MAME.Core
|
||||
zoom_control = neogeo_videoram[0x8000 | sprite_number];
|
||||
x_2 = neogeo_videoram[0x8400 | sprite_number];
|
||||
code_2 = neogeo_videoram[sprite_number << 6];
|
||||
|
||||
//sprite_number = (*(videoram + sprite_list_offset + sprite_index) & 0x1ff);
|
||||
//y_control = (ushort)(*(videoram + 0x8200) | sprite_number);
|
||||
//zoom_control = (ushort)(*(videoram + 0x8000) | sprite_number);
|
||||
//x_2 = (ushort)(*(videoram + 0x8400) | sprite_number);
|
||||
//code_2 = *(videoram + (sprite_number << 6));
|
||||
|
||||
if ((y_control & 0x40) != 0)
|
||||
{
|
||||
x = (x + zoom_x + 1) & 0x01ff;
|
||||
@ -191,11 +385,17 @@ namespace MAME.Core
|
||||
else
|
||||
{
|
||||
y = 0x200 - (y_control >> 7);
|
||||
x = neogeo_videoram[0x8400 | sprite_number] >> 7;
|
||||
//x = neogeo_videoram[0x8400 | sprite_number] >> 7;
|
||||
x = x_2 >> 7;
|
||||
zoom_y = zoom_control & 0xff;
|
||||
zoom_x = (zoom_control >> 8) & 0x0f;
|
||||
rows = y_control & 0x3f;
|
||||
}
|
||||
|
||||
fixed (int* zoom_x_tablesPtr = &zoom_x_tables[zoom_x, 0])
|
||||
{
|
||||
int* zoom_x_tables = zoom_x_tablesPtr;
|
||||
|
||||
if ((x >= 0x140) && (x <= 0x1f0))
|
||||
{
|
||||
continue;
|
||||
@ -264,11 +464,14 @@ namespace MAME.Core
|
||||
pixel_addr_offsety = scanline;
|
||||
for (i = 0; i < 0x10; i++)
|
||||
{
|
||||
if (zoom_x_tables[zoom_x, zoom_x_table_offset] != 0)
|
||||
//if (zoom_x_tables[zoom_x, zoom_x_table_offset] != 0)
|
||||
if (zoom_x_tables[zoom_x_table_offset] != 0)
|
||||
{
|
||||
if (sprite_gfx[gfx_offset] != 0)
|
||||
//if (sprite_gfx[gfx_offset] != 0)
|
||||
if (spriteGfx[gfx_offset] != 0)
|
||||
{
|
||||
Video.bitmapbaseN[iBitmap][pixel_addr_offsety * 384 + pixel_addr_offsetx] = pens[line_pens_offset + sprite_gfx[gfx_offset]];
|
||||
//Video.bitmapbaseN[iBitmap][pixel_addr_offsety * 384 + pixel_addr_offsetx] = pens[line_pens_offset + sprite_gfx[gfx_offset]];
|
||||
bitmapbase[pixel_addr_offsety * 384 + pixel_addr_offsetx] = pens[line_pens_offset + spriteGfx[gfx_offset]];
|
||||
}
|
||||
pixel_addr_offsetx++;
|
||||
}
|
||||
@ -284,13 +487,16 @@ namespace MAME.Core
|
||||
pixel_addr_offsety = scanline;
|
||||
for (i = 0; i < 0x10; i++)
|
||||
{
|
||||
if (zoom_x_tables[zoom_x, zoom_x_table_offset] != 0)
|
||||
//if (zoom_x_tables[zoom_x, zoom_x_table_offset] != 0)
|
||||
if (zoom_x_tables[zoom_x_table_offset] != 0)
|
||||
{
|
||||
if (x >= 0x200)
|
||||
{
|
||||
if (sprite_gfx[gfx_offset] != 0)
|
||||
//if (sprite_gfx[gfx_offset] != 0)
|
||||
if (spriteGfx[gfx_offset] != 0)
|
||||
{
|
||||
Video.bitmapbaseN[iBitmap][pixel_addr_offsety * 384 + pixel_addr_offsetx] = pens[line_pens_offset + sprite_gfx[gfx_offset]];
|
||||
//Video.bitmapbaseN[iBitmap][pixel_addr_offsety * 384 + pixel_addr_offsetx] = pens[line_pens_offset + sprite_gfx[gfx_offset]];
|
||||
bitmapbase[pixel_addr_offsety * 384 + pixel_addr_offsetx] = pens[line_pens_offset + spriteGfx[gfx_offset]];
|
||||
}
|
||||
pixel_addr_offsetx++;
|
||||
}
|
||||
@ -304,6 +510,168 @@ namespace MAME.Core
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//private static void draw_sprites(int iBitmap, int scanline)
|
||||
//{
|
||||
// int x_2, code_2;
|
||||
// int x, y, rows, zoom_x, zoom_y, sprite_list_offset, sprite_index, max_sprite_index, sprite_number, sprite_y, tile, attr_and_code_offs, code, zoom_x_table_offset, gfx_offset, line_pens_offset, x_inc, sprite_line, zoom_line;
|
||||
// ushort y_control, zoom_control, attr;
|
||||
// byte sprite_y_and_tile;
|
||||
// bool invert;
|
||||
// y = 0;
|
||||
// x = 0;
|
||||
// rows = 0;
|
||||
// zoom_y = 0;
|
||||
// zoom_x = 0;
|
||||
// if ((scanline & 0x01) != 0)
|
||||
// {
|
||||
// sprite_list_offset = 0x8680;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// sprite_list_offset = 0x8600;
|
||||
// }
|
||||
// for (max_sprite_index = 95; max_sprite_index >= 0; max_sprite_index--)
|
||||
// {
|
||||
// if (neogeo_videoram[sprite_list_offset + max_sprite_index] != 0)
|
||||
// {
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// if (max_sprite_index != 95)
|
||||
// {
|
||||
// max_sprite_index = max_sprite_index + 1;
|
||||
// }
|
||||
// for (sprite_index = 0; sprite_index < max_sprite_index; sprite_index++)
|
||||
// {
|
||||
// sprite_number = neogeo_videoram[sprite_list_offset + sprite_index] & 0x1ff;
|
||||
// y_control = neogeo_videoram[0x8200 | sprite_number];
|
||||
// zoom_control = neogeo_videoram[0x8000 | sprite_number];
|
||||
// x_2 = neogeo_videoram[0x8400 | sprite_number];
|
||||
// code_2 = neogeo_videoram[sprite_number << 6];
|
||||
// if ((y_control & 0x40) != 0)
|
||||
// {
|
||||
// x = (x + zoom_x + 1) & 0x01ff;
|
||||
// zoom_x = (zoom_control >> 8) & 0x0f;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// y = 0x200 - (y_control >> 7);
|
||||
// x = neogeo_videoram[0x8400 | sprite_number] >> 7;
|
||||
// zoom_y = zoom_control & 0xff;
|
||||
// zoom_x = (zoom_control >> 8) & 0x0f;
|
||||
// rows = y_control & 0x3f;
|
||||
// }
|
||||
// if ((x >= 0x140) && (x <= 0x1f0))
|
||||
// {
|
||||
// continue;
|
||||
// }
|
||||
// if (sprite_on_scanline(scanline, y, rows))
|
||||
// {
|
||||
// sprite_line = (scanline - y) & 0x1ff;
|
||||
// zoom_line = sprite_line & 0xff;
|
||||
// invert = ((sprite_line & 0x100) != 0) ? true : false;
|
||||
// if (invert)
|
||||
// {
|
||||
// zoom_line ^= 0xff;
|
||||
// }
|
||||
// if (rows > 0x20)
|
||||
// {
|
||||
// zoom_line = zoom_line % ((zoom_y + 1) << 1);
|
||||
// if (zoom_line > zoom_y)
|
||||
// {
|
||||
// zoom_line = ((zoom_y + 1) << 1) - 1 - zoom_line;
|
||||
// invert = !invert;
|
||||
// }
|
||||
// }
|
||||
// sprite_y_and_tile = zoomyrom[(zoom_y << 8) | zoom_line];
|
||||
// sprite_y = sprite_y_and_tile & 0x0f;
|
||||
// tile = sprite_y_and_tile >> 4;
|
||||
// if (invert)
|
||||
// {
|
||||
// sprite_y ^= 0x0f;
|
||||
// tile ^= 0x1f;
|
||||
// }
|
||||
// attr_and_code_offs = (sprite_number << 6) | (tile << 1);
|
||||
// attr = neogeo_videoram[attr_and_code_offs + 1];
|
||||
// code = ((attr << 12) & 0x70000) | neogeo_videoram[attr_and_code_offs];
|
||||
// if (auto_animation_disabled == 0)
|
||||
// {
|
||||
// if ((attr & 0x0008) != 0)
|
||||
// {
|
||||
// code = (code & ~0x07) | (auto_animation_counter & 0x07);
|
||||
// }
|
||||
// else if ((attr & 0x0004) != 0)
|
||||
// {
|
||||
// code = (code & ~0x03) | (auto_animation_counter & 0x03);
|
||||
// }
|
||||
// }
|
||||
// if ((attr & 0x0002) != 0)
|
||||
// {
|
||||
// sprite_y ^= 0x0f;
|
||||
// }
|
||||
// zoom_x_table_offset = 0;
|
||||
// gfx_offset = (int)(((code << 8) | (sprite_y << 4)) & sprite_gfx_address_mask);
|
||||
// line_pens_offset = attr >> 8 << 4;
|
||||
// if ((attr & 0x0001) != 0)
|
||||
// {
|
||||
// gfx_offset = gfx_offset + 0x0f;
|
||||
// x_inc = -1;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// x_inc = 1;
|
||||
// }
|
||||
// int pixel_addr_offsetx, pixel_addr_offsety;
|
||||
// if (x <= 0x01f0)
|
||||
// {
|
||||
// int i;
|
||||
// pixel_addr_offsetx = x + NEOGEO_HBEND;
|
||||
// pixel_addr_offsety = scanline;
|
||||
// for (i = 0; i < 0x10; i++)
|
||||
// {
|
||||
// if (zoom_x_tables[zoom_x, zoom_x_table_offset] != 0)
|
||||
// {
|
||||
// if (sprite_gfx[gfx_offset] != 0)
|
||||
// {
|
||||
// Video.bitmapbaseN[iBitmap][pixel_addr_offsety * 384 + pixel_addr_offsetx] = pens[line_pens_offset + sprite_gfx[gfx_offset]];
|
||||
// }
|
||||
// pixel_addr_offsetx++;
|
||||
// }
|
||||
// zoom_x_table_offset++;
|
||||
// gfx_offset += x_inc;
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// int i;
|
||||
// int x_save = x;
|
||||
// pixel_addr_offsetx = NEOGEO_HBEND;
|
||||
// pixel_addr_offsety = scanline;
|
||||
// for (i = 0; i < 0x10; i++)
|
||||
// {
|
||||
// if (zoom_x_tables[zoom_x, zoom_x_table_offset] != 0)
|
||||
// {
|
||||
// if (x >= 0x200)
|
||||
// {
|
||||
// if (sprite_gfx[gfx_offset] != 0)
|
||||
// {
|
||||
// Video.bitmapbaseN[iBitmap][pixel_addr_offsety * 384 + pixel_addr_offsetx] = pens[line_pens_offset + sprite_gfx[gfx_offset]];
|
||||
// }
|
||||
// pixel_addr_offsetx++;
|
||||
// }
|
||||
// x++;
|
||||
// }
|
||||
// zoom_x_table_offset++;
|
||||
// gfx_offset += x_inc;
|
||||
// }
|
||||
// x = x_save;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
private static void parse_sprites(int scanline)
|
||||
{
|
||||
ushort sprite_number, y_control;
|
||||
|
@ -199,24 +199,36 @@ namespace MAME.Core
|
||||
ycnt++;
|
||||
}
|
||||
}
|
||||
private static void draw_sprites(int priority)
|
||||
unsafe private static void draw_sprites(int priority)
|
||||
{
|
||||
fixed (ushort* pSpriteBuffer = &pgm_spritebufferram[0])
|
||||
fixed (byte* pVideoRegs = &pgm_videoregs[0])
|
||||
{
|
||||
ushort* spritePtr = pSpriteBuffer + pgm_sprite_source_offset;
|
||||
int offset = 0;
|
||||
|
||||
while (pgm_sprite_source_offset < 0x500)
|
||||
{
|
||||
int xpos = pgm_spritebufferram[pgm_sprite_source_offset + 0] & 0x07ff;
|
||||
int ypos = pgm_spritebufferram[pgm_sprite_source_offset + 1] & 0x03ff;
|
||||
int xzom = (pgm_spritebufferram[pgm_sprite_source_offset + 0] & 0x7800) >> 11;
|
||||
int xgrow = (pgm_spritebufferram[pgm_sprite_source_offset + 0] & 0x8000) >> 15;
|
||||
int yzom = (pgm_spritebufferram[pgm_sprite_source_offset + 1] & 0x7800) >> 11;
|
||||
int ygrow = (pgm_spritebufferram[pgm_sprite_source_offset + 1] & 0x8000) >> 15;
|
||||
int palt = (pgm_spritebufferram[pgm_sprite_source_offset + 2] & 0x1f00) >> 8;
|
||||
int flip = (pgm_spritebufferram[pgm_sprite_source_offset + 2] & 0x6000) >> 13;
|
||||
int boff = ((pgm_spritebufferram[pgm_sprite_source_offset + 2] & 0x007f) << 16) | (pgm_spritebufferram[pgm_sprite_source_offset + 3] & 0xffff);
|
||||
int wide = (pgm_spritebufferram[pgm_sprite_source_offset + 4] & 0x7e00) >> 9;
|
||||
int high = pgm_spritebufferram[pgm_sprite_source_offset + 4] & 0x01ff;
|
||||
int pri = (pgm_spritebufferram[pgm_sprite_source_offset + 2] & 0x0080) >> 7;
|
||||
int xzoom, yzoom;
|
||||
// 读取数据
|
||||
ushort* spriteData = (ushort*)spritePtr;
|
||||
int xpos = spriteData[0] & 0x07FF;
|
||||
int ypos = spriteData[1] & 0x03FF;
|
||||
int xzom = (spriteData[0] & 0x7800) >> 11;
|
||||
int xgrow = (spriteData[0] & 0x8000) >> 15;
|
||||
int yzom = (spriteData[1] & 0x7800) >> 11;
|
||||
int ygrow = (spriteData[1] & 0x8000) >> 15;
|
||||
ushort* spriteData2 = (ushort*)(spritePtr + 4);
|
||||
int palt = (spriteData2[0] & 0x1F00) >> 8;
|
||||
int flip = (spriteData2[0] & 0x6000) >> 13;
|
||||
int boff = ((spriteData2[0] & 0x007F) << 16) | spriteData2[1];
|
||||
ushort* spriteData3 = (ushort*)(spritePtr + 6);
|
||||
int wide = (spriteData3[0] & 0x7E00) >> 9;
|
||||
int high = spriteData3[0] & 0x01FF;
|
||||
int pri = (spriteData2[0] & 0x0080) >> 7;
|
||||
int pgm_sprite_zoomtable_offset = 0x1000;
|
||||
// 处理缩放
|
||||
int xzoom, yzoom;
|
||||
int* zoomTablePtr = (int*)(pVideoRegs + pgm_sprite_zoomtable_offset);
|
||||
if (xgrow != 0)
|
||||
{
|
||||
xzom = 0x10 - xzom;
|
||||
@ -225,21 +237,94 @@ namespace MAME.Core
|
||||
{
|
||||
yzom = 0x10 - yzom;
|
||||
}
|
||||
xzoom = ((pgm_videoregs[pgm_sprite_zoomtable_offset + xzom * 4] * 0x100 + pgm_videoregs[pgm_sprite_zoomtable_offset + xzom * 4 + 1]) << 16) | (pgm_videoregs[pgm_sprite_zoomtable_offset + xzom * 4 + 2] * 0x100 + pgm_videoregs[pgm_sprite_zoomtable_offset + xzom * 4 + 3]);
|
||||
yzoom = ((pgm_videoregs[pgm_sprite_zoomtable_offset + yzom * 4] * 0x100 + pgm_videoregs[pgm_sprite_zoomtable_offset + yzom * 4 + 1]) << 16) | (pgm_videoregs[pgm_sprite_zoomtable_offset + yzom * 4 + 2] * 0x100 + pgm_videoregs[pgm_sprite_zoomtable_offset + yzom * 4 + 3]);
|
||||
xzoom = zoomTablePtr[xzom * 4] * 0x10000 + zoomTablePtr[xzom * 4 + 1] * 0x100 + zoomTablePtr[xzom * 4 + 2];
|
||||
yzoom = zoomTablePtr[yzom * 4] * 0x10000 + zoomTablePtr[yzom * 4 + 1] * 0x100 + zoomTablePtr[yzom * 4 + 2];
|
||||
|
||||
// 调整偏移和边界检查
|
||||
boff *= 2;
|
||||
if (xpos > 0x3ff)
|
||||
if (xpos > 0x3FF)
|
||||
xpos -= 0x800;
|
||||
if (ypos > 0x1ff)
|
||||
if (ypos > 0x1FF)
|
||||
ypos -= 0x400;
|
||||
if (high == 0)
|
||||
break;
|
||||
if ((priority == 1) && (pri == 0))
|
||||
break;
|
||||
|
||||
// 调用绘制函数(注意:这个函数也需要被修改为接受指针或适当的参数类型)
|
||||
draw_sprite_new_zoomed(wide, high, xpos, ypos, palt, boff, flip, xzoom, xgrow, yzoom, ygrow);
|
||||
pgm_sprite_source_offset += 5;
|
||||
|
||||
// 移动到下一个精灵
|
||||
spritePtr += 10; // 每个精灵占用5个ushort,即10个字节
|
||||
pgm_sprite_source_offset += 5; // 假设pgm_sprite_source_offset是以ushort为单位递增的
|
||||
|
||||
// 注意:这里我们直接通过指针移动,因此不需要再次访问数组来更新pgm_sprite_source_offset对应的值
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//private static void draw_sprites(int priority)
|
||||
//{
|
||||
// while (pgm_sprite_source_offset < 0x500)
|
||||
// {
|
||||
// //用Span优化
|
||||
// Span<ushort> span_pgm_spritebufferram = pgm_spritebufferram.AsSpan();
|
||||
// int xpos = span_pgm_spritebufferram[pgm_sprite_source_offset + 0] & 0x07ff;
|
||||
// int ypos = span_pgm_spritebufferram[pgm_sprite_source_offset + 1] & 0x03ff;
|
||||
// int xzom = (span_pgm_spritebufferram[pgm_sprite_source_offset + 0] & 0x7800) >> 11;
|
||||
// int xgrow = (span_pgm_spritebufferram[pgm_sprite_source_offset + 0] & 0x8000) >> 15;
|
||||
// int yzom = (span_pgm_spritebufferram[pgm_sprite_source_offset + 1] & 0x7800) >> 11;
|
||||
// int ygrow = (span_pgm_spritebufferram[pgm_sprite_source_offset + 1] & 0x8000) >> 15;
|
||||
// int palt = (span_pgm_spritebufferram[pgm_sprite_source_offset + 2] & 0x1f00) >> 8;
|
||||
// int flip = (span_pgm_spritebufferram[pgm_sprite_source_offset + 2] & 0x6000) >> 13;
|
||||
// int boff = ((span_pgm_spritebufferram[pgm_sprite_source_offset + 2] & 0x007f) << 16) | (span_pgm_spritebufferram[pgm_sprite_source_offset + 3] & 0xffff);
|
||||
// int wide = (span_pgm_spritebufferram[pgm_sprite_source_offset + 4] & 0x7e00) >> 9;
|
||||
// int high = span_pgm_spritebufferram[pgm_sprite_source_offset + 4] & 0x01ff;
|
||||
// int pri = (span_pgm_spritebufferram[pgm_sprite_source_offset + 2] & 0x0080) >> 7;
|
||||
|
||||
|
||||
// //int xpos = pgm_spritebufferram[pgm_sprite_source_offset + 0] & 0x07ff;
|
||||
// //int ypos = pgm_spritebufferram[pgm_sprite_source_offset + 1] & 0x03ff;
|
||||
// //int xzom = (pgm_spritebufferram[pgm_sprite_source_offset + 0] & 0x7800) >> 11;
|
||||
// //int xgrow = (pgm_spritebufferram[pgm_sprite_source_offset + 0] & 0x8000) >> 15;
|
||||
// //int yzom = (pgm_spritebufferram[pgm_sprite_source_offset + 1] & 0x7800) >> 11;
|
||||
// //int ygrow = (pgm_spritebufferram[pgm_sprite_source_offset + 1] & 0x8000) >> 15;
|
||||
// //int palt = (pgm_spritebufferram[pgm_sprite_source_offset + 2] & 0x1f00) >> 8;
|
||||
// //int flip = (pgm_spritebufferram[pgm_sprite_source_offset + 2] & 0x6000) >> 13;
|
||||
// //int boff = ((pgm_spritebufferram[pgm_sprite_source_offset + 2] & 0x007f) << 16) | (pgm_spritebufferram[pgm_sprite_source_offset + 3] & 0xffff);
|
||||
// //int wide = (pgm_spritebufferram[pgm_sprite_source_offset + 4] & 0x7e00) >> 9;
|
||||
// //int high = pgm_spritebufferram[pgm_sprite_source_offset + 4] & 0x01ff;
|
||||
// //int pri = (pgm_spritebufferram[pgm_sprite_source_offset + 2] & 0x0080) >> 7;
|
||||
|
||||
// int xzoom, yzoom;
|
||||
// int pgm_sprite_zoomtable_offset = 0x1000;
|
||||
// if (xgrow != 0)
|
||||
// {
|
||||
// xzom = 0x10 - xzom;
|
||||
// }
|
||||
// if (ygrow != 0)
|
||||
// {
|
||||
// yzom = 0x10 - yzom;
|
||||
// }
|
||||
// Span<byte> span_pgm_videoregs = pgm_videoregs.AsSpan();
|
||||
// xzoom = ((span_pgm_videoregs[pgm_sprite_zoomtable_offset + xzom * 4] * 0x100 + span_pgm_videoregs[pgm_sprite_zoomtable_offset + xzom * 4 + 1]) << 16) | (span_pgm_videoregs[pgm_sprite_zoomtable_offset + xzom * 4 + 2] * 0x100 + span_pgm_videoregs[pgm_sprite_zoomtable_offset + xzom * 4 + 3]);
|
||||
// yzoom = ((span_pgm_videoregs[pgm_sprite_zoomtable_offset + yzom * 4] * 0x100 + span_pgm_videoregs[pgm_sprite_zoomtable_offset + yzom * 4 + 1]) << 16) | (span_pgm_videoregs[pgm_sprite_zoomtable_offset + yzom * 4 + 2] * 0x100 + span_pgm_videoregs[pgm_sprite_zoomtable_offset + yzom * 4 + 3]);
|
||||
|
||||
// //xzoom = ((pgm_videoregs[pgm_sprite_zoomtable_offset + xzom * 4] * 0x100 + pgm_videoregs[pgm_sprite_zoomtable_offset + xzom * 4 + 1]) << 16) | (pgm_videoregs[pgm_sprite_zoomtable_offset + xzom * 4 + 2] * 0x100 + pgm_videoregs[pgm_sprite_zoomtable_offset + xzom * 4 + 3]);
|
||||
// //yzoom = ((pgm_videoregs[pgm_sprite_zoomtable_offset + yzom * 4] * 0x100 + pgm_videoregs[pgm_sprite_zoomtable_offset + yzom * 4 + 1]) << 16) | (pgm_videoregs[pgm_sprite_zoomtable_offset + yzom * 4 + 2] * 0x100 + pgm_videoregs[pgm_sprite_zoomtable_offset + yzom * 4 + 3]);
|
||||
// boff *= 2;
|
||||
// if (xpos > 0x3ff)
|
||||
// xpos -= 0x800;
|
||||
// if (ypos > 0x1ff)
|
||||
// ypos -= 0x400;
|
||||
// if (high == 0)
|
||||
// break;
|
||||
// if ((priority == 1) && (pri == 0))
|
||||
// break;
|
||||
// draw_sprite_new_zoomed(wide, high, xpos, ypos, palt, boff, flip, xzoom, xgrow, yzoom, ygrow);
|
||||
// pgm_sprite_source_offset += 5;
|
||||
// }
|
||||
//}
|
||||
private static void pgm_tx_videoram_w(int offset, byte data)
|
||||
{
|
||||
int col, row;
|
||||
|
@ -115,6 +115,8 @@ namespace MAME.Core
|
||||
i1++;
|
||||
}
|
||||
}
|
||||
//TODO 移动到这里,但是大小,还需要考虑
|
||||
static short[] sample_data = new short[10000];
|
||||
public static void okim6295_update(int offset, int length)
|
||||
{
|
||||
int i;
|
||||
@ -124,7 +126,8 @@ namespace MAME.Core
|
||||
}
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
short[] sample_data = new short[10000];
|
||||
//不每次new,避免GC,排除问题。待验证影响
|
||||
//short[] sample_data = new short[10000];
|
||||
int remaining = length;
|
||||
while (remaining != 0)
|
||||
{
|
||||
|
@ -1032,21 +1032,35 @@ namespace MAME.Core
|
||||
ym2151_write_reg(i, 0);
|
||||
}
|
||||
}
|
||||
private static int op_calc(int i1, uint env, int pm)
|
||||
|
||||
unsafe static int op_calc(YM2151Operator* PSGoper, int i1, uint env, int pm)
|
||||
{
|
||||
uint p;
|
||||
p = (env << 3) + sin_tab[(((int)((PSG.oper[i1].phase & 0xffff0000) + (pm << 15))) >> 16) & 0x3ff];
|
||||
p = (env << 3) + sin_tab[(((int)((PSGoper[i1].phase & 0xffff0000) + (pm << 15))) >> 16) & 0x3ff];
|
||||
if (p >= 13 * 2 * 0x100)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return tl_tab[p];
|
||||
}
|
||||
private static int op_calc1(int i1, uint env, int pm)
|
||||
|
||||
//private static int op_calc(int i1, uint env, int pm)
|
||||
//{
|
||||
// uint p;
|
||||
// p = (env << 3) + sin_tab[(((int)((PSG.oper[i1].phase & 0xffff0000) + (pm << 15))) >> 16) & 0x3ff];
|
||||
// if (p >= 13 * 2 * 0x100)
|
||||
// {
|
||||
// return 0;
|
||||
// }
|
||||
// return tl_tab[p];
|
||||
//}
|
||||
|
||||
|
||||
unsafe static int op_calc1(YM2151Operator* PSGoper, int i1, uint env, int pm)
|
||||
{
|
||||
uint p;
|
||||
int i;
|
||||
i = (int)((PSG.oper[i1].phase & 0xffff0000) + pm);
|
||||
i = (int)((PSGoper[i1].phase & 0xffff0000) + pm);
|
||||
p = (env << 3) + sin_tab[(i >> 16) & 0x3ff];
|
||||
if (p >= 13 * 2 * 0x100)
|
||||
{
|
||||
@ -1054,63 +1068,155 @@ namespace MAME.Core
|
||||
}
|
||||
return tl_tab[p];
|
||||
}
|
||||
private static uint volume_calc(int i1, uint AM)
|
||||
|
||||
//private static int op_calc1_src(int i1, uint env, int pm)
|
||||
//{
|
||||
// uint p;
|
||||
// int i;
|
||||
// i = (int)((PSG.oper[i1].phase & 0xffff0000) + pm);
|
||||
// p = (env << 3) + sin_tab[(i >> 16) & 0x3ff];
|
||||
// if (p >= 13 * 2 * 0x100)
|
||||
// {
|
||||
// return 0;
|
||||
// }
|
||||
// return tl_tab[p];
|
||||
//}
|
||||
|
||||
unsafe static uint volume_calc(YM2151Operator* PSGoper, int i1, uint AM)
|
||||
{
|
||||
uint i11;
|
||||
i11 = PSG.oper[i1].tl + ((uint)PSG.oper[i1].volume) + (AM & PSG.oper[i1].AMmask);
|
||||
i11 = PSGoper[i1].tl + ((uint)PSGoper[i1].volume) + (AM & PSGoper[i1].AMmask);
|
||||
return i11;
|
||||
}
|
||||
private static void chan_calc(int chan)
|
||||
//private static uint volume_calc_old(int i1, uint AM)
|
||||
//{
|
||||
// uint i11;
|
||||
// i11 = PSG.oper[i1].tl + ((uint)PSG.oper[i1].volume) + (AM & PSG.oper[i1].AMmask);
|
||||
// return i11;
|
||||
//}
|
||||
|
||||
//chan_calc高频调用 单次Update 5467次 左右,下级堆栈volume_calc 20000+次 op_calc 10000+次
|
||||
|
||||
unsafe static void chan_calc(YM2151Operator* PSGoper, int* chanout, int* imem, int chan)
|
||||
{
|
||||
|
||||
//fixed (YM2151Operator* PSGoperPtr = &PSG.oper[0])
|
||||
{
|
||||
//YM2151Operator* PSGoper = PSGoperPtr;
|
||||
uint env;
|
||||
uint AM = 0;
|
||||
//m2 = c1 = c2 = mem = 0;
|
||||
chanout[8] = chanout[9] = chanout[10] = chanout[11] = 0;
|
||||
//op = PSG.oper[chan * 4]; /* M1 */
|
||||
//op = PSGoper[chan * 4]; /* M1 */
|
||||
//op.mem_connect = op.mem_value; /* restore delayed sample (MEM) value to m2 or c2 */
|
||||
set_mem(chan * 4);
|
||||
if (PSG.oper[chan * 4].ams != 0)
|
||||
set_mem(PSGoper, chanout, imem, chan * 4);
|
||||
if (PSGoper[chan * 4].ams != 0)
|
||||
{
|
||||
AM = PSG.lfa << (int)(PSG.oper[chan * 4].ams - 1);
|
||||
AM = PSG.lfa << (int)(PSGoper[chan * 4].ams - 1);
|
||||
}
|
||||
env = volume_calc((int)(chan * 4), AM);
|
||||
|
||||
env = volume_calc(PSGoper, (chan * 4), AM);
|
||||
//env = volume_calc_planB(PSGoper[chan * 4], AM);
|
||||
{
|
||||
int iout = PSG.oper[chan * 4].fb_out_prev + PSG.oper[chan * 4].fb_out_curr;
|
||||
PSG.oper[chan * 4].fb_out_prev = PSG.oper[chan * 4].fb_out_curr;
|
||||
int iout = PSGoper[chan * 4].fb_out_prev + PSGoper[chan * 4].fb_out_curr;
|
||||
PSGoper[chan * 4].fb_out_prev = PSGoper[chan * 4].fb_out_curr;
|
||||
|
||||
set_value1(chan * 4);
|
||||
set_value1(chanout, PSGoper, chan * 4);
|
||||
|
||||
PSG.oper[chan * 4].fb_out_curr = 0;
|
||||
PSGoper[chan * 4].fb_out_curr = 0;
|
||||
if (env < 13 * 64)
|
||||
{
|
||||
if (PSG.oper[chan * 4].fb_shift == 0)
|
||||
if (PSGoper[chan * 4].fb_shift == 0)
|
||||
{
|
||||
iout = 0;
|
||||
}
|
||||
PSG.oper[chan * 4].fb_out_curr = op_calc1((int)(chan * 4), env, (int)(iout << (int)PSG.oper[chan * 4].fb_shift));
|
||||
PSGoper[chan * 4].fb_out_curr = op_calc1(PSGoper, (chan * 4), env, (iout << (int)PSGoper[chan * 4].fb_shift));
|
||||
}
|
||||
}
|
||||
env = volume_calc((int)(chan * 4 + 1), AM); /* M2 */
|
||||
env = volume_calc(PSGoper, (chan * 4 + 1), AM); /* M2 */
|
||||
//env = volume_calc_planB(PSGoper[chan * 4 + 1], AM);/* M2 */
|
||||
if (env < 13 * 64)
|
||||
{
|
||||
//PSG.oper[chan * 4 + 1].connect += op_calc((int)(chan * 4 + 1), env, m2);
|
||||
set_value2(chan * 4 + 1, op_calc((int)(chan * 4 + 1), env, chanout[8]));// m2));
|
||||
//PSGoper[chan * 4 + 1].connect += op_calc((int)(chan * 4 + 1), env, m2);
|
||||
set_value2(chanout, chan * 4 + 1, op_calc(PSGoper, (chan * 4 + 1), env, chanout[8]));// m2));
|
||||
}
|
||||
env = volume_calc((int)(chan * 4 + 2), AM); /* C1 */
|
||||
env = volume_calc(PSGoper, (chan * 4 + 2), AM); /* C1 */
|
||||
//env = volume_calc_planB(PSGoper[chan * 4 + 2], AM); /* C1 */
|
||||
if (env < 13 * 64)
|
||||
{
|
||||
//PSG.oper[chan * 4 + 2].connect += op_calc((int)(chan * 4 + 2), env, c1);
|
||||
set_value2(chan * 4 + 2, op_calc((int)(chan * 4 + 2), env, chanout[9]));// c1));
|
||||
//PSGoper[chan * 4 + 2].connect += op_calc((int)(chan * 4 + 2), env, c1);
|
||||
set_value2(chanout, chan * 4 + 2, op_calc(PSGoper, (chan * 4 + 2), env, chanout[9]));// c1));
|
||||
}
|
||||
env = volume_calc((int)(chan * 4 + 3), AM); /* C2 */
|
||||
env = volume_calc(PSGoper, (chan * 4 + 3), AM); /* C2 */
|
||||
//env = volume_calc_planB(PSGoper[chan * 4 + 3], AM); /* C2 */
|
||||
if (env < 13 * 64)
|
||||
{
|
||||
chanout[chan] += op_calc((int)(chan * 4 + 3), env, chanout[10]);// c2);
|
||||
chanout[chan] += op_calc(PSGoper, (chan * 4 + 3), env, chanout[10]);// c2);
|
||||
}
|
||||
/* M1 */
|
||||
PSG.oper[chan * 4].mem_value = chanout[11];//mem;
|
||||
PSGoper[chan * 4].mem_value = chanout[11];//mem;
|
||||
}
|
||||
private static void chan7_calc()
|
||||
|
||||
}
|
||||
|
||||
//private static void chan_calc_src(int chan)
|
||||
//{
|
||||
// uint env;
|
||||
// uint AM = 0;
|
||||
// //m2 = c1 = c2 = mem = 0;
|
||||
// chanout[8] = chanout[9] = chanout[10] = chanout[11] = 0;
|
||||
// //op = PSG.oper[chan * 4]; /* M1 */
|
||||
// //op.mem_connect = op.mem_value; /* restore delayed sample (MEM) value to m2 or c2 */
|
||||
// set_mem(chan * 4);
|
||||
// if (PSG.oper[chan * 4].ams != 0)
|
||||
// {
|
||||
// AM = PSG.lfa << (int)(PSG.oper[chan * 4].ams - 1);
|
||||
// }
|
||||
|
||||
|
||||
// env = volume_calc((int)(chan * 4), AM);
|
||||
// //env = volume_calc_planB(PSG.oper[chan * 4], AM);
|
||||
// {
|
||||
// int iout = PSG.oper[chan * 4].fb_out_prev + PSG.oper[chan * 4].fb_out_curr;
|
||||
// PSG.oper[chan * 4].fb_out_prev = PSG.oper[chan * 4].fb_out_curr;
|
||||
|
||||
// set_value1(chan * 4);
|
||||
|
||||
// PSG.oper[chan * 4].fb_out_curr = 0;
|
||||
// if (env < 13 * 64)
|
||||
// {
|
||||
// if (PSG.oper[chan * 4].fb_shift == 0)
|
||||
// {
|
||||
// iout = 0;
|
||||
// }
|
||||
// PSG.oper[chan * 4].fb_out_curr = op_calc1((int)(chan * 4), env, (int)(iout << (int)PSG.oper[chan * 4].fb_shift));
|
||||
// }
|
||||
// }
|
||||
// env = volume_calc((int)(chan * 4 + 1), AM); /* M2 */
|
||||
// //env = volume_calc_planB(PSG.oper[chan * 4 + 1], AM);/* M2 */
|
||||
// if (env < 13 * 64)
|
||||
// {
|
||||
// //PSG.oper[chan * 4 + 1].connect += op_calc((int)(chan * 4 + 1), env, m2);
|
||||
// set_value2(chan * 4 + 1, op_calc((int)(chan * 4 + 1), env, chanout[8]));// m2));
|
||||
// }
|
||||
// env = volume_calc((int)(chan * 4 + 2), AM); /* C1 */
|
||||
// //env = volume_calc_planB(PSG.oper[chan * 4 + 2], AM); /* C1 */
|
||||
// if (env < 13 * 64)
|
||||
// {
|
||||
// //PSG.oper[chan * 4 + 2].connect += op_calc((int)(chan * 4 + 2), env, c1);
|
||||
// set_value2(chan * 4 + 2, op_calc((int)(chan * 4 + 2), env, chanout[9]));// c1));
|
||||
// }
|
||||
// env = volume_calc((int)(chan * 4 + 3), AM); /* C2 */
|
||||
// //env = volume_calc_planB(PSG.oper[chan * 4 + 3], AM); /* C2 */
|
||||
// if (env < 13 * 64)
|
||||
// {
|
||||
// chanout[chan] += op_calc((int)(chan * 4 + 3), env, chanout[10]);// c2);
|
||||
// }
|
||||
// /* M1 */
|
||||
// PSG.oper[chan * 4].mem_value = chanout[11];//mem;
|
||||
//}
|
||||
|
||||
unsafe static void chan7_calc(YM2151Operator* PSGoper, int* chanout, int* imem)
|
||||
{
|
||||
uint env;
|
||||
uint AM = 0;
|
||||
@ -1118,37 +1224,41 @@ namespace MAME.Core
|
||||
chanout[8] = chanout[9] = chanout[10] = chanout[11] = 0;
|
||||
//op = PSG.oper[7 * 4]; /* M1 */
|
||||
//op.mem_connect = op.mem_value; /* restore delayed sample (MEM) value to m2 or c2 */
|
||||
set_mem(7 * 4);
|
||||
if (PSG.oper[7 * 4].ams != 0)
|
||||
set_mem(PSGoper, chanout, imem, 7 * 4);
|
||||
if (PSGoper[7 * 4].ams != 0)
|
||||
{
|
||||
AM = PSG.lfa << (int)(PSG.oper[7 * 4].ams - 1);
|
||||
AM = PSG.lfa << (int)(PSGoper[7 * 4].ams - 1);
|
||||
}
|
||||
env = volume_calc(7 * 4, AM);
|
||||
int iout = PSG.oper[7 * 4].fb_out_prev + PSG.oper[7 * 4].fb_out_curr;
|
||||
PSG.oper[7 * 4].fb_out_prev = PSG.oper[7 * 4].fb_out_curr;
|
||||
set_value1(7 * 4);
|
||||
PSG.oper[7 * 4].fb_out_curr = 0;
|
||||
env = volume_calc(PSGoper, 7 * 4, AM);
|
||||
//env = volume_calc_planB(PSGoper[7*4], AM);
|
||||
int iout = PSGoper[7 * 4].fb_out_prev + PSGoper[7 * 4].fb_out_curr;
|
||||
PSGoper[7 * 4].fb_out_prev = PSGoper[7 * 4].fb_out_curr;
|
||||
set_value1(chanout, PSGoper, 7 * 4);
|
||||
PSGoper[7 * 4].fb_out_curr = 0;
|
||||
if (env < 13 * 64)
|
||||
{
|
||||
if (PSG.oper[7 * 4].fb_shift == 0)
|
||||
if (PSGoper[7 * 4].fb_shift == 0)
|
||||
{
|
||||
iout = 0;
|
||||
}
|
||||
PSG.oper[7 * 4].fb_out_curr = op_calc1(7 * 4, env, (iout << (int)PSG.oper[7 * 4].fb_shift));
|
||||
PSGoper[7 * 4].fb_out_curr = op_calc1(PSGoper, 7 * 4, env, (iout << (int)PSGoper[7 * 4].fb_shift));
|
||||
}
|
||||
env = volume_calc(7 * 4 + 1, AM); /* M2 */
|
||||
env = volume_calc(PSGoper, 7 * 4 + 1, AM); /* M2 */
|
||||
//env = volume_calc_planB(PSGoper[7 * 4 + 1], AM);/* M2 */
|
||||
if (env < 13 * 64)
|
||||
{
|
||||
//PSG.oper[7 * 4 + 1].connect += op_calc(7 * 4 + 1, env, m2);
|
||||
set_value2(7 * 4 + 1, op_calc(7 * 4 + 1, env, chanout[8]));// m2));
|
||||
//PSGoper[7 * 4 + 1].connect += op_calc(7 * 4 + 1, env, m2);
|
||||
set_value2(chanout, 7 * 4 + 1, op_calc(PSGoper, 7 * 4 + 1, env, chanout[8]));// m2));
|
||||
}
|
||||
env = volume_calc(7 * 4 + 2, AM); /* C1 */
|
||||
env = volume_calc(PSGoper, 7 * 4 + 2, AM); /* C1 */
|
||||
//env = volume_calc_planB(PSGoper[7 * 4 + 2], AM);/* C1 */
|
||||
if (env < 13 * 64)
|
||||
{
|
||||
//PSG.oper[7 * 4 + 2].connect += op_calc(7 * 4 + 2, env, c1);
|
||||
set_value2(7 * 4 + 2, op_calc(7 * 4 + 2, env, chanout[9]));// c1));
|
||||
//PSGoper[7 * 4 + 2].connect += op_calc(7 * 4 + 2, env, c1);
|
||||
set_value2(chanout, 7 * 4 + 2, op_calc(PSGoper, 7 * 4 + 2, env, chanout[9]));// c1));
|
||||
}
|
||||
env = volume_calc(7 * 4 + 3, AM); /* C2 */
|
||||
env = volume_calc(PSGoper, 7 * 4 + 3, AM); /* C2 */
|
||||
//env = volume_calc_planB(PSGoper[7 * 4 + 3], AM);/* C2 */
|
||||
if ((PSG.noise & 0x80) != 0)
|
||||
{
|
||||
uint noiseout;
|
||||
@ -1161,12 +1271,74 @@ namespace MAME.Core
|
||||
else
|
||||
{
|
||||
if (env < 13 * 64)
|
||||
chanout[7] += op_calc(7 * 4 + 3, env, chanout[10]);// c2);
|
||||
chanout[7] += op_calc(PSGoper, 7 * 4 + 3, env, chanout[10]);// c2);
|
||||
}
|
||||
/* M1 */
|
||||
PSG.oper[7 * 4].mem_value = chanout[11];//mem;
|
||||
PSGoper[7 * 4].mem_value = chanout[11];//mem;
|
||||
}
|
||||
private static void advance_eg()
|
||||
|
||||
//private static void chan7_calc_src()
|
||||
//{
|
||||
// uint env;
|
||||
// uint AM = 0;
|
||||
// //m2 = c1 = c2 = mem = 0;
|
||||
// chanout[8] = chanout[9] = chanout[10] = chanout[11] = 0;
|
||||
// //op = PSG.oper[7 * 4]; /* M1 */
|
||||
// //op.mem_connect = op.mem_value; /* restore delayed sample (MEM) value to m2 or c2 */
|
||||
// set_mem(7 * 4);
|
||||
// if (PSG.oper[7 * 4].ams != 0)
|
||||
// {
|
||||
// AM = PSG.lfa << (int)(PSG.oper[7 * 4].ams - 1);
|
||||
// }
|
||||
// env = volume_calc(7 * 4, AM);
|
||||
// //env = volume_calc_planB(PSG.oper[7*4], AM);
|
||||
// int iout = PSG.oper[7 * 4].fb_out_prev + PSG.oper[7 * 4].fb_out_curr;
|
||||
// PSG.oper[7 * 4].fb_out_prev = PSG.oper[7 * 4].fb_out_curr;
|
||||
// set_value1(7 * 4);
|
||||
// PSG.oper[7 * 4].fb_out_curr = 0;
|
||||
// if (env < 13 * 64)
|
||||
// {
|
||||
// if (PSG.oper[7 * 4].fb_shift == 0)
|
||||
// {
|
||||
// iout = 0;
|
||||
// }
|
||||
// PSG.oper[7 * 4].fb_out_curr = op_calc1(7 * 4, env, (iout << (int)PSG.oper[7 * 4].fb_shift));
|
||||
// }
|
||||
// env = volume_calc(7 * 4 + 1, AM); /* M2 */
|
||||
// //env = volume_calc_planB(PSG.oper[7 * 4 + 1], AM);/* M2 */
|
||||
// if (env < 13 * 64)
|
||||
// {
|
||||
// //PSG.oper[7 * 4 + 1].connect += op_calc(7 * 4 + 1, env, m2);
|
||||
// set_value2(7 * 4 + 1, op_calc(7 * 4 + 1, env, chanout[8]));// m2));
|
||||
// }
|
||||
// env = volume_calc(7 * 4 + 2, AM); /* C1 */
|
||||
// //env = volume_calc_planB(PSG.oper[7 * 4 + 2], AM);/* C1 */
|
||||
// if (env < 13 * 64)
|
||||
// {
|
||||
// //PSG.oper[7 * 4 + 2].connect += op_calc(7 * 4 + 2, env, c1);
|
||||
// set_value2(7 * 4 + 2, op_calc(7 * 4 + 2, env, chanout[9]));// c1));
|
||||
// }
|
||||
// env = volume_calc(7 * 4 + 3, AM); /* C2 */
|
||||
// //env = volume_calc_planB(PSG.oper[7 * 4 + 3], AM);/* C2 */
|
||||
// if ((PSG.noise & 0x80) != 0)
|
||||
// {
|
||||
// uint noiseout;
|
||||
|
||||
// noiseout = 0;
|
||||
// if (env < 0x3ff)
|
||||
// noiseout = (env ^ 0x3ff) * 2; /* range of the YM2151 noise output is -2044 to 2040 */
|
||||
// chanout[7] += (int)(((PSG.noise_rng & 0x10000) != 0) ? noiseout : -noiseout); /* bit 16 -> output */
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// if (env < 13 * 64)
|
||||
// chanout[7] += op_calc(7 * 4 + 3, env, chanout[10]);// c2);
|
||||
// }
|
||||
// /* M1 */
|
||||
// PSG.oper[7 * 4].mem_value = chanout[11];//mem;
|
||||
//}
|
||||
|
||||
unsafe static void advance_eg(YM2151Operator* PSGoper)
|
||||
{
|
||||
uint i;
|
||||
int i1 = 0;
|
||||
@ -1176,53 +1348,53 @@ namespace MAME.Core
|
||||
PSG.eg_timer -= PSG.eg_timer_overflow;
|
||||
PSG.eg_cnt++;
|
||||
/* envelope generator */
|
||||
//op = PSG.oper[i1]; /* CH 0 M1 */
|
||||
//op = PSGoper[i1]; /* CH 0 M1 */
|
||||
i = 32;
|
||||
do
|
||||
{
|
||||
switch (PSG.oper[i1].state)
|
||||
switch (PSGoper[i1].state)
|
||||
{
|
||||
case 4: /* attack phase */
|
||||
if ((PSG.eg_cnt & ((1 << PSG.oper[i1].eg_sh_ar) - 1)) == 0)
|
||||
if ((PSG.eg_cnt & ((1 << PSGoper[i1].eg_sh_ar) - 1)) == 0)
|
||||
{
|
||||
PSG.oper[i1].volume += (~PSG.oper[i1].volume *
|
||||
(eg_inc[PSG.oper[i1].eg_sel_ar + ((PSG.eg_cnt >> PSG.oper[i1].eg_sh_ar) & 7)])
|
||||
PSGoper[i1].volume += (~PSGoper[i1].volume *
|
||||
(eg_inc[PSGoper[i1].eg_sel_ar + ((PSG.eg_cnt >> PSGoper[i1].eg_sh_ar) & 7)])
|
||||
) >> 4;
|
||||
|
||||
if (PSG.oper[i1].volume <= 0)
|
||||
if (PSGoper[i1].volume <= 0)
|
||||
{
|
||||
PSG.oper[i1].volume = 0;
|
||||
PSG.oper[i1].state = 3;
|
||||
PSGoper[i1].volume = 0;
|
||||
PSGoper[i1].state = 3;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 3: /* decay phase */
|
||||
if ((PSG.eg_cnt & ((1 << PSG.oper[i1].eg_sh_d1r) - 1)) == 0)
|
||||
if ((PSG.eg_cnt & ((1 << PSGoper[i1].eg_sh_d1r) - 1)) == 0)
|
||||
{
|
||||
PSG.oper[i1].volume += eg_inc[PSG.oper[i1].eg_sel_d1r + ((PSG.eg_cnt >> PSG.oper[i1].eg_sh_d1r) & 7)];
|
||||
if (PSG.oper[i1].volume >= PSG.oper[i1].d1l)
|
||||
PSG.oper[i1].state = 2;
|
||||
PSGoper[i1].volume += eg_inc[PSGoper[i1].eg_sel_d1r + ((PSG.eg_cnt >> PSGoper[i1].eg_sh_d1r) & 7)];
|
||||
if (PSGoper[i1].volume >= PSGoper[i1].d1l)
|
||||
PSGoper[i1].state = 2;
|
||||
}
|
||||
break;
|
||||
case 2: /* sustain phase */
|
||||
if ((PSG.eg_cnt & ((1 << PSG.oper[i1].eg_sh_d2r) - 1)) == 0)
|
||||
if ((PSG.eg_cnt & ((1 << PSGoper[i1].eg_sh_d2r) - 1)) == 0)
|
||||
{
|
||||
PSG.oper[i1].volume += eg_inc[PSG.oper[i1].eg_sel_d2r + ((PSG.eg_cnt >> PSG.oper[i1].eg_sh_d2r) & 7)];
|
||||
if (PSG.oper[i1].volume >= 0x3ff)
|
||||
PSGoper[i1].volume += eg_inc[PSGoper[i1].eg_sel_d2r + ((PSG.eg_cnt >> PSGoper[i1].eg_sh_d2r) & 7)];
|
||||
if (PSGoper[i1].volume >= 0x3ff)
|
||||
{
|
||||
PSG.oper[i1].volume = 0x3ff;
|
||||
PSG.oper[i1].state = 0;
|
||||
PSGoper[i1].volume = 0x3ff;
|
||||
PSGoper[i1].state = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 1: /* release phase */
|
||||
if ((PSG.eg_cnt & ((1 << PSG.oper[i1].eg_sh_rr) - 1)) == 0)
|
||||
if ((PSG.eg_cnt & ((1 << PSGoper[i1].eg_sh_rr) - 1)) == 0)
|
||||
{
|
||||
PSG.oper[i1].volume += eg_inc[PSG.oper[i1].eg_sel_rr + ((PSG.eg_cnt >> PSG.oper[i1].eg_sh_rr) & 7)];
|
||||
if (PSG.oper[i1].volume >= 0x3ff)
|
||||
PSGoper[i1].volume += eg_inc[PSGoper[i1].eg_sel_rr + ((PSG.eg_cnt >> PSGoper[i1].eg_sh_rr) & 7)];
|
||||
if (PSGoper[i1].volume >= 0x3ff)
|
||||
{
|
||||
PSG.oper[i1].volume = 0x3ff;
|
||||
PSG.oper[i1].state = 0;
|
||||
PSGoper[i1].volume = 0x3ff;
|
||||
PSGoper[i1].state = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -1232,7 +1404,74 @@ namespace MAME.Core
|
||||
} while (i != 0);
|
||||
}
|
||||
}
|
||||
private static void advance()
|
||||
|
||||
//private static void advance_eg()
|
||||
//{
|
||||
// uint i;
|
||||
// int i1 = 0;
|
||||
// PSG.eg_timer += PSG.eg_timer_add;
|
||||
// while (PSG.eg_timer >= PSG.eg_timer_overflow)
|
||||
// {
|
||||
// PSG.eg_timer -= PSG.eg_timer_overflow;
|
||||
// PSG.eg_cnt++;
|
||||
// /* envelope generator */
|
||||
// //op = PSG.oper[i1]; /* CH 0 M1 */
|
||||
// i = 32;
|
||||
// do
|
||||
// {
|
||||
// switch (PSG.oper[i1].state)
|
||||
// {
|
||||
// case 4: /* attack phase */
|
||||
// if ((PSG.eg_cnt & ((1 << PSG.oper[i1].eg_sh_ar) - 1)) == 0)
|
||||
// {
|
||||
// PSG.oper[i1].volume += (~PSG.oper[i1].volume *
|
||||
// (eg_inc[PSG.oper[i1].eg_sel_ar + ((PSG.eg_cnt >> PSG.oper[i1].eg_sh_ar) & 7)])
|
||||
// ) >> 4;
|
||||
|
||||
// if (PSG.oper[i1].volume <= 0)
|
||||
// {
|
||||
// PSG.oper[i1].volume = 0;
|
||||
// PSG.oper[i1].state = 3;
|
||||
// }
|
||||
// }
|
||||
// break;
|
||||
// case 3: /* decay phase */
|
||||
// if ((PSG.eg_cnt & ((1 << PSG.oper[i1].eg_sh_d1r) - 1)) == 0)
|
||||
// {
|
||||
// PSG.oper[i1].volume += eg_inc[PSG.oper[i1].eg_sel_d1r + ((PSG.eg_cnt >> PSG.oper[i1].eg_sh_d1r) & 7)];
|
||||
// if (PSG.oper[i1].volume >= PSG.oper[i1].d1l)
|
||||
// PSG.oper[i1].state = 2;
|
||||
// }
|
||||
// break;
|
||||
// case 2: /* sustain phase */
|
||||
// if ((PSG.eg_cnt & ((1 << PSG.oper[i1].eg_sh_d2r) - 1)) == 0)
|
||||
// {
|
||||
// PSG.oper[i1].volume += eg_inc[PSG.oper[i1].eg_sel_d2r + ((PSG.eg_cnt >> PSG.oper[i1].eg_sh_d2r) & 7)];
|
||||
// if (PSG.oper[i1].volume >= 0x3ff)
|
||||
// {
|
||||
// PSG.oper[i1].volume = 0x3ff;
|
||||
// PSG.oper[i1].state = 0;
|
||||
// }
|
||||
// }
|
||||
// break;
|
||||
// case 1: /* release phase */
|
||||
// if ((PSG.eg_cnt & ((1 << PSG.oper[i1].eg_sh_rr) - 1)) == 0)
|
||||
// {
|
||||
// PSG.oper[i1].volume += eg_inc[PSG.oper[i1].eg_sel_rr + ((PSG.eg_cnt >> PSG.oper[i1].eg_sh_rr) & 7)];
|
||||
// if (PSG.oper[i1].volume >= 0x3ff)
|
||||
// {
|
||||
// PSG.oper[i1].volume = 0x3ff;
|
||||
// PSG.oper[i1].state = 0;
|
||||
// }
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
// i1++;
|
||||
// i--;
|
||||
// } while (i != 0);
|
||||
// }
|
||||
//}
|
||||
unsafe static void advance(YM2151Operator* PSGoper, uint* PSGfreq)
|
||||
{
|
||||
uint i;
|
||||
int a, p;
|
||||
@ -1319,39 +1558,39 @@ namespace MAME.Core
|
||||
}
|
||||
/* phase generator */
|
||||
uint i1 = 0;
|
||||
//op = PSG.oper[i1]; /* CH 0 M1 */
|
||||
//op = PSGoper[i1]; /* CH 0 M1 */
|
||||
i = 8;
|
||||
do
|
||||
{
|
||||
if (PSG.oper[i1].pms != 0) /* only when phase modulation from LFO is enabled for this channel */
|
||||
if (PSGoper[i1].pms != 0) /* only when phase modulation from LFO is enabled for this channel */
|
||||
{
|
||||
int mod_ind = PSG.lfp; /* -128..+127 (8bits signed) */
|
||||
if (PSG.oper[i1].pms < 6)
|
||||
mod_ind >>= (int)(6 - PSG.oper[i1].pms);
|
||||
if (PSGoper[i1].pms < 6)
|
||||
mod_ind >>= (int)(6 - PSGoper[i1].pms);
|
||||
else
|
||||
mod_ind <<= (int)(PSG.oper[i1].pms - 5);
|
||||
mod_ind <<= (int)(PSGoper[i1].pms - 5);
|
||||
if (mod_ind != 0)
|
||||
{
|
||||
uint kc_channel = (uint)(PSG.oper[i1].kc_i + mod_ind);
|
||||
PSG.oper[i1].phase += (uint)(((PSG.freq[kc_channel + PSG.oper[i1].dt2] + PSG.oper[i1].dt1) * PSG.oper[i1].mul) >> 1);
|
||||
PSG.oper[i1 + 1].phase += (uint)(((PSG.freq[kc_channel + PSG.oper[i1 + 1].dt2] + PSG.oper[i1 + 1].dt1) * PSG.oper[i1 + 1].mul) >> 1);
|
||||
PSG.oper[i1 + 2].phase += (uint)(((PSG.freq[kc_channel + PSG.oper[i1 + 2].dt2] + PSG.oper[i1 + 2].dt1) * PSG.oper[i1 + 2].mul) >> 1);
|
||||
PSG.oper[i1 + 3].phase += (uint)(((PSG.freq[kc_channel + PSG.oper[i1 + 3].dt2] + PSG.oper[i1 + 3].dt1) * PSG.oper[i1 + 3].mul) >> 1);
|
||||
uint kc_channel = (uint)(PSGoper[i1].kc_i + mod_ind);
|
||||
PSGoper[i1].phase += (uint)(((PSGfreq[kc_channel + PSGoper[i1].dt2] + PSGoper[i1].dt1) * PSGoper[i1].mul) >> 1);
|
||||
PSGoper[i1 + 1].phase += (uint)(((PSGfreq[kc_channel + PSGoper[i1 + 1].dt2] + PSGoper[i1 + 1].dt1) * PSGoper[i1 + 1].mul) >> 1);
|
||||
PSGoper[i1 + 2].phase += (uint)(((PSGfreq[kc_channel + PSGoper[i1 + 2].dt2] + PSGoper[i1 + 2].dt1) * PSGoper[i1 + 2].mul) >> 1);
|
||||
PSGoper[i1 + 3].phase += (uint)(((PSGfreq[kc_channel + PSGoper[i1 + 3].dt2] + PSGoper[i1 + 3].dt1) * PSGoper[i1 + 3].mul) >> 1);
|
||||
}
|
||||
else /* phase modulation from LFO is equal to zero */
|
||||
{
|
||||
PSG.oper[i1].phase += PSG.oper[i1].freq;
|
||||
PSG.oper[i1 + 1].phase += PSG.oper[i1 + 1].freq;
|
||||
PSG.oper[i1 + 2].phase += PSG.oper[i1 + 2].freq;
|
||||
PSG.oper[i1 + 3].phase += PSG.oper[i1 + 3].freq;
|
||||
PSGoper[i1].phase += PSGoper[i1].freq;
|
||||
PSGoper[i1 + 1].phase += PSGoper[i1 + 1].freq;
|
||||
PSGoper[i1 + 2].phase += PSGoper[i1 + 2].freq;
|
||||
PSGoper[i1 + 3].phase += PSGoper[i1 + 3].freq;
|
||||
}
|
||||
}
|
||||
else /* phase modulation from LFO is disabled */
|
||||
{
|
||||
PSG.oper[i1].phase += PSG.oper[i1].freq;
|
||||
PSG.oper[i1 + 1].phase += PSG.oper[i1 + 1].freq;
|
||||
PSG.oper[i1 + 2].phase += PSG.oper[i1 + 2].freq;
|
||||
PSG.oper[i1 + 3].phase += PSG.oper[i1 + 3].freq;
|
||||
PSGoper[i1].phase += PSGoper[i1].freq;
|
||||
PSGoper[i1 + 1].phase += PSGoper[i1 + 1].freq;
|
||||
PSGoper[i1 + 2].phase += PSGoper[i1 + 2].freq;
|
||||
PSGoper[i1 + 3].phase += PSGoper[i1 + 3].freq;
|
||||
}
|
||||
i1 += 4;
|
||||
i--;
|
||||
@ -1361,7 +1600,7 @@ namespace MAME.Core
|
||||
if (PSG.csm_req == 2) /* KEY ON */
|
||||
{
|
||||
i1 = 0;
|
||||
PSG.oper[i1] = PSG.oper[i1]; /* CH 0 M1 */
|
||||
PSGoper[i1] = PSGoper[i1]; /* CH 0 M1 */
|
||||
i = 32;
|
||||
do
|
||||
{
|
||||
@ -1374,7 +1613,7 @@ namespace MAME.Core
|
||||
else /* KEY OFF */
|
||||
{
|
||||
i1 = 0;
|
||||
PSG.oper[i1] = PSG.oper[i1]; /* CH 0 M1 */
|
||||
PSGoper[i1] = PSGoper[i1]; /* CH 0 M1 */
|
||||
i = 32;
|
||||
do
|
||||
{
|
||||
@ -1386,13 +1625,183 @@ namespace MAME.Core
|
||||
}
|
||||
}
|
||||
}
|
||||
public static void ym2151_update_one(int offset, int length)
|
||||
//private static void advance()
|
||||
//{
|
||||
// uint i;
|
||||
// int a, p;
|
||||
// /* LFO */
|
||||
// if ((PSG.test & 2) != 0)
|
||||
// {
|
||||
// PSG.lfo_phase = 0;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// PSG.lfo_timer += PSG.lfo_timer_add;
|
||||
// if (PSG.lfo_timer >= PSG.lfo_overflow)
|
||||
// {
|
||||
// PSG.lfo_timer -= PSG.lfo_overflow;
|
||||
// PSG.lfo_counter += PSG.lfo_counter_add;
|
||||
// PSG.lfo_phase += (PSG.lfo_counter >> 4);
|
||||
// PSG.lfo_phase &= 255;
|
||||
// PSG.lfo_counter &= 15;
|
||||
// }
|
||||
// }
|
||||
// i = PSG.lfo_phase;
|
||||
// /* calculate LFO AM and PM waveform value (all verified on real chip, except for noise algorithm which is impossible to analyse)*/
|
||||
// switch (PSG.lfo_wsel)
|
||||
// {
|
||||
// case 0:
|
||||
// /* saw */
|
||||
// /* AM: 255 down to 0 */
|
||||
// /* PM: 0 to 127, -127 to 0 (at PMD=127: LFP = 0 to 126, -126 to 0) */
|
||||
// a = (int)(255 - i);
|
||||
// if (i < 128)
|
||||
// p = (int)i;
|
||||
// else
|
||||
// p = (int)(i - 255);
|
||||
// break;
|
||||
// case 1:
|
||||
// /* square */
|
||||
// /* AM: 255, 0 */
|
||||
// /* PM: 128,-128 (LFP = exactly +PMD, -PMD) */
|
||||
// if (i < 128)
|
||||
// {
|
||||
// a = 255;
|
||||
// p = 128;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// a = 0;
|
||||
// p = -128;
|
||||
// }
|
||||
// break;
|
||||
// case 2:
|
||||
// /* triangle */
|
||||
// /* AM: 255 down to 1 step -2; 0 up to 254 step +2 */
|
||||
// /* PM: 0 to 126 step +2, 127 to 1 step -2, 0 to -126 step -2, -127 to -1 step +2*/
|
||||
// if (i < 128)
|
||||
// a = (int)(255 - (i * 2));
|
||||
// else
|
||||
// a = (int)((i * 2) - 256);
|
||||
// if (i < 64) /* i = 0..63 */
|
||||
// p = (int)(i * 2); /* 0 to 126 step +2 */
|
||||
// else if (i < 128) /* i = 64..127 */
|
||||
// p = (int)(255 - i * 2); /* 127 to 1 step -2 */
|
||||
// else if (i < 192) /* i = 128..191 */
|
||||
// p = (int)(256 - i * 2); /* 0 to -126 step -2*/
|
||||
// else /* i = 192..255 */
|
||||
// p = (int)(i * 2 - 511); /*-127 to -1 step +2*/
|
||||
// break;
|
||||
// case 3:
|
||||
// default: /*keep the compiler happy*/
|
||||
// a = lfo_noise_waveform[i];
|
||||
// p = a - 128;
|
||||
// break;
|
||||
// }
|
||||
// PSG.lfa = (uint)(a * PSG.amd / 128);
|
||||
// PSG.lfp = p * PSG.pmd / 128;
|
||||
// PSG.noise_p += PSG.noise_f;
|
||||
// i = (PSG.noise_p >> 16); /* number of events (shifts of the shift register) */
|
||||
// PSG.noise_p &= 0xffff;
|
||||
// while (i != 0)
|
||||
// {
|
||||
// uint j;
|
||||
// j = ((PSG.noise_rng ^ (PSG.noise_rng >> 3)) & 1) ^ 1;
|
||||
// PSG.noise_rng = (j << 16) | (PSG.noise_rng >> 1);
|
||||
// i--;
|
||||
// }
|
||||
// /* phase generator */
|
||||
// uint i1 = 0;
|
||||
// //op = PSG.oper[i1]; /* CH 0 M1 */
|
||||
// i = 8;
|
||||
// do
|
||||
// {
|
||||
// if (PSG.oper[i1].pms != 0) /* only when phase modulation from LFO is enabled for this channel */
|
||||
// {
|
||||
// int mod_ind = PSG.lfp; /* -128..+127 (8bits signed) */
|
||||
// if (PSG.oper[i1].pms < 6)
|
||||
// mod_ind >>= (int)(6 - PSG.oper[i1].pms);
|
||||
// else
|
||||
// mod_ind <<= (int)(PSG.oper[i1].pms - 5);
|
||||
// if (mod_ind != 0)
|
||||
// {
|
||||
// uint kc_channel = (uint)(PSG.oper[i1].kc_i + mod_ind);
|
||||
// PSG.oper[i1].phase += (uint)(((PSG.freq[kc_channel + PSG.oper[i1].dt2] + PSG.oper[i1].dt1) * PSG.oper[i1].mul) >> 1);
|
||||
// PSG.oper[i1 + 1].phase += (uint)(((PSG.freq[kc_channel + PSG.oper[i1 + 1].dt2] + PSG.oper[i1 + 1].dt1) * PSG.oper[i1 + 1].mul) >> 1);
|
||||
// PSG.oper[i1 + 2].phase += (uint)(((PSG.freq[kc_channel + PSG.oper[i1 + 2].dt2] + PSG.oper[i1 + 2].dt1) * PSG.oper[i1 + 2].mul) >> 1);
|
||||
// PSG.oper[i1 + 3].phase += (uint)(((PSG.freq[kc_channel + PSG.oper[i1 + 3].dt2] + PSG.oper[i1 + 3].dt1) * PSG.oper[i1 + 3].mul) >> 1);
|
||||
// }
|
||||
// else /* phase modulation from LFO is equal to zero */
|
||||
// {
|
||||
// PSG.oper[i1].phase += PSG.oper[i1].freq;
|
||||
// PSG.oper[i1 + 1].phase += PSG.oper[i1 + 1].freq;
|
||||
// PSG.oper[i1 + 2].phase += PSG.oper[i1 + 2].freq;
|
||||
// PSG.oper[i1 + 3].phase += PSG.oper[i1 + 3].freq;
|
||||
// }
|
||||
// }
|
||||
// else /* phase modulation from LFO is disabled */
|
||||
// {
|
||||
// PSG.oper[i1].phase += PSG.oper[i1].freq;
|
||||
// PSG.oper[i1 + 1].phase += PSG.oper[i1 + 1].freq;
|
||||
// PSG.oper[i1 + 2].phase += PSG.oper[i1 + 2].freq;
|
||||
// PSG.oper[i1 + 3].phase += PSG.oper[i1 + 3].freq;
|
||||
// }
|
||||
// i1 += 4;
|
||||
// i--;
|
||||
// } while (i != 0);
|
||||
// if (PSG.csm_req != 0) /* CSM KEYON/KEYOFF seqeunce request */
|
||||
// {
|
||||
// if (PSG.csm_req == 2) /* KEY ON */
|
||||
// {
|
||||
// i1 = 0;
|
||||
// PSG.oper[i1] = PSG.oper[i1]; /* CH 0 M1 */
|
||||
// i = 32;
|
||||
// do
|
||||
// {
|
||||
// KEY_ON(i1, 2);
|
||||
// i1++;
|
||||
// i--;
|
||||
// } while (i != 0);
|
||||
// PSG.csm_req = 1;
|
||||
// }
|
||||
// else /* KEY OFF */
|
||||
// {
|
||||
// i1 = 0;
|
||||
// PSG.oper[i1] = PSG.oper[i1]; /* CH 0 M1 */
|
||||
// i = 32;
|
||||
// do
|
||||
// {
|
||||
// KEY_OFF(i1, 0xfffffffe);
|
||||
// i1++;
|
||||
// i--;
|
||||
// } while (i != 0);
|
||||
// PSG.csm_req = 0;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
public unsafe static void ym2151_update_one(int offset, int length)
|
||||
{
|
||||
fixed (uint* PSGpanPtr = &PSG.pan[0])
|
||||
fixed (uint* PSGfreqPtr = &PSG.freq[0])
|
||||
fixed (YM2151Operator* PSGoperPtr = &PSG.oper[0])
|
||||
fixed (int* chanoutPtr = &chanout[0])
|
||||
fixed (int* streamoutput0Ptr = &Sound.ym2151stream.streamoutput[0][0])
|
||||
fixed (int* streamoutput1Ptr = &Sound.ym2151stream.streamoutput[0][1])
|
||||
fixed (int* imemPtr = &imem[0])
|
||||
{
|
||||
YM2151Operator* PSGoper = PSGoperPtr;
|
||||
uint* PSGpan = PSGpanPtr;
|
||||
uint* PSGfreq = PSGfreqPtr;
|
||||
int* chanout = chanoutPtr;
|
||||
int* streamoutput0 = streamoutput0Ptr;
|
||||
int* streamoutput1 = streamoutput1Ptr;
|
||||
int* imem = imemPtr;
|
||||
|
||||
int i;
|
||||
int outl, outr;
|
||||
for (i = 0; i < length; i++)
|
||||
{
|
||||
advance_eg();
|
||||
advance_eg(PSGoper);
|
||||
chanout[0] = 0;
|
||||
chanout[1] = 0;
|
||||
chanout[2] = 0;
|
||||
@ -1401,30 +1810,30 @@ namespace MAME.Core
|
||||
chanout[5] = 0;
|
||||
chanout[6] = 0;
|
||||
chanout[7] = 0;
|
||||
chan_calc(0);
|
||||
chan_calc(1);
|
||||
chan_calc(2);
|
||||
chan_calc(3);
|
||||
chan_calc(4);
|
||||
chan_calc(5);
|
||||
chan_calc(6);
|
||||
chan7_calc();
|
||||
outl = (int)(chanout[0] & PSG.pan[0]);
|
||||
outr = (int)(chanout[0] & PSG.pan[1]);
|
||||
outl += (int)(chanout[1] & PSG.pan[2]);
|
||||
outr += (int)(chanout[1] & PSG.pan[3]);
|
||||
outl += (int)(chanout[2] & PSG.pan[4]);
|
||||
outr += (int)(chanout[2] & PSG.pan[5]);
|
||||
outl += (int)(chanout[3] & PSG.pan[6]);
|
||||
outr += (int)(chanout[3] & PSG.pan[7]);
|
||||
outl += (int)(chanout[4] & PSG.pan[8]);
|
||||
outr += (int)(chanout[4] & PSG.pan[9]);
|
||||
outl += (int)(chanout[5] & PSG.pan[10]);
|
||||
outr += (int)(chanout[5] & PSG.pan[11]);
|
||||
outl += (int)(chanout[6] & PSG.pan[12]);
|
||||
outr += (int)(chanout[6] & PSG.pan[13]);
|
||||
outl += (int)(chanout[7] & PSG.pan[14]);
|
||||
outr += (int)(chanout[7] & PSG.pan[15]);
|
||||
chan_calc(PSGoper, chanout, imem, 0);
|
||||
chan_calc(PSGoper, chanout, imem, 1);
|
||||
chan_calc(PSGoper, chanout, imem, 2);
|
||||
chan_calc(PSGoper, chanout, imem, 3);
|
||||
chan_calc(PSGoper, chanout, imem, 4);
|
||||
chan_calc(PSGoper, chanout, imem, 5);
|
||||
chan_calc(PSGoper, chanout, imem, 6);
|
||||
chan7_calc(PSGoper, chanout, imem);
|
||||
outl = (int)(chanout[0] & PSGpan[0]);
|
||||
outr = (int)(chanout[0] & PSGpan[1]);
|
||||
outl += (int)(chanout[1] & PSGpan[2]);
|
||||
outr += (int)(chanout[1] & PSGpan[3]);
|
||||
outl += (int)(chanout[2] & PSGpan[4]);
|
||||
outr += (int)(chanout[2] & PSGpan[5]);
|
||||
outl += (int)(chanout[3] & PSGpan[6]);
|
||||
outr += (int)(chanout[3] & PSGpan[7]);
|
||||
outl += (int)(chanout[4] & PSGpan[8]);
|
||||
outr += (int)(chanout[4] & PSGpan[9]);
|
||||
outl += (int)(chanout[5] & PSGpan[10]);
|
||||
outr += (int)(chanout[5] & PSGpan[11]);
|
||||
outl += (int)(chanout[6] & PSGpan[12]);
|
||||
outr += (int)(chanout[6] & PSGpan[13]);
|
||||
outl += (int)(chanout[7] & PSGpan[14]);
|
||||
outr += (int)(chanout[7] & PSGpan[15]);
|
||||
if (outl > 32767)
|
||||
{
|
||||
outl = 32767;
|
||||
@ -1441,11 +1850,72 @@ namespace MAME.Core
|
||||
{
|
||||
outr = -32768;
|
||||
}
|
||||
Sound.ym2151stream.streamoutput[0][offset + i] = outl;
|
||||
Sound.ym2151stream.streamoutput[1][offset + i] = outr;
|
||||
advance();
|
||||
streamoutput0[offset + i] = outl;
|
||||
streamoutput1[offset + i] = outr;
|
||||
advance(PSGoper, PSGfreq);
|
||||
}
|
||||
}
|
||||
}
|
||||
//public static void ym2151_update_one(int offset, int length)
|
||||
//{
|
||||
// int i;
|
||||
// int outl, outr;
|
||||
// for (i = 0; i < length; i++)
|
||||
// {
|
||||
// advance_eg();
|
||||
// chanout[0] = 0;
|
||||
// chanout[1] = 0;
|
||||
// chanout[2] = 0;
|
||||
// chanout[3] = 0;
|
||||
// chanout[4] = 0;
|
||||
// chanout[5] = 0;
|
||||
// chanout[6] = 0;
|
||||
// chanout[7] = 0;
|
||||
// chan_calc(0);
|
||||
// chan_calc(1);
|
||||
// chan_calc(2);
|
||||
// chan_calc(3);
|
||||
// chan_calc(4);
|
||||
// chan_calc(5);
|
||||
// chan_calc(6);
|
||||
// chan7_calc();
|
||||
// outl = (int)(chanout[0] & PSG.pan[0]);
|
||||
// outr = (int)(chanout[0] & PSG.pan[1]);
|
||||
// outl += (int)(chanout[1] & PSG.pan[2]);
|
||||
// outr += (int)(chanout[1] & PSG.pan[3]);
|
||||
// outl += (int)(chanout[2] & PSG.pan[4]);
|
||||
// outr += (int)(chanout[2] & PSG.pan[5]);
|
||||
// outl += (int)(chanout[3] & PSG.pan[6]);
|
||||
// outr += (int)(chanout[3] & PSG.pan[7]);
|
||||
// outl += (int)(chanout[4] & PSG.pan[8]);
|
||||
// outr += (int)(chanout[4] & PSG.pan[9]);
|
||||
// outl += (int)(chanout[5] & PSG.pan[10]);
|
||||
// outr += (int)(chanout[5] & PSG.pan[11]);
|
||||
// outl += (int)(chanout[6] & PSG.pan[12]);
|
||||
// outr += (int)(chanout[6] & PSG.pan[13]);
|
||||
// outl += (int)(chanout[7] & PSG.pan[14]);
|
||||
// outr += (int)(chanout[7] & PSG.pan[15]);
|
||||
// if (outl > 32767)
|
||||
// {
|
||||
// outl = 32767;
|
||||
// }
|
||||
// else if (outl < -32768)
|
||||
// {
|
||||
// outl = -32768;
|
||||
// }
|
||||
// if (outr > 32767)
|
||||
// {
|
||||
// outr = 32767;
|
||||
// }
|
||||
// else if (outr < -32768)
|
||||
// {
|
||||
// outr = -32768;
|
||||
// }
|
||||
// Sound.ym2151stream.streamoutput[0][offset + i] = outl;
|
||||
// Sound.ym2151stream.streamoutput[1][offset + i] = outr;
|
||||
// advance();
|
||||
// }
|
||||
//}
|
||||
public static byte ym2151_status_port_0_r()
|
||||
{
|
||||
Sound.ym2151stream.stream_update();
|
||||
@ -1460,18 +1930,30 @@ namespace MAME.Core
|
||||
Sound.ym2151stream.stream_update();
|
||||
ym2151_write_reg(PSG.lastreg0, data);
|
||||
}
|
||||
private static void set_value1(int op1)
|
||||
|
||||
unsafe static void set_value1(int* chanout, YM2151Operator* PSGoper, int op1)
|
||||
{
|
||||
if (iconnect[op1] == 12)
|
||||
{
|
||||
chanout[9] = chanout[10] = chanout[11] = PSG.oper[op1].fb_out_prev;
|
||||
chanout[9] = chanout[10] = chanout[11] = PSGoper[op1].fb_out_prev;
|
||||
}
|
||||
else
|
||||
{
|
||||
chanout[iconnect[op1]] = PSG.oper[op1].fb_out_prev;
|
||||
chanout[iconnect[op1]] = PSGoper[op1].fb_out_prev;
|
||||
}
|
||||
}
|
||||
private static void set_value2(int op1, int i)
|
||||
//private static void set_value1(int op1)
|
||||
//{
|
||||
// if (iconnect[op1] == 12)
|
||||
// {
|
||||
// chanout[9] = chanout[10] = chanout[11] = PSG.oper[op1].fb_out_prev;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// chanout[iconnect[op1]] = PSG.oper[op1].fb_out_prev;
|
||||
// }
|
||||
//}
|
||||
unsafe static void set_value2(int* chanout, int op1, int i)
|
||||
{
|
||||
if (iconnect[op1] == 12)
|
||||
{
|
||||
@ -1482,13 +1964,32 @@ namespace MAME.Core
|
||||
chanout[iconnect[op1]] += i;
|
||||
}
|
||||
}
|
||||
private static void set_mem(int op1)
|
||||
|
||||
//private static void set_value2(int op1, int i)
|
||||
//{
|
||||
// if (iconnect[op1] == 12)
|
||||
// {
|
||||
// return;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// chanout[iconnect[op1]] += i;
|
||||
// }
|
||||
//}
|
||||
unsafe static void set_mem(YM2151Operator* PSGoper, int* chanout, int* imem, int op1)
|
||||
{
|
||||
if (imem[op1] == 8 || imem[op1] == 10 || imem[op1] == 11)
|
||||
{
|
||||
chanout[imem[op1]] = PSG.oper[op1].mem_value;
|
||||
chanout[imem[op1]] = PSGoper[op1].mem_value;
|
||||
}
|
||||
}
|
||||
//private static void set_mem(int op1)
|
||||
//{
|
||||
// if (imem[op1] == 8 || imem[op1] == 10 || imem[op1] == 11)
|
||||
// {
|
||||
// chanout[imem[op1]] = PSG.oper[op1].mem_value;
|
||||
// }
|
||||
//}
|
||||
public static void SaveStateBinary(BinaryWriter writer)
|
||||
{
|
||||
int i;
|
||||
|
Loading…
Reference in New Issue
Block a user