SPC music playback tools for real snes apu

Dependencies:   mbed

Committer:
akkera102
Date:
Thu Jan 19 04:51:28 2017 +0000
Revision:
8:072621697467
Parent:
3:b845c0cf715a
fifth

Who changed what in which revision?

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