|
|
1.1 root 1: /*
1.1.1.4 root 2: Hatari - psg.c
1.1 root 3:
1.1.1.4 root 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.1.3 root 6:
1.1.1.4 root 7: Programmable Sound Generator (YM-2149) - PSG
1.1.1.3 root 8:
1.1.1.4 root 9: Also used for the printer (centronics) port emulation (PSG Port B, Register 15)
1.1 root 10: */
1.1.1.5 ! root 11: char PSG_rcsid[] = "Hatari $Id: psg.c,v 1.8 2005/09/25 21:32:25 thothy Exp $";
1.1 root 12:
13: #include "main.h"
1.1.1.3 root 14: #include "configuration.h"
1.1.1.4 root 15: #include "ioMem.h"
1.1.1.5 ! root 16: #include "joy.h"
1.1.1.4 root 17: #include "m68000.h"
1.1 root 18: #include "memorySnapShot.h"
19: #include "sound.h"
1.1.1.4 root 20: #include "printer.h" /* because Printer I/O goes through PSG Register 15 */
1.1.1.3 root 21: #include "psg.h"
22:
1.1 root 23:
1.1.1.4 root 24: Uint8 PSGRegisterSelect; /* 0xff8800 (read/write) */
25: Uint8 PSGRegisters[16]; /* Register in PSG, see PSG_REG_xxxx */
26:
27: static BOOL bLastWriteToIOB; /* boolean flag: did the last write to the PSG go to IOB? */
1.1 root 28:
29:
30: /*-----------------------------------------------------------------------*/
31: /*
32: Reset variables used in PSG
33: */
34: void PSG_Reset(void)
35: {
1.1.1.4 root 36: PSGRegisterSelect = 0;
37: memset(PSGRegisters, 0, sizeof(PSGRegisters));
38: bLastWriteToIOB = FALSE;
1.1 root 39: }
40:
1.1.1.2 root 41:
42: /*-----------------------------------------------------------------------*/
1.1 root 43: /*
1.1.1.4 root 44: Save/Restore snapshot of local variables ('MemorySnapShot_Store' handles type)
1.1 root 45: */
46: void PSG_MemorySnapShot_Capture(BOOL bSave)
47: {
1.1.1.4 root 48: /* Save/Restore details */
49: MemorySnapShot_Store(&PSGRegisterSelect, sizeof(PSGRegisterSelect));
50: MemorySnapShot_Store(PSGRegisters, sizeof(PSGRegisters));
51: MemorySnapShot_Store(&bLastWriteToIOB, sizeof(bLastWriteToIOB));
1.1 root 52: }
53:
1.1.1.2 root 54:
55: /*-----------------------------------------------------------------------*/
1.1 root 56: /*
1.1.1.4 root 57: Write byte to 0xff88000, this is used as a selector for when we read/write
58: to address 0xff8802
1.1 root 59: */
1.1.1.4 root 60: void PSG_SelectRegister_WriteByte(void)
1.1 root 61: {
1.1.1.4 root 62: PSGRegisterSelect = IoMem[0xff8800] & 0x0f; /* Store register to select (value in bits 0-3) */
63:
64: M68000_WaitState();
1.1 root 65: }
66:
1.1.1.2 root 67:
68: /*-----------------------------------------------------------------------*/
1.1 root 69: /*
1.1.1.5 ! root 70: Read byte from 0xff8800, returns PSG data
1.1 root 71: */
1.1.1.4 root 72: void PSG_SelectRegister_ReadByte(void)
1.1 root 73: {
1.1.1.5 ! root 74: if (PSGRegisterSelect == 14)
! 75: {
! 76: /* Second parallel port joystick uses centronics strobe bit as fire button: */
! 77: if (ConfigureParams.Joysticks.Joy[JOYID_PARPORT2].nJoystickMode != JOYSTICK_DISABLED)
! 78: {
! 79: if (Joy_GetStickData(JOYID_PARPORT2) & 0x80)
! 80: PSGRegisters[14] &= ~32;
! 81: else
! 82: PSGRegisters[14] |= 32;
! 83: }
! 84: }
! 85: else if (PSGRegisterSelect == 15)
! 86: {
! 87: /* PSG register 15 is parallel port data register - used by parallel port joysticks: */
! 88: if (ConfigureParams.Joysticks.Joy[JOYID_PARPORT1].nJoystickMode != JOYSTICK_DISABLED)
! 89: {
! 90: PSGRegisters[15] &= 0x0f;
! 91: PSGRegisters[15] |= ~Joy_GetStickData(JOYID_PARPORT1) << 4;
! 92: }
! 93: if (ConfigureParams.Joysticks.Joy[JOYID_PARPORT2].nJoystickMode != JOYSTICK_DISABLED)
! 94: {
! 95: PSGRegisters[15] &= 0xf0;
! 96: PSGRegisters[15] |= ~Joy_GetStickData(JOYID_PARPORT2) & 0x0f;
! 97: }
! 98: }
! 99:
1.1.1.4 root 100: /* Read data last selected by register */
101: IoMem[0xff8800] = PSGRegisters[PSGRegisterSelect];
102:
103: M68000_WaitState();
1.1 root 104: }
105:
1.1.1.2 root 106:
107: /*-----------------------------------------------------------------------*/
1.1 root 108: /*
1.1.1.4 root 109: Write byte to 0xff8802, stores according to PSG select register (write 0xff8800)
110: */
111: void PSG_DataRegister_WriteByte(void)
112: {
113: Sound_Update(); /* Create samples up until this point with current values */
114: PSGRegisters[PSGRegisterSelect] = IoMem[0xff8802]; /* Write value to PSGRegisters[] */
115:
116: switch (PSGRegisterSelect)
117: {
118:
119: /* Check registers 8,9 and 10 which are 'amplitude' for each channel and
120: * store if wrote to (to check for sample playback) */
121: case PSG_REG_CHANNEL_A_AMP:
122: bWriteChannelAAmp = TRUE;
123: break;
124: case PSG_REG_CHANNEL_B_AMP:
125: bWriteChannelBAmp = TRUE;
126: break;
127: case PSG_REG_CHANNEL_C_AMP:
128: bWriteChannelCAmp = TRUE;
129: break;
130:
131: case PSG_REG_ENV_SHAPE: /* Whenever 'write' to register 13, cause envelope to reset */
132: bEnvelopeFreqFlag = TRUE;
133: bWriteEnvelopeFreq = TRUE;
134: break;
135:
136: /*
137: * FIXME: This is only a prelimary dirty hack!
138: * Port B (Printer port) - writing here needs to be dispatched to the printer
139: * STROBE (Port A bit5) does a short LOW and back to HIGH when the char is valid
140: * To print you need to write the character byte to IOB and you need to toggle STROBE
141: * (like EmuTOS does)....therefor we print when STROBE gets low and last write access to
142: * the PSG was to IOB
143: */
144: case PSG_REG_IO_PORTA:
145: /* Printer dispatching only when printing is activated */
146: if (ConfigureParams.Printer.bEnablePrinting)
147: {
148: /* Is STROBE low and did the last write go to IOB? */
149: if ((PSGRegisters[PSG_REG_IO_PORTA]&32)==0 && bLastWriteToIOB)
150: {
151: /* Seems like we want to print something... */
152: Printer_TransferByteTo((unsigned char) PSGRegisters[PSG_REG_IO_PORTB]);
153: }
154: }
155: break;
156: }
157:
158: /* Remember if we wrote to IO Port B */
159: bLastWriteToIOB = (PSGRegisterSelect == PSG_REG_IO_PORTB);
160:
161: M68000_WaitState();
1.1 root 162: }
163:
1.1.1.2 root 164:
165: /*-----------------------------------------------------------------------*/
1.1 root 166: /*
167: Read byte from 0xff8802, returns 0xff
168: */
1.1.1.4 root 169: void PSG_DataRegister_ReadByte(void)
1.1 root 170: {
1.1.1.4 root 171: IoMem[0xff8802] = 0xff;
172:
173: M68000_WaitState();
1.1 root 174: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.