This is vic20sound.c in view mode; [Download] [Up]
/* * vic20sound.c - implementation of VIC20 sound code * * Written by * Teemu Rantanen (tvr@cs.hut.fi) * * This file is part of VICE, the Versatile Commodore Emulator. * See README for copyright notice. * * 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. * */ #include <stdio.h> #include "vice.h" #include "sound.h" #include "maincpu.h" #include "utils.h" #include "vic20sound.h" /* warnings */ static warn_t *pwarn; /* argh */ static BYTE siddata[16]; /* noise magic */ #define NSHIFT(v, n) (((v)<<(n))|((((v)>>(23-(n)))^(v>>(18-(n))))&((1<<(n))-1))) #define NVALUE(v) (noiseLSB[v&0xff]|noiseMID[(v>>8)&0xff]|noiseMSB[(v>>16)&0xff]) #define NSEED 0x7ffff8 /* Noise tables */ #define NOISETABLESIZE 256 static BYTE noiseMSB[NOISETABLESIZE]; static BYTE noiseMID[NOISETABLESIZE]; static BYTE noiseLSB[NOISETABLESIZE]; /* needed data for one voice */ typedef struct voice_s { /* counter value */ DWORD f; /* counter step / sample */ DWORD fs; /* noise shift register. Note! rv may be 0 to 15 shifts 'behind' the real noise shift register value. Remaining shifts are done when it is referenced */ DWORD rv; } voice_t; /* needed data for SID */ struct sound_s { /* number of voices */ voice_t v[4]; /* 4-bit volume value */ BYTE vol; /* internal constant used for sample rate dependent calculations */ DWORD speed1; }; int sound_machine_calculate_samples(sound_t *psid, SWORD *pbuf, int nr) { int i; DWORD o0, o1, o2, o3; for (i = 0; i < nr; i++) { /* addfptrs */ psid->v[0].f += psid->v[0].fs; psid->v[1].f += psid->v[1].fs; psid->v[2].f += psid->v[2].fs; psid->v[3].f += psid->v[3].fs; /* noise */ if (psid->v[3].f < psid->v[3].fs) psid->v[3].rv = NSHIFT(psid->v[3].rv, 16); /* voices */ o0 = (psid->v[0].f & 0x80000000) >> 2; o1 = (psid->v[1].f & 0x80000000) >> 2; o2 = (psid->v[2].f & 0x80000000) >> 2; o3 = (DWORD)NVALUE(NSHIFT(psid->v[3].rv, psid->v[3].f >> 28)) << 22; /* sample */ pbuf[i] = ((SDWORD)((o0+o1+o2+o3)>>20)-0x800)*psid->vol; } return 0; } /* SID initialization routine */ sound_t *sound_machine_open(int speed, int cycles_per_sec) { DWORD i; sound_t *psid; psid = xmalloc(sizeof(*psid)); memset(psid, 0, sizeof(psid)); psid->speed1 = (cycles_per_sec << 8) / speed; psid->v[3].rv = NSEED; for (i = 0; i < NOISETABLESIZE; i++) { noiseLSB[i] = (((i>>(7-2))&0x04)|((i>>(4-1))&0x02)|((i>>(2-0))&0x01)); noiseMID[i] = (((i>>(13-8-4))&0x10)|((i<<(3-(11-8)))&0x08)); noiseMSB[i] = (((i<<(7-(22-16)))&0x80)|((i<<(6-(20-16)))&0x40) |((i<<(5-(16-16)))&0x20)); } for (i = 0; i < 16; i++) sound_machine_store(psid, i, siddata[i]); return psid; } void sound_machine_close(sound_t *psid) { free(psid); } void sound_reset(void) { int i; for (i = 10; i < 15; i++) store_sound(i, 0); warn_reset(pwarn); sound_prevent_clk_overflow(clk); } void sound_machine_init(void) { pwarn = warn_init("SOUNDVIC20", 128); } /* * XXX: This is _really_ experimental */ #define VIC20FREQBASE 65535 void store_sound(ADDRESS addr, BYTE value) { addr &= 0x0f; siddata[addr] = value; sound_store(addr, value); } void sound_machine_store(sound_t *psid, ADDRESS addr, BYTE value) { DWORD freq; int sbase, shift, div; #if 0 { char *t = " "; warn(pwarn, 8, "Sound support for VIC20 is at _very_ experimental stage.\n" "%sIf you think this doesn't sound right, please wait\n" "%sfor the next snapshot or help me get this right.\n" "%s // tvr", t, t, t); } #endif switch (addr) { case 10: case 11: case 12: case 13: sbase = (addr - 10)*4; shift = addr - 10; if (addr == 13) shift = 0; div = 255 - value; /* XXX: ? */ if (!div) div = 127; if (!(value & 0x80)) freq = 0; else freq = VIC20FREQBASE*(1 << shift)/div; psid->v[addr - 10].fs = psid->speed1 * freq; break; case 14: /* volume */ psid->vol = value & 0x0f; break; } } void sound_machine_prevent_clk_overflow(sound_t *psid, CLOCK sub) { } BYTE sound_machine_read(sound_t *psid, ADDRESS addr) { abort(); return 0; } char *sound_machine_dump_state(sound_t *psid) { char buf[1024]; sprintf(buf, "#SID: clk=%d v=%d\n", clk, psid->vol); return stralloc(buf); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.