进行一些内联优化,还有timer对象池优化

This commit is contained in:
sin365 2025-11-11 17:55:44 +08:00
parent d2cc4fa05d
commit 200ee3830b
17 changed files with 801 additions and 252 deletions

View File

@ -32,7 +32,7 @@ namespace cpu.m6800
private ushort M6803_DDR1 = 0x00, M6803_DDR2 = 0x01, M6803_DDR3 = 0x04, M6803_DDR4 = 0x05, M6803_PORT1 = 0x100, M6803_PORT2 = 0x101, M6803_PORT3 = 0x102, M6803_PORT4 = 0x103;
private byte M6800_RMCR_SS_MASK = 0x03, M6800_RMCR_SS_4096 = 0x03, M6800_RMCR_SS_1024 = 0x02, M6800_RMCR_SS_128 = 0x01, M6800_RMCR_SS_16 = 0x00, M6800_RMCR_CC_MASK = 0x0c;
private byte M6800_TRCSR_RDRF = 0x80, M6800_TRCSR_ORFE = 0x40, M6800_TRCSR_TDRE = 0x20, M6800_TRCSR_RIE = 0x10, M6800_TRCSR_RE = 0x08, M6800_TRCSR_TIE = 0x04, M6800_TRCSR_TE = 0x02, M6800_TRCSR_WU = 0x01, M6800_PORT2_IO4 = 0x10, M6800_PORT2_IO3 = 0x08;
private int[] M6800_RMCR_SS = new int[] { 16, 128, 1024, 4096 };
private static int[] M6800_RMCR_SS = new int[] { 16, 128, 1024, 4096 };
public enum M6800_TX_STATE
{
INIT = 0,
@ -64,7 +64,7 @@ namespace cpu.m6800
}
}
public uint timer_next;
public byte[] flags8i = new byte[256] /* increment */
public readonly static byte[] flags8i = new byte[256] /* increment */
{
0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
@ -83,7 +83,7 @@ namespace cpu.m6800
0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08
};
private byte[] flags8d = new byte[256] /* decrement */
private readonly static byte[] flags8d = new byte[256] /* decrement */
{
0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
@ -102,7 +102,7 @@ namespace cpu.m6800
0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08
};
private byte[] cycles_6800 = new byte[]
private readonly static byte[] cycles_6800 = new byte[]
{
/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
/*0*/ 99, 2,99,99,99,99, 2, 2, 4, 4, 2, 2, 2, 2, 2, 2,

View File

@ -56,7 +56,7 @@ namespace cpu.m6805
0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04
};
public byte[] cycles1 = new byte[]
public readonly static byte[] cycles1 = new byte[]
{
/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
/*0*/ 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,

View File

@ -85,7 +85,7 @@ namespace cpu.m6809
0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08
};
private byte[] cycles_6809 = new byte[]
private readonly static byte[] cycles_6809 = new byte[]
{
0x06,0x06,0x02,0x06,0x06,0x02,0x06,0x06,0x06,0x06,0x06,0x02,0x06,0x06,0x03,0x06,
0x00,0x00,0x02,0x04,0x02,0x02,0x05,0x09,0x02,0x02,0x03,0x02,0x03,0x02,0x08,0x06,

View File

@ -449,7 +449,7 @@ namespace cpu.nec
I.regs.b[Reg * 2 + 1] = (byte)((ushort)tmp1 / 0x100);
}
static byte[] JMP_table = new byte[] { 3, 10, 10 };
readonly static byte[] JMP_table = new byte[] { 3, 10, 10 };
//public void JMP(bool flag)
//{
// int tmp = (int)((sbyte)FETCH());
@ -732,7 +732,7 @@ namespace cpu.nec
I.regs.b[5] = (byte)((ushort)result2 / 0x100);
}
}
static byte[] ADD4S_table = new byte[] { 18, 19, 19 };
readonly static byte[] ADD4S_table = new byte[] { 18, 19, 19 };
public void ADD4S(ref int tmp, ref int tmp2)
{
int i, v1, v2, result;

View File

@ -15,7 +15,7 @@
public byte animation_counter;
}
public static crosshair_global global;
public static byte[] crosshair_raw_top = new byte[]
public readonly static byte[] crosshair_raw_top = new byte[]
{
0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,
0x00,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x00,

View File

@ -1,10 +1,6 @@
using cpu.m6800;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Runtime.ConstrainedExecution;
using System.Threading;
using System.Timers;
using static MAME.Core.EmuTimer;
namespace MAME.Core
@ -68,7 +64,6 @@ namespace MAME.Core
{
emu_timer.RemoveToList(ref timerlist, ref timer);
}
public void Insert(int index, emu_timer timer)
{
emu_timer.InsertToList(ref timerlist, index, ref timer);
@ -78,6 +73,11 @@ namespace MAME.Core
{
return timerlist.IndexOf(timer);
}
public void RemoveAt(int index)
{
emu_timer.RemoveAtToList(ref timerlist, index);
}
}
public class EmuTimer
@ -117,6 +117,11 @@ namespace MAME.Core
public Atime start;
public Atime expire;
// 引用计数字段
private int _refCount;
// 是否在检查池中
private bool _inReadyQueue;
internal void reset()
{
action = default;
@ -126,27 +131,25 @@ namespace MAME.Core
start = default;
expire = default;
_refCount = 0;
_inReadyQueue = false;
}
static Queue<emu_timer> _readyToRelease = new Queue<emu_timer>();
/// <summary>
/// 线程安全队列(因为析构函数是额外线程来的)
/// </summary>
static Queue<emu_timer> _failedDeletions = new Queue<emu_timer>();
static HashSet<emu_timer> _tempCheck = new HashSet<emu_timer>();
static Queue<emu_timer> _timerPool = new Queue<emu_timer>();
static int outTimerAllCount = 0;
static int newTimerCount = 0;
public static emu_timer GetEmu_timerNoRef()
{
emu_timer obj;
if (!_failedDeletions.TryDequeue(out obj))
{
if (!_timerPool.TryDequeue(out obj))
{
obj = new emu_timer();
newTimerCount++;
}
//这里引用计数为0直接放入带Ready里等待下一帧检测
obj.reset();
obj._inReadyQueue = true;
_readyToRelease.Enqueue(obj);
outTimerAllCount++;
return obj;
@ -157,47 +160,31 @@ namespace MAME.Core
if (_readyToRelease.Count < 1)
return;
int checkcount = _readyToRelease.Count;
int beforpoolcount = _failedDeletions.Count;
int beforpoolcount = _timerPool.Count;
int releaseCount = 0;
while(_readyToRelease.TryDequeue(out emu_timer ready))
while (_readyToRelease.TryDequeue(out emu_timer ready))
{
if (_tempCheck.Contains(ready))
continue;
_tempCheck.Add(ready);
ready._inReadyQueue = false;
if (ready._refCount <= 0)
{
ready.ReturnToPool();
releaseCount++;
}
}
//UnityEngine.Debug.Log($"CheckReadyRelaseAfterRun 检查数量{checkcount}| 出池数量{outTimerAllCount}其中new创建的数量{newTimerCount} 回收数量{releaseCount} ,处理前池数量{beforpoolcount},处理后池数量{_failedDeletions.Count}");
//UnityEngine.Debug.Log($"CheckReadyRelaseAfterRun 检查数量{checkcount}| 出池数量{outTimerAllCount}其中new创建的数量{newTimerCount} 回收数量{releaseCount} ,处理前池数量{beforpoolcount},处理后池数量{_timerPool.Count}");
outTimerAllCount = 0;
newTimerCount = 0;
_readyToRelease.Clear();
_tempCheck.Clear();
//_readyToRelease.Clear();
}
// 引用计数字段(线程安全)
private int _refCount = 1; // 初始为1表示创建时的引用
/// <summary>
/// 增加引用计数
/// </summary>
void AddRef()
{
int newCount = Interlocked.Increment(ref _refCount);
////引用计数重新回到1时移除。
////但是还是不在这里做把注释了,在每一帧开始之前统一检测
//if (newCount == 1)
//{
// UnityEngine.Debug.Log("CheckReadyRelaseAfterRun AddRef 复活");
// //if (_readyToRelease.Contains(this))
// //{
// // //UnityEngine.Debug.Log("移除ReadyToRelease");
// // _readyToRelease.Remove(this);
// //}
//}
//int newCount = Interlocked.Increment(ref _refCount);
_refCount++;
}
/// <summary>
@ -205,14 +192,14 @@ namespace MAME.Core
/// </summary>
void ReleaseRef()
{
int newCount = Interlocked.Decrement(ref _refCount);
if (newCount == 0)
//int newCount = Interlocked.Decrement(ref _refCount);
_refCount--;
if (_refCount == 0)
{
//UnityEngine.Debug.Log("CheckReadyRelaseAfterRun ReleaseRef 预回收");
// 引用计数为0释放资源并回池
ReadyToRelease();
}
else if (newCount < 0)
else if (_refCount < 0)
{
// 引用计数异常,不应出现负数
throw new InvalidOperationException("引用计数出现负数");
@ -221,7 +208,9 @@ namespace MAME.Core
void ReadyToRelease()
{
if (this._inReadyQueue) return;
//UnityEngine.Debug.Log("ReadyToRelease");
this._inReadyQueue = true;
_readyToRelease.Enqueue(this);
}
@ -230,7 +219,7 @@ namespace MAME.Core
/// </summary>
void ReturnToPool()
{
_failedDeletions.Enqueue(this);
_timerPool.Enqueue(this);
}
#region
@ -245,7 +234,6 @@ namespace MAME.Core
}
if (refattr != null)
refattr.ReleaseRef();
refattr = emu_timer;
refattr.AddRef();
}
@ -278,6 +266,11 @@ namespace MAME.Core
list[i].ReleaseRef();
list.Clear();
}
internal static void RemoveAtToList(ref List<emu_timer> list, int index)
{
list.RemoveAt(index);
}
#endregion
/*
static void EnqueueObj(emu_timer obj)
@ -760,77 +753,340 @@ namespace MAME.Core
}
}
//static void timer_list_remove_and_insert(emu_timer timer)
//{
// // 包一层引用避免引用计数中间丢失
// {
// emu_timer tempref = null;
// emu_timer.SetRefUsed(ref tempref, ref timer);
// // 内联移除逻辑
// bool isSpecialAction = (timer.action == TIME_ACT.Cpuint_cpunum_empty_event_queue ||
// timer.action == TIME_ACT.setvector);
// if (isSpecialAction)
// {
// // 优化批量移除相同action和过期时间的定时器
// for (int i = lt.Count - 1; i >= 0; i--)
// {
// emu_timer et = lt[i];
// if (et.action == timer.action &&
// Attotime.attotime_compare(et.expire, timer.expire) == 0)
// {
// lt.RemoveAt(i); // 直接从后往前移除,避免数组拷贝
// }
// }
// }
// else
// {
// // 优化:只移除第一个匹配的定时器
// int tempcount = lt.Count;
// for (int i = 0; i < tempcount; i++)
// {
// if (lt[i].action == timer.action)
// {
// lt.RemoveAt(i);
// break; // 找到第一个就退出
// }
// }
// }
// // 内联插入逻辑
// int insertIndex = lt.Count; // 默认插入到最后
// // 优化:只有当定时器启用时才按时间排序插入
// if (timer.enabled)
// {
// Atime expire = timer.expire;
// int tempcount = lt.Count;
// // 查找插入位置
// for (int i = 0; i < tempcount; i++)
// {
// if (Attotime.attotime_compare(lt[i].expire, expire) > 0)
// {
// insertIndex = i;
// break;
// }
// }
// }
// // 在找到的位置插入
// if (insertIndex < lt.Count)
// {
// lt.Insert(insertIndex, timer);
// }
// else
// {
// lt.Add(timer); // 添加到末尾比Insert性能更好[8](@ref)
// }
// emu_timer.SetNull(ref tempref);
// }
//}
//static void timer_list_remove_and_insert(emu_timer timer)
//{
// {
// emu_timer tempref = null;
// emu_timer.SetRefUsed(ref tempref, ref timer);
// List<emu_timer> ltsrc = lt.GetSrcList();
// // inline remove
// if (timer.action == TIME_ACT.Cpuint_cpunum_empty_event_queue || timer.action == TIME_ACT.setvector)
// {
// int low = 0;
// int high = ltsrc.Count - 1;
// int start = -1;
// while (low <= high)
// {
// int mid = low + (high - low) / 2;
// int cmp = Attotime.attotime_compare(ltsrc[mid].expire, timer.expire);
// if (cmp < 0)
// low = mid + 1;
// else if (cmp > 0)
// high = mid - 1;
// else
// {
// start = mid;
// high = mid - 1;
// }
// }
// if (start == -1) start = low;
// int end = start;
// int tempcount = ltsrc.Count;
// while (end < tempcount && Attotime.attotime_compare(ltsrc[end].expire, timer.expire) == 0)
// end++;
// for (int j = end - 1; j >= start; j--)
// {
// if (ltsrc[j].action == timer.action)
// lt.RemoveAt(j);
// }
// }
// else
// {
// int tempcount = lt.Count;
// for (int j = 0; j < tempcount; j++)
// {
// if (lt[j].action == timer.action)
// {
// lt.RemoveAt(j);
// break;
// }
// }
// }
// // inline insert
// int i1 = -1;
// if (timer.action == TIME_ACT.Cpuint_cpunum_empty_event_queue || timer.action == TIME_ACT.setvector)
// {
// int tempcount = ltsrc.Count;
// for (int j = 0; j < tempcount; j++)
// {
// emu_timer temptimer = ltsrc[j];
// if (temptimer.action == timer.action && Attotime.attotime_compare(temptimer.expire, global_basetime) <= 0)
// {
// i1 = j;
// break;
// }
// }
// }
// if (i1 == -1)
// {
// int low = 0;
// int high = ltsrc.Count - 1;
// int pos = ltsrc.Count;
// while (low <= high)
// {
// int mid = low + (high - low) / 2;
// if (Attotime.attotime_compare(ltsrc[mid].expire, timer.expire) > 0)
// {
// pos = mid;
// high = mid - 1;
// }
// else
// {
// low = mid + 1;
// }
// }
// lt.Insert(pos, timer);
// }
// emu_timer.SetNull(ref tempref);
// }
//}
//static void timer_list_insert(emu_timer timer1)
//{
// int i;
// int i1 = -1;
// if (timer1.action == TIME_ACT.Cpuint_cpunum_empty_event_queue || timer1.action == TIME_ACT.setvector)
// {
// //foreach (emu_timer et in lt)
// foreach (emu_timer et in lt.GetSrcList())
// {
// if (et.action == timer1.action && Attotime.attotime_compare(et.expire, global_basetime) <= 0)
// {
// i1 = lt.IndexOf(et);
// break;
// }
// }
// }
// if (i1 == -1)
// {
// Atime expire = timer1.enabled ? timer1.expire : Attotime.ATTOTIME_NEVER;
// for (i = 0; i < lt.Count; i++)
// {
// if (Attotime.attotime_compare(lt[i].expire, expire) > 0)
// {
// break;
// }
// }
// lt.Insert(i, timer1);
// }
//}
//手动优化
static void timer_list_insert(emu_timer timer1)
{
int i;
TIME_ACT currAct = timer1.action;
int i1 = -1;
if (timer1.action == TIME_ACT.Cpuint_cpunum_empty_event_queue || timer1.action == TIME_ACT.setvector)
var tlist = lt.GetSrcList();
int scanCount;
int tempMaxIdx = tlist.Count - 1;
if (currAct == TIME_ACT.Cpuint_cpunum_empty_event_queue || currAct == TIME_ACT.setvector)
{
//foreach (emu_timer et in lt)
foreach (emu_timer et in lt.GetSrcList())
//foreach (emu_timer et in lt.GetSrcList())
//{
// if (et.action == currAct && Attotime.attotime_compare(et.expire, global_basetime) <= 0)
// {
// i1 = lt.IndexOf(et);
// break;
// }
//}
scanCount = 0;
while (scanCount >= tempMaxIdx)
{
if (et.action == timer1.action && Attotime.attotime_compare(et.expire, global_basetime) <= 0)
emu_timer et = tlist[scanCount];
if (et.action == currAct && Attotime.attotime_compare(et.expire, global_basetime) <= 0)
{
i1 = lt.IndexOf(et);
i1 = scanCount;
break;
}
scanCount++;
}
}
if (i1 == -1)
{
Atime expire = timer1.enabled ? timer1.expire : Attotime.ATTOTIME_NEVER;
for (i = 0; i < lt.Count; i++)
scanCount = 0;
while (scanCount <= tempMaxIdx)
{
if (Attotime.attotime_compare(lt[i].expire, expire) > 0)
{
break;
}
emu_timer et = tlist[scanCount];
if (Attotime.attotime_compare(et.expire, expire) > 0)
break;
scanCount++;
}
lt.Insert(i, timer1);
lt.Insert(scanCount, 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)
// {
// timer_list_remove_lt1.Clear();
// //foreach (emu_timer et in lt)
// foreach (emu_timer et in lt.GetSrcList())
// {
// if (et.action == timer1.action && Attotime.attotime_compare(et.expire, timer1.expire) == 0)
// {
// timer_list_remove_lt1.Add(et);
// //lt.Remove(et);
// //break;
// }
// else if (et.action == timer1.action && Attotime.attotime_compare(et.expire, timer1.expire) < 0)
// {
// int i1 = 1;
// }
// else if (et.action == timer1.action && Attotime.attotime_compare(et.expire, timer1.expire) > 0)
// {
// int i1 = 1;
// }
// }
// foreach (emu_timer et1 in timer_list_remove_lt1)
// {
// lt.Remove(et1);
// }
// }
// else
// {
// //TODO MAME.NET原来这么foreach写删除是有问题的
// //foreach (emu_timer et in lt)
// foreach (emu_timer et in lt.GetSrcList())
// {
// if (et.action == timer1.action)
// {
// lt.Remove(et);
// break;
// }
// }
// }
//}
//修改优化
public static void timer_list_remove(emu_timer timer1)
{
if (timer1.action == TIME_ACT.Cpuint_cpunum_empty_event_queue || timer1.action == TIME_ACT.setvector)
{
timer_list_remove_lt1.Clear();
//foreach (emu_timer et in lt)
foreach (emu_timer et in lt.GetSrcList())
//timer_list_remove_lt1.Clear();
//foreach (emu_timer et in lt.GetSrcList())
//{
// if (et.action == timer1.action && Attotime.attotime_compare(et.expire, timer1.expire) == 0)
// timer_list_remove_lt1.Add(et);
//}
//foreach (emu_timer et1 in timer_list_remove_lt1)
// lt.Remove(et1);
var tlist = lt.GetSrcList();
int tempMaxIdx = tlist.Count - 1;
while (tempMaxIdx >= 0)
{
emu_timer et = tlist[tempMaxIdx];
if (et.action == timer1.action && Attotime.attotime_compare(et.expire, timer1.expire) == 0)
{
timer_list_remove_lt1.Add(et);
//lt.Remove(et);
//break;
}
else if (et.action == timer1.action && Attotime.attotime_compare(et.expire, timer1.expire) < 0)
{
int i1 = 1;
}
else if (et.action == timer1.action && Attotime.attotime_compare(et.expire, timer1.expire) > 0)
{
int i1 = 1;
}
}
foreach (emu_timer et1 in timer_list_remove_lt1)
{
lt.Remove(et1);
lt.Remove(et);
tempMaxIdx--;
}
}
else
{
//TODO MAME.NET原来这么foreach写删除是有问题的
//foreach (emu_timer et in lt)
foreach (emu_timer et in lt.GetSrcList())
//foreach (emu_timer et in lt.GetSrcList())
//{
// if (et.action == timer1.action)
// {
// lt.Remove(et);
// break;
// }
//}
var tlist = lt.GetSrcList();
int tempMaxIdx = tlist.Count - 1;
int scanCount = 0;
while (scanCount <= tempMaxIdx)
{
emu_timer et = tlist[scanCount];
if (et.action == timer1.action)
{
lt.Remove(et);
break;
}
scanCount++;
}
}
}

View File

@ -544,18 +544,18 @@
}
}
readonly static int[] K051960_sprites_draw_xoffset = new int[] { 0, 1, 4, 5, 16, 17, 20, 21 };
readonly static int[] K051960_sprites_draw_yoffset = new int[] { 0, 2, 8, 10, 32, 34, 40, 42 };
readonly static int[] K051960_sprites_draw_width = new int[] { 1, 2, 1, 2, 4, 2, 4, 8 };
readonly static int[] K051960_sprites_draw_height = new int[] { 1, 1, 2, 2, 2, 4, 4, 8 };
static int[] K051960_sprites_draw_sortedlist = new int[128];
public static void K051960_sprites_draw(RECT cliprect, int min_priority, int max_priority)
{
int ox, oy, code, color, pri, shadow, size, w, h, x, y, flipx, flipy, zoomx, zoomy, code2, color2, pri2;
int offs, pri_code;
int[] sortedlist = new int[128];
int[] xoffset = new int[] { 0, 1, 4, 5, 16, 17, 20, 21 };
int[] yoffset = new int[] { 0, 2, 8, 10, 32, 34, 40, 42 };
int[] width = new int[] { 1, 2, 1, 2, 4, 2, 4, 8 };
int[] height = new int[] { 1, 1, 2, 2, 2, 4, 4, 8 };
for (offs = 0; offs < 128; offs++)
{
sortedlist[offs] = -1;
K051960_sprites_draw_sortedlist[offs] = -1;
}
for (offs = 0; offs < 0x400; offs += 8)
{
@ -563,17 +563,17 @@
{
if (max_priority == -1)
{
sortedlist[(K051960_ram[offs] & 0x7f) ^ 0x7f] = offs;
K051960_sprites_draw_sortedlist[(K051960_ram[offs] & 0x7f) ^ 0x7f] = offs;
}
else
{
sortedlist[K051960_ram[offs] & 0x7f] = offs;
K051960_sprites_draw_sortedlist[K051960_ram[offs] & 0x7f] = offs;
}
}
}
for (pri_code = 0; pri_code < 128; pri_code++)
{
offs = sortedlist[pri_code];
offs = K051960_sprites_draw_sortedlist[pri_code];
if (offs == -1)
{
continue;
@ -594,8 +594,8 @@
}
}
size = (K051960_ram[offs + 1] & 0xe0) >> 5;
w = width[size];
h = height[size];
w = K051960_sprites_draw_width[size];
h = K051960_sprites_draw_height[size];
if (w >= 2) code &= ~0x01;
if (h >= 2) code &= ~0x02;
if (w >= 4) code &= ~0x04;
@ -631,19 +631,19 @@
sx = ox + 16 * x;
if (flipx != 0)
{
c += xoffset[(w - 1 - x)];
c += K051960_sprites_draw_xoffset[(w - 1 - x)];
}
else
{
c += xoffset[x];
c += K051960_sprites_draw_xoffset[x];
}
if (flipy != 0)
{
c += yoffset[(h - 1 - y)];
c += K051960_sprites_draw_yoffset[(h - 1 - y)];
}
else
{
c += yoffset[y];
c += K051960_sprites_draw_yoffset[y];
}
if (max_priority == -1)
{
@ -682,16 +682,16 @@
zw = (ox + ((zoomx * (x + 1) + (1 << 11)) >> 12)) - sx;
if (flipx != 0)
{
c += xoffset[(w - 1 - x)];
c += K051960_sprites_draw_xoffset[(w - 1 - x)];
}
else c += xoffset[x];
else c += K051960_sprites_draw_xoffset[x];
if (flipy != 0)
{
c += yoffset[(h - 1 - y)];
c += K051960_sprites_draw_yoffset[(h - 1 - y)];
}
else
{
c += yoffset[y];
c += K051960_sprites_draw_yoffset[y];
}
if (max_priority == -1)
{

View File

@ -153,7 +153,7 @@ namespace MAME.Core
#endregion
public static byte[] airduelm72_code = new byte[] {
public readonly static byte[] airduelm72_code = new byte[] {
0x68, 0x00, 0xd0, 0x1f, 0xc6, 0x06, 0xc0, 0x1c, 0x57, 0xea, 0x69, 0x0b, 0x00, 0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
@ -161,7 +161,7 @@ namespace MAME.Core
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};
public static byte[] gunforce_decryption_table = new byte[256] {
public readonly static byte[] gunforce_decryption_table = new byte[256] {
0xff,0x90,0x90,0x2c,0x90,0x90,0x43,0x88, 0x90,0x13,0x0a,0xbd,0xba,0x60,0xea,0x90, /* 00 */
0x90,0x90,0xf2,0x29,0xb3,0x22,0x90,0x0c, 0xa9,0x5f,0x9d,0x07,0x90,0x90,0x0b,0xbb, /* 10 */
0x8a,0x90,0x90,0x90,0x3a,0x3c,0x5a,0x38, 0x99,0x90,0xf8,0x89,0x90,0x91,0x90,0x55, /* 20 */

View File

@ -1,66 +1,107 @@
namespace MAME.Core
using System.Runtime.CompilerServices;
namespace MAME.Core
{
public unsafe partial class Drawgfx
{
public static void common_drawgfx_m92(byte* bb1, int code, int color, int flipx, int flipy, int sx, int sy, RECT clip, uint primask)
//public static void common_drawgfx_m92(byte* bb1, int code, int color, int flipx, int flipy, int sx, int sy, RECT clip, uint primask)
//{
// int ox;
// int oy;
// int ex;
// int ey;
// ox = sx;
// oy = sy;
// ex = sx + 0x10 - 1;
// if (sx < 0)
// {
// sx = 0;
// }
// if (sx < clip.min_x)
// {
// sx = clip.min_x;
// }
// if (ex >= 0x200)
// {
// ex = 0x200 - 1;
// }
// if (ex > clip.max_x)
// {
// ex = clip.max_x;
// }
// if (sx > ex)
// {
// return;
// }
// ey = sy + 0x10 - 1;
// if (sy < 0)
// {
// sy = 0;
// }
// if (sy < clip.min_y)
// {
// sy = clip.min_y;
// }
// if (ey >= 0x100)
// {
// ey = 0x100 - 1;
// }
// if (ey > clip.max_y)
// {
// ey = clip.max_y;
// }
// if (sy > ey)
// {
// return;
// }
// int sw = 0x10;
// int sh = 0x10;
// int ls = sx - ox;
// int ts = sy - oy;
// int dw = ex - sx + 1;
// int dh = ey - sy + 1;
// int colorbase = 0x10 * color;
// blockmove_8toN_transpen_pri16_m92(bb1, code, sw, sh, 0x10, ls, ts, flipx, flipy, dw, dh, colorbase, sy, sx, primask);
//}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe void common_drawgfx_m92(byte* bb1, int code, int color, int flipx, int flipy, int sx, int sy, RECT clip, uint primask)
{
int ox;
int oy;
int ex;
int ey;
ox = sx;
oy = sy;
ex = sx + 0x10 - 1;
if (sx < 0)
{
sx = 0;
}
if (sx < clip.min_x)
{
sx = clip.min_x;
}
if (ex >= 0x200)
{
ex = 0x200 - 1;
}
if (ex > clip.max_x)
{
ex = clip.max_x;
}
if (sx > ex)
{
return;
}
ey = sy + 0x10 - 1;
if (sy < 0)
{
sy = 0;
}
if (sy < clip.min_y)
{
sy = clip.min_y;
}
if (ey >= 0x100)
{
ey = 0x100 - 1;
}
if (ey > clip.max_y)
{
ey = clip.max_y;
}
if (sy > ey)
{
return;
}
int sw = 0x10;
int sh = 0x10;
// 使用常量折叠和预计算[5](@ref)
const int TEMP1 = 0x10 - 1; // 15
const int TEMP3 = 0x100 - 1; // 255
const int TEMP4 = 0x200 - 1; // 511
int ox = sx;
int oy = sy;
int ex = sx + TEMP1;
// 边界检查优化:减少分支预测错误[5](@ref)
sx = sx < 0 ? 0 : sx;
sx = sx < clip.min_x ? clip.min_x : sx;
ex = ex >= 0x200 ? TEMP4 : ex;
ex = ex > clip.max_x ? clip.max_x : ex;
if (sx > ex) return;
int ey = sy + TEMP1;
sy = sy < 0 ? 0 : sy;
sy = sy < clip.min_y ? clip.min_y : sy;
ey = ey >= 0x100 ? TEMP3 : ey;
ey = ey > clip.max_y ? clip.max_y : ey;
if (sy > ey) return;
// 使用局部变量避免重复计算[2,4](@ref)
int ls = sx - ox;
int ts = sy - oy;
int dw = ex - sx + 1;
int dh = ey - sy + 1;
int colorbase = 0x10 * color;
blockmove_8toN_transpen_pri16_m92(bb1, code, sw, sh, 0x10, ls, ts, flipx, flipy, dw, dh, colorbase, sy, sx, primask);
int colorbase = color << 4; // 用移位代替乘法 0x10 * color
// 内联关键函数调用
blockmove_8toN_transpen_pri16_m92(bb1, code, 0x10, 0x10, 0x10, ls, ts, flipx, flipy, dw, dh, colorbase, sy, sx, primask);
}
public unsafe static void blockmove_8toN_transpen_pri16_m92(byte* bb1, int code, int srcwidth, int srcheight, int srcmodulo, int leftskip, int topskip, int flipx, int flipy, int dstwidth, int dstheight, int colorbase, int sy, int sx, uint primask)
{
int ydir, xdir, col, i, j;

View File

@ -125,6 +125,7 @@ namespace MAME.Core
namcos1_playfield_control[offset & 0x1f] = data;
}
}
readonly static int[] draw_sprites_sprite_size = new int[] { 16, 8, 32, 4 };
public static void draw_sprites(int iBitmap, RECT cliprect)
{
int source_offset;
@ -132,14 +133,13 @@ namespace MAME.Core
int sprite_yoffs = namcos1_spriteram[0x800 + 0x07f7];
for (source_offset = 0xfe0; source_offset >= 0x800; source_offset -= 0x10)
{
int[] sprite_size = new int[] { 16, 8, 32, 4 };
int attr1 = namcos1_spriteram[source_offset + 10];
int attr2 = namcos1_spriteram[source_offset + 14];
int color = namcos1_spriteram[source_offset + 12];
int flipx = (attr1 & 0x20) >> 5;
int flipy = (attr2 & 0x01);
int sizex = sprite_size[(attr1 & 0xc0) >> 6];
int sizey = sprite_size[(attr2 & 0x06) >> 1];
int sizex = draw_sprites_sprite_size[(attr1 & 0xc0) >> 6];
int sizey = draw_sprites_sprite_size[(attr2 & 0x06) >> 1];
int tx = (attr1 & 0x18) & (~(sizex - 1));
int ty = (attr2 & 0x18) & (~(sizey - 1));
int sx = namcos1_spriteram[source_offset + 13] + ((color & 0x01) << 8);
@ -163,6 +163,7 @@ namespace MAME.Core
Drawgfx.common_drawgfx_na(sizex, sizey, tx, ty, sprite, color, flipx, flipy, sx & 0x1ff, ((sy + 16) & 0xff) - 16, cliprect);
}
}
readonly static int[] video_update_namcos1_disp_x = new int[] { 25, 27, 28, 29 };
public static void video_update_namcos1()
{
int i, j, scrollx, scrolly;
@ -195,9 +196,8 @@ namespace MAME.Core
}
for (i = 0; i < 4; i++)
{
int[] disp_x = new int[] { 25, 27, 28, 29 };
j = i << 2;
scrollx = (namcos1_playfield_control[j + 1] + (namcos1_playfield_control[j + 0] << 8)) - disp_x[i];
scrollx = (namcos1_playfield_control[j + 1] + (namcos1_playfield_control[j + 0] << 8)) - video_update_namcos1_disp_x[i];
scrolly = (namcos1_playfield_control[j + 3] + (namcos1_playfield_control[j + 2] << 8)) + 8;
if (Video.flip_screen_get())
{

View File

@ -416,17 +416,94 @@ namespace MAME.Core
}
return result;
}
//public static void MWriteByte(int address, sbyte value)
//{
// address &= 0xffffff;
// if (address >= 0x100000 && address <= 0x1fffff)
// {
// if (address == 0x100d0b && value == 0x06)//&&MC68000.m1.TotalExecutedCycles>0x3F6FC8C)
// {
// ulong l1 = MC68000.m1.TotalExecutedCycles;
// int i2 = 1;
// //m68000Form.iStatus = 1;
// }
// Memory.mainram[address & 0xffff] = (byte)value;
// }
// else if (address >= 0x2ffff0 && address <= 0x2fffff)
// {
// main_cpu_bank_select_w(value);
// }
// else if (address >= 0x300000 && address <= 0x31ffff)
// {
// if ((address & 0x01) == 0)
// {
// int i1 = 1;
// }
// else if ((address & 0x01) == 1)
// {
// watchdog_w();
// }
// }
// else if (address >= 0x320000 && address <= 0x33ffff)
// {
// if ((address & 0x01) == 0)
// {
// audio_command_w((byte)value);
// }
// else if ((address & 0x01) == 1)
// {
// int i1 = 1;
// }
// }
// else if (address >= 0x380000 && address <= 0x39ffff)
// {
// io_control_w((address & 0x7f) >> 1, (byte)value);
// }
// else if (address >= 0x3a0000 && address <= 0x3bffff)
// {
// if ((address & 0x01) == 1)
// {
// system_control_w((address & 0x1f) >> 1);
// }
// }
// else if (address >= 0x3c0000 && address <= 0x3dffff)
// {
// if ((address & 0x01) == 0)
// {
// neogeo_video_register_w((address & 0x0f) >> 1, (ushort)((value << 8) | (byte)value));
// }
// else if ((address & 0x01) == 1)
// {
// int i1 = 1;
// }
// }
// else if (address >= 0x400000 && address <= 0x7fffff)
// {
// int i1 = 1;
// //neogeo_paletteram_w((address - 0x400000) >> 1, data, mem_mask);
// }
// else if (address >= 0xd00000 && address <= 0xdfffff)
// {
// save_ram_w(address & 0xffff, (byte)value);
// }
// else
// {
// int i1 = 1;
// }
//}
//手动优化
public static void MWriteByte(int address, sbyte value)
{
address &= 0xffffff;
if (address >= 0x100000 && address <= 0x1fffff)
{
if (address == 0x100d0b && value == 0x06)//&&MC68000.m1.TotalExecutedCycles>0x3F6FC8C)
{
ulong l1 = MC68000.m1.TotalExecutedCycles;
int i2 = 1;
//m68000Form.iStatus = 1;
}
//if (address == 0x100d0b && value == 0x06)//&&MC68000.m1.TotalExecutedCycles>0x3F6FC8C)
//{
// ulong l1 = MC68000.m1.TotalExecutedCycles;
// int i2 = 1;
// //m68000Form.iStatus = 1;
//}
Memory.mainram[address & 0xffff] = (byte)value;
}
else if (address >= 0x2ffff0 && address <= 0x2fffff)
@ -435,13 +512,15 @@ namespace MAME.Core
}
else if (address >= 0x300000 && address <= 0x31ffff)
{
if ((address & 0x01) == 0)
/*if ((address & 0x01) == 0)
{
int i1 = 1;
}
else if ((address & 0x01) == 1)
else */if ((address & 0x01) == 1)
{
watchdog_w();
//watchdog_w();
//减少一次堆栈 无意义套娃
Watchdog.watchdog_reset();
}
}
else if (address >= 0x320000 && address <= 0x33ffff)
@ -450,10 +529,11 @@ namespace MAME.Core
{
audio_command_w((byte)value);
}
else if ((address & 0x01) == 1)
{
int i1 = 1;
}
//无意义
//else if ((address & 0x01) == 1)
//{
// int i1 = 1;
//}
}
else if (address >= 0x380000 && address <= 0x39ffff)
{
@ -472,24 +552,28 @@ namespace MAME.Core
{
neogeo_video_register_w((address & 0x0f) >> 1, (ushort)((value << 8) | (byte)value));
}
else if ((address & 0x01) == 1)
{
int i1 = 1;
}
}
else if (address >= 0x400000 && address <= 0x7fffff)
{
int i1 = 1;
//neogeo_paletteram_w((address - 0x400000) >> 1, data, mem_mask);
//无意义
//else if ((address & 0x01) == 1)
//{
// int i1 = 1;
//}
}
//无意义
//else if (address >= 0x400000 && address <= 0x7fffff)
//{
// int i1 = 1;
// //neogeo_paletteram_w((address - 0x400000) >> 1, data, mem_mask);
//}
else if (address >= 0xd00000 && address <= 0xdfffff)
{
save_ram_w(address & 0xffff, (byte)value);
}
else
{
int i1 = 1;
}
//无意义
//else
//{
// int i1 = 1;
//}
}
public static void MWriteWord(int address, short value)
{

View File

@ -96,10 +96,7 @@ namespace MAME.Core
neogeo_rng = (ushort)((neogeo_rng << 1) | newbit);
return old;
}
public static void kof99_bankswitch_w(int data)
{
int bankaddress;
int[] bankoffset = new int[]
readonly static int[] kof99_bankswitch_w_bankoffset = new int[]
{
0x000000, 0x100000, 0x200000, 0x300000,
0x3cc000, 0x4cc000, 0x3f2000, 0x4f2000,
@ -111,6 +108,10 @@ namespace MAME.Core
0x588800, 0x581800, 0x599800, 0x594800,
0x598000
};
public static void kof99_bankswitch_w(int data)
{
int bankaddress;
data =
(((data >> 14) & 1) << 0) +
(((data >> 6) & 1) << 1) +
@ -118,13 +119,10 @@ namespace MAME.Core
(((data >> 10) & 1) << 3) +
(((data >> 12) & 1) << 4) +
(((data >> 5) & 1) << 5);
bankaddress = 0x100000 + bankoffset[data];
bankaddress = 0x100000 + kof99_bankswitch_w_bankoffset[data];
main_cpu_bank_address = bankaddress;
}
public static void garou_bankswitch_w(int data)
{
int bankaddress;
int[] bankoffset = new int[]
readonly static int[] garou_bankswitch_w_bankoffset = new int[]
{
0x000000, 0x100000, 0x200000, 0x300000, // 00
0x280000, 0x380000, 0x2d0000, 0x3d0000, // 04
@ -141,6 +139,10 @@ namespace MAME.Core
0x5d0000, 0x5d8000, 0x5e0000, 0x5e8000, // 48
0x5f0000, 0x5f8000, 0x600000
};
public static void garou_bankswitch_w(int data)
{
int bankaddress;
data =
(((data >> 5) & 1) << 0) +
(((data >> 9) & 1) << 1) +
@ -148,13 +150,10 @@ namespace MAME.Core
(((data >> 6) & 1) << 3) +
(((data >> 14) & 1) << 4) +
(((data >> 12) & 1) << 5);
bankaddress = 0x100000 + bankoffset[data];
bankaddress = 0x100000 + garou_bankswitch_w_bankoffset[data];
main_cpu_bank_address = bankaddress;
}
public static void garouh_bankswitch_w(int data)
{
int bankaddress;
int[] bankoffset = new int[]
readonly static int[] garouh_bankswitch_w_bankoffset = new int[]
{
0x000000, 0x100000, 0x200000, 0x300000, // 00
0x280000, 0x380000, 0x2d0000, 0x3d0000, // 04
@ -173,6 +172,10 @@ namespace MAME.Core
0x000000, 0x000000, 0x000000, 0x000000, // 56
0x000000, 0x000000, 0x000000, 0x000000 // 60
};
public static void garouh_bankswitch_w(int data)
{
int bankaddress;
data =
(((data >> 4) & 1) << 0) +
(((data >> 8) & 1) << 1) +
@ -180,14 +183,11 @@ namespace MAME.Core
(((data >> 2) & 1) << 3) +
(((data >> 11) & 1) << 4) +
(((data >> 13) & 1) << 5);
bankaddress = 0x100000 + bankoffset[data];
bankaddress = 0x100000 + garouh_bankswitch_w_bankoffset[data];
main_cpu_bank_address = bankaddress;
}
public static void mslug3_bankswitch_w(int data)
readonly static int[] mslug3_bankswitch_w_bankoffset = new int[]
{
int bankaddress;
int[] bankoffset = new int[]
{
0x000000, 0x020000, 0x040000, 0x060000, // 00
0x070000, 0x090000, 0x0b0000, 0x0d0000, // 04
0x0e0000, 0x0f0000, 0x120000, 0x130000, // 08
@ -201,7 +201,10 @@ namespace MAME.Core
0x400000, 0x410000, 0x440000, 0x450000, // 40
0x460000, 0x470000, 0x4a0000, 0x4b0000, // 44
0x4c0000
};
};
public static void mslug3_bankswitch_w(int data)
{
int bankaddress;
data =
(((data >> 14) & 1) << 0) +
(((data >> 12) & 1) << 1) +
@ -209,13 +212,10 @@ namespace MAME.Core
(((data >> 6) & 1) << 3) +
(((data >> 3) & 1) << 4) +
(((data >> 9) & 1) << 5);
bankaddress = 0x100000 + bankoffset[data];
bankaddress = 0x100000 + mslug3_bankswitch_w_bankoffset[data];
main_cpu_bank_address = bankaddress;
}
public static void kof2000_bankswitch_w(int data)
{
int bankaddress;
int[] bankoffset = new int[]
readonly static int[] kof2000_bankswitch_w_bankoffset = new int[]
{
0x000000, 0x100000, 0x200000, 0x300000, // 00
0x3f7800, 0x4f7800, 0x3ff800, 0x4ff800, // 04
@ -227,6 +227,10 @@ namespace MAME.Core
0x52d000, 0x62d000, 0x52e800, 0x62e800, // 28
0x618000, 0x619000, 0x61a000, 0x61a800, // 32
};
public static void kof2000_bankswitch_w(int data)
{
int bankaddress;
data =
(((data >> 15) & 1) << 0) +
(((data >> 14) & 1) << 1) +
@ -234,7 +238,7 @@ namespace MAME.Core
(((data >> 3) & 1) << 3) +
(((data >> 10) & 1) << 4) +
(((data >> 5) & 1) << 5);
bankaddress = 0x100000 + bankoffset[data];
bankaddress = 0x100000 + kof2000_bankswitch_w_bankoffset[data];
main_cpu_bank_address = bankaddress;
}
public static void pvc_prot1()

View File

@ -8,7 +8,7 @@
public static byte kb_swap;
public static ushort olds_bs, kb_cmd3;
public static byte[][] kb_source_data;
public static byte[][] drgw2_source_data = new byte[0x08][]//[0xec]
public readonly static byte[][] drgw2_source_data = new byte[0x08][]//[0xec]
{
new byte[]{ 0, }, // Region 0, not used
new byte[]{ // Region 1, $13A886

View File

@ -11,7 +11,7 @@
public static byte port1_out, port2_out, port3_out, port4_out;
public static byte portA_in, portA_out, ddrA, portB_in, portB_out, ddrB;
public static int ic43_a, ic43_b;
public static byte[] tokio_prot_data = new byte[]
public readonly static byte[] tokio_prot_data = new byte[]
{
0x6c,
0x7f,0x5f,0x7f,0x6f,0x5f,0x77,0x5f,0x7f,0x5f,0x7f,0x5f,0x7f,0x5b,0x7f,0x5f,0x7f,
@ -295,10 +295,10 @@
}
ic43_a = res;
}
readonly static int[] boblbobl_ic43_b_w_xor = new int[] { 4, 1, 8, 2 };
public static void boblbobl_ic43_b_w(int offset, byte data)
{
int[] xor = new int[] { 4, 1, 8, 2 };
ic43_b = (data >> 4) ^ xor[offset];
ic43_b = (data >> 4) ^ boblbobl_ic43_b_w_xor[offset];
}
public static byte boblbobl_ic43_b_r(int offset)
{

View File

@ -671,6 +671,9 @@ namespace MAME.Core
{
current_bank = (byte)(data & 7);
}
static int[] opwolf_cchip_data_w_coin_table = new int[] { 0, 0 };
static byte[] opwolf_cchip_data_w_coin_offset = new byte[2];
public static void opwolf_cchip_data_w(int offset, ushort data)
{
cchip_ram[(current_bank * 0x400) + offset] = (byte)(data & 0xff);
@ -680,28 +683,28 @@ namespace MAME.Core
// Shouldn't we directly read the values from the ROM area ?
if (offset == 0x14)
{
int[] coin_table = new int[] { 0, 0 };
byte[] coin_offset = new byte[2];
//int[] coin_table = new int[] { 0, 0 };
//byte[] coin_offset = new byte[2];
int slot;
if ((opwolf_region == 1) || (opwolf_region == 2))
{
coin_table[0] = 0x03ffce;
coin_table[1] = 0x03ffce;
opwolf_cchip_data_w_coin_table[0] = 0x03ffce;
opwolf_cchip_data_w_coin_table[1] = 0x03ffce;
}
if ((opwolf_region == 3) || (opwolf_region == 4))
{
coin_table[0] = 0x03ffde;
coin_table[1] = 0x03ffee;
opwolf_cchip_data_w_coin_table[0] = 0x03ffde;
opwolf_cchip_data_w_coin_table[1] = 0x03ffee;
}
coin_offset[0] = (byte)(12 - (4 * ((data & 0x30) >> 4)));
coin_offset[1] = (byte)(12 - (4 * ((data & 0xc0) >> 6)));
opwolf_cchip_data_w_coin_offset[0] = (byte)(12 - (4 * ((data & 0x30) >> 4)));
opwolf_cchip_data_w_coin_offset[1] = (byte)(12 - (4 * ((data & 0xc0) >> 6)));
for (slot = 0; slot < 2; slot++)
{
if (coin_table[slot] != 0)
if (opwolf_cchip_data_w_coin_table[slot] != 0)
{
cchip_coins_for_credit[slot] = (byte)((Memory.mainrom[(coin_table[slot] + coin_offset[slot] + 0) / 2 * 2] * 0x100 + Memory.mainrom[(coin_table[slot] + coin_offset[slot] + 0) / 2 * 2 + 1]) & 0xff);
cchip_credits_for_coin[slot] = (byte)((Memory.mainrom[(coin_table[slot] + coin_offset[slot] + 2) / 2 * 2] * 0x100 + Memory.mainrom[(coin_table[slot] + coin_offset[slot] + 2) / 2 * 2 + 1]) & 0xff);
cchip_coins_for_credit[slot] = (byte)((Memory.mainrom[(opwolf_cchip_data_w_coin_table[slot] + opwolf_cchip_data_w_coin_offset[slot] + 0) / 2 * 2] * 0x100 + Memory.mainrom[(opwolf_cchip_data_w_coin_table[slot] + opwolf_cchip_data_w_coin_offset[slot] + 0) / 2 * 2 + 1]) & 0xff);
cchip_credits_for_coin[slot] = (byte)((Memory.mainrom[(opwolf_cchip_data_w_coin_table[slot] + opwolf_cchip_data_w_coin_offset[slot] + 2) / 2 * 2] * 0x100 + Memory.mainrom[(opwolf_cchip_data_w_coin_table[slot] + opwolf_cchip_data_w_coin_offset[slot] + 2) / 2 * 2 + 1]) & 0xff);
}
}
}
@ -712,6 +715,8 @@ namespace MAME.Core
}
}
}
static int[] opwolf_cchip_data_w2_coin_table = new int[] { 0, 0 };
static byte[] opwolf_cchip_data_w2_coin_offset = new byte[2];
public static void opwolf_cchip_data_w2(int offset, byte data)
{
cchip_ram[(current_bank * 0x400) + offset] = (byte)(data & 0xff);
@ -721,28 +726,28 @@ namespace MAME.Core
// Shouldn't we directly read the values from the ROM area ?
if (offset == 0x14)
{
int[] coin_table = new int[] { 0, 0 };
byte[] coin_offset = new byte[2];
//int[] coin_table = new int[] { 0, 0 };
//byte[] coin_offset = new byte[2];
int slot;
if ((opwolf_region == 1) || (opwolf_region == 2))
{
coin_table[0] = 0x03ffce;
coin_table[1] = 0x03ffce;
opwolf_cchip_data_w2_coin_table[0] = 0x03ffce;
opwolf_cchip_data_w2_coin_table[1] = 0x03ffce;
}
if ((opwolf_region == 3) || (opwolf_region == 4))
{
coin_table[0] = 0x03ffde;
coin_table[1] = 0x03ffee;
opwolf_cchip_data_w2_coin_table[0] = 0x03ffde;
opwolf_cchip_data_w2_coin_table[1] = 0x03ffee;
}
coin_offset[0] = (byte)(12 - (4 * ((data & 0x30) >> 4)));
coin_offset[1] = (byte)(12 - (4 * ((data & 0xc0) >> 6)));
opwolf_cchip_data_w2_coin_offset[0] = (byte)(12 - (4 * ((data & 0x30) >> 4)));
opwolf_cchip_data_w2_coin_offset[1] = (byte)(12 - (4 * ((data & 0xc0) >> 6)));
for (slot = 0; slot < 2; slot++)
{
if (coin_table[slot] != 0)
if (opwolf_cchip_data_w2_coin_table[slot] != 0)
{
cchip_coins_for_credit[slot] = (byte)((Memory.mainrom[(coin_table[slot] + coin_offset[slot] + 0) / 2 * 2] * 0x100 + Memory.mainrom[(coin_table[slot] + coin_offset[slot] + 0) / 2 * 2 + 1]) & 0xff);
cchip_credits_for_coin[slot] = (byte)((Memory.mainrom[(coin_table[slot] + coin_offset[slot] + 2) / 2 * 2] * 0x100 + Memory.mainrom[(coin_table[slot] + coin_offset[slot] + 2) / 2 * 2 + 1]) & 0xff);
cchip_coins_for_credit[slot] = (byte)((Memory.mainrom[(opwolf_cchip_data_w2_coin_table[slot] + opwolf_cchip_data_w2_coin_offset[slot] + 0) / 2 * 2] * 0x100 + Memory.mainrom[(opwolf_cchip_data_w2_coin_table[slot] + opwolf_cchip_data_w2_coin_offset[slot] + 0) / 2 * 2 + 1]) & 0xff);
cchip_credits_for_coin[slot] = (byte)((Memory.mainrom[(opwolf_cchip_data_w2_coin_table[slot] + opwolf_cchip_data_w2_coin_offset[slot] + 2) / 2 * 2] * 0x100 + Memory.mainrom[(opwolf_cchip_data_w2_coin_table[slot] + opwolf_cchip_data_w2_coin_offset[slot] + 2) / 2 * 2 + 1]) & 0xff);
}
}
}

View File

@ -286,18 +286,41 @@ namespace MAME.Core
}
}
}
//private int mix_3D()
//{
// int indx = 0, chan;
// for (chan = 0; chan < 3; chan++)
// {
// if (TONE_ENVELOPE(chan) != 0)
// {
// indx |= ((1 << (chan + 15)) | ((ay8910info.vol_enabled[chan] != 0) ? ay8910info.env_volume << (chan * 5) : 0));
// }
// else
// {
// indx |= ((ay8910info.vol_enabled[chan] != 0) ? TONE_VOLUME(chan) << (chan * 5) : 0);
// }
// }
// return ay8910info.vol3d_table[indx];
//}
//手动内联
private int mix_3D()
{
int indx = 0, chan;
for (chan = 0; chan < 3; chan++)
{
if (TONE_ENVELOPE(chan) != 0)
//if (TONE_ENVELOPE(chan) != 0)
if(((ay8910info.regs[TONE_ENVELOPE_REG_OFFSET + chan] >> TONE_ENVELOPE_MOVE) & TONE_ENVELOPE_VOLUME_MASK)!=0)
{
indx |= ((1 << (chan + 15)) | ((ay8910info.vol_enabled[chan] != 0) ? ay8910info.env_volume << (chan * 5) : 0));
}
else
{
indx |= ((ay8910info.vol_enabled[chan] != 0) ? TONE_VOLUME(chan) << (chan * 5) : 0);
indx |= ((ay8910info.vol_enabled[chan] != 0) ?
//TONE_VOLUME(chan)
(ay8910info.regs[TONE_VOLUME_REG_OFFSET + chan] & TONE_VOLUME_VOLUME_MASK)
<< (chan * 5)
: 0);
}
}
return ay8910info.vol3d_table[indx];
@ -373,6 +396,104 @@ namespace MAME.Core
break;
}
}
//public void ay8910_update(int offset, int length)
//{
// int chan, i, j;
// if (ay8910info.ready == 0)
// {
// for (chan = 0; chan < ay8910info.streams; chan++)
// {
// for (j = 0; j < length; j++)
// {
// stream.streamoutput_Ptrs[chan][offset + j] = 0;
// }
// }
// }
// for (i = 0; i < length; i++)
// {
// for (chan = 0; chan < 3; chan++)
// {
// ay8910info.count[chan]++;
// if (ay8910info.count[chan] >= TONE_PERIOD(chan))
// {
// ay8910info.output[chan] ^= 1;
// ay8910info.count[chan] = 0; ;
// }
// }
// ay8910info.count_noise++;
// if (ay8910info.count_noise >= NOISE_PERIOD())
// {
// if (((ay8910info.rng + 1) & 2) != 0)
// {
// ay8910info.output_noise ^= 1;
// }
// if ((ay8910info.rng & 1) != 0)
// {
// ay8910info.rng ^= 0x24000;
// }
// ay8910info.rng >>= 1;
// ay8910info.count_noise = 0;
// }
// for (chan = 0; chan < 3; chan++)
// {
// ay8910info.vol_enabled[chan] = (byte)((ay8910info.output[chan] | TONE_ENABLEQ(chan)) & (ay8910info.output_noise | NOISE_ENABLEQ(chan)));
// }
// if (ay8910info.holding == 0)
// {
// ay8910info.count_env++;
// if (ay8910info.count_env >= ENVELOPE_PERIOD() * ay8910info.step)
// {
// ay8910info.count_env = 0;
// ay8910info.env_step--;
// if (ay8910info.env_step < 0)
// {
// if (ay8910info.hold != 0)
// {
// if (ay8910info.alternate != 0)
// {
// ay8910info.attack ^= ay8910info.env_step_mask;
// }
// ay8910info.holding = 1;
// ay8910info.env_step = 0;
// }
// else
// {
// if (ay8910info.alternate != 0 && (ay8910info.env_step & (ay8910info.env_step_mask + 1)) != 0)
// {
// ay8910info.attack ^= ay8910info.env_step_mask;
// }
// ay8910info.env_step &= (sbyte)ay8910info.env_step_mask;
// }
// }
// }
// }
// ay8910info.env_volume = (ay8910info.env_step ^ ay8910info.attack);
// if (ay8910info.streams == 3)
// {
// for (chan = 0; chan < 3; chan++)
// {
// if (TONE_ENVELOPE(chan) != 0)
// {
// int i1 = ay8910info.env_table[chan][ay8910info.vol_enabled[chan] != 0 ? ay8910info.env_volume : 0];
// stream.streamoutput_Ptrs[chan][offset] = ay8910info.env_table[chan][ay8910info.vol_enabled[chan] != 0 ? ay8910info.env_volume : 0];
// }
// else
// {
// int i1 = ay8910info.vol_table[chan][ay8910info.vol_enabled[chan] != 0 ? TONE_VOLUME(chan) : 0];
// stream.streamoutput_Ptrs[chan][offset] = ay8910info.vol_table[chan][ay8910info.vol_enabled[chan] != 0 ? TONE_VOLUME(chan) : 0];
// }
// }
// }
// else
// {
// stream.streamoutput_Ptrs[0][offset] = mix_3D();
// }
// offset++;
// }
//}
//手动内联优化
public void ay8910_update(int offset, int length)
{
int chan, i, j;
@ -391,14 +512,16 @@ namespace MAME.Core
for (chan = 0; chan < 3; chan++)
{
ay8910info.count[chan]++;
if (ay8910info.count[chan] >= TONE_PERIOD(chan))
//if (ay8910info.count[chan] >= TONE_PERIOD(chan))
if (ay8910info.count[chan] >= (ay8910info.regs[chan << 1] | ((ay8910info.regs[(chan << 1) | 1] & 0x0f) << 8)))
{
ay8910info.output[chan] ^= 1;
ay8910info.count[chan] = 0; ;
}
}
ay8910info.count_noise++;
if (ay8910info.count_noise >= NOISE_PERIOD())
//if (ay8910info.count_noise >= NOISE_PERIOD())
if (ay8910info.count_noise >= (ay8910info.regs[6] & 0x1f))
{
if (((ay8910info.rng + 1) & 2) != 0)
{
@ -413,12 +536,23 @@ namespace MAME.Core
}
for (chan = 0; chan < 3; chan++)
{
ay8910info.vol_enabled[chan] = (byte)((ay8910info.output[chan] | TONE_ENABLEQ(chan)) & (ay8910info.output_noise | NOISE_ENABLEQ(chan)));
//ay8910info.vol_enabled[chan] = (byte)((ay8910info.output[chan] | TONE_ENABLEQ(chan)) & (ay8910info.output_noise | NOISE_ENABLEQ(chan)));
ay8910info.vol_enabled[chan] = (byte)((ay8910info.output[chan] |
//TONE_ENABLEQ(chan)
((ay8910info.regs[7] >> chan) & 1)
) & (ay8910info.output_noise |
//NOISE_ENABLEQ(chan)
((ay8910info.regs[7] >> (3 + chan)) & 1)
));
}
if (ay8910info.holding == 0)
{
ay8910info.count_env++;
if (ay8910info.count_env >= ENVELOPE_PERIOD() * ay8910info.step)
//if (ay8910info.count_env >= ENVELOPE_PERIOD() * ay8910info.step)
if (ay8910info.count_env >=
//ENVELOPE_PERIOD()
(ay8910info.regs[11] | (ay8910info.regs[12] << 8))
* ay8910info.step)
{
ay8910info.count_env = 0;
ay8910info.env_step--;
@ -449,21 +583,46 @@ namespace MAME.Core
{
for (chan = 0; chan < 3; chan++)
{
if (TONE_ENVELOPE(chan) != 0)
//if (TONE_ENVELOPE(chan) != 0)
if(((ay8910info.regs[TONE_ENVELOPE_REG_OFFSET + chan] >> TONE_ENVELOPE_MOVE) & TONE_ENVELOPE_VOLUME_MASK) != 0)
{
int i1 = ay8910info.env_table[chan][ay8910info.vol_enabled[chan] != 0 ? ay8910info.env_volume : 0];
stream.streamoutput_Ptrs[chan][offset] = ay8910info.env_table[chan][ay8910info.vol_enabled[chan] != 0 ? ay8910info.env_volume : 0];
}
else
{
int i1 = ay8910info.vol_table[chan][ay8910info.vol_enabled[chan] != 0 ? TONE_VOLUME(chan) : 0];
stream.streamoutput_Ptrs[chan][offset] = ay8910info.vol_table[chan][ay8910info.vol_enabled[chan] != 0 ? TONE_VOLUME(chan) : 0];
int i1 = ay8910info.vol_table[chan][ay8910info.vol_enabled[chan] != 0 ?
//TONE_VOLUME(chan)
ay8910info.regs[TONE_VOLUME_REG_OFFSET + chan] & TONE_VOLUME_VOLUME_MASK
: 0];
stream.streamoutput_Ptrs[chan][offset] = ay8910info.vol_table[chan][ay8910info.vol_enabled[chan] != 0 ?
//TONE_VOLUME(chan)
ay8910info.regs[TONE_VOLUME_REG_OFFSET + chan] & TONE_VOLUME_VOLUME_MASK
: 0];
}
}
}
else
{
stream.streamoutput_Ptrs[0][offset] = mix_3D();
//stream.streamoutput_Ptrs[0][offset] = mix_3D();
{
int indx = 0, tempchan;
for (tempchan = 0; tempchan < 3; tempchan++)
{
if (((ay8910info.regs[TONE_ENVELOPE_REG_OFFSET + tempchan] >> TONE_ENVELOPE_MOVE) & TONE_ENVELOPE_VOLUME_MASK) != 0)
{
indx |= ((1 << (tempchan + 15)) | ((ay8910info.vol_enabled[tempchan] != 0) ? ay8910info.env_volume << (tempchan * 5) : 0));
}
else
{
indx |= ((ay8910info.vol_enabled[tempchan] != 0) ?
(ay8910info.regs[TONE_VOLUME_REG_OFFSET + tempchan] & TONE_VOLUME_VOLUME_MASK)
<< (tempchan * 5)
: 0);
}
}
stream.streamoutput_Ptrs[0][offset] = ay8910info.vol3d_table[indx];
}
}
offset++;
}

View File

@ -287,7 +287,7 @@ namespace MAME.Core
6, 3, 0,-3,-6,-3, 0, 3,
7, 3, 0,-3,-7,-3, 0, 3,
};
private static byte[][] table = new byte[19][]
private readonly static byte[][] table = new byte[19][]
{
new byte[]{0x49, 0x4c, 0x4c, 0x12, 0x00, 0x00, 0x00, 0x00 },