mirror of
https://github.com/captain-amygdala/pistorm.git
synced 2026-04-25 03:35:03 +00:00
Incredibly questionable virtual AHI device support
To test this, install AHI (probably preferably 4.18) and copy pi-ahi.audio to DEVS:AHI and PI-AHI to DEVS:AudioModes. The IRQ trigger magically doesn't work, so this all runs of vertical blank... meaning that it stops working pretty much the instant you try to use it in an RTG mode. Not very useful at the moment, but I need to take a break from working on this to do a bunch of work.
This commit is contained in:
10
emulator.c
10
emulator.c
@@ -15,6 +15,8 @@
|
||||
#include "platforms/amiga/piscsi/piscsi-enums.h"
|
||||
#include "platforms/amiga/net/pi-net.h"
|
||||
#include "platforms/amiga/net/pi-net-enums.h"
|
||||
#include "platforms/amiga/ahi/pi_ahi.h"
|
||||
#include "platforms/amiga/ahi/pi-ahi-enums.h"
|
||||
#include "platforms/amiga/pistorm-dev/pistorm-dev.h"
|
||||
#include "platforms/amiga/pistorm-dev/pistorm-dev-enums.h"
|
||||
#include "gpio/ps_protocol.h"
|
||||
@@ -915,6 +917,10 @@ static inline int32_t platform_read_check(uint8_t type, uint32_t addr, uint32_t
|
||||
*res = rtg_read((addr & 0x0FFFFFFF), type);
|
||||
return 1;
|
||||
}
|
||||
if (addr >= PI_AHI_OFFSET && addr < PI_AHI_UPPER) {
|
||||
*res = handle_pi_ahi_read(addr, type);
|
||||
return 1;
|
||||
}
|
||||
if (custom_read_amiga(cfg, addr, &target, type) != -1) {
|
||||
*res = target;
|
||||
return 1;
|
||||
@@ -1097,6 +1103,10 @@ static inline int32_t platform_write_check(uint8_t type, uint32_t addr, uint32_t
|
||||
rtg_write((addr & 0x0FFFFFFF), val, type);
|
||||
return 1;
|
||||
}
|
||||
if (addr >= PI_AHI_OFFSET && addr < PI_AHI_UPPER) {
|
||||
handle_pi_ahi_write(addr, val, type);
|
||||
return 1;
|
||||
}
|
||||
if (custom_write_amiga(cfg, addr, val, type) != -1) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -29,4 +29,6 @@ void m68k_write_memory_8(unsigned int address, unsigned int value);
|
||||
void m68k_write_memory_16(unsigned int address, unsigned int value);
|
||||
void m68k_write_memory_32(unsigned int address, unsigned int value);
|
||||
|
||||
void stop_cpu_emulation(uint8_t disasm_cur);
|
||||
|
||||
#endif /* _EMULATOR_H */
|
||||
|
||||
BIN
platforms/amiga/ahi/ahi_driver_amiga/PI-AHI
Normal file
BIN
platforms/amiga/ahi/ahi_driver_amiga/PI-AHI
Normal file
Binary file not shown.
2
platforms/amiga/ahi/ahi_driver_amiga/build.sh
Normal file
2
platforms/amiga/ahi/ahi_driver_amiga/build.sh
Normal file
@@ -0,0 +1,2 @@
|
||||
vasmm68k_mot -quiet -phxass -Fhunk -m68020 -o PI-AHI prefsfile.a -I$VBCC/NDK39/include/include_i
|
||||
m68k-amigaos-gcc pi-ahi.c -O2 -o pi-ahi.audio -Wall -Wextra -Wno-unused-parameter -nostartfiles -m68020
|
||||
BIN
platforms/amiga/ahi/ahi_driver_amiga/pi-ahi.audio
Normal file
BIN
platforms/amiga/ahi/ahi_driver_amiga/pi-ahi.audio
Normal file
Binary file not shown.
757
platforms/amiga/ahi/ahi_driver_amiga/pi-ahi.c
Normal file
757
platforms/amiga/ahi/ahi_driver_amiga/pi-ahi.c
Normal file
@@ -0,0 +1,757 @@
|
||||
|
||||
#include <exec/exec.h>
|
||||
|
||||
#include <graphics/gfx.h>
|
||||
#include <graphics/gfxbase.h>
|
||||
#include <graphics/view.h>
|
||||
#include <proto/graphics.h>
|
||||
#include <clib/graphics_protos.h>
|
||||
|
||||
#include <dos/dos.h>
|
||||
#include <dos/dostags.h>
|
||||
|
||||
#include <proto/exec.h>
|
||||
#include <proto/dos.h>
|
||||
#include <proto/intuition.h>
|
||||
#include <proto/utility.h>
|
||||
|
||||
#include <hardware/intbits.h>
|
||||
|
||||
//#include <proto/ahi.h>
|
||||
#include <proto/ahi_sub.h>
|
||||
#include <clib/ahi_sub_protos.h>
|
||||
#include <clib/debug_protos.h>
|
||||
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "../pi-ahi-enums.h"
|
||||
#include "pi-ahi.h"
|
||||
|
||||
#define STR(s) #s
|
||||
#define XSTR(s) STR(s)
|
||||
|
||||
#define DEVICE_NAME "pi-ahi.audio"
|
||||
#define DEVICE_DATE "(16 Aug 2021)"
|
||||
#define DEVICE_ID_STRING "Pi-AHI " XSTR(DEVICE_VERSION) "." XSTR(DEVICE_REVISION) " " DEVICE_DATE
|
||||
#define DEVICE_VERSION 4
|
||||
#define DEVICE_REVISION 14
|
||||
#define DEVICE_PRIORITY 0
|
||||
|
||||
struct ExecBase *SysBase;
|
||||
struct UtilityBase *UtilityBase;
|
||||
struct Library *AHIsubBase = NULL;
|
||||
struct DosLibrary *DOSBase = NULL;
|
||||
struct GfxBase *GraphicsBase = NULL;
|
||||
|
||||
int __attribute__((no_reorder)) _start()
|
||||
{
|
||||
WRITESHORT(AHI_DEBUGMSG, 111);
|
||||
return -1;
|
||||
}
|
||||
|
||||
asm("romtag: \n"
|
||||
" dc.w "XSTR(RTC_MATCHWORD)" \n"
|
||||
" dc.l romtag \n"
|
||||
" dc.l endcode \n"
|
||||
" dc.b "XSTR(RTF_AUTOINIT)" \n"
|
||||
" dc.b "XSTR(DEVICE_VERSION)" \n"
|
||||
" dc.b "XSTR(NT_LIBRARY)" \n"
|
||||
" dc.b "XSTR(DEVICE_PRIORITY)" \n"
|
||||
" dc.l _device_name \n"
|
||||
" dc.l _device_id_string \n"
|
||||
" dc.l _auto_init_tables \n"
|
||||
"endcode: \n");
|
||||
|
||||
|
||||
const char device_name[] = DEVICE_NAME;
|
||||
const char device_id_string[] = DEVICE_ID_STRING;
|
||||
|
||||
struct pi_ahi *pi_ahi_base = NULL;
|
||||
|
||||
#define debug(...)
|
||||
#define debugval(...)
|
||||
//#define KPrintF(...)
|
||||
//#define KPrintF(a) kprintf((CONST_STRPTR)a)
|
||||
//#define debug(c, v) WRITESHORT(c, v)
|
||||
|
||||
//#define debugmsg(...)
|
||||
//#define debugbyte(...)
|
||||
//#define debugshort(...)
|
||||
//#define debuglong(...)
|
||||
#define debugmsg(v) WRITESHORT(AHI_DEBUGMSG, v)
|
||||
#define debugbyte(c, v) WRITEBYTE(c, v)
|
||||
#define debugshort(c, v) WRITESHORT(c, v)
|
||||
#define debuglong(c, v) WRITELONG(c, v)
|
||||
|
||||
static uint32_t __attribute__((used)) init (BPTR seg_list asm("a0"), struct Library *dev asm("d0"))
|
||||
{
|
||||
SysBase = *(struct ExecBase **)4L;
|
||||
|
||||
if (pi_ahi_base != NULL) {
|
||||
debugmsg(101);
|
||||
return 0;
|
||||
}
|
||||
|
||||
debuglong(AHI_U321, (uint32_t)dev);
|
||||
debugmsg(1);
|
||||
|
||||
char prefs[10] = "0";
|
||||
if (prefs[0] == '0') {} // TODO: prefs?
|
||||
|
||||
debugmsg(103);
|
||||
if(!(DOSBase = (struct DosLibrary *)OpenLibrary((STRPTR)"dos.library",0)))
|
||||
return 0;
|
||||
|
||||
if(!(UtilityBase = (struct UtilityBase *)OpenLibrary((STRPTR)"utility.library",0)))
|
||||
return 0;
|
||||
|
||||
if (!pi_ahi_base) {
|
||||
debugmsg(102);
|
||||
pi_ahi_base = AllocVec(sizeof(struct pi_ahi), MEMF_PUBLIC | MEMF_CLEAR);
|
||||
pi_ahi_base->ahi_base = dev;
|
||||
AHIsubBase = dev;
|
||||
}
|
||||
|
||||
debugmsg(104);
|
||||
|
||||
return (uint32_t)dev;
|
||||
}
|
||||
|
||||
static uint8_t* __attribute__((used)) expunge(struct Library *libbase asm("a6"))
|
||||
{
|
||||
debugmsg(999);
|
||||
|
||||
if(DOSBase) { CloseLibrary((struct Library *)DOSBase); DOSBase = NULL; }
|
||||
if(UtilityBase) { CloseLibrary((struct Library *)UtilityBase); UtilityBase = NULL; }
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t __attribute__((used)) null()
|
||||
{
|
||||
debugmsg(998);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __attribute__((used)) open(struct Library *dev asm("a6"), struct IORequest *iotd asm("a1"), uint32_t num asm("d0"), uint32_t flags asm("d1"))
|
||||
{
|
||||
debugmsg(2);
|
||||
debugmsg((uint32_t)dev);
|
||||
|
||||
if (!AHIsubBase) {
|
||||
debugmsg(201);
|
||||
AHIsubBase = dev;
|
||||
}
|
||||
|
||||
iotd->io_Error = 0;
|
||||
dev->lib_OpenCnt++;
|
||||
}
|
||||
|
||||
static uint8_t* __attribute__((used)) close(struct Library *dev asm("a6"), struct IORequest *iotd asm("a1"))
|
||||
{
|
||||
debugmsg(3);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __attribute__((used)) begin_io(struct Library *dev asm("a6"), struct IORequest *io asm("a1"))
|
||||
{
|
||||
debugmsg(4);
|
||||
if (pi_ahi_base == NULL || io == NULL)
|
||||
return;
|
||||
|
||||
if (!(io->io_Flags & IOF_QUICK)) {
|
||||
ReplyMsg(&io->io_Message);
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t __attribute__((used)) abort_io(struct Library *dev asm("a6"), struct IORequest *io asm("a1"))
|
||||
{
|
||||
debugmsg(5);
|
||||
if (!io) return IOERR_NOCMD;
|
||||
io->io_Error = IOERR_ABORTED;
|
||||
|
||||
return IOERR_ABORTED;
|
||||
}
|
||||
|
||||
static uint32_t __attribute__((used)) SoundFunc(struct Hook *hook asm("a0"), struct AHIAudioCtrlDrv *actrl asm("a2"), struct AHISoundMessage *chan asm("a1"))
|
||||
{
|
||||
debugmsg(9992);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t __attribute__((used)) PlayFunc(struct pi_ahi *ahi_data asm("a1")) {
|
||||
debugmsg(21);
|
||||
/*uint16_t intchk = READSHORT(AHI_INTCHK);
|
||||
if (intchk) {
|
||||
WRITESHORT(AHI_INTCHK, 1);
|
||||
if (!ahi_data->disable_cnt && ahi_data->slave_process) {
|
||||
WRITESHORT(AHI_INTCHK, 2);*/
|
||||
Signal((struct Task *)ahi_data->slave_process, 1L << ahi_data->play_signal);
|
||||
/*}
|
||||
return 1;
|
||||
} else {
|
||||
WRITESHORT(AHI_INTCHK, 3);
|
||||
}*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __attribute__((used)) MixFunc() {
|
||||
struct pi_ahi *ahi_data = pi_ahi_base;
|
||||
debugmsg(22);
|
||||
}
|
||||
|
||||
static void SlaveProcess()
|
||||
{
|
||||
struct Process *me = (struct Process *) FindTask(NULL);
|
||||
struct pi_ahi *ahi_data = pi_ahi_base;
|
||||
struct AHIAudioCtrlDrv *AudioCtrl = ahi_data->audioctrl;
|
||||
debuglong(AHI_U321, (uint32_t)ahi_data);
|
||||
debuglong(AHI_U322, (uint32_t)AudioCtrl->ahiac_PlayerFunc);
|
||||
debuglong(AHI_U323, AudioCtrl->ahiac_PlayerFreq);
|
||||
debuglong(AHI_U324, (uint32_t)AudioCtrl->ahiac_PreTimer);
|
||||
debugmsg(20);
|
||||
|
||||
uint32_t cur_buf = 0;
|
||||
|
||||
if (me) {} // TODO: Do something with me.
|
||||
|
||||
ahi_data->flags &= ~(1 | 2);
|
||||
|
||||
ahi_data->slave_signal = AllocSignal(-1);
|
||||
ahi_data->play_signal = AllocSignal(-1);
|
||||
ahi_data->mix_signal = AllocSignal(-1);
|
||||
|
||||
if((ahi_data->slave_signal != -1) && (ahi_data->play_signal != -1) && (ahi_data->mix_signal != -1)) {
|
||||
// Tell Master we're alive
|
||||
Signal(ahi_data->t_master, 1L << ahi_data->master_signal);
|
||||
|
||||
//AudioCtrl->ahiac_SoundFunc->h_Entry = (void *)SoundFunc;
|
||||
|
||||
for(;;) {
|
||||
uint32_t signalset;
|
||||
|
||||
debugmsg(2004);
|
||||
signalset = Wait((1L << ahi_data->slave_signal) | (1L << ahi_data->play_signal) | (1L << ahi_data->mix_signal));
|
||||
|
||||
if(signalset & (1L << ahi_data->slave_signal)) {
|
||||
debugmsg(2002);
|
||||
break;
|
||||
}
|
||||
|
||||
if(signalset & (1L << ahi_data->play_signal)) {
|
||||
//StartPlaying(AudioCtrl, me);
|
||||
debuglong(AHI_U321, AudioCtrl->ahiac_BuffSamples);
|
||||
debugmsg(2001);
|
||||
if (AudioCtrl->ahiac_PreTimer && AudioCtrl->ahiac_MixerFunc) {
|
||||
CallHookPkt(AudioCtrl->ahiac_PlayerFunc, AudioCtrl, NULL);
|
||||
if(!((*AudioCtrl->ahiac_PreTimer)())) {
|
||||
CallHookPkt(AudioCtrl->ahiac_MixerFunc, AudioCtrl, ahi_data->mix_buf[cur_buf]);
|
||||
WRITELONG(AHI_U321, AudioCtrl->ahiac_BuffSamples);
|
||||
WRITELONG(AHI_U322, AudioCtrl->ahiac_MixFreq);
|
||||
WRITELONG(AHI_U323, AudioCtrl->ahiac_Channels);
|
||||
WRITELONG(AHI_U324, AudioCtrl->ahiac_BuffType);
|
||||
WRITELONG(AHI_ADDR2, AudioCtrl->ahiac_PlayerFreq);
|
||||
WRITELONG(AHI_ADDR1, (uint32_t)ahi_data->mix_buf[cur_buf]);
|
||||
WRITESHORT(AHI_COMMAND, AHI_CMD_PLAY);
|
||||
cur_buf++;
|
||||
if (cur_buf == 8)
|
||||
cur_buf = 0;
|
||||
}
|
||||
(*AudioCtrl->ahiac_PostTimer)();
|
||||
} else {
|
||||
debugmsg(2002);
|
||||
}
|
||||
debugmsg(2005);
|
||||
}
|
||||
|
||||
if(signalset & (1L << ahi_data->mix_signal)) {
|
||||
// This never really happens
|
||||
}
|
||||
}
|
||||
} else {
|
||||
debugmsg(2006);
|
||||
}
|
||||
|
||||
ahi_data->flags &= ~(1 | 2);
|
||||
|
||||
Forbid();
|
||||
FreeSignal(ahi_data->slave_signal); ahi_data->slave_signal = -1;
|
||||
FreeSignal(ahi_data->play_signal); ahi_data->play_signal = -1;
|
||||
FreeSignal(ahi_data->mix_signal); ahi_data->mix_signal = -1;
|
||||
|
||||
ahi_data->slave_process = NULL;
|
||||
Signal((struct Task *)ahi_data->t_master, 1L << ahi_data->master_signal);
|
||||
}
|
||||
|
||||
static uint32_t __attribute__((used)) intAHIsub_AllocAudio(struct TagItem *tagList asm("a1"), struct AHIAudioCtrlDrv *AudioCtrl asm("a2"))
|
||||
{
|
||||
debugmsg(6);
|
||||
SysBase = *(struct ExecBase **)4L;
|
||||
|
||||
if (!DOSBase) {
|
||||
DOSBase = (struct DosLibrary *)OpenLibrary((STRPTR)"dos.library",37);
|
||||
}
|
||||
if(!UtilityBase) {
|
||||
UtilityBase = (struct UtilityBase *)OpenLibrary((STRPTR)"utility.library",37);
|
||||
}
|
||||
|
||||
debuglong(AHI_U321, sizeof(struct pi_ahi));
|
||||
debugmsg(601);
|
||||
if((AudioCtrl->ahiac_DriverData = AllocVec(sizeof(struct pi_ahi), MEMF_PUBLIC | MEMF_ANY | MEMF_CLEAR)))
|
||||
{
|
||||
debugmsg(603);
|
||||
struct pi_ahi *ahi_data = (struct pi_ahi*)AudioCtrl->ahiac_DriverData;
|
||||
ahi_data->audioctrl = AudioCtrl;
|
||||
if (pi_ahi_base != ahi_data) {
|
||||
pi_ahi_base = ahi_data;
|
||||
}
|
||||
ahi_data->ahi_base = AHIsubBase;
|
||||
ahi_data->slave_signal = -1;
|
||||
ahi_data->play_signal = -1;
|
||||
ahi_data->fart_signal = -1;
|
||||
ahi_data->mix_signal = -1;
|
||||
|
||||
debugmsg(604);
|
||||
ahi_data->t_master = FindTask(NULL);
|
||||
ahi_data->master_signal = AllocSignal(-1);
|
||||
if(ahi_data->master_signal != -1) {
|
||||
debuglong(AHI_U321, (uint32_t)ahi_data);
|
||||
debugmsg(605);
|
||||
Forbid();
|
||||
if(ahi_data->slave_process = CreateNewProcTags(NP_Entry, (uint32_t)&SlaveProcess, NP_Name, (uint32_t)device_name, NP_Priority, 127, TAG_DONE)) {
|
||||
debugmsg(606);
|
||||
ahi_data->slave_process->pr_Task.tc_UserData = AudioCtrl;
|
||||
}
|
||||
Permit();
|
||||
debugmsg(607);
|
||||
|
||||
if(ahi_data->slave_process) {
|
||||
debugmsg(608);
|
||||
Wait(1L << ahi_data->master_signal); // Wait for slave to come alive
|
||||
if(ahi_data->slave_process != NULL) {
|
||||
debugmsg(609);
|
||||
ahi_data->flags |= 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
debugmsg(610);
|
||||
|
||||
WRITELONG(AHI_U321, AudioCtrl->ahiac_PlayerFreq);
|
||||
WRITELONG(AHI_U322, AudioCtrl->ahiac_MixFreq);
|
||||
WRITELONG(AHI_U323, AudioCtrl->ahiac_Channels);
|
||||
WRITELONG(AHI_ADDR1, AudioCtrl->ahiac_MinPlayerFreq);
|
||||
WRITELONG(AHI_ADDR2, AudioCtrl->ahiac_MaxPlayerFreq);
|
||||
WRITESHORT(AHI_COMMAND, AHI_CMD_ALLOCAUDIO);
|
||||
|
||||
struct pi_ahi *ahi_data = (struct pi_ahi*)AudioCtrl->ahiac_DriverData;
|
||||
ahi_data->ahi_base = AHIsubBase;
|
||||
debugshort(AHI_U1, AudioCtrl->ahiac_MixFreq);
|
||||
debugmsg(602);
|
||||
ahi_data->mix_freq = AudioCtrl->ahiac_MixFreq;
|
||||
AudioCtrl->ahiac_BuffSamples = AudioCtrl->ahiac_MixFreq / 50;
|
||||
|
||||
return AHISF_KNOWSTEREO | AHISF_MIXING;// | AHISF_TIMING;
|
||||
}
|
||||
|
||||
static void __attribute__((used)) intAHIsub_FreeAudio(struct AHIAudioCtrlDrv *AudioCtrl asm("a2")) {
|
||||
debugmsg(7);
|
||||
WRITESHORT(AHI_COMMAND, AHI_CMD_FREEAUDIO);
|
||||
if(AudioCtrl->ahiac_DriverData)
|
||||
{
|
||||
struct pi_ahi *ahi_data = (struct pi_ahi*)AudioCtrl->ahiac_DriverData;
|
||||
|
||||
if(ahi_data->slave_process)
|
||||
{
|
||||
if(ahi_data->slave_signal != -1)
|
||||
{
|
||||
Signal((struct Task *)ahi_data->slave_process, 1L << ahi_data->slave_signal);
|
||||
ahi_data->quitting = 1;
|
||||
}
|
||||
Wait(1L << ahi_data->master_signal);
|
||||
}
|
||||
|
||||
FreeSignal(ahi_data->master_signal);
|
||||
FreeVec(AudioCtrl->ahiac_DriverData);
|
||||
AudioCtrl->ahiac_DriverData = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t __attribute__((used)) intAHIsub_Stop(uint32_t Flags asm("d0"), struct AHIAudioCtrlDrv *AudioCtrl asm("a2")) {
|
||||
debugmsg(9);
|
||||
WRITESHORT(AHI_COMMAND, AHI_CMD_STOP);
|
||||
if(Flags & AHISF_PLAY) {
|
||||
struct pi_ahi *ahi_data = (struct pi_ahi*)AudioCtrl->ahiac_DriverData;
|
||||
|
||||
if (ahi_data->play_soft_int) {
|
||||
debugmsg(91);
|
||||
Forbid();
|
||||
RemIntServer(INTB_VERTB, ahi_data->play_soft_int);
|
||||
Permit();
|
||||
FreeVec(ahi_data->play_soft_int); ahi_data->play_soft_int = NULL;
|
||||
}
|
||||
|
||||
debugmsg(93);
|
||||
for (int i = 0; i < 8; i++) {
|
||||
debuglong(AHI_U321, i);
|
||||
debugmsg(94);
|
||||
if (ahi_data->samp_buf[i]) { FreeVec(ahi_data->samp_buf[i]); ahi_data->samp_buf[i] = NULL; }
|
||||
if (ahi_data->mix_buf[i]) { FreeVec(ahi_data->mix_buf[i]); ahi_data->mix_buf[i] = NULL; }
|
||||
}
|
||||
|
||||
ahi_data->playing = 0;
|
||||
}
|
||||
|
||||
return AHIE_OK;
|
||||
}
|
||||
|
||||
static uint32_t __attribute__((used)) intAHIsub_Start(uint32_t flags asm("d0"), struct AHIAudioCtrlDrv *AudioCtrl asm("a2")) {
|
||||
debugmsg(8);
|
||||
if(flags & AHISF_PLAY) {
|
||||
intAHIsub_Stop(flags, AudioCtrl);
|
||||
struct pi_ahi *ahi_data = (struct pi_ahi*)AudioCtrl->ahiac_DriverData;
|
||||
debugshort(AHI_U1, AudioCtrl->ahiac_BuffType);
|
||||
debuglong(AHI_U321, AudioCtrl->ahiac_BuffSize);
|
||||
debugmsg(81);
|
||||
|
||||
ahi_data->play_soft_int = AllocVec(sizeof(struct Interrupt), MEMF_PUBLIC | MEMF_ANY | MEMF_CLEAR);
|
||||
ahi_data->mix_soft_int = AllocVec(sizeof(struct Interrupt), MEMF_PUBLIC | MEMF_ANY | MEMF_CLEAR);
|
||||
if (!ahi_data->play_soft_int || !ahi_data->mix_soft_int) {
|
||||
debugmsg(82);
|
||||
if (ahi_data->play_soft_int) { FreeVec(ahi_data->play_soft_int); ahi_data->play_soft_int = 0; }
|
||||
return AHIE_NOMEM;
|
||||
}
|
||||
|
||||
ahi_data->buffer_type = AudioCtrl->ahiac_BuffType;
|
||||
ahi_data->buffer_size = AudioCtrl->ahiac_BuffSize;
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
ahi_data->samp_buf[i] = AllocVec(512 * 4, MEMF_PUBLIC | MEMF_ANY | MEMF_CLEAR);
|
||||
ahi_data->mix_buf[i] = AllocVec(0x1000, MEMF_PUBLIC | MEMF_ANY | MEMF_CLEAR);
|
||||
}
|
||||
|
||||
ahi_data->play_soft_int->is_Code = (void (* )())PlayFunc;
|
||||
ahi_data->play_soft_int->is_Node.ln_Type = NT_INTERRUPT;
|
||||
ahi_data->play_soft_int->is_Node.ln_Pri = -60;
|
||||
ahi_data->play_soft_int->is_Node.ln_Name = (char *)device_name;
|
||||
ahi_data->play_soft_int->is_Data = ahi_data;
|
||||
Forbid();
|
||||
AddIntServer(INTB_VERTB, ahi_data->play_soft_int);
|
||||
Permit();
|
||||
WRITESHORT(AHI_COMMAND, AHI_CMD_START);
|
||||
|
||||
ahi_data->playing = 1;
|
||||
}
|
||||
|
||||
return AHIE_OK;
|
||||
}
|
||||
|
||||
static uint32_t __attribute__((used)) intAHIsub_GetAttr(uint32_t attr_ asm("d0"), int32_t arg_ asm("d1"), int32_t def_ asm("d2"), struct TagItem *tagList asm("a1"), struct AHIAudioCtrlDrv *AudioCtrl asm("a2")) {
|
||||
const uint16_t freqs[] = {
|
||||
4096,
|
||||
8192,
|
||||
11025,
|
||||
22050,
|
||||
44100,
|
||||
48000,
|
||||
};
|
||||
|
||||
uint32_t attr = attr_;
|
||||
int32_t arg = arg_, def = def_;
|
||||
debugmsg(10);
|
||||
debuglong(AHI_U321, attr);
|
||||
debuglong(AHI_U322, arg);
|
||||
debuglong(AHI_U323, def);
|
||||
debugmsg(1001);
|
||||
switch(attr)
|
||||
{
|
||||
case AHIDB_Bits:
|
||||
debugmsg(1002);
|
||||
return 16;
|
||||
case AHIDB_Frequencies:
|
||||
debugmsg(1003);
|
||||
return 6;
|
||||
case AHIDB_Frequency:
|
||||
debugmsg(1004);
|
||||
return freqs[arg];
|
||||
case AHIDB_Index:
|
||||
debuglong(AHI_U321, arg_);
|
||||
debugmsg(1005);
|
||||
for (int i = 0; i < 6; i++) {
|
||||
if (freqs[i] == arg)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
case AHIDB_Author:
|
||||
debugmsg(1006);
|
||||
return (int32_t) "PiStorm AHI";
|
||||
case AHIDB_Copyright:
|
||||
debugmsg(1007);
|
||||
return (int32_t) "The PiStorms";
|
||||
case AHIDB_Version:
|
||||
debugmsg(1008);
|
||||
return (int32_t) device_id_string;
|
||||
case AHIDB_Annotation:
|
||||
debugmsg(1009);
|
||||
return (int32_t) "Based in part on the Toccata driver";
|
||||
case AHIDB_Record:
|
||||
debugmsg(1010);
|
||||
return FALSE;
|
||||
case AHIDB_FullDuplex:
|
||||
debugmsg(1011);
|
||||
return TRUE;
|
||||
case AHIDB_Realtime:
|
||||
debugmsg(1012);
|
||||
return TRUE;
|
||||
case AHIDB_MaxChannels:
|
||||
debugmsg(1013);
|
||||
return 16;
|
||||
case AHIDB_MaxPlaySamples:
|
||||
debugmsg(1014);
|
||||
return def + 0x8000;
|
||||
case AHIDB_MaxRecordSamples:
|
||||
debugmsg(1015);
|
||||
return 0;
|
||||
case AHIDB_MinMonitorVolume:
|
||||
debugmsg(1016);
|
||||
return 0x0;
|
||||
case AHIDB_MaxMonitorVolume:
|
||||
debugmsg(1017);
|
||||
return 0x10000;
|
||||
case AHIDB_MinInputGain:
|
||||
debugmsg(1018);
|
||||
return 0x0;
|
||||
case AHIDB_MaxInputGain:
|
||||
debugmsg(1019);
|
||||
return 0x0;
|
||||
case AHIDB_MinOutputVolume:
|
||||
debugmsg(1020);
|
||||
return 0x0;
|
||||
case AHIDB_MaxOutputVolume:
|
||||
debugmsg(1021);
|
||||
return 0x10000;
|
||||
case AHIDB_Inputs:
|
||||
debugmsg(1022);
|
||||
return 0;
|
||||
case AHIDB_Input:
|
||||
debugmsg(1023);
|
||||
return 0;
|
||||
case AHIDB_Outputs:
|
||||
debugmsg(1024);
|
||||
return 1;
|
||||
case AHIDB_Output:
|
||||
debugmsg(1025);
|
||||
switch (arg) {
|
||||
case 0: return (int32_t) "Snake 1";
|
||||
case 1: return (int32_t) "Snake 2";
|
||||
case 2: return (int32_t) "Snake 3";
|
||||
case 3: return (int32_t) "Snake 4";
|
||||
case 4: return (int32_t) "Snake 5";
|
||||
case 5: return (int32_t) "Snake 6";
|
||||
case 6: return (int32_t) "Snake 7";
|
||||
case 7: return (int32_t) "Snake 8";
|
||||
}
|
||||
default:
|
||||
debugmsg(1099);
|
||||
return def;
|
||||
}
|
||||
}
|
||||
|
||||
static int32_t __attribute__((used)) intAHIsub_HardwareControl(uint32_t attr asm("d0"), uint32_t arg asm("d1"), struct AHIAudioCtrlDrv *AudioCtrl asm("a2"))
|
||||
{
|
||||
return 0;
|
||||
|
||||
debugmsg(11);
|
||||
int32_t rc = TRUE;
|
||||
struct pi_ahi *ahi_data = (struct pi_ahi*)AudioCtrl->ahiac_DriverData;
|
||||
|
||||
switch (attr) {
|
||||
case AHIC_MonitorVolume:
|
||||
debugmsg(1101);
|
||||
ahi_data->monitor_volume = arg;
|
||||
break;
|
||||
case AHIC_MonitorVolume_Query:
|
||||
debugmsg(1102);
|
||||
rc = ahi_data->monitor_volume;
|
||||
break;
|
||||
case AHIC_InputGain:
|
||||
debugmsg(1103);
|
||||
ahi_data->input_gain = arg;
|
||||
break;
|
||||
case AHIC_InputGain_Query:
|
||||
debugmsg(1104);
|
||||
rc = ahi_data->input_gain;
|
||||
break;
|
||||
case AHIC_OutputVolume:
|
||||
debugmsg(1105);
|
||||
ahi_data->output_volume = arg;
|
||||
break;
|
||||
case AHIC_OutputVolume_Query:
|
||||
debugmsg(1106);
|
||||
rc = ahi_data->output_volume;
|
||||
break;
|
||||
case AHIC_Input:
|
||||
debugmsg(1107);
|
||||
break;
|
||||
case AHIC_Input_Query:
|
||||
debugmsg(1108);
|
||||
break;
|
||||
case AHIC_Output:
|
||||
debugmsg(1109);
|
||||
rc = TRUE;
|
||||
break;
|
||||
case AHIC_Output_Query:
|
||||
debugmsg(1110);
|
||||
rc = 0;
|
||||
break;
|
||||
default:
|
||||
debugmsg(1199);
|
||||
rc = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static uint32_t __attribute__((used)) intAHIsub_SetEffect(uint8_t *effect asm("a0"), struct AHIAudioCtrlDrv *AudioCtrl asm("a2"))
|
||||
{
|
||||
debugmsg(12);
|
||||
return AHIS_UNKNOWN;
|
||||
}
|
||||
|
||||
static uint32_t __attribute__((used)) intAHIsub_LoadSound(uint16_t sound asm("d0"), uint32_t type asm("d1"), struct AHISampleInfo *info asm("a0"), struct AHIAudioCtrlDrv *AudioCtrl asm("a2"))
|
||||
{
|
||||
debugmsg(13);
|
||||
debugshort(AHI_U1, sound);
|
||||
debuglong(AHI_U321, type);
|
||||
debuglong(AHI_U322, (uint32_t)info);
|
||||
debugmsg(131);
|
||||
if (type == AHIST_DYNAMICSAMPLE) {
|
||||
debuglong(AHI_U321, info->ahisi_Type);
|
||||
debuglong(AHI_U322, (uint32_t)info->ahisi_Address);
|
||||
debuglong(AHI_U323, info->ahisi_Length);
|
||||
debugmsg(134);
|
||||
}
|
||||
else {
|
||||
debugmsg(135);
|
||||
}
|
||||
|
||||
return AHIS_UNKNOWN;
|
||||
}
|
||||
|
||||
static uint32_t __attribute__((used)) intAHIsub_UnloadSound(uint16_t sound asm("d0"), struct AHIAudioCtrlDrv *AudioCtrl asm("a2"))
|
||||
{
|
||||
debugmsg(132);
|
||||
debugshort(AHI_U1, sound);
|
||||
debugmsg(133);
|
||||
|
||||
return AHIS_UNKNOWN;
|
||||
}
|
||||
|
||||
static void __attribute__((used)) intAHIsub_Enable(struct AHIAudioCtrlDrv *AudioCtrl asm("a2"))
|
||||
{
|
||||
debugmsg(14);
|
||||
Enable();
|
||||
//WRITESHORT(AHI_DISABLE, 0);
|
||||
}
|
||||
|
||||
static void __attribute__((used)) intAHIsub_Disable(struct AHIAudioCtrlDrv *AudioCtrl asm("a2"))
|
||||
{
|
||||
debugmsg(15);
|
||||
Disable();
|
||||
//WRITESHORT(AHI_DISABLE, 1);
|
||||
}
|
||||
|
||||
static uint32_t __attribute__((used)) intAHIsub_Update(uint32_t flags asm("d0"), struct AHIAudioCtrlDrv *AudioCtrlDrv asm("a2"))
|
||||
{
|
||||
debugmsg(16);
|
||||
return AHIS_UNKNOWN;
|
||||
}
|
||||
|
||||
static uint32_t __attribute__((used)) intAHIsub_SetVol(uint16_t channel asm("d0"), uint32_t volume asm("d1"), uint32_t pan asm("d2"), struct AHIAudioCtrlDrv *AudioCtrl asm("a2"), uint32_t flags asm("d3"))
|
||||
{
|
||||
debugmsg(17);
|
||||
debugshort(AHI_U1, channel);
|
||||
debuglong(AHI_U321, volume);
|
||||
debuglong(AHI_U322, pan);
|
||||
debuglong(AHI_U323, flags);
|
||||
debugmsg(171);
|
||||
|
||||
return AHIS_UNKNOWN;
|
||||
}
|
||||
|
||||
static uint32_t __attribute__((used)) intAHIsub_SetFreq(uint16_t channel asm("d0"), uint32_t freq asm("d1"), struct AHIAudioCtrlDrv *AudioCtrl asm("a2"), uint32_t flags asm("d2"))
|
||||
{
|
||||
debugmsg(18);
|
||||
debugshort(AHI_U1, channel);
|
||||
debuglong(AHI_U321, freq);
|
||||
debuglong(AHI_U323, flags);
|
||||
debugmsg(181);
|
||||
WRITELONG(AHI_U321, freq);
|
||||
WRITELONG(AHI_COMMAND, AHI_CMD_RATE);
|
||||
|
||||
return AHIS_UNKNOWN;
|
||||
}
|
||||
|
||||
static uint32_t __attribute__((used)) intAHIsub_SetSound(uint16_t channel asm("d0"), uint16_t sound asm("d1"), uint32_t offset asm("d2"), int32_t length asm("d3"), struct AHIAudioCtrlDrv *AudioCtrl asm("a2"), uint32_t flags asm("d4"))
|
||||
{
|
||||
debugmsg(19);
|
||||
debugshort(AHI_U1, channel);
|
||||
debuglong(AHI_U321, sound);
|
||||
debuglong(AHI_U323, offset);
|
||||
debuglong(AHI_U323, length);
|
||||
debuglong(AHI_U324, flags);
|
||||
debugmsg(191);
|
||||
|
||||
struct pi_ahi *ahi_data = (struct pi_ahi*)AudioCtrl->ahiac_DriverData;
|
||||
|
||||
debuglong(AHI_U321, (uint32_t)ahi_data);
|
||||
debuglong(AHI_U322, (uint32_t)AudioCtrl->ahiac_PlayerFunc);
|
||||
debuglong(AHI_U323, AudioCtrl->ahiac_PlayerFreq);
|
||||
debuglong(AHI_U324, (uint32_t)AudioCtrl->ahiac_PreTimer);
|
||||
debugmsg(192);
|
||||
|
||||
Signal((struct Task *)ahi_data->slave_process, 1L << ahi_data->mix_signal);
|
||||
|
||||
Permit();
|
||||
|
||||
return AHIS_UNKNOWN;
|
||||
}
|
||||
|
||||
static uint32_t function_table[] = {
|
||||
(uint32_t)open,
|
||||
(uint32_t)close,
|
||||
(uint32_t)expunge,
|
||||
(uint32_t)null,
|
||||
(uint32_t)intAHIsub_AllocAudio, // AllocAudio
|
||||
(uint32_t)intAHIsub_FreeAudio, // FreeAudio
|
||||
(uint32_t)intAHIsub_Disable, // Disable
|
||||
(uint32_t)intAHIsub_Enable, // Enable
|
||||
(uint32_t)intAHIsub_Start, // Start
|
||||
(uint32_t)intAHIsub_Update, // Update
|
||||
(uint32_t)intAHIsub_Stop, // Stop
|
||||
(uint32_t)intAHIsub_SetVol, // SetVol
|
||||
(uint32_t)intAHIsub_SetFreq, // SetFreq
|
||||
(uint32_t)intAHIsub_SetSound, // SetSound
|
||||
(uint32_t)intAHIsub_SetEffect, // SetEffect
|
||||
(uint32_t)intAHIsub_LoadSound, // LoadSound
|
||||
(uint32_t)intAHIsub_UnloadSound, // UnloadSound
|
||||
(uint32_t)intAHIsub_GetAttr, // GetAttr
|
||||
(uint32_t)intAHIsub_HardwareControl, // HardwareControl
|
||||
(uint32_t)null,
|
||||
(uint32_t)null,
|
||||
(uint32_t)null,
|
||||
-1
|
||||
};
|
||||
|
||||
const uint32_t auto_init_tables[4] = {
|
||||
sizeof(struct pi_ahi),
|
||||
(uint32_t)function_table,
|
||||
0,
|
||||
(uint32_t)init,
|
||||
};
|
||||
28
platforms/amiga/ahi/ahi_driver_amiga/pi-ahi.h
Normal file
28
platforms/amiga/ahi/ahi_driver_amiga/pi-ahi.h
Normal file
@@ -0,0 +1,28 @@
|
||||
struct pi_ahi {
|
||||
struct Task *t_master;
|
||||
struct Library *ahi_base;
|
||||
struct Interrupt *play_soft_int;
|
||||
struct Interrupt *mix_soft_int;
|
||||
struct Task *t_slave;
|
||||
struct Process *slave_process;
|
||||
int8_t master_signal;
|
||||
int8_t slave_signal;
|
||||
int8_t play_signal;
|
||||
int8_t mix_signal;
|
||||
int8_t fart_signal;
|
||||
int8_t snake_signal;
|
||||
int8_t pad81;
|
||||
int8_t pad82;
|
||||
uint8_t *samp_buf[8];
|
||||
uint8_t *mix_buf[8];
|
||||
uint32_t mix_freq;
|
||||
uint32_t flags;
|
||||
int32_t monitor_volume, input_gain, output_volume;
|
||||
uint16_t buffer_type;
|
||||
uint16_t pad;
|
||||
uint32_t buffer_size;
|
||||
uint16_t disable_cnt;
|
||||
uint16_t quitting;
|
||||
uint16_t playing;
|
||||
struct AHIAudioCtrlDrv *audioctrl;
|
||||
};
|
||||
104
platforms/amiga/ahi/ahi_driver_amiga/prefsfile.a
Normal file
104
platforms/amiga/ahi/ahi_driver_amiga/prefsfile.a
Normal file
@@ -0,0 +1,104 @@
|
||||
|
||||
incdir include:
|
||||
include devices/ahi.i
|
||||
include libraries/ahi_sub.i
|
||||
|
||||
TRUE EQU 1
|
||||
FALSE EQU 0
|
||||
|
||||
BEG:
|
||||
|
||||
*** FORM AHIM
|
||||
dc.l ID_FORM
|
||||
dc.l E-S
|
||||
S:
|
||||
dc.l ID_AHIM
|
||||
|
||||
|
||||
*** AUDN
|
||||
dc.l ID_AUDN
|
||||
dc.l .e-.s
|
||||
.s:
|
||||
dc.b "pi-ahi",0,0
|
||||
.e:
|
||||
CNOP 0,2
|
||||
|
||||
*** AUDM
|
||||
ModeA:
|
||||
dc.l ID_AUDM
|
||||
dc.l .e-.s
|
||||
.s
|
||||
dc.l AHIDB_AudioID, $000A0001
|
||||
|
||||
dc.l AHIDB_Volume, TRUE
|
||||
dc.l AHIDB_Panning, TRUE
|
||||
dc.l AHIDB_Stereo, FALSE
|
||||
dc.l AHIDB_HiFi, TRUE
|
||||
dc.l AHIDB_MultTable, FALSE
|
||||
|
||||
dc.l AHIDB_Name, .name-.s
|
||||
dc.l TAG_DONE
|
||||
.name dc.b "PiStorm AHI: 8 bit Mono",0
|
||||
.e
|
||||
CNOP 0,2
|
||||
|
||||
*** AUDM
|
||||
ModeB:
|
||||
dc.l ID_AUDM
|
||||
dc.l .e-.s
|
||||
.s
|
||||
dc.l AHIDB_AudioID, $000A0002
|
||||
|
||||
dc.l AHIDB_Volume, TRUE
|
||||
dc.l AHIDB_Panning, TRUE
|
||||
dc.l AHIDB_Stereo, TRUE
|
||||
dc.l AHIDB_HiFi, TRUE
|
||||
dc.l AHIDB_MultTable, FALSE
|
||||
|
||||
dc.l AHIDB_Name, .name-.s
|
||||
dc.l TAG_DONE
|
||||
.name dc.b "PiStorm AHI: 8 bit Stereo",0
|
||||
.e
|
||||
CNOP 0,2
|
||||
|
||||
*** AUDM
|
||||
ModeC:
|
||||
dc.l ID_AUDM
|
||||
dc.l .e-.s
|
||||
.s
|
||||
dc.l AHIDB_AudioID, $000A0003
|
||||
|
||||
dc.l AHIDB_Volume, TRUE
|
||||
dc.l AHIDB_Panning, TRUE
|
||||
dc.l AHIDB_Stereo, FALSE
|
||||
dc.l AHIDB_HiFi, TRUE
|
||||
dc.l AHIDB_MultTable, FALSE
|
||||
|
||||
dc.l AHIDB_Name, .name-.s
|
||||
dc.l TAG_DONE
|
||||
.name dc.b "PiStorm AHI: 16 bit Mono",0,0
|
||||
.e
|
||||
CNOP 0,2
|
||||
|
||||
*** AUDM
|
||||
ModeD:
|
||||
dc.l ID_AUDM
|
||||
dc.l .e-.s
|
||||
.s
|
||||
dc.l AHIDB_AudioID, $000A0004
|
||||
|
||||
dc.l AHIDB_Volume, TRUE
|
||||
dc.l AHIDB_Panning, TRUE
|
||||
dc.l AHIDB_Stereo, TRUE
|
||||
dc.l AHIDB_HiFi, TRUE
|
||||
dc.l AHIDB_MultTable, FALSE
|
||||
|
||||
dc.l AHIDB_Name, .name-.s
|
||||
dc.l TAG_DONE
|
||||
.name dc.b "PiStorm AHI: 16 bit Stereo",0,0
|
||||
.e
|
||||
CNOP 0,2
|
||||
|
||||
E:
|
||||
CNOP 0,2
|
||||
END:
|
||||
51
platforms/amiga/ahi/pi-ahi-enums.h
Normal file
51
platforms/amiga/ahi/pi-ahi-enums.h
Normal file
@@ -0,0 +1,51 @@
|
||||
#define PI_AHI_OFFSET 0x88000000
|
||||
#define PI_AHI_REGSIZE 0x00010000
|
||||
#define PI_AHI_UPPER 0x8A000000
|
||||
|
||||
enum pi_ahi_regs {
|
||||
AHI_COMMAND = 0x00,
|
||||
AHI_U1 = 0x02,
|
||||
AHI_U2 = 0x04,
|
||||
AHI_U3 = 0x06,
|
||||
AHI_U4 = 0x08,
|
||||
AHI_U5 = 0x0A,
|
||||
AHI_U6 = 0x0C,
|
||||
AHI_SNAKE = 0x0E,
|
||||
AHI_ADDR1 = 0x10,
|
||||
AHI_ADDR2 = 0x14,
|
||||
AHI_ADDR3 = 0x18,
|
||||
AHI_ADDR4 = 0x1C,
|
||||
AHI_U81 = 0x20,
|
||||
AHI_U82 = 0x21,
|
||||
AHI_U83 = 0x22,
|
||||
AHI_U84 = 0x23,
|
||||
|
||||
AHI_U321 = 0x30,
|
||||
AHI_U322 = 0x34,
|
||||
AHI_U323 = 0x38,
|
||||
AHI_U324 = 0x3C,
|
||||
|
||||
AHI_DEBUGMSG = 0x200,
|
||||
AHI_INTCHK = 0x204,
|
||||
AHI_DISABLE = 0x206,
|
||||
};
|
||||
|
||||
enum pi_ahi_commands {
|
||||
AHI_CMD_PLAY,
|
||||
AHI_CMD_STOP,
|
||||
AHI_CMD_START,
|
||||
AHI_CMD_CHANNELS,
|
||||
AHI_CMD_RATE,
|
||||
AHI_CMD_FORMAT,
|
||||
AHI_CMD_ALLOCAUDIO,
|
||||
AHI_CMD_FREEAUDIO,
|
||||
AHI_CMD_NUM,
|
||||
};
|
||||
|
||||
#define WRITESHORT(cmd, val) *(volatile unsigned short *)((unsigned long)(PI_AHI_OFFSET)+cmd) = val;
|
||||
#define WRITELONG(cmd, val) *(volatile unsigned long *)((unsigned long)(PI_AHI_OFFSET)+cmd) = val;
|
||||
#define WRITEBYTE(cmd, val) *(volatile unsigned char *)((unsigned long)(PI_AHI_OFFSET)+cmd) = val;
|
||||
|
||||
#define READSHORT(cmd) *(volatile unsigned short *)((unsigned long)(PI_AHI_OFFSET)+cmd)
|
||||
#define READLONG(cmd) *(volatile unsigned long *)((unsigned long)(PI_AHI_OFFSET)+cmd)
|
||||
#define READBYTE(cmd) *(volatile unsigned char *)((unsigned long)(PI_AHI_OFFSET)+cmd)
|
||||
630
platforms/amiga/ahi/pi_ahi.c
Normal file
630
platforms/amiga/ahi/pi_ahi.c
Normal file
@@ -0,0 +1,630 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "emulator.h"
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <endian.h>
|
||||
#include "config_file/config_file.h"
|
||||
#include <pthread.h>
|
||||
#include "gpio/ps_protocol.h"
|
||||
#include "platforms/amiga/amiga-interrupts.h"
|
||||
#include "pi_ahi.h"
|
||||
#include "pi-ahi-enums.h"
|
||||
|
||||
#include <alsa/asoundlib.h>
|
||||
|
||||
//#define AHI_DEBUG
|
||||
|
||||
uint32_t ahi_u32[4];
|
||||
uint32_t ahi_addr[4];
|
||||
uint16_t ahi_u16[8];
|
||||
uint16_t ahi_u8[8];
|
||||
|
||||
#ifdef AHI_DEBUG
|
||||
void print_ahi_debugmsg(int val, int type);
|
||||
void print_ahi_sample_type(uint16_t type);
|
||||
static const char *op_type_names[4] = {
|
||||
"BYTE",
|
||||
"WORD",
|
||||
"LONGWORD",
|
||||
"MEM",
|
||||
};
|
||||
#define DEBUG printf
|
||||
#define PRINT_AHI_DEBUGMSG print_ahi_debugmsg
|
||||
#define PRINT_AHI_SAMPLE_TYPE print_ahi_sample_type
|
||||
#else
|
||||
#define PRINT_AHI_DEBUGMSG(...)
|
||||
#define PRINT_AHI_SAMPLE_TYPE(...)
|
||||
#define DEBUG(...)
|
||||
void print_ahi_sample_type(uint16_t type);
|
||||
#endif
|
||||
|
||||
char pcm_device[255] = "plughw:1,0";
|
||||
uint32_t tmp, dir, buff_size;
|
||||
uint32_t playback_rate = 48000;
|
||||
int32_t channels = 2, seconds;
|
||||
|
||||
snd_pcm_t *pcm_handle;
|
||||
snd_pcm_hw_params_t *params;
|
||||
snd_pcm_uframes_t frames;
|
||||
|
||||
char dbgbuf[255] = "blep";
|
||||
char dbgout[255] = "blep";
|
||||
|
||||
int loops;
|
||||
|
||||
extern struct emulator_config *cfg;
|
||||
char *shitbuf;
|
||||
|
||||
uint32_t sndbuf_offset = 0, old_sndbuf_offset = 0, ahi_shutdown = 0, timing_enabled = 0, ahi_interrupt_triggered = 0, irq_disabled = 1;
|
||||
uint32_t ahi_ints_triggered = 0, ahi_ints_handled = 0, ahi_ints_spurious = 0;
|
||||
|
||||
static struct timespec diff(struct timespec start, struct timespec end)
|
||||
{
|
||||
struct timespec temp;
|
||||
if ((end.tv_nsec - start.tv_nsec) < 0) {
|
||||
temp.tv_sec = end.tv_sec - start.tv_sec - 1;
|
||||
temp.tv_nsec = 1000000000 + end.tv_nsec-start.tv_nsec;
|
||||
} else {
|
||||
temp.tv_sec = end.tv_sec-start.tv_sec;
|
||||
temp.tv_nsec = end.tv_nsec-start.tv_nsec;
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
|
||||
extern uint16_t emulated_irqs;
|
||||
extern uint8_t emulated_ipl;
|
||||
static const uint8_t IPL[14] = {1, 1, 1, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 6 };
|
||||
|
||||
static inline void emulate_irq(unsigned int irq) {
|
||||
emulated_irqs |= 1 << irq;
|
||||
uint8_t ipl = IPL[irq];
|
||||
|
||||
if (emulated_ipl < ipl) {
|
||||
emulated_ipl = ipl;
|
||||
}
|
||||
}
|
||||
|
||||
void *ahi_timing_task(void *args) {
|
||||
printf("[PI-AHI] AHI timing thread running.\n");
|
||||
|
||||
struct timespec f1, f2;
|
||||
struct timespec c1, c2;
|
||||
int32_t timer_interval[2] = { 18000000, 20000000 };
|
||||
|
||||
for (;;) {
|
||||
if (timing_enabled) {
|
||||
clock_gettime(CLOCK_REALTIME, &f1);
|
||||
do {
|
||||
usleep(0);
|
||||
clock_gettime(CLOCK_REALTIME, &f2);
|
||||
} while (diff(f1, f2).tv_nsec <= timer_interval[0]);
|
||||
|
||||
while (diff(f1, f2).tv_nsec <= timer_interval[1]) {
|
||||
clock_gettime(CLOCK_REALTIME, &f2);
|
||||
}
|
||||
|
||||
if (!irq_disabled) {
|
||||
emulate_irq(13);
|
||||
ahi_interrupt_triggered = 1;
|
||||
ahi_ints_triggered++;
|
||||
}
|
||||
|
||||
clock_gettime(CLOCK_REALTIME, &c2);
|
||||
if (diff(c1, c2).tv_sec >= 1) {
|
||||
//printf("Triggered %d times in one second. (Handled: %d Spurious: %d)\n", ahi_ints_triggered, ahi_ints_handled, ahi_ints_spurious);
|
||||
ahi_ints_triggered = 0;
|
||||
ahi_ints_handled = 0;
|
||||
ahi_ints_spurious = 0;
|
||||
clock_gettime(CLOCK_REALTIME, &c1);
|
||||
}
|
||||
} else {
|
||||
clock_gettime(CLOCK_REALTIME, &c1);
|
||||
usleep(1);
|
||||
}
|
||||
|
||||
if (ahi_shutdown) {
|
||||
ahi_shutdown = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
printf("[PI-AHI] AHI timing thread shutting down.\n");
|
||||
return args;
|
||||
}
|
||||
|
||||
uint32_t pi_ahi_init(char *dev) {
|
||||
pthread_t ahi_tid = 0;
|
||||
int err;
|
||||
|
||||
err = pthread_create(&ahi_tid, NULL, &ahi_timing_task, NULL);
|
||||
if (err != 0) {
|
||||
printf("[!!!PI-AHI] Could not start AHI timing thread: [%s]", strerror(err));
|
||||
goto pcm_init_fail;
|
||||
} else {
|
||||
pthread_setname_np(ahi_tid, "pistorm: ahi");
|
||||
printf("[PI-AHI] AHI timing thread started successfully.\n");
|
||||
}
|
||||
|
||||
if (dev) {
|
||||
int32_t res = 0;
|
||||
|
||||
res = snd_pcm_open(&pcm_handle, pcm_device, SND_PCM_STREAM_PLAYBACK, 0);
|
||||
if (res < 0) {
|
||||
printf("[PI-AHI] Failed to open sound device %s for playback: %s\n", pcm_device, snd_strerror(res));
|
||||
return 1;
|
||||
}
|
||||
|
||||
snd_pcm_hw_params_malloc(¶ms);
|
||||
snd_pcm_hw_params_any(pcm_handle, params);
|
||||
|
||||
res = snd_pcm_hw_params_set_access(pcm_handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
|
||||
if (res < 0) {
|
||||
printf("[PI-AHI] Failed to set interleaved mode: %s\n", snd_strerror(res));
|
||||
goto pcm_init_fail;
|
||||
}
|
||||
|
||||
res = snd_pcm_hw_params_set_format(pcm_handle, params, SND_PCM_FORMAT_S16_BE);
|
||||
if (res < 0) {
|
||||
printf("[PI-AHI] Failed to set sound format: %s\n", snd_strerror(res));
|
||||
goto pcm_init_fail;
|
||||
}
|
||||
|
||||
res = snd_pcm_hw_params_set_channels(pcm_handle, params, channels);
|
||||
if (res < 0) {
|
||||
printf("[PI-AHI] Failed to set 16 channels: %s\n", snd_strerror(res));
|
||||
goto pcm_init_fail;
|
||||
}
|
||||
|
||||
res = snd_pcm_hw_params_set_rate_near(pcm_handle, params, &playback_rate, 0);
|
||||
if (res < 0) {
|
||||
printf("[PI-AHI] Failed to set sample rate: %s\n", snd_strerror(res));
|
||||
goto pcm_init_fail;
|
||||
}
|
||||
|
||||
res = snd_pcm_hw_params(pcm_handle, params);
|
||||
if (res < 0) {
|
||||
printf("[PI-AHI] Failed to set PCM parameters: %s\n", snd_strerror(res));
|
||||
goto pcm_init_fail;
|
||||
}
|
||||
|
||||
snd_pcm_hw_params_get_period_size(params, &frames, 0);
|
||||
buff_size = frames * channels * 2;
|
||||
shitbuf = malloc(256 * SIZE_KILO);
|
||||
|
||||
snd_pcm_prepare(pcm_handle);
|
||||
|
||||
printf("[PI-AHI] PCM name: %s\n", snd_pcm_name(pcm_handle));
|
||||
printf("[PI-AHI] PCM state: %s\n", snd_pcm_state_name(snd_pcm_state(pcm_handle)));
|
||||
snd_pcm_hw_params_get_channels(params, &tmp);
|
||||
printf("[PI-AHI] Channels: %i\n", tmp);
|
||||
printf("[PI-AHI] Buffer size: %i\n", buff_size);
|
||||
|
||||
goto pcm_init_done;
|
||||
|
||||
pcm_init_fail:
|
||||
snd_pcm_close(pcm_handle); return 1;
|
||||
pcm_init_done:
|
||||
|
||||
printf("[PI-AHI] Some Pi-AHI enabled: %s\n", dev);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
void pi_ahi_shutdown() {
|
||||
printf("[PI-AHI] Shutting down Pi-AHI.\n");
|
||||
if (pcm_handle) {
|
||||
snd_pcm_drop(pcm_handle);
|
||||
snd_pcm_close(pcm_handle);
|
||||
pcm_handle = NULL;
|
||||
if (shitbuf) {
|
||||
free(shitbuf);
|
||||
shitbuf = NULL;
|
||||
}
|
||||
}
|
||||
ahi_shutdown = 1;
|
||||
printf("[PI-AHI] Pi-AHI shut down.\n");
|
||||
}
|
||||
|
||||
uint32_t dbg_repeat;
|
||||
|
||||
void pi_ahi_do_cmd(uint32_t val) {
|
||||
switch (val) {
|
||||
case AHI_CMD_START:
|
||||
//timing_enabled = 1;
|
||||
//irq_disabled = 0;
|
||||
printf("[PI-AHI] Driver sent START command.\n");
|
||||
break;
|
||||
case AHI_CMD_STOP:
|
||||
printf("[PI-AHI] Driver sent STOP command.\n");
|
||||
// fallthrough
|
||||
case AHI_CMD_FREEAUDIO:
|
||||
//irq_disabled = 1;
|
||||
//timing_enabled = 0;
|
||||
snd_pcm_drop(pcm_handle);
|
||||
snd_pcm_prepare(pcm_handle);
|
||||
break;
|
||||
case AHI_CMD_RATE: {
|
||||
//printf("[PI-AHI] Set rate to %d.\n", ahi_u32[0]);
|
||||
break;
|
||||
}
|
||||
case AHI_CMD_PLAY: {
|
||||
int32_t res = 0;
|
||||
uint8_t *bufptr = get_mapped_data_pointer_by_address(cfg, ahi_addr[0]);
|
||||
uint16_t *bepptr = (uint16_t *)get_mapped_data_pointer_by_address(cfg, ahi_addr[0]);
|
||||
//printf("[PI-AHI] Driver sent PLAY command: %d samples @$%.8X ($%.8X).\n", ahi_u32[0], ahi_addr[0], (uint32_t)bufptr);
|
||||
if (ahi_u32[0] != 0 && ahi_addr[0] != 0) {
|
||||
uint32_t bsize = ahi_u32[0] * get_ahi_sample_size(ahi_u32[3]) * get_ahi_channels(ahi_u32[3]);
|
||||
uint32_t hz = (ahi_u32[0] * (ahi_addr[1] >> 16));
|
||||
sprintf(dbgbuf, "Samples: %d Rate(?): %dHz MixFreq: %d PlayFreq: %d Channels: %d Bsize: %d Type: %d", ahi_u32[0], hz, ahi_u32[1], (ahi_addr[1] >> 16), ahi_u32[2], bsize, ahi_u32[3]);
|
||||
if (strcmp(dbgbuf, dbgout) == 0) {
|
||||
dbg_repeat++;
|
||||
} else {
|
||||
printf("%s", dbgbuf);
|
||||
if (dbg_repeat) {
|
||||
//printf (" [line repeated %d times]", dbg_repeat);
|
||||
dbg_repeat = 0;
|
||||
}
|
||||
//printf("\n");
|
||||
strcpy(dbgout, dbgbuf);
|
||||
}
|
||||
//printf("Buffer: %.4X %.4X %.4X %.4X\n", bepptr[0], bepptr[1], bepptr[2], bepptr[3]);
|
||||
if (ahi_u32[1] == playback_rate) {
|
||||
memcpy(shitbuf + sndbuf_offset, bufptr, bsize);
|
||||
}
|
||||
else {
|
||||
uint32_t dst_bsize = 0;
|
||||
if ((ahi_addr[1] >> 16) == 0) {
|
||||
dst_bsize = playback_rate / 50;
|
||||
} else {
|
||||
dst_bsize = playback_rate / (ahi_addr[1] >> 16);
|
||||
}
|
||||
dst_bsize *= get_ahi_sample_size(ahi_u32[3]) * get_ahi_channels(ahi_u32[3]);
|
||||
//printf("Resampling from %d to %d (%d bytes to %d bytes).\n", ahi_u32[1], playback_rate, bsize, dst_bsize);
|
||||
if (get_ahi_channels(ahi_u32[3]) == 2) {
|
||||
uint32_t *u32ptr = (uint32_t *)bufptr;
|
||||
uint32_t *dstptr = (uint32_t *)&shitbuf[sndbuf_offset];
|
||||
float step = (float)bsize / (float)dst_bsize;
|
||||
float index_f = 0.0f;
|
||||
for (uint32_t i = 0; i < (dst_bsize / 4); i++) {
|
||||
uint32_t index = (uint32_t)index_f;
|
||||
index_f += step;
|
||||
dstptr[i] = u32ptr[index];
|
||||
}
|
||||
bsize = dst_bsize;
|
||||
} else {
|
||||
uint16_t *u16ptr = (uint16_t *)bufptr;
|
||||
}
|
||||
}
|
||||
sndbuf_offset += bsize;
|
||||
while (sndbuf_offset >= old_sndbuf_offset + buff_size) {
|
||||
//printf("Writing %d bytes to the PCM...\n", buff_size);
|
||||
res = snd_pcm_writei(pcm_handle, shitbuf + old_sndbuf_offset, frames);
|
||||
old_sndbuf_offset = old_sndbuf_offset + buff_size;
|
||||
if (old_sndbuf_offset >= 127 * SIZE_KILO) {
|
||||
//printf("Buffer wrap.\n");
|
||||
memcpy(shitbuf, bufptr + (sndbuf_offset % buff_size), bsize - (sndbuf_offset % buff_size));
|
||||
sndbuf_offset = (sndbuf_offset % buff_size);
|
||||
old_sndbuf_offset = (sndbuf_offset - (sndbuf_offset % buff_size));
|
||||
}
|
||||
if (res == -EPIPE) {
|
||||
//printf("PCM epipe.\n");
|
||||
snd_pcm_prepare(pcm_handle);
|
||||
} else if (res < 0) {
|
||||
printf("ERROR. Can't write to PCM device. %s\n", snd_strerror(res));
|
||||
snd_pcm_prepare(pcm_handle);
|
||||
}
|
||||
//snd_pcm_hw_params(pcm_handle, params);
|
||||
//printf("[PI-AHI] PCM name: %s\n", snd_pcm_name(pcm_handle));
|
||||
//printf("[PI-AHI] PCM state: %s\n", snd_pcm_state_name(snd_pcm_state(pcm_handle)));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case AHI_CMD_ALLOCAUDIO: {
|
||||
printf("[PI-AHI] AllocAudio:\n");
|
||||
printf("MixFreq: %d PlayFreq: %d Channels: %d ", ahi_u32[1], (ahi_u32[0] >> 16), ahi_u32[2]);
|
||||
printf("MinPlayFreq: %d MaxPlayFreq: %d\n", (ahi_addr[0] >> 16), (ahi_addr[1] >> 16));
|
||||
sprintf(dbgout, "blep");
|
||||
dbg_repeat = 0;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
printf("[!!!PI_AHI] Unknown command %d.\n", val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void handle_pi_ahi_write(uint32_t addr_, uint32_t val, uint8_t type) {
|
||||
uint32_t addr = addr_ & 0xFFFF;
|
||||
#ifndef DEBUG_AHI
|
||||
if (type) {};
|
||||
#endif
|
||||
|
||||
switch(addr) {
|
||||
case AHI_COMMAND:
|
||||
pi_ahi_do_cmd(val);
|
||||
break;
|
||||
case AHI_U81: case AHI_U82: case AHI_U83: case AHI_U84: {
|
||||
int i = (addr - AHI_U81);
|
||||
ahi_u8[i] = val;
|
||||
break;
|
||||
}
|
||||
case AHI_U1: case AHI_U2: case AHI_U3: case AHI_U4: case AHI_U5: case AHI_U6: {
|
||||
int i = (addr - AHI_U1) / 2;
|
||||
ahi_u16[i] = val;
|
||||
break;
|
||||
}
|
||||
case AHI_ADDR1: case AHI_ADDR2: case AHI_ADDR3: case AHI_ADDR4: {
|
||||
int i = (addr - AHI_ADDR1) / 4;
|
||||
ahi_addr[i] = val;
|
||||
break;
|
||||
}
|
||||
case AHI_U321: case AHI_U322: case AHI_U323: case AHI_U324: {
|
||||
int i = (addr - AHI_U321) / 4;
|
||||
ahi_u32[i] = val;
|
||||
break;
|
||||
}
|
||||
case AHI_DEBUGMSG:
|
||||
PRINT_AHI_DEBUGMSG(val, type);
|
||||
break;
|
||||
case AHI_DISABLE:
|
||||
if (val == 1) {
|
||||
irq_disabled++;
|
||||
} else {
|
||||
if(irq_disabled > 0) {
|
||||
irq_disabled--;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case AHI_INTCHK:
|
||||
switch(val) {
|
||||
case 1:
|
||||
amiga_clear_emulating_irq();
|
||||
DEBUG("Interrupt handler triggered. IRQ enabled: %d\n", irq_enabled);
|
||||
break;
|
||||
case 2:
|
||||
ahi_ints_handled++;
|
||||
DEBUG("Sending play signal.\n");
|
||||
break;
|
||||
case 3:
|
||||
ahi_ints_spurious++;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DEBUG("[PI-AHI] %s write to %.4X (%.8X): %.8X (%d)\n", op_type_names[type], addr, addr_, val, val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t handle_pi_ahi_read(uint32_t addr_, uint8_t type) {
|
||||
uint32_t addr = addr_ & 0xFFFF;
|
||||
#ifndef DEBUG_AHI
|
||||
if (type) {};
|
||||
#endif
|
||||
|
||||
switch(addr) {
|
||||
case AHI_U81: case AHI_U82: case AHI_U83: case AHI_U84: {
|
||||
int i = (addr - AHI_U81);
|
||||
return ahi_u8[i];
|
||||
break;
|
||||
}
|
||||
case AHI_U1: case AHI_U2: case AHI_U3: case AHI_U4: case AHI_U5: case AHI_U6: {
|
||||
int i = (addr - AHI_U1) / 2;
|
||||
return ahi_u16[i];
|
||||
break;
|
||||
}
|
||||
case AHI_ADDR1: case AHI_ADDR2: case AHI_ADDR3: case AHI_ADDR4: {
|
||||
int i = (addr - AHI_ADDR1) / 4;
|
||||
return ahi_addr[i];
|
||||
break;
|
||||
}
|
||||
case AHI_U321: case AHI_U322: case AHI_U323: case AHI_U324: {
|
||||
int i = (addr - AHI_U321) / 4;
|
||||
return ahi_u32[i];
|
||||
break;
|
||||
}
|
||||
case AHI_INTCHK:
|
||||
if (ahi_interrupt_triggered) {
|
||||
ahi_interrupt_triggered = 0;
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DEBUG("[PI-AHI] %s read from %.4X (%.8X)?!\n", op_type_names[type], addr, addr_);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void print_ahi_sample_type(uint16_t type) {
|
||||
switch(type) {
|
||||
case AHIST_M8S: printf("8-bit signed [Mono]"); break;
|
||||
case AHIST_S8S: printf("8-bit signed [Stereo]"); break;
|
||||
case AHIST_M16S: printf("16-bit signed [Mono]"); break;
|
||||
case AHIST_S16S: printf("16-bit signed [Stereo]"); break;
|
||||
case AHIST_M32S: printf("32-bit signed [Mono]"); break;
|
||||
case AHIST_S32S: printf("32-bit signed [Stereo]"); break;
|
||||
default: printf("UNKNOWN FORMAT (%d)", type);
|
||||
}
|
||||
}
|
||||
|
||||
int get_ahi_sample_size(uint16_t type) {
|
||||
switch(type) {
|
||||
case AHIST_M8S:
|
||||
case AHIST_S8S: return 1;
|
||||
case AHIST_M16S:
|
||||
case AHIST_S16S: return 2;
|
||||
case AHIST_M32S:
|
||||
case AHIST_S32S: return 4;
|
||||
default: return 2;
|
||||
}
|
||||
}
|
||||
|
||||
int get_ahi_channels(uint16_t type) {
|
||||
switch(type) {
|
||||
case AHIST_M8S:
|
||||
case AHIST_M16S:
|
||||
case AHIST_M32S: return 1;
|
||||
case AHIST_S8S:
|
||||
case AHIST_S16S:
|
||||
case AHIST_S32S: return 2;
|
||||
default: return 1;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef AHI_DEBUG
|
||||
void print_ahi_debugmsg(int val, int type) {
|
||||
switch (val) {
|
||||
case 1: printf("[PI-AHI-amiga] Called INIT. Dev: %.8X\n", ahi_u32[0]); break;
|
||||
case 101: printf("[PI-AHI-amiga] !!!INIT: AHISubBase already set.\n"); break;
|
||||
case 102: printf("[PI-AHI-amiga] Allocating driver base.\n"); break;
|
||||
case 103: printf("[PI-AHI-amiga] Opening libraries.\n"); break;
|
||||
case 104: printf("[PI-AHI-amiga] Init done.\n"); break;
|
||||
|
||||
case 2: printf("[PI-AHI-amiga] Called OPEN.\n"); break;
|
||||
case 201: printf("[PI-AHI-amiga] OPEN: Set AHISubBase.\n"); break;
|
||||
|
||||
case 3: printf("[PI-AHI-amiga] Called CLOSE.\n"); break;
|
||||
case 4: printf("[PI-AHI-amiga] Called BEGINIO (but how!?).\n"); break;
|
||||
case 5: printf("[PI-AHI-amiga] Called ABORTIO (but how!?).\n"); break;
|
||||
case 6: printf("[PI-AHI-amiga] Called ALLOCAUDIO.\n"); break;
|
||||
case 601: printf("[PI-AHI-amiga] Allocating %d bytes for DriverData.\n", ahi_u32[0]); break;
|
||||
case 602: printf("[PI-AHI-amiga] Setting mixing frequency to %d.\n", ahi_u16[0]); break;
|
||||
case 603: printf("[PI-AHI-amiga] Setting up crap for the slave process.\n"); break;
|
||||
case 604: printf("[PI-AHI-amiga] Find tasks and stuff.\n"); break;
|
||||
case 605: printf("[PI-AHI-amiga] Forbidding and creating slace process. ahi-data = %.8X\n", ahi_u32[0]); break;
|
||||
case 606: printf("[PI-AHI-amiga] Slave process created.\n"); break;
|
||||
case 607: printf("[PI-AHI-amiga] Permitting and moving on.\n"); break;
|
||||
case 608: printf("[PI-AHI-amiga] Setting some crap for the slave process.\n"); break;
|
||||
case 609: printf("[PI-AHI-amiga] Setting owner flags.\n"); break;
|
||||
case 610: printf("[PI-AHI-amiga] Done with slave process stuff, resuming.\n"); break;
|
||||
|
||||
case 7: printf("[PI-AHI-amiga] Called FREEAUDIO.\n"); break;
|
||||
case 8: printf("[PI-AHI-amiga] Called START.\n"); break;
|
||||
case 81: printf("[PI-AHI-amiga] Buffer type: ");
|
||||
PRINT_AHI_SAMPLE_TYPE(ahi_u16[0]);
|
||||
printf(" Buffer size: %d\n", ahi_u32[0]);
|
||||
break;
|
||||
case 82: printf("[!!!PI-AHI-amiga] Out of memory allocating soft interrupts!\n"); break;
|
||||
|
||||
case 9: printf("[PI-AHI-amiga] Called STOP.\n"); break;
|
||||
case 91: printf("[PI-AHI-amiga] Free Play SoftInt.\n"); break;
|
||||
case 92: printf("[PI-AHI-amiga] Free Mix SoftInt.\n"); break;
|
||||
case 93: printf("[PI-AHI-amiga] Free buffers.\n"); break;
|
||||
case 94: printf("[PI-AHI-amiga] Free loop %d...\n", ahi_u32[0] + 1); break;
|
||||
|
||||
case 10: printf("[PI-AHI-amiga] Called GETATTR.\n"); break;
|
||||
case 1001: printf("[PI-AHI-amiga] Attr: %.8X Arg: %.8X Def: %.8X.\n", ahi_u32[0], ahi_u32[1], ahi_u32[2]); break;
|
||||
case 1002: printf("[PI-AHI-amiga] Query Bits.\n"); break;
|
||||
case 1003: printf("[PI-AHI-amiga] Query NumFrequencies.\n"); break;
|
||||
case 1004: printf("[PI-AHI-amiga] Get Frequency (index).\n"); break;
|
||||
case 1005: printf("[PI-AHI-amiga] Index Frequency.\n"); break;
|
||||
case 1006: printf("[PI-AHI-amiga] Query Author.\n"); break;
|
||||
case 1007: printf("[PI-AHI-amiga] Query Copyright.\n"); break;
|
||||
case 1008: printf("[PI-AHI-amiga] Query Version.\n"); break;
|
||||
case 1009: printf("[PI-AHI-amiga] Query Annotation.\n"); break;
|
||||
case 1010: printf("[PI-AHI-amiga] Query Recording capability.\n"); break;
|
||||
case 1011: printf("[PI-AHI-amiga] Query Full Duplex.\n"); break;
|
||||
case 1012: printf("[PI-AHI-amiga] Query Realtime.\n"); break;
|
||||
case 1013: printf("[PI-AHI-amiga] Query MaxChannels.\n"); break;
|
||||
case 1014: printf("[PI-AHI-amiga] Query MaxPlaySamples.\n"); break;
|
||||
case 1015: printf("[PI-AHI-amiga] Query MaxRecordSamples.\n"); break;
|
||||
case 1016: printf("[PI-AHI-amiga] Query MinMonitorVolume.\n"); break;
|
||||
case 1017: printf("[PI-AHI-amiga] Query MaxMonitorVolume.\n"); break;
|
||||
case 1018: printf("[PI-AHI-amiga] Query MinInputGain.\n"); break;
|
||||
case 1019: printf("[PI-AHI-amiga] Query MaxInputGain.\n"); break;
|
||||
case 1020: printf("[PI-AHI-amiga] Query MinOutputVolume.\n"); break;
|
||||
case 1021: printf("[PI-AHI-amiga] Query MaxOutputVolume.\n"); break;
|
||||
case 1022: printf("[PI-AHI-amiga] Query Inputs.\n"); break;
|
||||
case 1023: printf("[PI-AHI-amiga] Query Input (index).\n"); break;
|
||||
case 1024: printf("[PI-AHI-amiga] Query Outputs.\n"); break;
|
||||
case 1025: printf("[PI-AHI-amiga] Query Output (index).\n"); break;
|
||||
case 1099: printf("[!!!PI-AHI-amiga] GETATTR: Hit default case!\n"); break;
|
||||
|
||||
case 11: printf("[PI-AHI-amiga] Called HARDWARECONTROL.\n"); break;
|
||||
case 1101: printf("[PI-AHI-amiga] Set MonitorVolume.\n"); break;
|
||||
case 1102: printf("[PI-AHI-amiga] Query MonitorVolume.\n"); break;
|
||||
case 1103: printf("[PI-AHI-amiga] Set InputGain.\n"); break;
|
||||
case 1104: printf("[PI-AHI-amiga] Query InputGain.\n"); break;
|
||||
case 1105: printf("[PI-AHI-amiga] Set OutputVolume.\n"); break;
|
||||
case 1106: printf("[PI-AHI-amiga] Query OutputVolume.\n"); break;
|
||||
case 1107: printf("[PI-AHI-amiga] Set Input.\n"); break;
|
||||
case 1108: printf("[PI-AHI-amiga] Query Input.\n"); break;
|
||||
case 1109: printf("[PI-AHI-amiga] Set Output.\n"); break;
|
||||
case 1110: printf("[PI-AHI-amiga] Query Output.\n"); break;
|
||||
case 1199: printf("[!!!PI-AHI-amiga] HARDWARECONTROL: Hit default case!\n"); break;
|
||||
|
||||
case 12: printf("[PI-AHI-amiga] Called SETEFFECT.\n"); break;
|
||||
|
||||
case 13: printf("[PI-AHI-amiga] Called LOADSOUND.\n"); break;
|
||||
case 131: printf("[PI-AHI-amiga] Sound: %d Type: ", ahi_u16[0]);
|
||||
switch (ahi_u32[0]) {
|
||||
case AHIST_SAMPLE: printf("Sample"); break;
|
||||
case AHIST_DYNAMICSAMPLE: printf("Dynamic Sample"); break;
|
||||
case AHIST_INPUT: printf("Input!?"); break;
|
||||
default: printf("UNKNOWN TYPE %d", ahi_u32[0]); break;
|
||||
}
|
||||
printf(" Info: %.8X\n", ahi_u32[1]);
|
||||
break;
|
||||
case 132: printf("[PI-AHI-amiga] Called UNLOADSOUND.\n"); break;
|
||||
case 133: printf("[PI-AHI-amiga] Sound: %d\n", ahi_u16[0]); break;
|
||||
case 134: printf("[PI-AHI-amiga] Buffer type: ");
|
||||
PRINT_AHI_SAMPLE_TYPE(ahi_u32[0]);
|
||||
printf(" Address: %.8X Length: %d\n", ahi_u32[1], ahi_u32[2]);
|
||||
break;
|
||||
|
||||
case 14: printf("[PI-AHI-amiga] Called ENABLE.\n"); break;
|
||||
case 141: printf("[PI-AHI-amiga] Enable()\n"); break;
|
||||
|
||||
case 15: printf("[PI-AHI-amiga] Called DISABLE.\n"); break;
|
||||
case 151: printf("[PI-AHI-amiga] Disable()\n"); break;
|
||||
|
||||
case 16: printf("[PI-AHI-amiga] Called UPDATE.\n"); break;
|
||||
|
||||
case 17: printf("[PI-AHI-amiga] Called SETVOL.\n"); break;
|
||||
case 171:
|
||||
printf("[PI-AHI-amiga] Channel: %d Volume: %d Pan: %d Flags: %.8X\n", ahi_u16[0], ahi_u32[0], ahi_u32[1], ahi_u32[2]);
|
||||
break;
|
||||
|
||||
case 18: printf("[PI-AHI-amiga] Called SETFREQ.\n"); break;
|
||||
case 181:
|
||||
printf("[PI-AHI-amiga] Channel: %d Freq: %d Flags: %.8X\n", ahi_u16[0], ahi_u32[0], ahi_u32[2]);
|
||||
break;
|
||||
|
||||
case 19: printf("[PI-AHI-amiga] Called SETSOUND.\n"); break;
|
||||
case 191:
|
||||
printf("[PI-AHI-amiga] Channel: %d Sound: %d Offset: %d Length: %d Flags: %.8X\n", ahi_u16[0], ahi_u32[0], ahi_u32[1], ahi_u32[2], ahi_u32[3]);
|
||||
break;
|
||||
case 192:
|
||||
printf("[PI-AHI-amiga] SETSOUND: ahi-data = %.8X\n", ahi_u32[0]);
|
||||
printf("[PI-AHI-amiga] PlayerFunc: %.8X MixerFunc: %.8X PreTimer: %.8X\n", ahi_u32[1], ahi_u32[2], ahi_u32[3]);
|
||||
break;
|
||||
|
||||
case 20:
|
||||
printf("[PI-AHI-amiga] We're in the slave process! ahi-data = %.8X\n", ahi_u32[0]);
|
||||
printf("[PI-AHI-amiga] PlayerFunc: %.8X MixerFunc: %.8X PreTimer: %.8X\n", ahi_u32[1], ahi_u32[2], ahi_u32[3]);
|
||||
break;
|
||||
case 2001: printf("[PI-AHI-amiga] SLAVE:PlaySignal. BuffSamples: %d\n", ahi_u32[0]); break;
|
||||
case 2002: printf("[PI-AHI-amiga] SLAVE:MixSignal\n"); break;
|
||||
case 2004: printf("[PI-AHI-amiga] SLAVE:Waiting for signal\n"); break;
|
||||
case 2005: printf("[PI-AHI-amiga] SLAVE:PlaySignal End\n"); break;
|
||||
case 2006: printf("[PI-AHI-amiga] SLAVE:Failed to allocate signals?\n"); break;
|
||||
|
||||
case 21: printf("[PI-AHI-amiga] Called PLAYFUNC.\n"); break;
|
||||
case 22: printf("[PI-AHI-amiga] Called MIXFUNC.\n"); break;
|
||||
|
||||
// Debug messages of dubious usefulness
|
||||
case 998: printf("[!!!PI-AHI-amiga] NULL function called!\n"); break;
|
||||
case 999: printf("[!!!PI-AHI-amiga] EXPUNGE called!\n"); break;
|
||||
default:
|
||||
printf("[PI-AHI] %s write to DEBUGMSG: %.8X (%d)\n", op_type_names[type], val, val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
17
platforms/amiga/ahi/pi_ahi.h
Normal file
17
platforms/amiga/ahi/pi_ahi.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#define AHIST_M8S 0
|
||||
#define AHIST_M16S 1
|
||||
#define AHIST_S8S 2
|
||||
#define AHIST_S16S 3
|
||||
#define AHIST_M32S 8
|
||||
#define AHIST_S32S 10
|
||||
|
||||
#define AHIST_SAMPLE 0
|
||||
#define AHIST_DYNAMICSAMPLE 1
|
||||
#define AHIST_INPUT (1<<29)
|
||||
|
||||
uint32_t pi_ahi_init(char *dev);
|
||||
void pi_ahi_shutdown();
|
||||
void handle_pi_ahi_write(uint32_t addr_, uint32_t val, uint8_t type);
|
||||
uint32_t handle_pi_ahi_read(uint32_t addr_, uint8_t type);
|
||||
int get_ahi_sample_size(uint16_t type);
|
||||
int get_ahi_channels(uint16_t type);
|
||||
@@ -13,6 +13,8 @@
|
||||
#include "net/pi-net.h"
|
||||
#include "piscsi/piscsi-enums.h"
|
||||
#include "piscsi/piscsi.h"
|
||||
#include "ahi/pi_ahi.h"
|
||||
#include "ahi/pi-ahi-enums.h"
|
||||
#include "pistorm-dev/pistorm-dev-enums.h"
|
||||
#include "pistorm-dev/pistorm-dev.h"
|
||||
#include "platforms/platforms.h"
|
||||
@@ -66,7 +68,7 @@ extern int force_move_slow_to_chip;
|
||||
#define min(a, b) (a < b) ? a : b
|
||||
#define max(a, b) (a > b) ? a : b
|
||||
|
||||
uint8_t rtg_enabled = 0, piscsi_enabled = 0, pinet_enabled = 0, kick13_mode = 0, pistorm_dev_enabled = 1;
|
||||
uint8_t rtg_enabled = 0, piscsi_enabled = 0, pinet_enabled = 0, kick13_mode = 0, pistorm_dev_enabled = 1, pi_ahi_enabled = 0;
|
||||
uint8_t a314_emulation_enabled = 0, a314_initialized = 0;
|
||||
|
||||
extern uint32_t piscsi_base, pistorm_dev_base;
|
||||
@@ -285,6 +287,13 @@ void adjust_ranges_amiga(struct emulator_config *cfg) {
|
||||
cfg->custom_low = min(cfg->custom_low, piscsi_base);
|
||||
}
|
||||
}
|
||||
if (pi_ahi_enabled) {
|
||||
if (cfg->custom_low == 0)
|
||||
cfg->custom_low = PI_AHI_OFFSET;
|
||||
else
|
||||
cfg->custom_low = min(cfg->custom_low, PI_AHI_OFFSET);
|
||||
cfg->custom_high = max(cfg->custom_high, PI_AHI_UPPER);
|
||||
}
|
||||
if (pinet_enabled) {
|
||||
if (cfg->custom_low == 0)
|
||||
cfg->custom_low = PINET_OFFSET;
|
||||
@@ -516,6 +525,21 @@ void setvar_amiga(struct emulator_config *cfg, char *var, char *val) {
|
||||
adjust_ranges_amiga(cfg);
|
||||
}
|
||||
|
||||
if (CHKVAR("pi-ahi")&& !pi_ahi_enabled) {
|
||||
printf("[AMIGA] PI-AHI Audio Crap Enabled.\n");
|
||||
uint32_t res = 1;
|
||||
if (val && strlen(val) != 0)
|
||||
res = pi_ahi_init(val);
|
||||
else
|
||||
res = pi_ahi_init("default");
|
||||
if (res == 0) {
|
||||
pi_ahi_enabled = 1;
|
||||
adjust_ranges_amiga(cfg);
|
||||
} else {
|
||||
printf("[AMIGA] Failed to enable PI-AHI.\n");
|
||||
}
|
||||
}
|
||||
|
||||
if CHKVAR("no-pistorm-dev") {
|
||||
pistorm_dev_enabled = 0;
|
||||
printf("[AMIGA] Disabling PiStorm interaction device.\n");
|
||||
@@ -609,6 +633,10 @@ void shutdown_platform_amiga(struct emulator_config *cfg) {
|
||||
if (pinet_enabled) {
|
||||
pinet_enabled = 0;
|
||||
}
|
||||
if (pi_ahi_enabled) {
|
||||
pi_ahi_shutdown();
|
||||
pi_ahi_enabled = 0;
|
||||
}
|
||||
if (a314_emulation_enabled) {
|
||||
a314_emulation_enabled = 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user