Search
lxdream.org :: lxdream :: r465:3bd7be575792
lxdream 0.9.1
released Jun 29
Download Now
changeset465:3bd7be575792
parent464:8e099fad42a6
child466:a6935f46ed78
authornkeynes
dateSat 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
src/aica/aica.h
src/aica/audio.c
src/aica/audio.h
1.1 --- a/src/aica/aica.c Sat Oct 27 05:44:54 2007 +0000
1.2 +++ b/src/aica/aica.c Sat Oct 27 05:47:21 2007 +0000
1.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 well
1.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.17
1.18 -/* 20 years in seconds */
1.19 -#define RTC_OFFSET 631152000
1.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 the
1.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) state
1.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.38
1.39 /**
1.40 * Initialize the AICA subsystem. Note requires that
1.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.53
1.54 void aica_start( void )
1.55 @@ -71,29 +90,22 @@
1.56
1.57 }
1.58
1.59 -/**
1.60 - * Keep track of what we've done so far this second, to try to keep the
1.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.75
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.93
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.100
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.108
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 should
1.113 * work in the meantime.
1.114 */
1.115
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.123
1.124 int pending = MMIO_READ( AICA2, AICA_IRQ );
1.125 if( pending == 0 || event < pending )
1.126 @@ -133,24 +146,24 @@
1.127
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.137
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 +0000
2.2 +++ b/src/aica/aica.h Sat Oct 27 05:47:21 2007 +0000
2.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 defined
2.9 * here are relative to the SH4 memory map (0x00700000 based), rather than
2.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 timestamp
2.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 +0000
3.2 +++ b/src/aica/audio.c Sat Oct 27 05:47:21 2007 +0000
3.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 sound
3.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.17
3.18 audio_driver_t audio_driver = NULL;
3.19 @@ -48,6 +48,20 @@
3.20 extern char *arm_mem;
3.21
3.22 /**
3.23 + * Preserve audio channel state only - don't bother saving the buffers
3.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 the
3.38 * output buffers, flushing any current data and reallocating as
3.39 * necessary.
3.40 @@ -189,7 +203,7 @@
3.41
3.42 memset( &result_buf, 0, sizeof(result_buf) );
3.43
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 +0000
4.2 +++ b/src/aica/audio.h Sat Oct 27 05:47:21 2007 +0000
4.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 1
4.12
4.13 #include <stdint.h>
4.14 +#include <stdio.h>
4.15 #include <glib/gtypes.h>
4.16
4.17 #ifdef __cplusplus
4.18 extern "C" {
4.19 #endif
4.20
4.21 +#define AUDIO_CHANNEL_COUNT 64
4.22 +
4.23 #define AUDIO_FMT_8BIT 0
4.24 #define AUDIO_FMT_16BIT 1
4.25 #define AUDIO_FMT_ADPCM 2
4.26 @@ -107,6 +110,8 @@
4.27 void audio_start_channel( int channel );
4.28 void audio_stop_channel( int channel );
4.29
4.30 +void audio_save_state( FILE *f );
4.31 +int audio_load_state( FILE *f );
4.32
4.33 #ifdef __cplusplus
4.34 }
.