SPC music playback tools for real snes apu

Dependencies:   mbed

Committer:
akkera102
Date:
Mon Jan 09 13:54:39 2017 +0000
Revision:
0:5bd52e196edb
first

Who changed what in which revision?

UserRevisionLine numberNew contents of line
akkera102 0:5bd52e196edb 1 /* hwapu - SPC music playback tools for real snes apu
akkera102 0:5bd52e196edb 2 * Copyright (C) 2004-2005 Raphael Assenat <raph@raphnet.net>
akkera102 0:5bd52e196edb 3 *
akkera102 0:5bd52e196edb 4 * This program is free software; you can redistribute it and/or modify
akkera102 0:5bd52e196edb 5 * it under the terms of the GNU General Public License as published by
akkera102 0:5bd52e196edb 6 * the Free Software Foundation; either version 2 of the License, or
akkera102 0:5bd52e196edb 7 * (at your option) any later version.
akkera102 0:5bd52e196edb 8 *
akkera102 0:5bd52e196edb 9 * This program is distributed in the hope that it will be useful,
akkera102 0:5bd52e196edb 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
akkera102 0:5bd52e196edb 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
akkera102 0:5bd52e196edb 12 * GNU General Public License for more details.
akkera102 0:5bd52e196edb 13 *
akkera102 0:5bd52e196edb 14 * You should have received a copy of the GNU General Public License
akkera102 0:5bd52e196edb 15 * along with this program; if not, write to the Free Software
akkera102 0:5bd52e196edb 16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
akkera102 0:5bd52e196edb 17 */
akkera102 0:5bd52e196edb 18 #include <stdio.h>
akkera102 0:5bd52e196edb 19 #include "apuplay.h"
akkera102 0:5bd52e196edb 20 #include "apu.h"
akkera102 0:5bd52e196edb 21 #include "dsploader.h"
akkera102 0:5bd52e196edb 22 #include "bootcode.h"
akkera102 0:5bd52e196edb 23 #ifdef PROGRESS_SPINNER
akkera102 0:5bd52e196edb 24 #include "pspin.h"
akkera102 0:5bd52e196edb 25 #endif
akkera102 0:5bd52e196edb 26
akkera102 0:5bd52e196edb 27 extern int g_debug;
akkera102 0:5bd52e196edb 28 extern int g_verbose;
akkera102 0:5bd52e196edb 29 extern int g_exit_now;
akkera102 0:5bd52e196edb 30 extern int g_playing;
akkera102 0:5bd52e196edb 31 extern int g_progress;
akkera102 0:5bd52e196edb 32
akkera102 0:5bd52e196edb 33 int LoadAPU_embedded(FILE *fptr)
akkera102 0:5bd52e196edb 34 {
akkera102 0:5bd52e196edb 35 int i=0, j=0, count=0, val=0;
akkera102 0:5bd52e196edb 36
akkera102 0:5bd52e196edb 37 unsigned char spc_pcl;
akkera102 0:5bd52e196edb 38 unsigned char spc_pch;
akkera102 0:5bd52e196edb 39 unsigned char spc_a;
akkera102 0:5bd52e196edb 40 unsigned char spc_x;
akkera102 0:5bd52e196edb 41 unsigned char spc_y;
akkera102 0:5bd52e196edb 42 unsigned char spc_sw;
akkera102 0:5bd52e196edb 43 unsigned char spc_sp;
akkera102 0:5bd52e196edb 44
akkera102 0:5bd52e196edb 45 // unsigned char spcdata[65536];
akkera102 0:5bd52e196edb 46 // unsigned char spcram[64];
akkera102 0:5bd52e196edb 47
akkera102 0:5bd52e196edb 48 unsigned char dsp_kon=0;
akkera102 0:5bd52e196edb 49 unsigned char dsp_flg=0;
akkera102 0:5bd52e196edb 50 unsigned char dsp_esa=0;
akkera102 0:5bd52e196edb 51 unsigned char dsp_edl=0;
akkera102 0:5bd52e196edb 52
akkera102 0:5bd52e196edb 53 unsigned char workbuf[64];
akkera102 0:5bd52e196edb 54
akkera102 0:5bd52e196edb 55 int echosize, echoregion, bootptr, readcount=0;
akkera102 0:5bd52e196edb 56
akkera102 0:5bd52e196edb 57 fseek(fptr, 0x25, SEEK_SET);
akkera102 0:5bd52e196edb 58
akkera102 0:5bd52e196edb 59 fread(&spc_pcl, 1, 1, fptr);
akkera102 0:5bd52e196edb 60 fread(&spc_pch, 1, 1, fptr);
akkera102 0:5bd52e196edb 61 fread(&spc_a, 1, 1, fptr);
akkera102 0:5bd52e196edb 62 fread(&spc_x, 1, 1, fptr);
akkera102 0:5bd52e196edb 63 fread(&spc_y, 1, 1, fptr);
akkera102 0:5bd52e196edb 64 fread(&spc_sw, 1, 1, fptr);
akkera102 0:5bd52e196edb 65 fread(&spc_sp, 1, 1, fptr);
akkera102 0:5bd52e196edb 66
akkera102 0:5bd52e196edb 67 if (g_debug) {
akkera102 0:5bd52e196edb 68 printf("PC: %02x%02x\n", spc_pch, spc_pcl);
akkera102 0:5bd52e196edb 69 printf("A: %02X\n", spc_a);
akkera102 0:5bd52e196edb 70 printf("X: %02X\n", spc_x);
akkera102 0:5bd52e196edb 71 printf("Y: %02X\n", spc_y);
akkera102 0:5bd52e196edb 72 printf("SW: %02X\n", spc_sw);
akkera102 0:5bd52e196edb 73 printf("SP: %02X\n", spc_sp);
akkera102 0:5bd52e196edb 74 }
akkera102 0:5bd52e196edb 75
akkera102 0:5bd52e196edb 76 apu_reset();
akkera102 0:5bd52e196edb 77 apu_initTransfer(0x0002);
akkera102 0:5bd52e196edb 78
akkera102 0:5bd52e196edb 79 if (g_verbose)
akkera102 0:5bd52e196edb 80 printf("Restoring dsp registers...\n");
akkera102 0:5bd52e196edb 81
akkera102 0:5bd52e196edb 82 if (g_exit_now || !g_playing) { apu_reset(); return 0; }
akkera102 0:5bd52e196edb 83
akkera102 0:5bd52e196edb 84 /* first, we send a small program called the dsploader which we will
akkera102 0:5bd52e196edb 85 * use to restore the DSP registers (with our modified KON and FLG to
akkera102 0:5bd52e196edb 86 * keep it silent) */
akkera102 0:5bd52e196edb 87 if (apu_writeBytes(dsploader, 16)) {
akkera102 0:5bd52e196edb 88 fprintf(stderr, "Timeout sending dsploader\n");
akkera102 0:5bd52e196edb 89 return -1;
akkera102 0:5bd52e196edb 90 }
akkera102 0:5bd52e196edb 91 apu_endTransfer(0x0002);
akkera102 0:5bd52e196edb 92
akkera102 0:5bd52e196edb 93 if (g_exit_now || !g_playing) { apu_reset(); return 0; }
akkera102 0:5bd52e196edb 94
akkera102 0:5bd52e196edb 95 /* restore the 128 dsp registers one by one with the help of the dsp loader. */
akkera102 0:5bd52e196edb 96 fseek(fptr, OFFSET_DSPDATA, SEEK_SET);
akkera102 0:5bd52e196edb 97 for (i=0; i<128; i+=64)
akkera102 0:5bd52e196edb 98 {
akkera102 0:5bd52e196edb 99 fread(workbuf, 64, 1, fptr);
akkera102 0:5bd52e196edb 100 for (j=0; j<64; j++)
akkera102 0:5bd52e196edb 101 {
akkera102 0:5bd52e196edb 102 /* mute all voices and stop all notes */
akkera102 0:5bd52e196edb 103 if (i+j == DSP_FLG) {
akkera102 0:5bd52e196edb 104 dsp_flg = workbuf[j]; // save it for later
akkera102 0:5bd52e196edb 105 workbuf[j] = DSP_FLG_MUTE|DSP_FLG_ECEN;
akkera102 0:5bd52e196edb 106 }
akkera102 0:5bd52e196edb 107 if (i+j == DSP_KON) {
akkera102 0:5bd52e196edb 108 dsp_kon = workbuf[j]; // save it for later
akkera102 0:5bd52e196edb 109 workbuf[j] = 0x00;
akkera102 0:5bd52e196edb 110 }
akkera102 0:5bd52e196edb 111
akkera102 0:5bd52e196edb 112 // take note of some values while we upload...
akkera102 0:5bd52e196edb 113 if (i+j == DSP_ESA) { dsp_esa = workbuf[j]; }
akkera102 0:5bd52e196edb 114 if (i+j == DSP_EDL) { dsp_edl = workbuf[j]; }
akkera102 0:5bd52e196edb 115
akkera102 0:5bd52e196edb 116 apu_write(1, workbuf[j]);
akkera102 0:5bd52e196edb 117 apu_write(0, i+j);
akkera102 0:5bd52e196edb 118 if (!apu_waitInport(0, i+j, 500)) {
akkera102 0:5bd52e196edb 119 if (apu_read(0)==0xaa) {
akkera102 0:5bd52e196edb 120 // fprintf(stderr, "ingored\n");
akkera102 0:5bd52e196edb 121 } else {
akkera102 0:5bd52e196edb 122 fprintf(stderr, "timeout 3\n"); return -1;
akkera102 0:5bd52e196edb 123 }
akkera102 0:5bd52e196edb 124 }
akkera102 0:5bd52e196edb 125
akkera102 0:5bd52e196edb 126 if (g_exit_now || !g_playing) { apu_reset(); return 0; }
akkera102 0:5bd52e196edb 127 #ifdef PROGRESS_SPINNER
akkera102 0:5bd52e196edb 128 if (g_progress) {
akkera102 0:5bd52e196edb 129 pspin_update();
akkera102 0:5bd52e196edb 130 }
akkera102 0:5bd52e196edb 131 #endif
akkera102 0:5bd52e196edb 132 }
akkera102 0:5bd52e196edb 133
akkera102 0:5bd52e196edb 134 }
akkera102 0:5bd52e196edb 135 // if (g_verbose)
akkera102 0:5bd52e196edb 136 // printf("\n");
akkera102 0:5bd52e196edb 137
akkera102 0:5bd52e196edb 138 /* after receiving 128 registers, the dsp loaded will jump
akkera102 0:5bd52e196edb 139 * inside the rom at address $ffc9. Once 0xAA appears in
akkera102 0:5bd52e196edb 140 * port0, the apu is ready for a new transfer. */
akkera102 0:5bd52e196edb 141 if (!apu_waitInport(0, 0xaa, 500)) {
akkera102 0:5bd52e196edb 142 fprintf(stderr, "timeout 4\n"); return -1;
akkera102 0:5bd52e196edb 143 }
akkera102 0:5bd52e196edb 144
akkera102 0:5bd52e196edb 145 // fseek(fptr, OFFSET_SPCRAM, SEEK_SET);
akkera102 0:5bd52e196edb 146 // fread(spcram, 64, 1, fptr);
akkera102 0:5bd52e196edb 147
akkera102 0:5bd52e196edb 148 /* save a bunch of registers to be restored
akkera102 0:5bd52e196edb 149 * later by the "bootcode" */
akkera102 0:5bd52e196edb 150 bootcode[BOOT_DSP_FLG] = dsp_flg;
akkera102 0:5bd52e196edb 151 bootcode[BOOT_DSP_KON] = dsp_kon;
akkera102 0:5bd52e196edb 152 bootcode[BOOT_A] = spc_a;
akkera102 0:5bd52e196edb 153 bootcode[BOOT_Y] = spc_y;
akkera102 0:5bd52e196edb 154 bootcode[BOOT_X] = spc_x;
akkera102 0:5bd52e196edb 155 bootcode[BOOT_SP] = spc_sp - 3; // save new stack pointer
akkera102 0:5bd52e196edb 156
akkera102 0:5bd52e196edb 157 /* save address $0000 and $0001 to be restored by "bootcode" */
akkera102 0:5bd52e196edb 158 fseek(fptr, OFFSET_SPCDATA, SEEK_SET);
akkera102 0:5bd52e196edb 159 fread(workbuf, 2, 1, fptr);
akkera102 0:5bd52e196edb 160 bootcode[0x01] = workbuf[0];
akkera102 0:5bd52e196edb 161 bootcode[0x04] = workbuf[1];
akkera102 0:5bd52e196edb 162
akkera102 0:5bd52e196edb 163 /* save most spc registers (0xf0 to 0xff) into bootcode to be restored
akkera102 0:5bd52e196edb 164 * later */
akkera102 0:5bd52e196edb 165 fseek(fptr, OFFSET_SPCDATA+0xf0, SEEK_SET);
akkera102 0:5bd52e196edb 166 fread(workbuf, 0x10, 1, fptr);
akkera102 0:5bd52e196edb 167 for (i=0xf0; i<=0xff; i++) {
akkera102 0:5bd52e196edb 168 switch (i)
akkera102 0:5bd52e196edb 169 {
akkera102 0:5bd52e196edb 170 case SPC_PORT0: bootcode[BOOT_SPC_PORT0] = workbuf[i-0xf0]; break;
akkera102 0:5bd52e196edb 171 case SPC_PORT1: bootcode[BOOT_SPC_PORT1] = workbuf[i-0xf0]; break;
akkera102 0:5bd52e196edb 172 case SPC_PORT2: bootcode[BOOT_SPC_PORT2] = workbuf[i-0xf0]; break;
akkera102 0:5bd52e196edb 173 case SPC_PORT3: bootcode[BOOT_SPC_PORT3] = workbuf[i-0xf0]; break;
akkera102 0:5bd52e196edb 174 case SPC_TIMER0: bootcode[BOOT_SPC_TIMER0] = workbuf[i-0xf0]; break;
akkera102 0:5bd52e196edb 175 case SPC_TIMER1: bootcode[BOOT_SPC_TIMER1] = workbuf[i-0xf0]; break;
akkera102 0:5bd52e196edb 176 case SPC_TIMER2: bootcode[BOOT_SPC_TIMER2] = workbuf[i-0xf0]; break;
akkera102 0:5bd52e196edb 177 case SPC_CONTROL: bootcode[BOOT_SPC_CONTROL] = workbuf[i-0xf0]; break;
akkera102 0:5bd52e196edb 178 case SPC_REGADD: bootcode[BOOT_SPC_REGADD] = workbuf[i-0xf0]; break;
akkera102 0:5bd52e196edb 179 }
akkera102 0:5bd52e196edb 180 }
akkera102 0:5bd52e196edb 181
akkera102 0:5bd52e196edb 182
akkera102 0:5bd52e196edb 183
akkera102 0:5bd52e196edb 184 /* to produce an echo effect, the dsp uses a memory region.
akkera102 0:5bd52e196edb 185 * ESA: Esa * 100h becomes the lead-off address of the echo
akkera102 0:5bd52e196edb 186 * region. Calculate this address... */
akkera102 0:5bd52e196edb 187 echoregion = dsp_esa * 256;
akkera102 0:5bd52e196edb 188
akkera102 0:5bd52e196edb 189 /* echo delay. The bigger the delay is, more memory is needed.
akkera102 0:5bd52e196edb 190 * calculate how much memory used... */
akkera102 0:5bd52e196edb 191 echosize = dsp_edl * 2048;
akkera102 0:5bd52e196edb 192 if (echosize==0) { echosize = 4; }
akkera102 0:5bd52e196edb 193
akkera102 0:5bd52e196edb 194 if (g_debug) {
akkera102 0:5bd52e196edb 195 printf("debug: echoregion: $%04x, size %d\n", echoregion, echosize);
akkera102 0:5bd52e196edb 196 }
akkera102 0:5bd52e196edb 197
akkera102 0:5bd52e196edb 198 apu_initTransfer(0x0002);
akkera102 0:5bd52e196edb 199 if (g_verbose)
akkera102 0:5bd52e196edb 200 printf("Restoring spc700 memory...\n");
akkera102 0:5bd52e196edb 201
akkera102 0:5bd52e196edb 202 if (g_debug) {
akkera102 0:5bd52e196edb 203 printf("debug: Sending spc memory from 0x02 to 0xef\n");
akkera102 0:5bd52e196edb 204 }
akkera102 0:5bd52e196edb 205 /* send the first part of the memory (0x02 to 0xef)
akkera102 0:5bd52e196edb 206 * After 0xef comes spc700 registers (0xf0 to 0xff). Those
akkera102 0:5bd52e196edb 207 * are taken care of by the bootcode. 0x00 and 0x01 are
akkera102 0:5bd52e196edb 208 * retored by the bootcode too. */
akkera102 0:5bd52e196edb 209 fseek(fptr, OFFSET_SPCDATA, SEEK_SET);
akkera102 0:5bd52e196edb 210 for (j=0; j<256; j+=64)
akkera102 0:5bd52e196edb 211 {
akkera102 0:5bd52e196edb 212 fread(workbuf, 64, 1, fptr);
akkera102 0:5bd52e196edb 213 for (i=0; i<0x40; i++) {
akkera102 0:5bd52e196edb 214 if (j+i>=0xf0) { break; }
akkera102 0:5bd52e196edb 215 if (j==0 && i<2) { continue; } // skip $0000 and $0001
akkera102 0:5bd52e196edb 216 apu_write(1, workbuf[i]);
akkera102 0:5bd52e196edb 217 apu_write(0, j+i-2);
akkera102 0:5bd52e196edb 218 if (!apu_waitInport(0, j+i-2, 500)) {
akkera102 0:5bd52e196edb 219 fprintf(stderr, "timeout 5\n"); return -1;
akkera102 0:5bd52e196edb 220 }
akkera102 0:5bd52e196edb 221 #ifdef PROGRESS_SPINNER
akkera102 0:5bd52e196edb 222 if (g_progress)
akkera102 0:5bd52e196edb 223 pspin_update();
akkera102 0:5bd52e196edb 224 #endif
akkera102 0:5bd52e196edb 225 if (g_exit_now || !g_playing) { apu_reset(); return 0; }
akkera102 0:5bd52e196edb 226 }
akkera102 0:5bd52e196edb 227 if (j+i>=0xf0) { break; }
akkera102 0:5bd52e196edb 228 }
akkera102 0:5bd52e196edb 229
akkera102 0:5bd52e196edb 230 // if (g_verbose)
akkera102 0:5bd52e196edb 231 // printf("\n");
akkera102 0:5bd52e196edb 232
akkera102 0:5bd52e196edb 233 if (apu_newTransfer(0x100)) { apu_reset(); return -1; }
akkera102 0:5bd52e196edb 234
akkera102 0:5bd52e196edb 235 if (g_debug) {
akkera102 0:5bd52e196edb 236 printf("debug: Sending spc memory from 0x100 to 0xffc0\n");
akkera102 0:5bd52e196edb 237 }
akkera102 0:5bd52e196edb 238 /* upload the external memory region data (0x100 (page 1) to 0xffbf (rom),
akkera102 0:5bd52e196edb 239 * and look for an area with the same consecutive value repeated 77 times */
akkera102 0:5bd52e196edb 240 fseek(fptr, OFFSET_SPCDATA+0x100, SEEK_SET);
akkera102 0:5bd52e196edb 241 bootptr = -1;
akkera102 0:5bd52e196edb 242 for (i=0x100; i <= 65471; i+= 16)
akkera102 0:5bd52e196edb 243 {
akkera102 0:5bd52e196edb 244 fread(workbuf, 16, 1, fptr);
akkera102 0:5bd52e196edb 245
akkera102 0:5bd52e196edb 246 for (j=0; j<16; j++) {
akkera102 0:5bd52e196edb 247 /* push program counter and status ward on stack */
akkera102 0:5bd52e196edb 248 if ((i+j) == (0x100 +spc_sp - 0)) {
akkera102 0:5bd52e196edb 249 workbuf[j] = spc_pch;
akkera102 0:5bd52e196edb 250 }
akkera102 0:5bd52e196edb 251 if ((i+j) == (0x100 +spc_sp - 1)) {
akkera102 0:5bd52e196edb 252 workbuf[j] = spc_pcl;
akkera102 0:5bd52e196edb 253 }
akkera102 0:5bd52e196edb 254 if ((i+j) == (0x100 +spc_sp - 2)) {
akkera102 0:5bd52e196edb 255 workbuf[j] = spc_sw;
akkera102 0:5bd52e196edb 256 }
akkera102 0:5bd52e196edb 257
akkera102 0:5bd52e196edb 258 if ((i > echoregion + echosize) || (i < echoregion) )
akkera102 0:5bd52e196edb 259 {
akkera102 0:5bd52e196edb 260 if (val==workbuf[j]) {
akkera102 0:5bd52e196edb 261 count++;
akkera102 0:5bd52e196edb 262 if (count>=77) {
akkera102 0:5bd52e196edb 263 bootptr = i+j-77;
akkera102 0:5bd52e196edb 264 // printf("nbptr: %d\n", i+j-77);
akkera102 0:5bd52e196edb 265 }
akkera102 0:5bd52e196edb 266 }
akkera102 0:5bd52e196edb 267 else {
akkera102 0:5bd52e196edb 268 val = workbuf[j];
akkera102 0:5bd52e196edb 269 count = 0;
akkera102 0:5bd52e196edb 270 }
akkera102 0:5bd52e196edb 271 }
akkera102 0:5bd52e196edb 272 else
akkera102 0:5bd52e196edb 273 {
akkera102 0:5bd52e196edb 274 count = 0;
akkera102 0:5bd52e196edb 275 }
akkera102 0:5bd52e196edb 276 }
akkera102 0:5bd52e196edb 277
akkera102 0:5bd52e196edb 278 if (apu_writeBytes(workbuf, 16))
akkera102 0:5bd52e196edb 279 {
akkera102 0:5bd52e196edb 280 fprintf(stderr, "Transfer error\n");
akkera102 0:5bd52e196edb 281 return -1;
akkera102 0:5bd52e196edb 282 }
akkera102 0:5bd52e196edb 283
akkera102 0:5bd52e196edb 284 if (i % 256 == 0) {
akkera102 0:5bd52e196edb 285 readcount += 256;
akkera102 0:5bd52e196edb 286 #ifdef PROGRESS_SPINNER
akkera102 0:5bd52e196edb 287 if (g_progress) {
akkera102 0:5bd52e196edb 288 pspin_update();
akkera102 0:5bd52e196edb 289 }
akkera102 0:5bd52e196edb 290 #endif
akkera102 0:5bd52e196edb 291 }
akkera102 0:5bd52e196edb 292 if (g_exit_now || !g_playing) { apu_reset(); return 0; }
akkera102 0:5bd52e196edb 293 }
akkera102 0:5bd52e196edb 294
akkera102 0:5bd52e196edb 295 // bootptr = 0x2e47;
akkera102 0:5bd52e196edb 296 if (g_debug) {
akkera102 0:5bd52e196edb 297 printf("debug: area for bootcode: $%04x (%02X)\n", bootptr, val);
akkera102 0:5bd52e196edb 298 }
akkera102 0:5bd52e196edb 299
akkera102 0:5bd52e196edb 300 /* we did not find an area of 77 consecutive identical byte values. */
akkera102 0:5bd52e196edb 301 if (bootptr == -1)
akkera102 0:5bd52e196edb 302 {
akkera102 0:5bd52e196edb 303 /* We will have to use the echo region. The region will need to be
akkera102 0:5bd52e196edb 304 * at least 77 bytes... */
akkera102 0:5bd52e196edb 305 if (echosize < 77) {
akkera102 0:5bd52e196edb 306 fprintf(stderr, "This spc file does not have sufficient ram to be loaded");
akkera102 0:5bd52e196edb 307 return -1;
akkera102 0:5bd52e196edb 308 }
akkera102 0:5bd52e196edb 309 else {
akkera102 0:5bd52e196edb 310 /* we will use the echo region */
akkera102 0:5bd52e196edb 311 bootptr = echoregion;
akkera102 0:5bd52e196edb 312 }
akkera102 0:5bd52e196edb 313 }
akkera102 0:5bd52e196edb 314
akkera102 0:5bd52e196edb 315 if (g_debug) {
akkera102 0:5bd52e196edb 316 printf("debug: Sending spc memory from 0xffc0 to 0xffff\n");
akkera102 0:5bd52e196edb 317 }
akkera102 0:5bd52e196edb 318 /* upload the external memory area overlapping with the rom... I guess
akkera102 0:5bd52e196edb 319 * if we write to those address from the SPC it really writes to this
akkera102 0:5bd52e196edb 320 * memory area, but if you read you'll probably get the ROM code. Maybe
akkera102 0:5bd52e196edb 321 * it's really Read/Write from the DSP point of view... TODO: Check this
akkera102 0:5bd52e196edb 322 *
akkera102 0:5bd52e196edb 323 * Maybe also setting SPC_CONTROL msb bit enables this region? It's not
akkera102 0:5bd52e196edb 324 * documented my manual...
akkera102 0:5bd52e196edb 325 * */
akkera102 0:5bd52e196edb 326 if (bootcode[BOOT_SPC_CONTROL] & 0x80) {
akkera102 0:5bd52e196edb 327 fseek(fptr, OFFSET_SPCRAM, SEEK_SET);
akkera102 0:5bd52e196edb 328 fread(workbuf, 64, 1, fptr);
akkera102 0:5bd52e196edb 329 }
akkera102 0:5bd52e196edb 330 else {
akkera102 0:5bd52e196edb 331 fseek(fptr, OFFSET_SPCDATA + 65472, SEEK_SET);
akkera102 0:5bd52e196edb 332 fread(workbuf, 64, 1, fptr);
akkera102 0:5bd52e196edb 333 }
akkera102 0:5bd52e196edb 334
akkera102 0:5bd52e196edb 335 if (apu_writeBytes(workbuf, 64)) {
akkera102 0:5bd52e196edb 336 return -1;
akkera102 0:5bd52e196edb 337 }
akkera102 0:5bd52e196edb 338
akkera102 0:5bd52e196edb 339 // if (g_verbose)
akkera102 0:5bd52e196edb 340 // printf("\n");
akkera102 0:5bd52e196edb 341
akkera102 0:5bd52e196edb 342 if (apu_newTransfer(bootptr)) { apu_reset(); return -1; }
akkera102 0:5bd52e196edb 343
akkera102 0:5bd52e196edb 344 /* Copy our bootcode into the area we found */
akkera102 0:5bd52e196edb 345 if (apu_writeBytes(bootcode, 77)) {
akkera102 0:5bd52e196edb 346 fprintf(stderr, "Bootcode transfer error\n");
akkera102 0:5bd52e196edb 347 return -1;
akkera102 0:5bd52e196edb 348 }
akkera102 0:5bd52e196edb 349
akkera102 0:5bd52e196edb 350 apu_endTransfer(bootptr);
akkera102 0:5bd52e196edb 351
akkera102 0:5bd52e196edb 352 //i = 0;
akkera102 0:5bd52e196edb 353 if (!apu_waitInport(0, 0x53, 500)) {
akkera102 0:5bd52e196edb 354 fprintf(stderr, "timeout 7\n");
akkera102 0:5bd52e196edb 355 return -1;
akkera102 0:5bd52e196edb 356 }
akkera102 0:5bd52e196edb 357
akkera102 0:5bd52e196edb 358 if (g_debug) {
akkera102 0:5bd52e196edb 359 printf("Setting final port values $%02X $%02X $%02X $%02X\n",
akkera102 0:5bd52e196edb 360 bootcode[BOOT_SPC_PORT0], bootcode[BOOT_SPC_PORT1],
akkera102 0:5bd52e196edb 361 bootcode[BOOT_SPC_PORT2], bootcode[BOOT_SPC_PORT3]);
akkera102 0:5bd52e196edb 362 }
akkera102 0:5bd52e196edb 363
akkera102 0:5bd52e196edb 364 /* Restore the ports to the value they
akkera102 0:5bd52e196edb 365 * had in the .spc (this is not done by the bootcode because
akkera102 0:5bd52e196edb 366 * Port0-3 have 2 different values (The value set internally is
akkera102 0:5bd52e196edb 367 * seen externaly and the value seen internally is set externally) */
akkera102 0:5bd52e196edb 368 apu_write(0, bootcode[BOOT_SPC_PORT0]);
akkera102 0:5bd52e196edb 369 apu_write(1, bootcode[BOOT_SPC_PORT1]);
akkera102 0:5bd52e196edb 370 apu_write(2, bootcode[BOOT_SPC_PORT2]);
akkera102 0:5bd52e196edb 371 apu_write(3, bootcode[BOOT_SPC_PORT3]);
akkera102 0:5bd52e196edb 372
akkera102 0:5bd52e196edb 373
akkera102 0:5bd52e196edb 374 if (g_exit_now || !g_playing) { apu_reset(); return 0; }
akkera102 0:5bd52e196edb 375 return 0;
akkera102 0:5bd52e196edb 376 }
akkera102 0:5bd52e196edb 377
akkera102 0:5bd52e196edb 378