|
|
1.1 root 1: /*
1.1.1.6 root 2: Hatari - ymFormat.c
3:
1.1.1.14! root 4: This file is distributed under the GNU General Public License, version 2
! 5: or at 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.13 root 9: const char YMFormat_fileid[] = "Hatari ymFormat.c : " __DATE__ " " __TIME__;
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:
1.1.1.13 root 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: */
1.1.1.11 root 32: bool YMFormat_BeginRecording(const char *filename)
1.1 root 33: {
1.1.1.10 root 34: /* Free any previous data, don't save */
1.1.1.13 root 35: bRecordingYM = false;
1.1.1.10 root 36: YMFormat_EndRecording();
37:
38: /* Make sure we have a proper filename to use */
39: if (!filename || strlen(filename) <= 0)
40: {
1.1.1.13 root 41: return false;
1.1.1.10 root 42: }
43: pszYMFileName = strdup(filename);
44: if (!pszYMFileName)
45: {
1.1.1.13 root 46: return false;
1.1.1.10 root 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;
1.1.1.13 root 57: return false;
1.1.1.10 root 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.13 root 67: bRecordingYM = true; /* Ready to record */
1.1.1.10 root 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.13 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: *
1.1.1.13 root 87: * Convert to new workspace and return true if all OK.
1.1.1.10 root 88: */
1.1.1.11 root 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:
1.1.1.13 root 127: return true;
1.1.1.10 root 128: }
1.1.1.13 root 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 */
1.1.1.13 root 146: File_Save(pszYMFileName, pYMWorkspace,(size_t)(nYMVBLS*NUM_PSG_SOUND_REGISTERS)+4, false);
1.1.1.10 root 147: /* And inform user */
148: Log_AlertDlg(LOG_INFO, "YM sound data recording has been stopped.");
149: }
150: else
1.1.1.11 root 151: Log_AlertDlg(LOG_ERROR, "YM sound data conversion failed!");
1.1.1.10 root 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 */
1.1.1.13 root 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++)
1.1.1.11 root 183: *pYMData++ = SoundRegs[i];
1.1.1.10 root 184: /* Handle register '13'(PSG_REG_ENV_SHAPE) correctly - store 0xFF is did not write to this frame */
185: if (bEnvelopeFreqFlag)
1.1.1.11 root 186: *pYMData++ = SoundRegs[PSG_REG_ENV_SHAPE];
1.1.1.10 root 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.