From b460bc6f3e9e75047262af116aaae78ea082d672 Mon Sep 17 00:00:00 2001
From: Phillip Stephens <antidote.crk@gmail.com>
Date: Tue, 21 Feb 2023 08:39:57 -0800
Subject: [PATCH] Nearly match hardware.c (hwFlushStream non-matching), and
 link

Former-commit-id: d2ca30a5ced23b84b86d4aecd90a2e816c89eccc
---
 configure.py               |   2 +-
 include/musyx/musyx_priv.h |   1 +
 src/musyx/hardware.c       | 106 ++++++++++++++++++++++++++++++++++---
 3 files changed, 101 insertions(+), 8 deletions(-)

diff --git a/configure.py b/configure.py
index 11eba264..b0472ac6 100755
--- a/configure.py
+++ b/configure.py
@@ -943,7 +943,7 @@ LIBS = [
             ["musyx/snd_math", True],
             ["musyx/snd_midictrl", False],
             ["musyx/snd_service", True],
-            ["musyx/hardware", False],
+            ["musyx/hardware", True],
             "musyx/hw_aramdma",
             ["musyx/dsp_import", True],
             ["musyx/hw_dolphin", True],
diff --git a/include/musyx/musyx_priv.h b/include/musyx/musyx_priv.h
index 197505a8..7865a8fa 100644
--- a/include/musyx/musyx_priv.h
+++ b/include/musyx/musyx_priv.h
@@ -680,6 +680,7 @@ void aramUploadData(void* mram, unsigned long aram, unsigned long len, unsigned
                     void (*callback)(unsigned long), unsigned long user);
 void aramFreeStreamBuffer(u8 id);
 void* aramStoreData(void* src, unsigned long len);
+void aramRemoveData(void * aram, unsigned long len);
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/musyx/hardware.c b/src/musyx/hardware.c
index 20ad5e14..98804764 100644
--- a/src/musyx/hardware.c
+++ b/src/musyx/hardware.c
@@ -388,8 +388,36 @@ bool hwRemoveInput(u8 studio, SND_STUDIO_INPUT* in_desc) {
 
 void hwChangeStudio(u32 v, u8 studio) { salReconnectVoice(&dspVoice[v], studio); }
 
-u32 hwGetPos(u32 v) {}
+u32 hwGetPos(u32 v) {
+  unsigned long pos; // r31
+  unsigned long off; // r30
+  if (dspVoice[v].state != 2) {
+    return 0;
+  }
 
+  switch (dspVoice[v].smp_info.compType) {
+  case 0:
+  case 1:
+  case 4:
+  case 5:
+    pos = ((dspVoice[v].currentAddr - (u32)dspVoice[v].smp_info.addr * 2) / 16) * 14;
+    off = dspVoice[v].currentAddr & 0xf;
+    if (off >= 2) {
+      pos += off - 2;
+    }
+    break;
+  case 3:
+    pos = dspVoice[v].currentAddr - (u32)dspVoice[v].smp_info.addr;
+    break;
+  case 2:
+    pos = dspVoice[v].currentAddr - ((u32)dspVoice[v].smp_info.addr / 2);
+    break;
+  }
+
+  return pos;
+}
+
+#if NONMATCHING
 void hwFlushStream(void* base, unsigned long offset, unsigned long bytes,
                    unsigned char hwStreamHandle, void (*callback)(unsigned long),
                    unsigned long user) {
@@ -401,7 +429,57 @@ void hwFlushStream(void* base, unsigned long offset, unsigned long bytes,
   aramUploadData((void*)((u32)base + (offset & ~31)), aram + (offset & ~31),
                  bytes + ((offset & 31) + 31) & ~31, 1, callback, user);
 }
-
+#else
+/* clang-format off */
+#pragma push
+#pragma optimization_level 0
+#pragma optimizewithasm off
+extern void _savegpr_25();
+extern void _restgpr_25();
+asm void hwFlushStream(void* base, unsigned long offset, unsigned long bytes,
+                   unsigned char hwStreamHandle, void (*callback)(unsigned long),
+                   unsigned long user) {
+  nofralloc
+  stwu r1, -0x30(r1)
+  mflr r0
+  stw r0, 0x34(r1)
+  addi r11, r1, 0x30
+  bl _savegpr_25
+  mr r25, r3
+  mr r29, r4
+  mr r26, r5
+  mr r27, r7
+  mr r28, r8
+  mr r3, r6
+  addi r4, r1, 8
+  bl aramGetStreamBufferAddress
+  clrlwi r0, r29, 0x1b
+  rlwinm r30, r29, 0, 0, 0x1a
+  add r26, r26, r0
+  mr r31, r3
+  addi r0, r26, 0x1f
+  add r29, r25, r30
+  rlwinm r26, r0, 0, 0, 0x1a
+  mr r3, r29
+  mr r4, r26
+  bl DCStoreRange
+  mr r3, r29
+  mr r5, r26
+  mr r7, r27
+  mr r8, r28
+  add r4, r31, r30
+  li r6, 1
+  bl aramUploadData
+  addi r11, r1, 0x30
+  bl _restgpr_25
+  lwz r0, 0x34(r1)
+  mtlr r0
+  addi r1, r1, 0x30
+  blr
+}
+#pragma pop
+/* clang-format on */
+#endif
 u32 hwInitStream(u32 len) { return aramAllocateStreamBuffer(len); }
 
 void hwExitStream(u8 id) { aramFreeStreamBuffer(id); }
@@ -418,15 +496,27 @@ void hwInitSampleMem(u32 baseAddr, u32 length) { aramInit(length); }
 
 void hwExitSampleMem() { aramExit(); }
 
-u32 convert_length(u32 len, u8 type) {}
+u32 convert_length(u32 len, u8 type) {
+  switch (type) {
+  case 0:
+  case 1:
+  case 4:
+  case 5:
+    return (((u32)((len + 0xD) / 0xe))) * 8;
+  case 2:
+    return len * 2;
+  }
+  return len;
+}
 
 void hwSaveSample(void* header, void* data) {
   u32 len;
   u8 type;
 
-  header = ((u32*)header);
-  len = ((u32*)header)[0];
-  type = ((u32*)header)[1] >> 0x18;
+  header = (void*)((u32*)header)[0];
+  header = (void*)((u32*)header)[1];
+  len = (u32)header & 0xFFFFFF;
+  type = (u32)header >> 0x18;
   *((u32*)data) = (u32)aramStoreData((void*)*((u32*)data), convert_length(len, type));
 }
 
@@ -434,7 +524,9 @@ void hwSetSaveSampleCallback(ARAMUploadCallback callback, unsigned long chunckSi
   aramSetUploadCallback(callback);
 }
 
-void hwRemoveSample(void* header, void* data) {}
+void hwRemoveSample(void* header, void* data) {
+  aramRemoveData(data, convert_length(((u32*)header)[1] & 0xFFFFFF, ((u32*)header)[1] >> 0x18));
+}
 
 void hwSyncSampleMem() { aramSyncTransferQueue(); }