From 0634207bf0327adab793da2b476ad26b458869ca Mon Sep 17 00:00:00 2001
From: sin365 <353374337@qq.com>
Date: Sat, 18 Jan 2025 19:06:19 +0800
Subject: [PATCH] =?UTF-8?q?CAPCOM=20YM2151=20=E4=B8=BB=E8=A6=81=E9=AB=98?=
=?UTF-8?q?=E9=A2=91=E5=87=BD=E6=95=B0=20unsafe=20=E6=8C=87=E9=92=88?=
=?UTF-8?q?=E4=BC=98=E5=8C=96=20|=20CPS=20NeoGeo=20PGS=20draw=20=E5=87=BD?=
=?UTF-8?q?=E6=95=B0=20=E6=8C=87=E9=92=88=E4=BC=98=E5=8C=96?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../Assets/Plugins/UMAME/Log/EmuLogger.cs | 8 +
.../Assets/Plugins/UMAME/ObjectPoolAuto.cs | 417 +++++++++
.../Plugins/UMAME/ObjectPoolAuto.cs.meta | 11 +
.../Assets/Plugins/UMAME/cpu/nec/Nec.cs | 5 +-
MAME.Unity/Assets/Plugins/UMAME/emu/Cpuint.cs | 22 +-
.../Assets/Plugins/UMAME/emu/EmuTimer.cs | 12 +-
.../Assets/Plugins/UMAME/mame/neogeo/Video.cs | 626 ++++++++++---
.../Assets/Plugins/UMAME/mame/pgm/Video.cs | 155 +++-
.../Assets/Plugins/UMAME/sound/OKI6295.cs | 5 +-
.../Assets/Plugins/UMAME/sound/YM2151.cs | 845 ++++++++++++++----
10 files changed, 1756 insertions(+), 350 deletions(-)
create mode 100644 MAME.Unity/Assets/Plugins/UMAME/ObjectPoolAuto.cs
create mode 100644 MAME.Unity/Assets/Plugins/UMAME/ObjectPoolAuto.cs.meta
diff --git a/MAME.Unity/Assets/Plugins/UMAME/Log/EmuLogger.cs b/MAME.Unity/Assets/Plugins/UMAME/Log/EmuLogger.cs
index 28acc3a..4d8b2b4 100644
--- a/MAME.Unity/Assets/Plugins/UMAME/Log/EmuLogger.cs
+++ b/MAME.Unity/Assets/Plugins/UMAME/Log/EmuLogger.cs
@@ -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
}
}
diff --git a/MAME.Unity/Assets/Plugins/UMAME/ObjectPoolAuto.cs b/MAME.Unity/Assets/Plugins/UMAME/ObjectPoolAuto.cs
new file mode 100644
index 0000000..1189454
--- /dev/null
+++ b/MAME.Unity/Assets/Plugins/UMAME/ObjectPoolAuto.cs
@@ -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
+ {
+ /************************************************************************************************************************/
+
+ ///
+ /// 获取或者创建一个新的
+ ///
+ /// Remember to 需要回收参见这个
+ public static T Acquire()
+ where T : class, new()
+ => ObjectPool.Acquire();
+
+ ///
+ /// 获取或者创建一个新的
+ ///
+ /// Remember to 需要回收参见这个
+ public static void Acquire(out T item)
+ where T : class, new()
+ => item = ObjectPool.Acquire();
+ /************************************************************************************************************************/
+
+ ///
+ /// 回收对象
+ ///
+ public static void Release(T item)
+ where T : class, new()
+ => ObjectPool.Release(item);
+
+ ///
+ /// 回收对象
+ ///
+ public static void Release(ref T item) where T : class, new()
+ {
+ if (item != null)
+ {
+ ObjectPool.Release(item);
+ item = null;
+ }
+ }
+
+ /************************************************************************************************************************/
+ public const string
+ NotClearError = " They must be cleared before being released to the pool and not modified after that.";
+
+ /************************************************************************************************************************/
+
+ ///
+ /// 获取或创建List
+ ///
+ /// Remember to 回收参见此方法
+ public static List AcquireList()
+ {
+ var list = ObjectPool>.Acquire();
+ EmuLogger.Assert(list.Count == 0, "A pooled list is not empty." + NotClearError);
+ return list;
+ }
+
+ ///
+ /// 回收List
+ ///
+ public static void Release(List list)
+ {
+ list.Clear();
+ ObjectPool>.Release(list);
+ }
+ ///
+ /// 回收List内容
+ ///
+ ///
+ ///
+ public static void ReleaseListContent(List list) where T : class, new()
+ {
+ foreach (var item in list)
+ {
+ ObjectPool.Release(item);
+ }
+ list.Clear();
+ }
+
+ /************************************************************************************************************************/
+
+ ///
+ /// 获取或创建HashSet
+ ///
+ public static HashSet AcquireSet()
+ {
+ var set = ObjectPool>.Acquire();
+ EmuLogger.Assert(set.Count == 0, "A pooled set is not empty." + NotClearError);
+ return set;
+ }
+
+ ///
+ /// 释放HashSet
+ ///
+ public static void Release(HashSet set)
+ {
+ set.Clear();
+ ObjectPool>.Release(set);
+ }
+
+ /************************************************************************************************************************/
+
+ ///
+ /// 获取一个字符串StringBuilder
+ ///
+ /// Remember to 回收参见这个
+ public static StringBuilder AcquireStringBuilder()
+ {
+ var builder = ObjectPool.Acquire();
+ EmuLogger.Assert(builder.Length == 0, $"A pooled {nameof(StringBuilder)} is not empty." + NotClearError);
+ return builder;
+ }
+
+ ///
+ /// 回收 StringBuilder
+ ///
+ public static void Release(StringBuilder builder)
+ {
+ builder.Length = 0;
+ ObjectPool.Release(builder);
+ }
+
+ ///
+ /// 回收 StringBuilder
+ ///
+ public static string ReleaseToString(this StringBuilder builder)
+ {
+ var result = builder.ToString();
+ Release(builder);
+ return result;
+ }
+
+ /************************************************************************************************************************/
+
+ private static class Cache
+ {
+ public static readonly Dictionary, T>>
+ Results = new Dictionary, T>>();
+ }
+
+ ///
+ /// 此方法主要用于频繁绘制缓存,比如说GUI绘制
+ ///
+ public static T GetCachedResult(Func function)
+ {
+ var method = function.Method;
+ if (!Cache.Results.TryGetValue(method, out var result))
+ {
+
+ result = new KeyValuePair, T>(function, function());
+ Cache.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
+ {
+ /************************************************************************************************************************/
+
+ ///
+ /// Calls to get a spare if
+ ///
+ public static IDisposable Acquire(out T item)
+ where T : class, new()
+ => ObjectPool.Disposable.Acquire(out item);
+
+ /************************************************************************************************************************/
+
+ ///
+ /// Calls to get a spare if
+ ///
+ public static IDisposable AcquireList(out List list)
+ {
+ var disposable = ObjectPool>.Disposable.Acquire(out list, onRelease: (l) => l.Clear());
+ EmuLogger.Assert(list.Count == 0, "A pooled list is not empty." + NotClearError);
+ return disposable;
+ }
+
+ /************************************************************************************************************************/
+
+ ///
+ /// Calls to get a spare if
+ ///
+ public static IDisposable AcquireSet(out HashSet set)
+ {
+ var disposable = ObjectPool>.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 where T : class, new()
+ {
+ /************************************************************************************************************************/
+
+ private static readonly List
+ Items = new List();
+
+ /************************************************************************************************************************/
+
+ /// The number of spare items currently in the pool.
+ 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);
+ }
+ }
+ }
+
+ /************************************************************************************************************************/
+
+ ///
+ /// If the is less than the specified value, this method increases it to that value by
+ /// creating new objects.
+ ///
+ public static void SetMinCount(int count)
+ {
+ if (Count < count)
+ Count = count;
+ }
+
+ /************************************************************************************************************************/
+
+ /// The of the internal list of spare items.
+ public static int Capacity
+ {
+ get => Items.Capacity;
+ set
+ {
+ if (Items.Count > value)
+ Items.RemoveRange(value, Items.Count - value);
+ Items.Capacity = value;
+ }
+ }
+
+ /************************************************************************************************************************/
+
+ /// Returns a spare item if there are any, or creates a new one.
+ /// Remember to it when you are done.
+ 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;
+ }
+ }
+
+ /************************************************************************************************************************/
+
+ /// Adds the `item` to the list of spares so it can be reused.
+ public static void Release(T item)
+ {
+ Items.Add(item);
+
+ }
+
+ /************************************************************************************************************************/
+
+ /// Returns a description of the state of this pool.
+ public static string GetDetails()
+ {
+ return
+ $"{typeof(T).Name}" +
+ $" ({nameof(Count)} = {Items.Count}" +
+ $", {nameof(Capacity)} = {Items.Capacity}" +
+ ")";
+ }
+
+ /************************************************************************************************************************/
+
+ ///
+ /// An system to allow pooled objects to be acquired and released within using
+ /// statements instead of needing to manually release everything.
+ ///
+ public sealed class Disposable : IDisposable
+ {
+ /************************************************************************************************************************/
+
+ private static readonly List LazyStack = new List();
+
+ private static int _ActiveDisposables;
+
+ private T _Item;
+ private Action _OnRelease;
+
+ /************************************************************************************************************************/
+
+ private Disposable() { }
+
+ ///
+ /// Calls to set the `item` and returns an
+ /// that will call on the `item` when disposed.
+ ///
+ public static IDisposable Acquire(out T item, Action onRelease = null)
+ {
+ Disposable disposable;
+
+ if (LazyStack.Count <= _ActiveDisposables)
+ {
+ LazyStack.Add(disposable = new Disposable());
+ }
+ else
+ {
+ disposable = LazyStack[_ActiveDisposables];
+ }
+
+ _ActiveDisposables++;
+
+ disposable._Item = item = ObjectPool.Acquire();
+ disposable._OnRelease = onRelease;
+ return disposable;
+ }
+
+ /************************************************************************************************************************/
+
+ void IDisposable.Dispose()
+ {
+ _OnRelease?.Invoke(_Item);
+ Release(_Item);
+ _ActiveDisposables--;
+ }
+ /************************************************************************************************************************/
+ }
+ }
+
+ #region ExtFunctions
+ public struct PoolHandle : IDisposable
+ where T : class, new()
+ {
+ public T Ins;
+ internal static PoolHandle Create(T poolIns)
+ {
+ return new PoolHandle { Ins = poolIns };
+ }
+
+ public void Dispose()
+ {
+ ObjectPoolAuto.Release(Ins);
+ }
+ }
+ public struct PoolListHandle : IDisposable
+ {
+ public List Ins;
+ internal static PoolListHandle Create(List poolIns)
+ {
+ return new PoolListHandle { Ins = poolIns };
+ }
+
+ public void Dispose()
+ {
+ ObjectPoolAuto.Release(Ins);
+ }
+ }
+
+ public static PoolHandle PoolScope()
+ where T : class, new()
+ {
+ return PoolHandle.Create(ObjectPoolAuto.Acquire());
+ }
+ public static PoolListHandle PoolListScope()
+ {
+ return PoolListHandle.Create(ObjectPoolAuto.AcquireList());
+ }
+ #endregion
+
+ }
+}
+
+
diff --git a/MAME.Unity/Assets/Plugins/UMAME/ObjectPoolAuto.cs.meta b/MAME.Unity/Assets/Plugins/UMAME/ObjectPoolAuto.cs.meta
new file mode 100644
index 0000000..7dc7aae
--- /dev/null
+++ b/MAME.Unity/Assets/Plugins/UMAME/ObjectPoolAuto.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: f22c2fa157c9e6045ad5307124c8a365
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/MAME.Unity/Assets/Plugins/UMAME/cpu/nec/Nec.cs b/MAME.Unity/Assets/Plugins/UMAME/cpu/nec/Nec.cs
index 3609c9b..e19b5b3 100644
--- a/MAME.Unity/Assets/Plugins/UMAME/cpu/nec/Nec.cs
+++ b/MAME.Unity/Assets/Plugins/UMAME/cpu/nec/Nec.cs
@@ -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.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)
{
diff --git a/MAME.Unity/Assets/Plugins/UMAME/emu/Cpuint.cs b/MAME.Unity/Assets/Plugins/UMAME/emu/Cpuint.cs
index 6ff6a25..41e2770 100644
--- a/MAME.Unity/Assets/Plugins/UMAME/emu/Cpuint.cs
+++ b/MAME.Unity/Assets/Plugins/UMAME/emu/Cpuint.cs
@@ -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.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.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 lsirq = new List();
+ //List lsirq = new List();
+ List lsirq = ObjectPoolAuto.AcquireList();
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();
for (i = 0; i < n; i++)
{
- lirq.Add(new irq());
+ irq _irq = ObjectPoolAuto.Acquire();
+ lirq.Add(_irq);
+ //lirq.Add(new irq());
lirq[i].cpunum = reader.ReadInt32();
lirq[i].line = reader.ReadInt32();
lirq[i].state = (LineState)reader.ReadInt32();
diff --git a/MAME.Unity/Assets/Plugins/UMAME/emu/EmuTimer.cs b/MAME.Unity/Assets/Plugins/UMAME/emu/EmuTimer.cs
index 5fe2437..5bfcf85 100644
--- a/MAME.Unity/Assets/Plugins/UMAME/emu/EmuTimer.cs
+++ b/MAME.Unity/Assets/Plugins/UMAME/emu/EmuTimer.cs
@@ -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 timer_list_remove_lt1 = new List();
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 lt1 = new List();
+ 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);
}
diff --git a/MAME.Unity/Assets/Plugins/UMAME/mame/neogeo/Video.cs b/MAME.Unity/Assets/Plugins/UMAME/mame/neogeo/Video.cs
index 45d98c0..e65bb3e 100644
--- a/MAME.Unity/Assets/Plugins/UMAME/mame/neogeo/Video.cs
+++ b/MAME.Unity/Assets/Plugins/UMAME/mame/neogeo/Video.cs
@@ -145,165 +145,533 @@ 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 span_neogeo_videoram = neogeo_videoram.AsSpan();
+ // Span span_bitmapbaseN_iBitmap = Video.bitmapbaseN[iBitmap].AsSpan();
+ // Span span_sprite_gfx = sprite_gfx.AsSpan();
+ // Span 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;
+ // }
+ // }
+ // }
+ //}
+
+ ///
+ /// draw_sprites (Unsafa 尝试提升效率)
+ ///
+ ///
+ ///
+ unsafe 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)
+
+ 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])
{
- 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)
+ 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;
+ byte sprite_y_and_tile;
+ bool invert;
+ y = 0;
+ x = 0;
+ rows = 0;
+ zoom_y = 0;
+ zoom_x = 0;
+ if ((scanline & 0x01) != 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;
+ sprite_list_offset = 0x8680;
}
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;
+ sprite_list_offset = 0x8600;
}
- if ((x >= 0x140) && (x <= 0x1f0))
+ for (max_sprite_index = 95; max_sprite_index >= 0; max_sprite_index--)
{
- continue;
+ if (neogeo_videoram[sprite_list_offset + max_sprite_index] != 0)
+ {
+ break;
+ }
}
- if (sprite_on_scanline(scanline, y, rows))
+ if (max_sprite_index != 95)
{
- sprite_line = (scanline - y) & 0x1ff;
- zoom_line = sprite_line & 0xff;
- invert = ((sprite_line & 0x100) != 0) ? true : false;
- if (invert)
+ 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];
+
+ //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)
{
- 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;
+ x = (x + zoom_x + 1) & 0x01ff;
+ zoom_x = (zoom_control >> 8) & 0x0f;
}
else
{
- x_inc = 1;
+ y = 0x200 - (y_control >> 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;
}
- int pixel_addr_offsetx, pixel_addr_offsety;
- if (x <= 0x01f0)
+
+ fixed (int* zoom_x_tablesPtr = &zoom_x_tables[zoom_x, 0])
{
- int i;
- pixel_addr_offsetx = x + NEOGEO_HBEND;
- pixel_addr_offsety = scanline;
- for (i = 0; i < 0x10; i++)
+ int* zoom_x_tables = zoom_x_tablesPtr;
+
+ if ((x >= 0x140) && (x <= 0x1f0))
{
- if (zoom_x_tables[zoom_x, zoom_x_table_offset] != 0)
+ 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)
{
- 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_line ^= 0xff;
}
- 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 (rows > 0x20)
{
- if (x >= 0x200)
+ zoom_line = zoom_line % ((zoom_y + 1) << 1);
+ if (zoom_line > zoom_y)
{
- if (sprite_gfx[gfx_offset] != 0)
+ 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 (zoom_x_tables[zoom_x_table_offset] != 0)
{
- Video.bitmapbaseN[iBitmap][pixel_addr_offsety * 384 + pixel_addr_offsetx] = pens[line_pens_offset + sprite_gfx[gfx_offset]];
+ //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]];
+ bitmapbase[pixel_addr_offsety * 384 + pixel_addr_offsetx] = pens[line_pens_offset + spriteGfx[gfx_offset]];
+ }
+ pixel_addr_offsetx++;
}
- pixel_addr_offsetx++;
+ zoom_x_table_offset++;
+ gfx_offset += x_inc;
}
- x++;
}
- 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 (zoom_x_tables[zoom_x_table_offset] != 0)
+ {
+ if (x >= 0x200)
+ {
+ //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]];
+ bitmapbase[pixel_addr_offsety * 384 + pixel_addr_offsetx] = pens[line_pens_offset + spriteGfx[gfx_offset]];
+ }
+ pixel_addr_offsetx++;
+ }
+ x++;
+ }
+ zoom_x_table_offset++;
+ gfx_offset += x_inc;
+ }
+ x = x_save;
+ }
}
- x = x_save;
}
}
}
}
+
+ //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;
diff --git a/MAME.Unity/Assets/Plugins/UMAME/mame/pgm/Video.cs b/MAME.Unity/Assets/Plugins/UMAME/mame/pgm/Video.cs
index 7dc926e..ba98608 100644
--- a/MAME.Unity/Assets/Plugins/UMAME/mame/pgm/Video.cs
+++ b/MAME.Unity/Assets/Plugins/UMAME/mame/pgm/Video.cs
@@ -199,47 +199,132 @@ namespace MAME.Core
ycnt++;
}
}
- private static void draw_sprites(int priority)
+ unsafe private static void draw_sprites(int priority)
{
- while (pgm_sprite_source_offset < 0x500)
+ fixed (ushort* pSpriteBuffer = &pgm_spritebufferram[0])
+ fixed (byte* pVideoRegs = &pgm_videoregs[0])
{
- 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)
+ ushort* spritePtr = pSpriteBuffer + pgm_sprite_source_offset;
+ int offset = 0;
+
+ while (pgm_sprite_source_offset < 0x500)
{
- xzom = 0x10 - xzom;
+ // 读取数据
+ 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;
+ }
+ if (ygrow != 0)
+ {
+ yzom = 0x10 - yzom;
+ }
+ 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)
+ 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);
+
+ // 移动到下一个精灵
+ spritePtr += 10; // 每个精灵占用5个ushort,即10个字节
+ pgm_sprite_source_offset += 5; // 假设pgm_sprite_source_offset是以ushort为单位递增的
+
+ // 注意:这里我们直接通过指针移动,因此不需要再次访问数组来更新pgm_sprite_source_offset对应的值
}
- if (ygrow != 0)
- {
- 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]);
- 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 draw_sprites(int priority)
+ //{
+ // while (pgm_sprite_source_offset < 0x500)
+ // {
+ // //用Span优化
+ // Span 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 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;
diff --git a/MAME.Unity/Assets/Plugins/UMAME/sound/OKI6295.cs b/MAME.Unity/Assets/Plugins/UMAME/sound/OKI6295.cs
index 86667ff..2d3c02c 100644
--- a/MAME.Unity/Assets/Plugins/UMAME/sound/OKI6295.cs
+++ b/MAME.Unity/Assets/Plugins/UMAME/sound/OKI6295.cs
@@ -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)
{
diff --git a/MAME.Unity/Assets/Plugins/UMAME/sound/YM2151.cs b/MAME.Unity/Assets/Plugins/UMAME/sound/YM2151.cs
index e43c318..1b40bb5 100644
--- a/MAME.Unity/Assets/Plugins/UMAME/sound/YM2151.cs
+++ b/MAME.Unity/Assets/Plugins/UMAME/sound/YM2151.cs
@@ -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)
{
- 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);
- {
- 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);
+ //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 = PSGoper[chan * 4]; /* M1 */
+ //op.mem_connect = op.mem_value; /* restore delayed sample (MEM) value to m2 or c2 */
+ set_mem(PSGoper, chanout, imem, chan * 4);
+ if (PSGoper[chan * 4].ams != 0)
+ {
+ AM = PSG.lfa << (int)(PSGoper[chan * 4].ams - 1);
+ }
- PSG.oper[chan * 4].fb_out_curr = 0;
+ env = volume_calc(PSGoper, (chan * 4), AM);
+ //env = volume_calc_planB(PSGoper[chan * 4], AM);
+ {
+ 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(chanout, PSGoper, chan * 4);
+
+ PSGoper[chan * 4].fb_out_curr = 0;
+ if (env < 13 * 64)
+ {
+ if (PSGoper[chan * 4].fb_shift == 0)
+ {
+ iout = 0;
+ }
+ PSGoper[chan * 4].fb_out_curr = op_calc1(PSGoper, (chan * 4), env, (iout << (int)PSGoper[chan * 4].fb_shift));
+ }
+ }
+ env = volume_calc(PSGoper, (chan * 4 + 1), AM); /* M2 */
+ //env = volume_calc_planB(PSGoper[chan * 4 + 1], AM);/* M2 */
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));
+ //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(PSGoper, (chan * 4 + 2), AM); /* C1 */
+ //env = volume_calc_planB(PSGoper[chan * 4 + 2], AM); /* C1 */
+ if (env < 13 * 64)
+ {
+ //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(PSGoper, (chan * 4 + 3), AM); /* C2 */
+ //env = volume_calc_planB(PSGoper[chan * 4 + 3], AM); /* C2 */
+ if (env < 13 * 64)
+ {
+ chanout[chan] += op_calc(PSGoper, (chan * 4 + 3), env, chanout[10]);// c2);
+ }
+ /* M1 */
+ PSGoper[chan * 4].mem_value = chanout[11];//mem;
}
- env = volume_calc((int)(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 */
- 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 */
- 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;
+
}
- 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,66 +1625,297 @@ 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)
{
- int i;
- int outl, outr;
- for (i = 0; i < length; i++)
+ 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])
{
- 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)
+ 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++)
{
- outl = 32767;
+ advance_eg(PSGoper);
+ 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(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;
+ }
+ else if (outl < -32768)
+ {
+ outl = -32768;
+ }
+ if (outr > 32767)
+ {
+ outr = 32767;
+ }
+ else if (outr < -32768)
+ {
+ outr = -32768;
+ }
+ streamoutput0[offset + i] = outl;
+ streamoutput1[offset + i] = outr;
+ advance(PSGoper, PSGfreq);
}
- 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 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;