|
|
1.1 root 1: /*
1.1.1.6 root 2: Hatari - ymFormat.c
3:
4: This file is distributed under the GNU Public License, version 2 or at
5: your option any later version. Read the file gpl.txt for details.
1.1 root 6:
7: YM File output, for use with STSound etc...
8: */
1.1.1.10! root 9: const char YMFormat_rcsid[] = "Hatari $Id: ymFormat.c,v 1.17 2007/10/31 21:31:50 eerot Exp $";
1.1 root 10:
11: #include "main.h"
1.1.1.7 root 12: #include "configuration.h"
1.1 root 13: #include "file.h"
1.1.1.7 root 14: #include "log.h"
1.1 root 15: #include "psg.h"
16: #include "sound.h"
17: #include "ymFormat.h"
1.1.1.7 root 18:
1.1 root 19:
1.1.1.2 root 20: #define YM_MAX_VBLS (50*60*8) /* 50=1 second, 50*60=1 minute, 50*60*8=8 minutes, or 24000 */
21: #define YM_RECORDSIZE (4+(YM_MAX_VBLS*NUM_PSG_SOUND_REGISTERS)) /* ~330k for 8 minutes */
1.1 root 22:
23: BOOL bRecordingYM = FALSE;
1.1.1.10! root 24: static int nYMVBLS = 0;
! 25: static Uint8 *pYMData, *pYMWorkspace = NULL;
! 26: static char *pszYMFileName = NULL;
1.1.1.2 root 27:
28: /*-----------------------------------------------------------------------*/
1.1.1.10! root 29: /**
! 30: * Start recording YM registers to workspace
! 31: */
! 32: BOOL YMFormat_BeginRecording(const char *filename)
1.1 root 33: {
1.1.1.10! root 34: /* Free any previous data, don't save */
! 35: bRecordingYM = FALSE;
! 36: YMFormat_EndRecording();
! 37:
! 38: /* Make sure we have a proper filename to use */
! 39: if (!filename || strlen(filename) <= 0)
! 40: {
! 41: return FALSE;
! 42: }
! 43: pszYMFileName = strdup(filename);
! 44: if (!pszYMFileName)
! 45: {
! 46: return FALSE;
! 47: }
! 48:
! 49: /* Create YM workspace */
! 50: pYMWorkspace = (Uint8 *)malloc(YM_RECORDSIZE);
! 51:
! 52: if (!pYMWorkspace)
! 53: {
! 54: /* Failed to allocate memory, cannot record */
! 55: free(pszYMFileName);
! 56: pszYMFileName = NULL;
! 57: return FALSE;
! 58: }
! 59:
! 60: /* Get workspace pointer and store 4 byte header */
! 61: pYMData = pYMWorkspace;
! 62: *pYMData++ = 'Y';
! 63: *pYMData++ = 'M';
! 64: *pYMData++ = '3';
! 65: *pYMData++ = '!';
1.1.1.6 root 66:
1.1.1.10! root 67: bRecordingYM = TRUE; /* Ready to record */
! 68: nYMVBLS = 0; /* Number of VBLs of information */
1.1.1.6 root 69:
1.1.1.10! root 70: /* And inform user */
! 71: Log_AlertDlg(LOG_INFO, "YM sound data recording has been started.");
1.1.1.6 root 72:
1.1.1.10! root 73: return TRUE;
1.1 root 74: }
75:
1.1.1.2 root 76:
77: /*-----------------------------------------------------------------------*/
1.1.1.10! root 78: /**
! 79: * Convert YM data to stream for output
! 80: *
! 81: * Data is:
! 82: * 4 Byte header 'YM3!'
! 83: * VBL Count x 14 PSG registers
! 84: * BUT
! 85: * We need data in a register stream, eg Reg 0, VBL 1, VBL 2, VBL n and then next register...
! 86: *
! 87: * Convert to new workspace and return TRUE if all OK
! 88: */
! 89: static BOOL YMFormat_ConvertToStreams(void)
1.1 root 90: {
1.1.1.10! root 91: Uint8 *pNewYMWorkspace;
! 92: Uint8 *pTmpYMData, *pNewYMData;
! 93: Uint8 *pTmpYMStream, *pNewYMStream;
! 94: int Reg, Count;
! 95:
! 96: /* Allocate new workspace to convert data to */
! 97: pNewYMWorkspace = (Uint8 *)malloc(YM_RECORDSIZE);
! 98: if (pNewYMWorkspace)
! 99: {
! 100: /* Convert data, first copy over header */
! 101: pTmpYMData = pYMWorkspace;
! 102: pNewYMData = pNewYMWorkspace;
! 103: *pNewYMData++ = *pTmpYMData++;
! 104: *pNewYMData++ = *pTmpYMData++;
! 105: *pNewYMData++ = *pTmpYMData++;
! 106: *pNewYMData++ = *pTmpYMData++;
! 107:
! 108: /* Now copy over each stream */
! 109: for(Reg=0; Reg<NUM_PSG_SOUND_REGISTERS; Reg++)
! 110: {
! 111: /* Get pointer to source / destination */
! 112: pTmpYMStream = pTmpYMData + Reg;
! 113: pNewYMStream = pNewYMData + (Reg*nYMVBLS);
! 114:
! 115: /* Copy recording VBLs worth */
! 116: for(Count=0; Count<nYMVBLS; Count++)
! 117: {
! 118: *pNewYMStream++ = *pTmpYMStream;
! 119: pTmpYMStream += NUM_PSG_SOUND_REGISTERS;
! 120: }
! 121: }
! 122:
! 123: /* Delete old workspace and assign new */
! 124: free(pYMWorkspace);
! 125: pYMWorkspace = pNewYMWorkspace;
! 126:
! 127: return TRUE;
! 128: }
! 129: return FALSE;
1.1 root 130: }
131:
1.1.1.2 root 132:
133: /*-----------------------------------------------------------------------*/
1.1.1.10! root 134: /**
! 135: * End recording YM registers and save as '.YM' file
! 136: */
! 137: void YMFormat_EndRecording(void)
1.1 root 138: {
1.1.1.10! root 139: /* Recording, have recorded information? */
! 140: if (bRecordingYM && pszYMFileName && pYMWorkspace && nYMVBLS)
! 141: {
! 142: /* Convert YM to correct format(list of register 1, then register 2...) */
! 143: if (YMFormat_ConvertToStreams())
! 144: {
! 145: /* Save YM File */
! 146: File_Save(pszYMFileName, pYMWorkspace,(size_t)(nYMVBLS*NUM_PSG_SOUND_REGISTERS)+4, FALSE);
! 147: /* And inform user */
! 148: Log_AlertDlg(LOG_INFO, "YM sound data recording has been stopped.");
! 149: }
! 150: else
! 151: Log_AlertDlg(LOG_INFO, "YM sound data conversion failed!");
! 152:
! 153: }
! 154: /* And free */
! 155: if (pYMWorkspace)
! 156: {
! 157: free(pYMWorkspace);
! 158: pYMWorkspace = NULL;
! 159: }
! 160: if (pszYMFileName)
! 161: {
! 162: free(pszYMFileName);
! 163: pszYMFileName = NULL;
! 164: }
! 165: /* Stop recording */
! 166: bRecordingYM = FALSE;
1.1 root 167: }
168:
1.1.1.2 root 169:
170: /*-----------------------------------------------------------------------*/
1.1.1.10! root 171: /**
! 172: * Store a VBLs worth of YM registers to workspace - call each VBL
! 173: */
1.1 root 174: void YMFormat_UpdateRecording(void)
175: {
1.1.1.10! root 176: int i;
1.1 root 177:
1.1.1.10! root 178: /* Can record this VBL information? */
! 179: if (bRecordingYM)
! 180: {
! 181: /* Copy VBL registers to workspace */
! 182: for(i=0; i<(NUM_PSG_SOUND_REGISTERS-1); i++)
! 183: *pYMData++ = PSGRegisters[i];
! 184: /* Handle register '13'(PSG_REG_ENV_SHAPE) correctly - store 0xFF is did not write to this frame */
! 185: if (bEnvelopeFreqFlag)
! 186: *pYMData++ = PSGRegisters[PSG_REG_ENV_SHAPE];
! 187: else
! 188: *pYMData++ = 0xff;
! 189:
! 190: /* Increase VBL count */
! 191: nYMVBLS++;
! 192: /* If run out of workspace, just save */
! 193: if (nYMVBLS>=YM_MAX_VBLS)
! 194: YMFormat_EndRecording();
! 195: }
1.1 root 196: }
197:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.