CAPCOM YM2151 主要高频函数 unsafe 指针优化 | CPS NeoGeo PGS draw 函数 指针优化
This commit is contained in:
parent
0fc5acac4c
commit
0634207bf0
@ -20,6 +20,14 @@ namespace MAME.Core
|
||||
{
|
||||
Act_Log?.Invoke(msg);
|
||||
}
|
||||
|
||||
|
||||
public static void Assert(bool conditional, string msg)
|
||||
{
|
||||
if (conditional)
|
||||
return;
|
||||
Act_Log?.Invoke(msg);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
417
MAME.Unity/Assets/Plugins/UMAME/ObjectPoolAuto.cs
Normal file
417
MAME.Unity/Assets/Plugins/UMAME/ObjectPoolAuto.cs
Normal file
@ -0,0 +1,417 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MAME.Core
|
||||
{
|
||||
internal static class ObjectPoolAuto
|
||||
{
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>
|
||||
/// 获取或者创建一个新的
|
||||
/// </summary>
|
||||
/// <remarks>Remember to <see cref="Release{T}(T)"/> 需要回收参见这个</remarks>
|
||||
public static T Acquire<T>()
|
||||
where T : class, new()
|
||||
=> ObjectPool<T>.Acquire();
|
||||
|
||||
/// <summary>
|
||||
/// 获取或者创建一个新的
|
||||
/// </summary>
|
||||
/// <remarks>Remember to <see cref="Release{T}(T)"/> 需要回收参见这个</remarks>
|
||||
public static void Acquire<T>(out T item)
|
||||
where T : class, new()
|
||||
=> item = ObjectPool<T>.Acquire();
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>
|
||||
/// 回收对象
|
||||
/// </summary>
|
||||
public static void Release<T>(T item)
|
||||
where T : class, new()
|
||||
=> ObjectPool<T>.Release(item);
|
||||
|
||||
/// <summary>
|
||||
/// 回收对象
|
||||
/// </summary>
|
||||
public static void Release<T>(ref T item) where T : class, new()
|
||||
{
|
||||
if (item != null)
|
||||
{
|
||||
ObjectPool<T>.Release(item);
|
||||
item = null;
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
public const string
|
||||
NotClearError = " They must be cleared before being released to the pool and not modified after that.";
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>
|
||||
/// 获取或创建List
|
||||
/// </summary>
|
||||
/// <remarks>Remember to <see cref="Release{T}(List{T})"/> 回收参见此方法</remarks>
|
||||
public static List<T> AcquireList<T>()
|
||||
{
|
||||
var list = ObjectPool<List<T>>.Acquire();
|
||||
EmuLogger.Assert(list.Count == 0, "A pooled list is not empty." + NotClearError);
|
||||
return list;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 回收List
|
||||
/// </summary>
|
||||
public static void Release<T>(List<T> list)
|
||||
{
|
||||
list.Clear();
|
||||
ObjectPool<List<T>>.Release(list);
|
||||
}
|
||||
/// <summary>
|
||||
/// 回收List内容
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="list"></param>
|
||||
public static void ReleaseListContent<T>(List<T> list) where T : class, new()
|
||||
{
|
||||
foreach (var item in list)
|
||||
{
|
||||
ObjectPool<T>.Release(item);
|
||||
}
|
||||
list.Clear();
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>
|
||||
/// 获取或创建HashSet
|
||||
/// </summary>
|
||||
public static HashSet<T> AcquireSet<T>()
|
||||
{
|
||||
var set = ObjectPool<HashSet<T>>.Acquire();
|
||||
EmuLogger.Assert(set.Count == 0, "A pooled set is not empty." + NotClearError);
|
||||
return set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 释放HashSet
|
||||
/// </summary>
|
||||
public static void Release<T>(HashSet<T> set)
|
||||
{
|
||||
set.Clear();
|
||||
ObjectPool<HashSet<T>>.Release(set);
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>
|
||||
/// 获取一个字符串StringBuilder
|
||||
/// </summary>
|
||||
/// <remarks>Remember to <see cref="Release(StringBuilder)"/>回收参见这个</remarks>
|
||||
public static StringBuilder AcquireStringBuilder()
|
||||
{
|
||||
var builder = ObjectPool<StringBuilder>.Acquire();
|
||||
EmuLogger.Assert(builder.Length == 0, $"A pooled {nameof(StringBuilder)} is not empty." + NotClearError);
|
||||
return builder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 回收 StringBuilder
|
||||
/// </summary>
|
||||
public static void Release(StringBuilder builder)
|
||||
{
|
||||
builder.Length = 0;
|
||||
ObjectPool<StringBuilder>.Release(builder);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 回收 StringBuilder
|
||||
/// </summary>
|
||||
public static string ReleaseToString(this StringBuilder builder)
|
||||
{
|
||||
var result = builder.ToString();
|
||||
Release(builder);
|
||||
return result;
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
private static class Cache<T>
|
||||
{
|
||||
public static readonly Dictionary<MethodInfo, KeyValuePair<Func<T>, T>>
|
||||
Results = new Dictionary<MethodInfo, KeyValuePair<Func<T>, T>>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 此方法主要用于频繁绘制缓存,比如说GUI绘制
|
||||
/// </summary>
|
||||
public static T GetCachedResult<T>(Func<T> function)
|
||||
{
|
||||
var method = function.Method;
|
||||
if (!Cache<T>.Results.TryGetValue(method, out var result))
|
||||
{
|
||||
|
||||
result = new KeyValuePair<Func<T>, T>(function, function());
|
||||
Cache<T>.Results.Add(method, result);
|
||||
}
|
||||
else if (result.Key != function)
|
||||
{
|
||||
EmuLogger.Log(
|
||||
$"{nameof(GetCachedResult)}<{typeof(T).Name}>" +
|
||||
$" was previously called on {method.Name} with a different target." +
|
||||
" This likely means that a new delegate is being passed into every call" +
|
||||
" so it can't actually return the same cached object.");
|
||||
}
|
||||
|
||||
return result.Value;
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
public static class Disposable
|
||||
{
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>
|
||||
/// Calls <see cref="ObjectPool{T}.Disposable.Acquire"/> to get a spare <see cref="List{T}"/> if
|
||||
/// </summary>
|
||||
public static IDisposable Acquire<T>(out T item)
|
||||
where T : class, new()
|
||||
=> ObjectPool<T>.Disposable.Acquire(out item);
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>
|
||||
/// Calls <see cref="ObjectPool{T}.Disposable.Acquire"/> to get a spare <see cref="List{T}"/> if
|
||||
/// </summary>
|
||||
public static IDisposable AcquireList<T>(out List<T> list)
|
||||
{
|
||||
var disposable = ObjectPool<List<T>>.Disposable.Acquire(out list, onRelease: (l) => l.Clear());
|
||||
EmuLogger.Assert(list.Count == 0, "A pooled list is not empty." + NotClearError);
|
||||
return disposable;
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>
|
||||
/// Calls <see cref="ObjectPool{T}.Disposable.Acquire"/> to get a spare <see cref="HashSet{T}"/> if
|
||||
/// </summary>
|
||||
public static IDisposable AcquireSet<T>(out HashSet<T> set)
|
||||
{
|
||||
var disposable = ObjectPool<HashSet<T>>.Disposable.Acquire(out set, onRelease: (s) => s.Clear());
|
||||
EmuLogger.Assert(set.Count == 0, "A pooled set is not empty." + NotClearError);
|
||||
return disposable;
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
}
|
||||
/************************************************************************************************************************/
|
||||
public static class ObjectPool<T> where T : class, new()
|
||||
{
|
||||
/************************************************************************************************************************/
|
||||
|
||||
private static readonly List<T>
|
||||
Items = new List<T>();
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>The number of spare items currently in the pool.</summary>
|
||||
public static int Count
|
||||
{
|
||||
get => Items.Count;
|
||||
set
|
||||
{
|
||||
var count = Items.Count;
|
||||
if (count < value)
|
||||
{
|
||||
if (Items.Capacity < value)
|
||||
Items.Capacity = Mathf.NextPowerOfTwo(value);
|
||||
|
||||
do
|
||||
{
|
||||
Items.Add(new T());
|
||||
count++;
|
||||
}
|
||||
while (count < value);
|
||||
|
||||
}
|
||||
else if (count > value)
|
||||
{
|
||||
Items.RemoveRange(value, count - value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>
|
||||
/// If the <see cref="Count"/> is less than the specified value, this method increases it to that value by
|
||||
/// creating new objects.
|
||||
/// </summary>
|
||||
public static void SetMinCount(int count)
|
||||
{
|
||||
if (Count < count)
|
||||
Count = count;
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>The <see cref="List{T}.Capacity"/> of the internal list of spare items.</summary>
|
||||
public static int Capacity
|
||||
{
|
||||
get => Items.Capacity;
|
||||
set
|
||||
{
|
||||
if (Items.Count > value)
|
||||
Items.RemoveRange(value, Items.Count - value);
|
||||
Items.Capacity = value;
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>Returns a spare item if there are any, or creates a new one.</summary>
|
||||
/// <remarks>Remember to <see cref="Release(T)"/> it when you are done.</remarks>
|
||||
public static T Acquire()
|
||||
{
|
||||
var count = Items.Count;
|
||||
if (count == 0)
|
||||
{
|
||||
return new T();
|
||||
}
|
||||
else
|
||||
{
|
||||
count--;
|
||||
var item = Items[count];
|
||||
Items.RemoveAt(count);
|
||||
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>Adds the `item` to the list of spares so it can be reused.</summary>
|
||||
public static void Release(T item)
|
||||
{
|
||||
Items.Add(item);
|
||||
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>Returns a description of the state of this pool.</summary>
|
||||
public static string GetDetails()
|
||||
{
|
||||
return
|
||||
$"{typeof(T).Name}" +
|
||||
$" ({nameof(Count)} = {Items.Count}" +
|
||||
$", {nameof(Capacity)} = {Items.Capacity}" +
|
||||
")";
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>
|
||||
/// An <see cref="IDisposable"/> system to allow pooled objects to be acquired and released within <c>using</c>
|
||||
/// statements instead of needing to manually release everything.
|
||||
/// </summary>
|
||||
public sealed class Disposable : IDisposable
|
||||
{
|
||||
/************************************************************************************************************************/
|
||||
|
||||
private static readonly List<Disposable> LazyStack = new List<Disposable>();
|
||||
|
||||
private static int _ActiveDisposables;
|
||||
|
||||
private T _Item;
|
||||
private Action<T> _OnRelease;
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
private Disposable() { }
|
||||
|
||||
/// <summary>
|
||||
/// Calls <see cref="ObjectPool{T}.Acquire"/> to set the `item` and returns an <see cref="IDisposable"/>
|
||||
/// that will call <see cref="Release(T)"/> on the `item` when disposed.
|
||||
/// </summary>
|
||||
public static IDisposable Acquire(out T item, Action<T> onRelease = null)
|
||||
{
|
||||
Disposable disposable;
|
||||
|
||||
if (LazyStack.Count <= _ActiveDisposables)
|
||||
{
|
||||
LazyStack.Add(disposable = new Disposable());
|
||||
}
|
||||
else
|
||||
{
|
||||
disposable = LazyStack[_ActiveDisposables];
|
||||
}
|
||||
|
||||
_ActiveDisposables++;
|
||||
|
||||
disposable._Item = item = ObjectPool<T>.Acquire();
|
||||
disposable._OnRelease = onRelease;
|
||||
return disposable;
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
void IDisposable.Dispose()
|
||||
{
|
||||
_OnRelease?.Invoke(_Item);
|
||||
Release(_Item);
|
||||
_ActiveDisposables--;
|
||||
}
|
||||
/************************************************************************************************************************/
|
||||
}
|
||||
}
|
||||
|
||||
#region ExtFunctions
|
||||
public struct PoolHandle<T> : IDisposable
|
||||
where T : class, new()
|
||||
{
|
||||
public T Ins;
|
||||
internal static PoolHandle<T> Create(T poolIns)
|
||||
{
|
||||
return new PoolHandle<T> { Ins = poolIns };
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
ObjectPoolAuto.Release<T>(Ins);
|
||||
}
|
||||
}
|
||||
public struct PoolListHandle<T> : IDisposable
|
||||
{
|
||||
public List<T> Ins;
|
||||
internal static PoolListHandle<T> Create(List<T> poolIns)
|
||||
{
|
||||
return new PoolListHandle<T> { Ins = poolIns };
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
ObjectPoolAuto.Release<T>(Ins);
|
||||
}
|
||||
}
|
||||
|
||||
public static PoolHandle<T> PoolScope<T>()
|
||||
where T : class, new()
|
||||
{
|
||||
return PoolHandle<T>.Create(ObjectPoolAuto.Acquire<T>());
|
||||
}
|
||||
public static PoolListHandle<T> PoolListScope<T>()
|
||||
{
|
||||
return PoolListHandle<T>.Create(ObjectPoolAuto.AcquireList<T>());
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
11
MAME.Unity/Assets/Plugins/UMAME/ObjectPoolAuto.cs.meta
Normal file
11
MAME.Unity/Assets/Plugins/UMAME/ObjectPoolAuto.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f22c2fa157c9e6045ad5307124c8a365
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -61,7 +61,10 @@ namespace cpu.nec
|
||||
{
|
||||
if (line >= 0 && line < 35)
|
||||
{
|
||||
Cpuint.lirq.Add(new irq(cpunum, line, state, vector, EmuTimer.get_current_time()));
|
||||
irq _irq = ObjectPoolAuto.Acquire<irq>();
|
||||
_irq.Init(cpunum, line, state, vector, EmuTimer.get_current_time());
|
||||
Cpuint.lirq.Add(_irq);
|
||||
//Cpuint.lirq.Add(new irq(cpunum, line, state, vector, EmuTimer.get_current_time()));
|
||||
int event_index = Cpuint.input_event_index[cpunum, line]++;
|
||||
if (event_index >= 35)
|
||||
{
|
||||
|
@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Numerics;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace MAME.Core
|
||||
@ -57,7 +58,7 @@ namespace MAME.Core
|
||||
{
|
||||
|
||||
}
|
||||
public irq(int _cpunum, int _line, LineState _state, int _vector, Atime _time)
|
||||
public void Init(int _cpunum, int _line, LineState _state, int _vector, Atime _time)
|
||||
{
|
||||
cpunum = _cpunum;
|
||||
line = _line;
|
||||
@ -134,7 +135,10 @@ namespace MAME.Core
|
||||
public static void cpunum_set_input_line(int cpunum, int line, LineState state)
|
||||
{
|
||||
int vector = (line >= 0 && line < 35) ? interrupt_vector[cpunum, line] : 0xff;
|
||||
lirq.Add(new irq(cpunum, line, state, vector, EmuTimer.get_current_time()));
|
||||
irq _irq = ObjectPoolAuto.Acquire<irq>();
|
||||
_irq.Init(cpunum, line, state, vector, EmuTimer.get_current_time());
|
||||
lirq.Add(_irq);
|
||||
//lirq.Add(new irq(cpunum, line, state, vector, EmuTimer.get_current_time()));
|
||||
Cpuexec.cpu[cpunum].cpunum_set_input_line_and_vector(cpunum, line, state, vector);
|
||||
}
|
||||
public static void cpunum_set_input_line_vector(int cpunum, int line, int vector)
|
||||
@ -149,13 +153,17 @@ namespace MAME.Core
|
||||
{
|
||||
if (line >= 0 && line < 35)
|
||||
{
|
||||
lirq.Add(new irq(cpunum, line, state, vector, EmuTimer.get_current_time()));
|
||||
irq _irq = ObjectPoolAuto.Acquire<irq>();
|
||||
_irq.Init(cpunum, line, state, vector, EmuTimer.get_current_time());
|
||||
lirq.Add(_irq);
|
||||
//lirq.Add(new irq(cpunum, line, state, vector, EmuTimer.get_current_time()));
|
||||
EmuTimer.timer_set_internal(EmuTimer.TIME_ACT.Cpuint_cpunum_empty_event_queue);
|
||||
}
|
||||
}
|
||||
public static void cpunum_empty_event_queue()
|
||||
{
|
||||
List<irq> lsirq = new List<irq>();
|
||||
//List<irq> lsirq = new List<irq>();
|
||||
List<irq> lsirq = ObjectPoolAuto.AcquireList<irq>();
|
||||
if (lirq.Count == 0)
|
||||
{
|
||||
int i1 = 1;
|
||||
@ -219,12 +227,14 @@ namespace MAME.Core
|
||||
foreach (irq irq1 in lsirq)
|
||||
{
|
||||
input_event_index[irq1.cpunum, irq1.line] = 0;
|
||||
ObjectPoolAuto.Release(irq1);
|
||||
lirq.Remove(irq1);
|
||||
}
|
||||
if (lirq.Count > 0)
|
||||
{
|
||||
int i1 = 1;
|
||||
}
|
||||
ObjectPoolAuto.Release(lsirq);
|
||||
}
|
||||
public static int cpu_irq_callback(int cpunum, int line)
|
||||
{
|
||||
@ -348,7 +358,9 @@ namespace MAME.Core
|
||||
lirq = new List<irq>();
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
lirq.Add(new irq());
|
||||
irq _irq = ObjectPoolAuto.Acquire<irq>();
|
||||
lirq.Add(_irq);
|
||||
//lirq.Add(new irq());
|
||||
lirq[i].cpunum = reader.ReadInt32();
|
||||
lirq[i].line = reader.ReadInt32();
|
||||
lirq[i].state = (LineState)reader.ReadInt32();
|
||||
|
@ -25,10 +25,6 @@ namespace MAME.Core
|
||||
public Atime period;
|
||||
public Atime start;
|
||||
public Atime expire;
|
||||
public emu_timer()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
public class emu_timer2
|
||||
{
|
||||
@ -502,16 +498,18 @@ namespace MAME.Core
|
||||
lt.Insert(i, timer1);
|
||||
}
|
||||
}
|
||||
|
||||
static List<emu_timer> timer_list_remove_lt1 = new List<emu_timer>();
|
||||
public static void timer_list_remove(emu_timer timer1)
|
||||
{
|
||||
if (timer1.action == TIME_ACT.Cpuint_cpunum_empty_event_queue || timer1.action == TIME_ACT.setvector)
|
||||
{
|
||||
List<emu_timer> lt1 = new List<emu_timer>();
|
||||
timer_list_remove_lt1.Clear();
|
||||
foreach (emu_timer et in lt)
|
||||
{
|
||||
if (et.action == timer1.action && Attotime.attotime_compare(et.expire, timer1.expire) == 0)
|
||||
{
|
||||
lt1.Add(et);
|
||||
timer_list_remove_lt1.Add(et);
|
||||
//lt.Remove(et);
|
||||
//break;
|
||||
}
|
||||
@ -524,7 +522,7 @@ namespace MAME.Core
|
||||
int i1 = 1;
|
||||
}
|
||||
}
|
||||
foreach (emu_timer et1 in lt1)
|
||||
foreach (emu_timer et1 in timer_list_remove_lt1)
|
||||
{
|
||||
lt.Remove(et1);
|
||||
}
|
||||
|
@ -145,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<ushort> span_neogeo_videoram = neogeo_videoram.AsSpan();
|
||||
// Span<int> span_bitmapbaseN_iBitmap = Video.bitmapbaseN[iBitmap].AsSpan();
|
||||
// Span<byte> span_sprite_gfx = sprite_gfx.AsSpan();
|
||||
// Span<int> span_pens = pens.AsSpan();
|
||||
// for (max_sprite_index = 95; max_sprite_index >= 0; max_sprite_index--)
|
||||
// {
|
||||
// if (span_neogeo_videoram[sprite_list_offset + max_sprite_index] != 0)
|
||||
// {
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// if (max_sprite_index != 95)
|
||||
// {
|
||||
// max_sprite_index = max_sprite_index + 1;
|
||||
// }
|
||||
// for (sprite_index = 0; sprite_index < max_sprite_index; sprite_index++)
|
||||
// {
|
||||
// sprite_number = span_neogeo_videoram[sprite_list_offset + sprite_index] & 0x1ff;
|
||||
// y_control = span_neogeo_videoram[0x8200 | sprite_number];
|
||||
// zoom_control = span_neogeo_videoram[0x8000 | sprite_number];
|
||||
// x_2 = span_neogeo_videoram[0x8400 | sprite_number];
|
||||
// code_2 = span_neogeo_videoram[sprite_number << 6];
|
||||
// if ((y_control & 0x40) != 0)
|
||||
// {
|
||||
// x = (x + zoom_x + 1) & 0x01ff;
|
||||
// zoom_x = (zoom_control >> 8) & 0x0f;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// y = 0x200 - (y_control >> 7);
|
||||
// x = span_neogeo_videoram[0x8400 | sprite_number] >> 7;
|
||||
// zoom_y = zoom_control & 0xff;
|
||||
// zoom_x = (zoom_control >> 8) & 0x0f;
|
||||
// rows = y_control & 0x3f;
|
||||
// }
|
||||
// if ((x >= 0x140) && (x <= 0x1f0))
|
||||
// {
|
||||
// continue;
|
||||
// }
|
||||
// if (sprite_on_scanline(scanline, y, rows))
|
||||
// {
|
||||
// sprite_line = (scanline - y) & 0x1ff;
|
||||
// zoom_line = sprite_line & 0xff;
|
||||
// invert = ((sprite_line & 0x100) != 0) ? true : false;
|
||||
// if (invert)
|
||||
// {
|
||||
// zoom_line ^= 0xff;
|
||||
// }
|
||||
// if (rows > 0x20)
|
||||
// {
|
||||
// zoom_line = zoom_line % ((zoom_y + 1) << 1);
|
||||
// if (zoom_line > zoom_y)
|
||||
// {
|
||||
// zoom_line = ((zoom_y + 1) << 1) - 1 - zoom_line;
|
||||
// invert = !invert;
|
||||
// }
|
||||
// }
|
||||
// sprite_y_and_tile = zoomyrom[(zoom_y << 8) | zoom_line];
|
||||
// sprite_y = sprite_y_and_tile & 0x0f;
|
||||
// tile = sprite_y_and_tile >> 4;
|
||||
// if (invert)
|
||||
// {
|
||||
// sprite_y ^= 0x0f;
|
||||
// tile ^= 0x1f;
|
||||
// }
|
||||
// attr_and_code_offs = (sprite_number << 6) | (tile << 1);
|
||||
// attr = span_neogeo_videoram[attr_and_code_offs + 1];
|
||||
// code = ((attr << 12) & 0x70000) | span_neogeo_videoram[attr_and_code_offs];
|
||||
// if (auto_animation_disabled == 0)
|
||||
// {
|
||||
// if ((attr & 0x0008) != 0)
|
||||
// {
|
||||
// code = (code & ~0x07) | (auto_animation_counter & 0x07);
|
||||
// }
|
||||
// else if ((attr & 0x0004) != 0)
|
||||
// {
|
||||
// code = (code & ~0x03) | (auto_animation_counter & 0x03);
|
||||
// }
|
||||
// }
|
||||
// if ((attr & 0x0002) != 0)
|
||||
// {
|
||||
// sprite_y ^= 0x0f;
|
||||
// }
|
||||
// zoom_x_table_offset = 0;
|
||||
// gfx_offset = (int)(((code << 8) | (sprite_y << 4)) & sprite_gfx_address_mask);
|
||||
// line_pens_offset = attr >> 8 << 4;
|
||||
// if ((attr & 0x0001) != 0)
|
||||
// {
|
||||
// gfx_offset = gfx_offset + 0x0f;
|
||||
// x_inc = -1;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// x_inc = 1;
|
||||
// }
|
||||
// int pixel_addr_offsetx, pixel_addr_offsety;
|
||||
// if (x <= 0x01f0)
|
||||
// {
|
||||
// int i;
|
||||
// pixel_addr_offsetx = x + NEOGEO_HBEND;
|
||||
// pixel_addr_offsety = scanline;
|
||||
// for (i = 0; i < 0x10; i++)
|
||||
// {
|
||||
// if (zoom_x_tables[zoom_x, zoom_x_table_offset] != 0)
|
||||
// {
|
||||
// //if (sprite_gfx[gfx_offset] != 0)
|
||||
// if (span_sprite_gfx[gfx_offset] != 0)
|
||||
// {
|
||||
// //Video.bitmapbaseN[iBitmap][pixel_addr_offsety * 384 + pixel_addr_offsetx] = pens[line_pens_offset + sprite_gfx[gfx_offset]];
|
||||
// span_bitmapbaseN_iBitmap[pixel_addr_offsety * 384 + pixel_addr_offsetx] = span_pens[line_pens_offset + span_sprite_gfx[gfx_offset]];
|
||||
// }
|
||||
// pixel_addr_offsetx++;
|
||||
// }
|
||||
// zoom_x_table_offset++;
|
||||
// gfx_offset += x_inc;
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// int i;
|
||||
// int x_save = x;
|
||||
// pixel_addr_offsetx = NEOGEO_HBEND;
|
||||
// pixel_addr_offsety = scanline;
|
||||
// for (i = 0; i < 0x10; i++)
|
||||
// {
|
||||
// if (zoom_x_tables[zoom_x, zoom_x_table_offset] != 0)
|
||||
// {
|
||||
// if (x >= 0x200)
|
||||
// {
|
||||
// //if (sprite_gfx[gfx_offset] != 0)
|
||||
// if (span_sprite_gfx[gfx_offset] != 0)
|
||||
// {
|
||||
// //Video.bitmapbaseN[iBitmap][pixel_addr_offsety * 384 + pixel_addr_offsetx] = pens[line_pens_offset + sprite_gfx[gfx_offset]];
|
||||
// span_bitmapbaseN_iBitmap[pixel_addr_offsety * 384 + pixel_addr_offsetx] = span_pens[line_pens_offset + span_sprite_gfx[gfx_offset]];
|
||||
// }
|
||||
// pixel_addr_offsetx++;
|
||||
// }
|
||||
// x++;
|
||||
// }
|
||||
// zoom_x_table_offset++;
|
||||
// gfx_offset += x_inc;
|
||||
// }
|
||||
// x = x_save;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
/// <summary>
|
||||
/// draw_sprites (Unsafa 尝试提升效率)
|
||||
/// </summary>
|
||||
/// <param name="iBitmap"></param>
|
||||
/// <param name="scanline"></param>
|
||||
unsafe private static void draw_sprites(int iBitmap, int scanline)
|
||||
{
|
||||
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;
|
||||
|
@ -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<ushort> span_pgm_spritebufferram = pgm_spritebufferram.AsSpan();
|
||||
// int xpos = span_pgm_spritebufferram[pgm_sprite_source_offset + 0] & 0x07ff;
|
||||
// int ypos = span_pgm_spritebufferram[pgm_sprite_source_offset + 1] & 0x03ff;
|
||||
// int xzom = (span_pgm_spritebufferram[pgm_sprite_source_offset + 0] & 0x7800) >> 11;
|
||||
// int xgrow = (span_pgm_spritebufferram[pgm_sprite_source_offset + 0] & 0x8000) >> 15;
|
||||
// int yzom = (span_pgm_spritebufferram[pgm_sprite_source_offset + 1] & 0x7800) >> 11;
|
||||
// int ygrow = (span_pgm_spritebufferram[pgm_sprite_source_offset + 1] & 0x8000) >> 15;
|
||||
// int palt = (span_pgm_spritebufferram[pgm_sprite_source_offset + 2] & 0x1f00) >> 8;
|
||||
// int flip = (span_pgm_spritebufferram[pgm_sprite_source_offset + 2] & 0x6000) >> 13;
|
||||
// int boff = ((span_pgm_spritebufferram[pgm_sprite_source_offset + 2] & 0x007f) << 16) | (span_pgm_spritebufferram[pgm_sprite_source_offset + 3] & 0xffff);
|
||||
// int wide = (span_pgm_spritebufferram[pgm_sprite_source_offset + 4] & 0x7e00) >> 9;
|
||||
// int high = span_pgm_spritebufferram[pgm_sprite_source_offset + 4] & 0x01ff;
|
||||
// int pri = (span_pgm_spritebufferram[pgm_sprite_source_offset + 2] & 0x0080) >> 7;
|
||||
|
||||
|
||||
// //int xpos = pgm_spritebufferram[pgm_sprite_source_offset + 0] & 0x07ff;
|
||||
// //int ypos = pgm_spritebufferram[pgm_sprite_source_offset + 1] & 0x03ff;
|
||||
// //int xzom = (pgm_spritebufferram[pgm_sprite_source_offset + 0] & 0x7800) >> 11;
|
||||
// //int xgrow = (pgm_spritebufferram[pgm_sprite_source_offset + 0] & 0x8000) >> 15;
|
||||
// //int yzom = (pgm_spritebufferram[pgm_sprite_source_offset + 1] & 0x7800) >> 11;
|
||||
// //int ygrow = (pgm_spritebufferram[pgm_sprite_source_offset + 1] & 0x8000) >> 15;
|
||||
// //int palt = (pgm_spritebufferram[pgm_sprite_source_offset + 2] & 0x1f00) >> 8;
|
||||
// //int flip = (pgm_spritebufferram[pgm_sprite_source_offset + 2] & 0x6000) >> 13;
|
||||
// //int boff = ((pgm_spritebufferram[pgm_sprite_source_offset + 2] & 0x007f) << 16) | (pgm_spritebufferram[pgm_sprite_source_offset + 3] & 0xffff);
|
||||
// //int wide = (pgm_spritebufferram[pgm_sprite_source_offset + 4] & 0x7e00) >> 9;
|
||||
// //int high = pgm_spritebufferram[pgm_sprite_source_offset + 4] & 0x01ff;
|
||||
// //int pri = (pgm_spritebufferram[pgm_sprite_source_offset + 2] & 0x0080) >> 7;
|
||||
|
||||
// int xzoom, yzoom;
|
||||
// int pgm_sprite_zoomtable_offset = 0x1000;
|
||||
// if (xgrow != 0)
|
||||
// {
|
||||
// xzom = 0x10 - xzom;
|
||||
// }
|
||||
// if (ygrow != 0)
|
||||
// {
|
||||
// yzom = 0x10 - yzom;
|
||||
// }
|
||||
// Span<byte> span_pgm_videoregs = pgm_videoregs.AsSpan();
|
||||
// xzoom = ((span_pgm_videoregs[pgm_sprite_zoomtable_offset + xzom * 4] * 0x100 + span_pgm_videoregs[pgm_sprite_zoomtable_offset + xzom * 4 + 1]) << 16) | (span_pgm_videoregs[pgm_sprite_zoomtable_offset + xzom * 4 + 2] * 0x100 + span_pgm_videoregs[pgm_sprite_zoomtable_offset + xzom * 4 + 3]);
|
||||
// yzoom = ((span_pgm_videoregs[pgm_sprite_zoomtable_offset + yzom * 4] * 0x100 + span_pgm_videoregs[pgm_sprite_zoomtable_offset + yzom * 4 + 1]) << 16) | (span_pgm_videoregs[pgm_sprite_zoomtable_offset + yzom * 4 + 2] * 0x100 + span_pgm_videoregs[pgm_sprite_zoomtable_offset + yzom * 4 + 3]);
|
||||
|
||||
// //xzoom = ((pgm_videoregs[pgm_sprite_zoomtable_offset + xzom * 4] * 0x100 + pgm_videoregs[pgm_sprite_zoomtable_offset + xzom * 4 + 1]) << 16) | (pgm_videoregs[pgm_sprite_zoomtable_offset + xzom * 4 + 2] * 0x100 + pgm_videoregs[pgm_sprite_zoomtable_offset + xzom * 4 + 3]);
|
||||
// //yzoom = ((pgm_videoregs[pgm_sprite_zoomtable_offset + yzom * 4] * 0x100 + pgm_videoregs[pgm_sprite_zoomtable_offset + yzom * 4 + 1]) << 16) | (pgm_videoregs[pgm_sprite_zoomtable_offset + yzom * 4 + 2] * 0x100 + pgm_videoregs[pgm_sprite_zoomtable_offset + yzom * 4 + 3]);
|
||||
// boff *= 2;
|
||||
// if (xpos > 0x3ff)
|
||||
// xpos -= 0x800;
|
||||
// if (ypos > 0x1ff)
|
||||
// ypos -= 0x400;
|
||||
// if (high == 0)
|
||||
// break;
|
||||
// if ((priority == 1) && (pri == 0))
|
||||
// break;
|
||||
// draw_sprite_new_zoomed(wide, high, xpos, ypos, palt, boff, flip, xzoom, xgrow, yzoom, ygrow);
|
||||
// pgm_sprite_source_offset += 5;
|
||||
// }
|
||||
//}
|
||||
private static void pgm_tx_videoram_w(int offset, byte data)
|
||||
{
|
||||
int col, row;
|
||||
|
@ -115,6 +115,8 @@ namespace MAME.Core
|
||||
i1++;
|
||||
}
|
||||
}
|
||||
//TODO 移动到这里,但是大小,还需要考虑
|
||||
static short[] sample_data = new short[10000];
|
||||
public static void okim6295_update(int offset, int length)
|
||||
{
|
||||
int i;
|
||||
@ -124,7 +126,8 @@ namespace MAME.Core
|
||||
}
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
short[] sample_data = new short[10000];
|
||||
//不每次new,避免GC,排除问题。待验证影响
|
||||
//short[] sample_data = new short[10000];
|
||||
int remaining = length;
|
||||
while (remaining != 0)
|
||||
{
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user