revision 465:3bd7be575792
summary |
tree |
shortlog |
changelog |
graph |
changeset |
raw | bz2 | zip | gz changeset | 465:3bd7be575792 |
parent | 464:8e099fad42a6 |
child | 466:a6935f46ed78 |
author | nkeynes |
date | Sat Oct 27 05:47:21 2007 +0000 (16 years ago) |
Fix AICA save state section to include the current audio + IO state
![]() | src/aica/aica.c | view | annotate | diff | log | |
![]() | src/aica/aica.h | view | annotate | diff | log | |
![]() | src/aica/audio.c | view | annotate | diff | log | |
![]() | src/aica/audio.h | view | annotate | diff | log |
1.1 --- a/src/aica/aica.c Sat Oct 27 05:44:54 2007 +00001.2 +++ b/src/aica/aica.c Sat Oct 27 05:47:21 2007 +00001.3 @@ -1,7 +1,8 @@1.4 /**1.5 - * $Id: aica.c,v 1.24 2007-10-24 21:24:09 nkeynes Exp $1.6 + * $Id: aica.c,v 1.25 2007-10-27 05:47:21 nkeynes Exp $1.7 *1.8 - * This is the core sound system (ie the bit which does the actual work)1.9 + * This module implements the AICA's IO interfaces, as well1.10 + * as providing the core AICA module to the system.1.11 *1.12 * Copyright (c) 2005 Nathan Keynes.1.13 *1.14 @@ -43,9 +44,23 @@1.15 aica_start, aica_run_slice, aica_stop,1.16 aica_save_state, aica_load_state };1.18 -/* 20 years in seconds */1.19 -#define RTC_OFFSET 6311520001.20 -unsigned int aica_time_of_day = 0;1.21 +struct aica_state_struct {1.22 + uint32_t time_of_day;1.23 + /**1.24 + * Keep track of what we've done so far this second, to try to keep the1.25 + * precision of samples/second.1.26 + */1.27 + uint32_t samples_done;1.28 + uint32_t nanosecs_done;1.29 + /**1.30 + * Event (IRQ) state1.31 + */1.32 + int event_pending;1.33 + int clear_count;1.34 +};1.35 +1.36 +static struct aica_state_struct aica_state;1.37 +1.39 /**1.40 * Initialize the AICA subsystem. Note requires that1.41 @@ -62,8 +77,12 @@1.42 void aica_reset( void )1.43 {1.44 arm_reset();1.45 + aica_state.time_of_day = 0x5bfc8900;1.46 + aica_state.samples_done = 0;1.47 + aica_state.nanosecs_done = 0;1.48 + aica_state.event_pending = 0;1.49 + aica_state.clear_count = 0;1.50 aica_event(2); /* Pre-deliver a timer interrupt */1.51 - aica_time_of_day = 0x5bfc8900;1.52 }1.54 void aica_start( void )1.55 @@ -71,29 +90,22 @@1.57 }1.59 -/**1.60 - * Keep track of what we've done so far this second, to try to keep the1.61 - * precision of samples/second.1.62 - */1.63 -int samples_done = 0;1.64 -uint32_t nanosecs_done = 0;1.65 -1.66 uint32_t aica_run_slice( uint32_t nanosecs )1.67 {1.68 /* Run arm instructions */1.69 int reset = MMIO_READ( AICA2, AICA_RESET );1.70 if( (reset & 1) == 0 ) { /* Running */1.71 - int num_samples = (int)((uint64_t)AICA_SAMPLE_RATE * (nanosecs_done + nanosecs) / 1000000000) - samples_done;1.72 + int num_samples = (int)((uint64_t)AICA_SAMPLE_RATE * (aica_state.nanosecs_done + nanosecs) / 1000000000) - aica_state.samples_done;1.73 num_samples = arm_run_slice( num_samples );1.74 audio_mix_samples( num_samples );1.76 - samples_done += num_samples;1.77 - nanosecs_done += nanosecs;1.78 + aica_state.samples_done += num_samples;1.79 + aica_state.nanosecs_done += nanosecs;1.80 }1.81 - if( nanosecs_done > 1000000000 ) {1.82 - samples_done -= AICA_SAMPLE_RATE;1.83 - nanosecs_done -= 1000000000;1.84 - aica_time_of_day++;1.85 + if( aica_state.nanosecs_done > 1000000000 ) {1.86 + aica_state.samples_done -= AICA_SAMPLE_RATE;1.87 + aica_state.nanosecs_done -= 1000000000;1.88 + aica_state.time_of_day++;1.89 }1.90 return nanosecs;1.91 }1.92 @@ -105,26 +117,27 @@1.94 void aica_save_state( FILE *f )1.95 {1.96 + fwrite( &aica_state, sizeof(struct aica_state_struct), 1, f );1.97 arm_save_state( f );1.98 + audio_save_state(f);1.99 }1.101 int aica_load_state( FILE *f )1.102 {1.103 - return arm_load_state( f );1.104 + fread( &aica_state, sizeof(struct aica_state_struct), 1, f );1.105 + arm_load_state( f );1.106 + return audio_load_state(f);1.107 }1.109 -int aica_event_pending = 0;1.110 -int aica_clear_count = 0;1.111 -1.112 /* Note: This is probably not necessarily technically correct but it should1.113 * work in the meantime.1.114 */1.116 void aica_event( int event )1.117 {1.118 - if( aica_event_pending == 0 )1.119 + if( aica_state.event_pending == 0 )1.120 armr.int_pending |= CPSR_F;1.121 - aica_event_pending |= (1<<event);1.122 + aica_state.event_pending |= (1<<event);1.124 int pending = MMIO_READ( AICA2, AICA_IRQ );1.125 if( pending == 0 || event < pending )1.126 @@ -133,24 +146,24 @@1.128 void aica_clear_event( )1.129 {1.130 - aica_clear_count++;1.131 - if( aica_clear_count == 4 ) {1.132 + aica_state.clear_count++;1.133 + if( aica_state.clear_count == 4 ) {1.134 int i;1.135 - aica_clear_count = 0;1.136 + aica_state.clear_count = 0;1.138 for( i=0; i<8; i++ ) {1.139 - if( aica_event_pending & (1<<i) ) {1.140 - aica_event_pending &= ~(1<<i);1.141 + if( aica_state.event_pending & (1<<i) ) {1.142 + aica_state.event_pending &= ~(1<<i);1.143 break;1.144 }1.145 }1.146 for( ;i<8; i++ ) {1.147 - if( aica_event_pending & (1<<i) ) {1.148 + if( aica_state.event_pending & (1<<i) ) {1.149 MMIO_WRITE( AICA2, AICA_IRQ, i );1.150 break;1.151 }1.152 }1.153 - if( aica_event_pending == 0 )1.154 + if( aica_state.event_pending == 0 )1.155 armr.int_pending &= ~CPSR_F;1.156 }1.157 }1.158 @@ -202,6 +215,7 @@1.159 void mmio_region_AICA2_write( uint32_t reg, uint32_t val )1.160 {1.161 uint32_t tmp;1.162 +1.163 switch( reg ) {1.164 case AICA_RESET:1.165 tmp = MMIO_READ( AICA2, AICA_RESET );1.166 @@ -209,8 +223,8 @@1.167 /* ARM enabled - execute a core reset */1.168 DEBUG( "ARM enabled" );1.169 arm_reset();1.170 - samples_done = 0;1.171 - nanosecs_done = 0;1.172 + aica_state.samples_done = 0;1.173 + aica_state.nanosecs_done = 0;1.174 } else if( (tmp&1) == 0 && (val&1) == 1 ) {1.175 DEBUG( "ARM disabled" );1.176 }1.177 @@ -255,10 +269,10 @@1.178 int32_t rv = 0;1.179 switch( reg ) {1.180 case AICA_RTCHI:1.181 - rv = (aica_time_of_day >> 16) & 0xFFFF;1.182 + rv = (aica_state.time_of_day >> 16) & 0xFFFF;1.183 break;1.184 case AICA_RTCLO:1.185 - rv = aica_time_of_day & 0xFFFF;1.186 + rv = aica_state.time_of_day & 0xFFFF;1.187 break;1.188 }1.189 // DEBUG( "Read AICA RTC %d => %08X", reg, rv );1.190 @@ -274,12 +288,12 @@1.191 break;1.192 case AICA_RTCLO:1.193 if( MMIO_READ( AICARTC, AICA_RTCEN ) & 0x01 ) {1.194 - aica_time_of_day = (aica_time_of_day & 0xFFFF0000) | (val & 0xFFFF);1.195 + aica_state.time_of_day = (aica_state.time_of_day & 0xFFFF0000) | (val & 0xFFFF);1.196 }1.197 break;1.198 case AICA_RTCHI:1.199 if( MMIO_READ( AICARTC, AICA_RTCEN ) & 0x01 ) {1.200 - aica_time_of_day = (aica_time_of_day & 0xFFFF) | (val<<16);1.201 + aica_state.time_of_day = (aica_state.time_of_day & 0xFFFF) | (val<<16);1.202 MMIO_WRITE( AICARTC, AICA_RTCEN, 0 );1.203 }1.204 break;
2.1 --- a/src/aica/aica.h Sat Oct 27 05:44:54 2007 +00002.2 +++ b/src/aica/aica.h Sat Oct 27 05:47:21 2007 +00002.3 @@ -1,5 +1,5 @@2.4 /**2.5 - * $Id: aica.h,v 1.11 2007-10-24 21:24:09 nkeynes Exp $2.6 + * $Id: aica.h,v 1.12 2007-10-27 05:47:21 nkeynes Exp $2.7 *2.8 * MMIO definitions for the AICA sound chip. Note that the regions defined2.9 * here are relative to the SH4 memory map (0x00700000 based), rather than2.10 @@ -82,3 +82,9 @@2.11 * per sample, which isn't cycle accurate at the moment.2.12 */2.13 #define AICA_SAMPLE_PERIOD (1000000000 / 44100)2.14 +2.15 +/**2.16 + * Offset between the AICA RTC and the unix timestamp2.17 + * (20 years expressed in seconds)2.18 + */2.19 +#define AICA_RTC_OFFSET 631152000
3.1 --- a/src/aica/audio.c Sat Oct 27 05:44:54 2007 +00003.2 +++ b/src/aica/audio.c Sat Oct 27 05:47:21 2007 +00003.3 @@ -1,5 +1,5 @@3.4 /**3.5 - * $Id: audio.c,v 1.10 2007-10-24 21:24:09 nkeynes Exp $3.6 + * $Id: audio.c,v 1.11 2007-10-27 05:47:21 nkeynes Exp $3.7 *3.8 * Audio mixer core. Combines all the active streams into a single sound3.9 * buffer for output.3.10 @@ -38,7 +38,7 @@3.11 uint32_t output_format;3.12 uint32_t output_rate;3.13 uint32_t output_sample_size;3.14 - struct audio_channel channels[64];3.15 + struct audio_channel channels[AUDIO_CHANNEL_COUNT];3.16 } audio;3.18 audio_driver_t audio_driver = NULL;3.19 @@ -48,6 +48,20 @@3.20 extern char *arm_mem;3.22 /**3.23 + * Preserve audio channel state only - don't bother saving the buffers3.24 + */3.25 +void audio_save_state( FILE *f )3.26 +{3.27 + fwrite( &audio.channels[0], sizeof(struct audio_channel), AUDIO_CHANNEL_COUNT, f );3.28 +}3.29 +3.30 +int audio_load_state( FILE *f )3.31 +{3.32 + int read = fread( &audio.channels[0], sizeof(struct audio_channel), AUDIO_CHANNEL_COUNT, f );3.33 + return (read == AUDIO_CHANNEL_COUNT ? 0 : -1 );3.34 +}3.35 +3.36 +/**3.37 * Set the output driver, sample rate and format. Also initializes the3.38 * output buffers, flushing any current data and reallocating as3.39 * necessary.3.40 @@ -189,7 +203,7 @@3.42 memset( &result_buf, 0, sizeof(result_buf) );3.44 - for( i=0; i < 64; i++ ) {3.45 + for( i=0; i < AUDIO_CHANNEL_COUNT; i++ ) {3.46 audio_channel_t channel = &audio.channels[i];3.47 if( channel->active ) {3.48 int32_t sample;
4.1 --- a/src/aica/audio.h Sat Oct 27 05:44:54 2007 +00004.2 +++ b/src/aica/audio.h Sat Oct 27 05:47:21 2007 +00004.3 @@ -1,5 +1,5 @@4.4 /**4.5 - * $Id: audio.h,v 1.9 2007-10-24 21:24:09 nkeynes Exp $4.6 + * $Id: audio.h,v 1.10 2007-10-27 05:47:21 nkeynes Exp $4.7 *4.8 * Audio engine, ie the part that does the actual work.4.9 *4.10 @@ -19,12 +19,15 @@4.11 #define dream_audio_H 14.13 #include <stdint.h>4.14 +#include <stdio.h>4.15 #include <glib/gtypes.h>4.17 #ifdef __cplusplus4.18 extern "C" {4.19 #endif4.21 +#define AUDIO_CHANNEL_COUNT 644.22 +4.23 #define AUDIO_FMT_8BIT 04.24 #define AUDIO_FMT_16BIT 14.25 #define AUDIO_FMT_ADPCM 24.26 @@ -107,6 +110,8 @@4.27 void audio_start_channel( int channel );4.28 void audio_stop_channel( int channel );4.30 +void audio_save_state( FILE *f );4.31 +int audio_load_state( FILE *f );4.33 #ifdef __cplusplus4.34 }
.