1
0
mirror of https://git.code.sf.net/p/fuse-emulator/fuse synced 2026-01-30 04:22:18 +03:00
Files
fuse/ay.c
2004-06-15 09:48:40 +00:00

137 lines
3.8 KiB
C

/* ay.c: AY-8-3912 routines
Copyright (c) 1999-2004 Philip Kendall
$Id$
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Author contact information:
E-mail: pak21-fuse@srcf.ucam.org
Postal address: 15 Crescent Road, Wokingham, Berks, RG40 2DB, England
*/
#include <config.h>
#include "compat.h"
#include "machine.h"
#include "printer.h"
#include "psg.h"
#include "sound.h"
/* Unused bits in the AY registers are silently zeroed out; these masks
accomplish this */
static const libspectrum_byte mask[ AY_REGISTERS ] = {
0xff, 0x0f, 0xff, 0x0f, 0xff, 0x0f, 0x1f, 0xff,
0x1f, 0x1f, 0x1f, 0xff, 0xff, 0x0f, 0xff, 0xff,
};
/* What happens when the AY register port (traditionally 0xfffd on the 128K
machines) is read from */
libspectrum_byte
ay_registerport_read( libspectrum_word port GCC_UNUSED, int *attached )
{
int current;
const libspectrum_byte port_input = 0xbf; /* always allow serial output */
*attached = 1;
current = machine_current->ay.current_register;
/* The AY I/O ports return input directly from the port when in
input mode; but in output mode, they return an AND between the
register value and the port input. So, allow for this when
reading R14... */
if( current == 14 ) {
if(machine_current->ay.registers[7] & 0x40)
return (port_input & machine_current->ay.registers[14]);
else
return port_input;
}
/* R15 is simpler to do, as the 8912 lacks the second I/O port, and
the input-mode input is always 0xff */
if( current == 15 && !( machine_current->ay.registers[7] & 0x80 ) )
return 0xff;
/* Otherwise return register value, appropriately masked */
return machine_current->ay.registers[ current ] & mask[ current ];
}
/* And when it's written to */
void
ay_registerport_write( libspectrum_word port GCC_UNUSED, libspectrum_byte b )
{
machine_current->ay.current_register = (b & 15);
}
/* What happens when the AY data port (traditionally 0xbffd on the 128K
machines) is written to; no corresponding read function as this
always returns 0xff */
void
ay_dataport_write( libspectrum_word port GCC_UNUSED, libspectrum_byte b )
{
int current;
current = machine_current->ay.current_register;
machine_current->ay.registers[ current ] = b & mask[ current ];
sound_ay_write( current, b, tstates );
if( psg_recording ) psg_write_register( current, b );
if( current == 14 ) printer_serial_write( b );
}
int
ay_from_snapshot( libspectrum_snap *snap, int capabilities )
{
size_t i;
if( capabilities & LIBSPECTRUM_MACHINE_CAPABILITY_AY ) {
ay_registerport_write( 0xfffd,
libspectrum_snap_out_ay_registerport( snap ) );
for( i = 0; i < AY_REGISTERS; i++ ) {
machine_current->ay.registers[i] =
libspectrum_snap_ay_registers( snap, i );
sound_ay_write( i, machine_current->ay.registers[i], 0 );
}
}
return 0;
}
int
ay_to_snapshot( libspectrum_snap *snap )
{
size_t i;
libspectrum_snap_set_out_ay_registerport(
snap, machine_current->ay.current_register
);
for( i = 0; i < AY_REGISTERS; i++ )
libspectrum_snap_set_ay_registers( snap, i,
machine_current->ay.registers[i] );
return 0;
}