more SVP work
authornotaz <notasas@gmail.com>
Tue, 15 Jan 2008 18:55:10 +0000 (18:55 +0000)
committernotaz <notasas@gmail.com>
Tue, 15 Jan 2008 18:55:10 +0000 (18:55 +0000)
git-svn-id: file:///home/notaz/opt/svn/PicoDrive@320 be3aeb3a-fb24-0410-a615-afba39da0efa

Pico/PicoInt.h
Pico/VideoPort.c
Pico/carthw/carthw.h
Pico/carthw/svp/Memory.c
Pico/carthw/svp/imageformat.txt [new file with mode: 0644]
Pico/carthw/svp/ssp16.c
Pico/carthw/svp/svp.c
platform/linux/port_config.h

index ef0e8df..85b2579 100644 (file)
@@ -437,7 +437,7 @@ extern int PsndLen_exc_add;
 // VideoPort.c\r
 PICO_INTERNAL_ASM void PicoVideoWrite(unsigned int a,unsigned short d);\r
 PICO_INTERNAL_ASM unsigned int PicoVideoRead(unsigned int a);\r
-extern int (*PicoDmaHook)(unsigned int source, unsigned short **srcp, unsigned short **limitp);\r
+extern int (*PicoDmaHook)(unsigned int source, int len, unsigned short **srcp, unsigned short **limitp);\r
 \r
 // Misc.c\r
 PICO_INTERNAL void SRAMWriteEEPROM(unsigned int d);\r
index 1065618..f5d4e1b 100644 (file)
@@ -22,7 +22,7 @@ typedef unsigned int   u32;
 #define UTYPES_DEFINED\r
 #endif\r
 \r
-int (*PicoDmaHook)(unsigned int source, unsigned short **srcp, unsigned short **limitp) = NULL;\r
+int (*PicoDmaHook)(unsigned int source, int len, unsigned short **srcp, unsigned short **limitp) = NULL;\r
 \r
 static __inline void AutoIncrement(void)\r
 {\r
@@ -138,7 +138,7 @@ static void DmaSlow(int len)
       pd=(u16 *)(Pico.rom+(source&~1));\r
       pdend=(u16 *)(Pico.rom+Pico.romsize);\r
     }\r
-    else if (PicoDmaHook && PicoDmaHook(source, &pd, &pdend));\r
+    else if (PicoDmaHook && PicoDmaHook(source, len, &pd, &pdend));\r
     else {\r
       elprintf(EL_VDPDMA|EL_ANOMALY, "DmaSlow[%i] %06x->%04x: invalid src", Pico.video.type, source, a);\r
       return;\r
index 70fe1bc..397dc28 100644 (file)
@@ -3,8 +3,8 @@
 #include "svp/ssp16.h"
 
 typedef struct {
-       unsigned char ram[0x20000];
-       // TODO: IRAM?
+       unsigned char iram_rom[0x20000]; // IRAM (0-0x7ff) and program ROM (0x800-0x1ffff)
+       unsigned char dram[0x20000];
        ssp1601_t ssp1601;
 } svp_t;
 
index 84d942c..1dcaedb 100644 (file)
@@ -21,7 +21,7 @@ unsigned int PicoSVPRead16(unsigned int a, int realsize)
   unsigned int d = 0;
 
   if ((a & 0xfe0000) == 0x300000)
-    *(u16 *)(svp->ram + (a&0x1fffe)) = d;
+    d = *(u16 *)(svp->dram + (a&0x1fffe));
 
   elprintf(EL_UIO, "SVP r%i: [%06x] %04x @%06x", realsize, a&0xffffff, d, SekPc);
 
@@ -40,7 +40,7 @@ void PicoSVPWrite16(unsigned int a, unsigned int d, int realsize)
   static int clearing_ram = 0;
 
   if ((a & 0xfe0000) == 0x300000)
-    *(u16 *)(svp->ram + (a&0x1fffe)) = d;
+    *(u16 *)(svp->dram + (a&0x1fffe)) = d;
 
   // debug: detect RAM clears..
   CLEAR_DETECT(0x0221dc, 0x0221f0, "SVP RAM CLEAR (1)");
@@ -49,5 +49,9 @@ void PicoSVPWrite16(unsigned int a, unsigned int d, int realsize)
   clearing_ram = 0;
 
   elprintf(EL_UIO, "SVP w%i: [%06x], %04x @%06x", realsize, a&0xffffff, d, SekPc);
+
+  // just guessing here
+       if (a == 0xa15002) svp->ssp1601.gr[SSP_XST].h = d;
+  else if (a == 0xa15006) svp->ssp1601.gr[SSP_PM0].h = d;
 }
 
diff --git a/Pico/carthw/svp/imageformat.txt b/Pico/carthw/svp/imageformat.txt
new file mode 100644 (file)
index 0000000..a16eae7
--- /dev/null
@@ -0,0 +1,67 @@
+
+vscroll:                 1 (0); 209 (26) - alternates every 4 frames
+vram range for patterns: 0000-999f (low scr 0000-395f,72e0-999f;  high 3980-999f)
+name table address:      c000
+seen DMAs (in order):    [300002-3026c3]->[0020-26e1] len 4961
+                         [3026c2-303943]->[26e0-3961] len 2369
+                        [303942-306003]->[72e0-99a1] len 4961
+                        ---
+                        [306002-3086c3]->[3980-6041] len 4961
+                        [3086c2-309943]->[6040-72c1] len 2369
+                        [309942-30c003]->[72e0-99a2] len 4961
+tile arrangement:
+
+000: 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000
+001: 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000
+002: 001 003 005 007 009 00b 00d 00f 011 013 015 017 019 01b 01d 01f 021 023 025 027 029 02b 02d 02f 031 033 035 037 039 03b 03d 03f
+003: 002 004 006 008 00a 00c 00e 010 012 014 016 018 01a 01c 01e 020 022 024 026 028 02a 02c 02e 030 032 034 036 038 03a 03c 03e 040
+004: 041 043 045 047 049 04b 04d 04f 051 053 055 057 059 05b 05d 05f 061 063 065 067 069 06b 06d 06f 071 073 075 077 079 07b 07d 07f
+005: 042 044 046 048 04a 04c 04e 050 052 054 056 058 05a 05c 05e 060 062 064 066 068 06a 06c 06e 070 072 074 076 078 07a 07c 07e 080
+006: 081 083 085 087 089 08b 08d 08f 091 093 095 097 099 09b 09d 09f 0a1 0a3 0a5 0a7 0a9 0ab 0ad 0af 0b1 0b3 0b5 0b7 0b9 0bb 0bd 0bf
+007: 082 084 086 088 08a 08c 08e 090 092 094 096 098 09a 09c 09e 0a0 0a2 0a4 0a6 0a8 0aa 0ac 0ae 0b0 0b2 0b4 0b6 0b8 0ba 0bc 0be 0c0
+008: 0c1 0c3 0c5 0c7 0c9 0cb 0cd 0cf 0d1 0d3 0d5 0d7 0d9 0db 0dd 0df 0e1 0e3 0e5 0e7 0e9 0eb 0ed 0ef 0f1 0f3 0f5 0f7 0f9 0fb 0fd 0ff
+009: 0c2 0c4 0c6 0c8 0ca 0cc 0ce 0d0 0d2 0d4 0d6 0d8 0da 0dc 0de 0e0 0e2 0e4 0e6 0e8 0ea 0ec 0ee 0f0 0f2 0f4 0f6 0f8 0fa 0fc 0fe 100
+010: 101 103 105 107 109 10b 10d 10f 111 113 115 117 119 11b 11d 11f 121 123 125 127 129 12b 12d 12f 131 133 135 137 139 13b 13d 13f
+011: 102 104 106 108 10a 10c 10e 110 112 114 116 118 11a 11c 11e 120 122 124 126 128 12a 12c 12e 130 132 134 136 138 13a 13c 13e 140
+012: 141 143 145 147 149 14b 14d 14f 151 153 155 157 159 15b 15d 15f 161 163 165 167 169 16b 16d 16f 171 173 175 177 179 17b 17d 17f
+013: 142 144 146 148 14a 14c 14e 150 152 154 156 158 15a 15c 15e 160 162 164 166 168 16a 16c 16e 170 172 174 176 178 17a 17c 17e 180
+014: 181 183 185 187 189 18b 18d 18f 191 193 195 197 199 19b 19d 19f 1a1 1a3 1a5 1a7 1a9 1ab 1ad 1af 1b1 1b3 1b5 1b7 1b9 1bb 1bd 1bf
+015: 182 184 186 188 18a 18c 18e 190 192 194 196 198 19a 19c 19e 1a0 1a2 1a4 1a6 1a8 1aa 1ac 1ae 1b0 1b2 1b4 1b6 1b8 1ba 1bc 1be 1c0
+016: 1c1 1c3 1c5 1c7 1c9 397 399 39b 39d 39f 3a1 3a3 3a5 3a7 3a9 3ab 3ad 3af 3b1 3b3 3b5 3b7 3b9 3bb 3bd 3bf 3c1 3c3 3c5 3c7 3c9 3cb
+017: 1c2 1c4 1c6 1c8 1ca 398 39a 39c 39e 3a0 3a2 3a4 3a6 3a8 3aa 3ac 3ae 3b0 3b2 3b4 3b6 3b8 3ba 3bc 3be 3c0 3c2 3c4 3c6 3c8 3ca 3cc
+018: 3cd 3cf 3d1 3d3 3d5 3d7 3d9 3db 3dd 3df 3e1 3e3 3e5 3e7 3e9 3eb 3ed 3ef 3f1 3f3 3f5 3f7 3f9 3fb 3fd 3ff 401 403 405 407 409 40b
+019: 3ce 3d0 3d2 3d4 3d6 3d8 3da 3dc 3de 3e0 3e2 3e4 3e6 3e8 3ea 3ec 3ee 3f0 3f2 3f4 3f6 3f8 3fa 3fc 3fe 400 402 404 406 408 40a 40c
+020: 40d 40f 411 413 415 417 419 41b 41d 41f 421 423 425 427 429 42b 42d 42f 431 433 435 437 439 43b 43d 43f 441 443 445 447 449 44b
+021: 40e 410 412 414 416 418 41a 41c 41e 420 422 424 426 428 42a 42c 42e 430 432 434 436 438 43a 43c 43e 440 442 444 446 448 44a 44c
+022: 44d 44f 451 453 455 457 459 45b 45d 45f 461 463 465 467 469 46b 46d 46f 471 473 475 477 479 47b 47d 47f 481 483 485 487 489 48b
+023: 44e 450 452 454 456 458 45a 45c 45e 460 462 464 466 468 46a 46c 46e 470 472 474 476 478 47a 47c 47e 480 482 484 486 488 48a 48c
+024: 48d 48f 491 493 495 497 499 49b 49d 49f 4a1 4a3 4a5 4a7 4a9 4ab 4ad 4af 4b1 4b3 4b5 4b7 4b9 4bb 4bd 4bf 4c1 4c3 4c5 4c7 4c9 4cb
+025: 48e 490 492 494 496 498 49a 49c 49e 4a0 4a2 4a4 4a6 4a8 4aa 4ac 4ae 4b0 4b2 4b4 4b6 4b8 4ba 4bc 4be 4c0 4c2 4c4 4c6 4c8 4ca 4cc
+026: 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000
+027: 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000
+028: 1cc 1ce 1d0 1d2 1d4 1d6 1d8 1da 1dc 1de 1e0 1e2 1e4 1e6 1e8 1ea 1ec 1ee 1f0 1f2 1f4 1f6 1f8 1fa 1fc 1fe 200 202 204 206 208 20a
+029: 1cd 1cf 1d1 1d3 1d5 1d7 1d9 1db 1dd 1df 1e1 1e3 1e5 1e7 1e9 1eb 1ed 1ef 1f1 1f3 1f5 1f7 1f9 1fb 1fd 1ff 201 203 205 207 209 20b
+030: 20c 20e 210 212 214 216 218 21a 21c 21e 220 222 224 226 228 22a 22c 22e 230 232 234 236 238 23a 23c 23e 240 242 244 246 248 24a
+031: 20d 20f 211 213 215 217 219 21b 21d 21f 221 223 225 227 229 22b 22d 22f 231 233 235 237 239 23b 23d 23f 241 243 245 247 249 24b
+032: 24c 24e 250 252 254 256 258 25a 25c 25e 260 262 264 266 268 26a 26c 26e 270 272 274 276 278 27a 27c 27e 280 282 284 286 288 28a
+033: 24d 24f 251 253 255 257 259 25b 25d 25f 261 263 265 267 269 26b 26d 26f 271 273 275 277 279 27b 27d 27f 281 283 285 287 289 28b
+034: 28c 28e 290 292 294 296 298 29a 29c 29e 2a0 2a2 2a4 2a6 2a8 2aa 2ac 2ae 2b0 2b2 2b4 2b6 2b8 2ba 2bc 2be 2c0 2c2 2c4 2c6 2c8 2ca
+035: 28d 28f 291 293 295 297 299 29b 29d 29f 2a1 2a3 2a5 2a7 2a9 2ab 2ad 2af 2b1 2b3 2b5 2b7 2b9 2bb 2bd 2bf 2c1 2c3 2c5 2c7 2c9 2cb
+036: 2cc 2ce 2d0 2d2 2d4 2d6 2d8 2da 2dc 2de 2e0 2e2 2e4 2e6 2e8 2ea 2ec 2ee 2f0 2f2 2f4 2f6 2f8 2fa 2fc 2fe 300 302 304 306 308 30a
+037: 2cd 2cf 2d1 2d3 2d5 2d7 2d9 2db 2dd 2df 2e1 2e3 2e5 2e7 2e9 2eb 2ed 2ef 2f1 2f3 2f5 2f7 2f9 2fb 2fd 2ff 301 303 305 307 309 30b
+038: 30c 30e 310 312 314 316 318 31a 31c 31e 320 322 324 326 328 32a 32c 32e 330 332 334 336 338 33a 33c 33e 340 342 344 346 348 34a
+039: 30d 30f 311 313 315 317 319 31b 31d 31f 321 323 325 327 329 32b 32d 32f 331 333 335 337 339 33b 33d 33f 341 343 345 347 349 34b
+040: 34c 34e 350 352 354 356 358 35a 35c 35e 360 362 364 366 368 36a 36c 36e 370 372 374 376 378 37a 37c 37e 380 382 384 386 388 38a
+041: 34d 34f 351 353 355 357 359 35b 35d 35f 361 363 365 367 369 36b 36d 36f 371 373 375 377 379 37b 37d 37f 381 383 385 387 389 38b
+042: 38c 38e 390 392 394 397 399 39b 39d 39f 3a1 3a3 3a5 3a7 3a9 3ab 3ad 3af 3b1 3b3 3b5 3b7 3b9 3bb 3bd 3bf 3c1 3c3 3c5 3c7 3c9 3cb
+043: 38d 38f 391 393 395 398 39a 39c 39e 3a0 3a2 3a4 3a6 3a8 3aa 3ac 3ae 3b0 3b2 3b4 3b6 3b8 3ba 3bc 3be 3c0 3c2 3c4 3c6 3c8 3ca 3cc
+044: 3cd 3cf 3d1 3d3 3d5 3d7 3d9 3db 3dd 3df 3e1 3e3 3e5 3e7 3e9 3eb 3ed 3ef 3f1 3f3 3f5 3f7 3f9 3fb 3fd 3ff 401 403 405 407 409 40b
+045: 3ce 3d0 3d2 3d4 3d6 3d8 3da 3dc 3de 3e0 3e2 3e4 3e6 3e8 3ea 3ec 3ee 3f0 3f2 3f4 3f6 3f8 3fa 3fc 3fe 400 402 404 406 408 40a 40c
+046: 40d 40f 411 413 415 417 419 41b 41d 41f 421 423 425 427 429 42b 42d 42f 431 433 435 437 439 43b 43d 43f 441 443 445 447 449 44b
+047: 40e 410 412 414 416 418 41a 41c 41e 420 422 424 426 428 42a 42c 42e 430 432 434 436 438 43a 43c 43e 440 442 444 446 448 44a 44c
+048: 44d 44f 451 453 455 457 459 45b 45d 45f 461 463 465 467 469 46b 46d 46f 471 473 475 477 479 47b 47d 47f 481 483 485 487 489 48b
+049: 44e 450 452 454 456 458 45a 45c 45e 460 462 464 466 468 46a 46c 46e 470 472 474 476 478 47a 47c 47e 480 482 484 486 488 48a 48c
+050: 48d 48f 491 493 495 497 499 49b 49d 49f 4a1 4a3 4a5 4a7 4a9 4ab 4ad 4af 4b1 4b3 4b5 4b7 4b9 4bb 4bd 4bf 4c1 4c3 4c5 4c7 4c9 4cb
+051: 48e 490 492 494 496 498 49a 49c 49e 4a0 4a2 4a4 4a6 4a8 4aa 4ac 4ae 4b0 4b2 4b4 4b6 4b8 4ba 4bc 4be 4c0 4c2 4c4 4c6 4c8 4ca 4cc
+052: 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000
+053: 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000
index 26c4cac..da8409f 100644 (file)
  *   size: 16
  *   desc: Status register. From MAME: bits 0-9 are CONTROL, other FLAG
  *     fedc ba98 7654 3210
- *       210 - RPL (?)       (e: "loop size", fir16_32.sc)
+ *       210 - RPL (?)       "Loop size". If non-zero, makes (rX+) and (rX-) respectively
+ *                           modulo-increment and modulo-decrement. The value shows which
+ *                           power of 2 to use, i.e. 4 means modulo by 16.
+ *                           (e: fir16_32.sc, IIR_4B.SC, DECIM.SC)
  *       43  - RB (?)
- *       5   - GP0_0 (ST5?)  Changed before acessing AL (affects banking?).
- *       6   - GP0_1 (ST6?)  Cleared before acessing AL (affects banking?). Set after.
- *       7   - IE (?)        Not used by SVP code (never set, but preserved)?
- *       8   - OP (?)        Not used by SVP code (only cleared)?
+ *       5   - GP0_0 (ST5?)  Changed before acessing PM0 (affects banking?).
+ *       6   - GP0_1 (ST6?)  Cleared before acessing PM0 (affects banking?). Set after.
+ *                           datasheet says these (5,6) bits correspond to hardware pins.
+ *       7   - IE (?)        Not directly used by SVP code (never set, but preserved)?
+ *       8   - OP (?)        Not used by SVP code (only cleared)? (MAME: saturated value
+ *                           (probably means clamping? i.e. 0x7ffc + 9 -> 0x7fff))
  *       9   - MACS (?)      Not used by SVP code (only cleared)? (e: "mac shift")
  *       a   - GPI_0         Interrupt 0 enable/status?
  *       b   - GPI_1         Interrupt 1 enable/status?
  *
  *
  * There are 8 8-bit pointer registers rX. r0-r3 (ri) point to RAM0, r4-r7 (rj) point to RAM1.
- * They can be accessed directly, or 2 indirection levels can be used [ (r0), ((r0)) ],
- * which work similar to * and ** operators in C.
+ * They can be accessed directly, or 2 indirection levels can be used [ (rX), ((rX)) ],
+ * which work similar to * and ** operators in C, only they use different memory banks and
+ * ((rX)) also does post-increment. First indirection level (rX) accesses RAMx, second accesses
+ * program memory at address read from (rX), and increments value in (rX).
  *
  * r0,r1,r2,r4,r5,r6 can be modified [ex: ldi r0, 5].
  * 3 modifiers can be applied (optional):
- *  + : post-increment [ex: ld a, (r0+) ]
- *  - : post-decrement
- *  +!: same as '+' ???
+ *  + : post-increment [ex: ld a, (r0+) ]. Can be made modulo-increment by setting RPL bits in ST.
+ *  - : post-decrement. Can be made modulo-decrement by setting RPL bits in ST (not sure).
+ *  +!: post-increment, unaffected by RPL (probably).
+ * These are only used on 1st indirection level, so things like [ld a, ((r0+))] and [ld X, r6-]
+ * ar probably invalid.
  *
  * r3 and r7 are special and can not be changed (at least Samsung samples and SVP code never do).
  * They are fixed to the start of their RAM banks. (They are probably changeable for ssp1605+,
  *
  * Assumptions in this code
  *   P is not directly writeable
+ *   flags correspond to full 32bit accumulator
+ *   only Z and N status flags are emulated (others unused by SVP)
+ *   modifiers for 'OP a, ri' are ignored (invalid?/not used by SVP)
+ *   modifiers '+' and '+!' act the same (this is most likely wrong)
+ *   'ld d, (a)' loads from program ROM
  */
 
 #include "../../PicoInt.h"
 #define rPMC   ssp->gr[SSP_PMC]                // will keep addr in .h, mode in .l
 #define rAL    ssp->gr[SSP_A].l
 
-#define GET_PC() (PC - (unsigned short *)Pico.rom)
-#define GET_PC_OFFS() ((unsigned int)PC - (unsigned int)Pico.rom)
-#define SET_PC(d) PC = (unsigned short *)Pico.rom + d
+#define rA32   ssp->gr[SSP_A].v
+#define rIJ    ssp->r
+
+#define IJind  (((op>>6)&4)|(op&3))
+
+#define GET_PC() (PC - (unsigned short *)svp->iram_rom)
+#define GET_PPC_OFFS() ((unsigned int)PC - (unsigned int)svp->iram_rom - 2)
+#define SET_PC(d) PC = (unsigned short *)svp->iram_rom + d
 
 #define REG_READ(r) (((r) <= 4) ? ssp->gr[r].h : read_handlers[r]())
+// if r is 'A', should we set flags?
 #define REG_WRITE(r,d) { \
        int r1 = r; \
-       if (r1 > 4) write_handlers[r1](d); \
+       if (r1 >= 4) write_handlers[r1](d); \
        else if (r1 > 0) ssp->gr[r1].h = d; \
 }
 
+// flags
+#define FLAG_L (1<<0xc)
+#define FLAG_Z (1<<0xd)
+#define FLAG_V (1<<0xe)
+#define FLAG_N (1<<0xf)
+
+// update ZN according to 32bit ACC.
+#define UPD_ACC_ZN \
+       rST &= ~(FLAG_Z|FLAG_N); \
+       if (!rA32) rST |= FLAG_Z; \
+       else rST |= (rA32>>16)&FLAG_N;
+
+// it seems SVP code never checks for L and OV, so we leave them out.
+// rST |= (t>>4)&FLAG_L;
+#define UPD_t_LZVN \
+       rST &= ~(FLAG_L|FLAG_Z|FLAG_V|FLAG_N); \
+       if (!t) rST |= FLAG_Z; \
+       else    rST |= t&FLAG_N; \
+
+// standard cond processing.
+// again, only Z and N is checked, as SVP doesn't seem to use any other conds.
+#define COND_CHECK \
+       switch (op&0xf0) { \
+               case 0x00: cond = 1; break; /* always true */ \
+               case 0x50: cond = !((rST ^ (op<<5)) & FLAG_Z); break; /* Z matches f(?) bit */ \
+               case 0x70: cond = !((rST ^ (op<<7)) & FLAG_N); break; /* N matches f(?) bit */ \
+               default:elprintf(EL_SVP, "unimplemented cond @ %04x", GET_PPC_OFFS()); break; \
+       }
+
+// ops with accumulator.
+// how is low word really affected by these?
+// not sure if 'ld A' affects flags (assume it does..)
+#define OP_LDA(x) \
+       ssp->gr[SSP_A].h = x; \
+       UPD_ACC_ZN
+
+#define OP_SUBA(x) { \
+       u32 t = (ssp->gr[SSP_A].v >> 16) - (x); \
+       UPD_t_LZVN \
+       ssp->gr[SSP_A].h = t; \
+}
+
+#define OP_CMPA(x) { \
+       u32 t = (ssp->gr[SSP_A].v >> 16) - (x); \
+       UPD_t_LZVN \
+}
+
+#define OP_ADDA(x) { \
+       u32 t = (ssp->gr[SSP_A].v >> 16) + (x); \
+       UPD_t_LZVN \
+       ssp->gr[SSP_A].h = t; \
+}
+
+#define OP_ANDA(x) \
+       ssp->gr[SSP_A].v &= (x) << 16; \
+       UPD_ACC_ZN
+
+#define OP_ORA(x) \
+       ssp->gr[SSP_A].v |= (x) << 16; \
+       UPD_ACC_ZN
+
+#define OP_EORA(x) \
+       ssp->gr[SSP_A].v ^= (x) << 16; \
+       UPD_ACC_ZN
+
+
 static ssp1601_t *ssp = NULL;
 static unsigned short *PC;
 static int g_cycles;
+// debug
+static int running = 0;
 
 // -----------------------------------------------------
 // register i/o handlers
@@ -179,34 +267,45 @@ static int g_cycles;
 // 0-4, 13
 static u32 read_unknown(void)
 {
-       elprintf(EL_ANOMALY|EL_SVP, "ssp16: unknown read @ %04x", GET_PC_OFFS());
+       elprintf(EL_ANOMALY|EL_SVP, "ssp16: unknown read @ %04x", GET_PPC_OFFS());
        return 0;
 }
 
 static void write_unknown(u32 d)
 {
-       elprintf(EL_ANOMALY|EL_SVP, "ssp16: unknown write @ %04x", GET_PC_OFFS());
+       elprintf(EL_ANOMALY|EL_SVP, "ssp16: unknown write @ %04x", GET_PPC_OFFS());
+}
+
+// 4
+static void write_ST(u32 d)
+{
+       if ((rST ^ d) & 7) {
+               elprintf(EL_SVP, "ssp16: RPL %i -> %i @ %04x", rST&7, d&7, GET_PPC_OFFS());
+               running = 0;
+       }
+       rST = d;
 }
 
 // 5
 static u32 read_STACK(void)
 {
-       u32 d = 0;
-       if (rSTACK < 6) {
-               d = ssp->stack[rSTACK];
-               rSTACK++;
-       } else
-               elprintf(EL_ANOMALY|EL_SVP, "ssp16: stack underflow! (%i) @ %04x", rSTACK, GET_PC_OFFS());
-       return d;
+       //elprintf(EL_SVP, "pop  %i @ %04x", rSTACK, GET_PPC_OFFS());
+       --rSTACK;
+       if ((short)rSTACK < 0) {
+               rSTACK = 5;
+               elprintf(EL_ANOMALY|EL_SVP, "ssp16: stack underflow! (%i) @ %04x", rSTACK, GET_PPC_OFFS());
+       }
+       return ssp->stack[rSTACK];
 }
 
 static void write_STACK(u32 d)
 {
-       if (rSTACK > 0) {
-               rSTACK--;
-               ssp->stack[rSTACK] = d;
-       } else
-               elprintf(EL_ANOMALY|EL_SVP, "ssp16: stack overflow! (%i) @ %04x", rSTACK, GET_PC_OFFS());
+       if (rSTACK >= 6) {
+               //running = 0;
+               elprintf(EL_ANOMALY|EL_SVP, "ssp16: stack overflow! (%i) @ %04x", rSTACK, GET_PPC_OFFS());
+               rSTACK = 0;
+       }
+       ssp->stack[rSTACK++] = d;
 }
 
 // 6
@@ -228,18 +327,72 @@ static u32 read_P(void)
        return rP.h;
 }
 
+// -----------------------------------------------------
+
+static void iram_write(int addr, u32 d, int reg, int inc)
+{
+       if ((addr&0xfc00) != 0x8000)
+               elprintf(EL_SVP|EL_ANOMALY, "ssp invalid IRAM addr: %04x", addr<<1);
+       elprintf(EL_SVP, "ssp IRAM w [%06x] %04x (inc %i)", (addr<<1)&0x7ff, d, inc);
+       ((unsigned short *)svp->iram_rom)[addr&0x3ff] = d;
+       ssp->pmac_write[reg] += inc<<16;
+}
+
 static u32 pm_io(int reg, int write, u32 d)
 {
        if (ssp->emu_status & SSP_PMC_SET) {
-               elprintf(EL_SVP, "PM%i (%c) set to %08x @ %04x", reg, write ? 'w' : 'r', rPMC.v, GET_PC_OFFS());
+               elprintf(EL_SVP, "PM%i (%c) set to %08x @ %04x", reg, write ? 'w' : 'r', rPMC.v, GET_PPC_OFFS());
                ssp->pmac_read[write ? reg + 6 : reg] = rPMC.v;
                ssp->emu_status &= ~SSP_PMC_SET;
                return 0;
        }
 
-       if (ssp->pmac_read[reg] != 0) {
-               elprintf(EL_SVP, "PM%i %c @ %04x", reg, write ? 'w' : 'r', GET_PC_OFFS());
-               // do something depending on mode
+       // just in case
+       ssp->emu_status &= ~SSP_PMC_HAVE_ADDR;
+
+//     if (ssp->pmac_read[reg] != 0)
+       if (reg == 4 || (rST & 0x60))
+       {
+               if (write)
+               {
+                       int mode = ssp->pmac_write[reg]&0xffff;
+                       int addr = ssp->pmac_write[reg]>>16;
+                       switch (mode) {
+                               case 0x0018: elprintf(EL_SVP, "ssp DRAM w [%06x] %04x", addr<<1, d);
+                                            ((unsigned short *)svp->dram)[addr] = d;
+                                            break;
+                               case 0x0818: elprintf(EL_SVP, "ssp DRAM w [%06x] %04x (inc 1)", addr<<1, d);
+                                            ((unsigned short *)svp->dram)[addr] = d;
+                                            ssp->pmac_write[reg] += 1<<16;
+                                            break;
+                               case 0x081c: iram_write(addr, d, reg, 1); break; // checked: used by code @ 0902
+                               case 0x101c: iram_write(addr, d, reg, 2); break; // checked: used by code @ 3b7c
+                               default:     elprintf(EL_SVP|EL_ANOMALY, "ssp PM%i unhandled write mode %04x, [%06x] %04x @ %04x",
+                                                       reg, mode, addr<<1, d, GET_PPC_OFFS()); break;
+                       }
+               }
+               else
+               {
+                       int mode = ssp->pmac_read[reg]&0xffff;
+                       int addr = ssp->pmac_read[reg]>>16;
+                       switch (mode) {
+                               case 0x0809: elprintf(EL_SVP, "ssp ROM  r [%06x] %04x", (addr|((mode&0xf)<<16))<<1,
+                                                       ((unsigned short *)Pico.rom)[addr|((mode&0xf)<<16)]);
+                                            // possibly correct, the first word read is some sort of counter, sane values in ROM
+                                            ssp->pmac_read[reg] += 1<<16;
+                                            return ((unsigned short *)Pico.rom)[addr|((mode&0xf)<<16)];
+                               case 0x0018: elprintf(EL_SVP, "ssp DRAM r [%06x] %04x", addr<<1, ((unsigned short *)svp->dram)[addr]);
+                                            return ((unsigned short *)svp->dram)[addr]; // checked
+                               case 0x0818: elprintf(EL_SVP, "ssp DRAM r [%06x] %04x (inc 1)", addr<<1, ((unsigned short *)svp->dram)[addr]);
+                                            ssp->pmac_read[reg] += 1<<16;
+                                            return ((unsigned short *)svp->dram)[addr];
+                               case 0x3018: elprintf(EL_SVP, "ssp DRAM r [%06x] %04x (inc 32)", addr<<1, ((unsigned short *)svp->dram)[addr]);
+                                            ssp->pmac_read[reg] += 32<<16;
+                                            return ((unsigned short *)svp->dram)[addr];
+                               default:     elprintf(EL_SVP|EL_ANOMALY, "ssp PM%i unhandled read  mode %04x, [%06x] @ %04x",
+                                                       reg, mode, addr<<1, GET_PPC_OFFS()); break;
+                       }
+               }
                return 0;
        }
 
@@ -251,7 +404,8 @@ static u32 read_PM0(void)
 {
        u32 d = pm_io(0, 0, 0);
        if (d != (u32)-1) return d;
-       elprintf(EL_SVP, "PM0 raw r %04x @ %04x", rPM0, GET_PC_OFFS());
+       if (GET_PPC_OFFS() != 0x800 || rPM0 != 0) // debug
+               elprintf(EL_SVP, "PM0 raw r %04x @ %04x", rPM0, GET_PPC_OFFS());
        return rPM0;
 }
 
@@ -259,7 +413,7 @@ static void write_PM0(u32 d)
 {
        u32 r = pm_io(0, 1, d);
        if (r != (u32)-1) return;
-       elprintf(EL_SVP, "PM0 raw w %04x @ %04x", d, GET_PC_OFFS());
+       elprintf(EL_SVP, "PM0 raw w %04x @ %04x", d, GET_PPC_OFFS());
        rPM0 = d;
 }
 
@@ -269,8 +423,8 @@ static u32 read_PM1(void)
        u32 d = pm_io(1, 0, 0);
        if (d != (u32)-1) return d;
        // can be removed?
-       elprintf(EL_SVP, "PM1 raw r %04x @ %04x", rPM1, GET_PC_OFFS());
-       return rPM0;
+       elprintf(EL_SVP, "PM1 raw r %04x @ %04x", rPM1, GET_PPC_OFFS());
+       return rPM1;
 }
 
 static void write_PM1(u32 d)
@@ -278,8 +432,8 @@ static void write_PM1(u32 d)
        u32 r = pm_io(1, 1, d);
        if (r != (u32)-1) return;
        // can be removed?
-       elprintf(EL_SVP, "PM1 raw w %04x @ %04x", d, GET_PC_OFFS());
-       rPM0 = d;
+       elprintf(EL_SVP, "PM1 raw w %04x @ %04x", d, GET_PPC_OFFS());
+       rPM1 = d;
 }
 
 // 10
@@ -288,8 +442,8 @@ static u32 read_PM2(void)
        u32 d = pm_io(2, 0, 0);
        if (d != (u32)-1) return d;
        // can be removed?
-       elprintf(EL_SVP, "PM2 raw r %04x @ %04x", rPM2, GET_PC_OFFS());
-       return rPM0;
+       elprintf(EL_SVP, "PM2 raw r %04x @ %04x", rPM2, GET_PPC_OFFS());
+       return rPM2;
 }
 
 static void write_PM2(u32 d)
@@ -297,8 +451,8 @@ static void write_PM2(u32 d)
        u32 r = pm_io(2, 1, d);
        if (r != (u32)-1) return;
        // can be removed?
-       elprintf(EL_SVP, "PM2 raw w %04x @ %04x", d, GET_PC_OFFS());
-       rPM0 = d;
+       elprintf(EL_SVP, "PM2 raw w %04x @ %04x", d, GET_PPC_OFFS());
+       rPM2 = d;
 }
 
 // 11
@@ -308,8 +462,8 @@ static u32 read_XST(void)
        u32 d = pm_io(3, 0, 0);
        if (d != (u32)-1) return d;
 
-       elprintf(EL_SVP, "XST raw r %04x @ %04x", rXST, GET_PC_OFFS());
-       return rPM0;
+       elprintf(EL_SVP, "XST raw r %04x @ %04x", rXST, GET_PPC_OFFS());
+       return rXST;
 }
 
 static void write_XST(u32 d)
@@ -318,8 +472,8 @@ static void write_XST(u32 d)
        u32 r = pm_io(3, 1, d);
        if (r != (u32)-1) return;
 
-       elprintf(EL_SVP, "XST raw w %04x @ %04x", d, GET_PC_OFFS());
-       rPM0 = d;
+       elprintf(EL_SVP, "XST raw w %04x @ %04x", d, GET_PPC_OFFS());
+       rXST = d;
 }
 
 // 12
@@ -328,8 +482,8 @@ static u32 read_PM4(void)
        u32 d = pm_io(4, 0, 0);
        if (d != (u32)-1) return d;
        // can be removed?
-       elprintf(EL_SVP, "PM4 raw r %04x @ %04x", rPM4, GET_PC_OFFS());
-       return rPM0;
+       elprintf(EL_SVP, "PM4 raw r %04x @ %04x", rPM4, GET_PPC_OFFS());
+       return rPM4;
 }
 
 static void write_PM4(u32 d)
@@ -337,8 +491,8 @@ static void write_PM4(u32 d)
        u32 r = pm_io(4, 1, d);
        if (r != (u32)-1) return;
        // can be removed?
-       elprintf(EL_SVP, "PM4 raw w %04x @ %04x", d, GET_PC_OFFS());
-       rPM0 = d;
+       elprintf(EL_SVP, "PM4 raw w %04x @ %04x", d, GET_PPC_OFFS());
+       rPM4 = d;
 }
 
 // 14
@@ -346,8 +500,9 @@ static u32 read_PMC(void)
 {
        if (ssp->emu_status & SSP_PMC_HAVE_ADDR) {
                if (ssp->emu_status & SSP_PMC_SET)
-                       elprintf(EL_ANOMALY|EL_SVP, "prev PMC not used @ %04x", GET_PC_OFFS());
+                       elprintf(EL_ANOMALY|EL_SVP, "prev PMC not used @ %04x", GET_PPC_OFFS());
                ssp->emu_status |= SSP_PMC_SET;
+               ssp->emu_status &= ~SSP_PMC_HAVE_ADDR;
                return rPMC.l;
        } else {
                ssp->emu_status |= SSP_PMC_HAVE_ADDR;
@@ -359,8 +514,9 @@ static void write_PMC(u32 d)
 {
        if (ssp->emu_status & SSP_PMC_HAVE_ADDR) {
                if (ssp->emu_status & SSP_PMC_SET)
-                       elprintf(EL_ANOMALY|EL_SVP, "prev PMC not used @ %04x", GET_PC_OFFS());
+                       elprintf(EL_ANOMALY|EL_SVP, "prev PMC not used @ %04x", GET_PPC_OFFS());
                ssp->emu_status |= SSP_PMC_SET;
+               ssp->emu_status &= ~SSP_PMC_HAVE_ADDR;
                rPMC.l = d;
        } else {
                ssp->emu_status |= SSP_PMC_HAVE_ADDR;
@@ -404,7 +560,8 @@ static read_func_t read_handlers[16] =
 static write_func_t write_handlers[16] =
 {
        write_unknown, write_unknown, write_unknown, write_unknown, // -, X, Y, A
-       write_unknown,  // 4 ST
+//     write_unknown,  // 4 ST
+       write_ST,       // 4 ST (debug hook)
        write_STACK,
        write_PC,
        write_unknown,  // 7 P
@@ -418,50 +575,418 @@ static write_func_t write_handlers[16] =
        write_AL
 };
 
+// -----------------------------------------------------
+// pointer register handlers
+
+//
+#define ptr1_read(op) ptr1_read_(op&3,(op>>6)&4,(op<<1)&0x18)
+
+static u32 ptr1_read_(int ri, int isj2, int modi3)
+{
+       //int t = (op&3) | ((op>>6)&4) | ((op<<1)&0x18);
+       int t = ri | isj2 | modi3;
+       switch (t)
+       {
+               // mod=0 (00)
+               case 0x00:
+               case 0x01:
+               case 0x02: return ssp->RAM0[ssp->r0[t&3]];
+               case 0x03: return ssp->RAM0[0];
+               case 0x04:
+               case 0x05:
+               case 0x06: return ssp->RAM1[ssp->r1[t&3]];
+               case 0x07: return ssp->RAM1[0];
+               // mod=1 (01), "+!"
+               // mod=3,      "+"
+               case 0x08:
+               case 0x18:
+               case 0x09:
+               case 0x19:
+               case 0x0a:
+               case 0x1a: return ssp->RAM0[ssp->r0[t&3]++];
+               case 0x0b: return ssp->RAM0[1];
+               case 0x0c:
+               case 0x1c:
+               case 0x0d:
+               case 0x1d:
+               case 0x0e:
+               case 0x1e: return ssp->RAM1[ssp->r1[t&3]++];
+               case 0x0f: return ssp->RAM1[1];
+               // mod=2 (10), "-"
+               case 0x10:
+               case 0x11:
+               case 0x12: return ssp->RAM0[ssp->r0[t&3]--];
+               case 0x13: return ssp->RAM0[2];
+               case 0x14:
+               case 0x15:
+               case 0x16: return ssp->RAM1[ssp->r1[t&3]--];
+               case 0x17: return ssp->RAM1[2];
+               // mod=3 (11)
+               case 0x1b: return ssp->RAM0[3];
+               case 0x1f: return ssp->RAM1[3];
+       }
+
+       return 0;
+}
+
+static void ptr1_write(int op, u32 d)
+{
+       int t = (op&3) | ((op>>6)&4) | ((op<<1)&0x18);
+       switch (t)
+       {
+               // mod=0 (00)
+               case 0x00:
+               case 0x01:
+               case 0x02: ssp->RAM0[ssp->r0[t&3]] = d; return;
+               case 0x03: ssp->RAM0[0] = d; return;
+               case 0x04:
+               case 0x05:
+               case 0x06: ssp->RAM1[ssp->r1[t&3]] = d; return;
+               case 0x07: ssp->RAM1[0] = d; return;
+               // mod=1 (01), "+!"
+               // mod=3,      "+"
+               case 0x08:
+               case 0x18:
+               case 0x09:
+               case 0x19:
+               case 0x0a:
+               case 0x1a: ssp->RAM0[ssp->r0[t&3]++] = d; return;
+               case 0x0b: ssp->RAM0[1] = d; return;
+               case 0x0c:
+               case 0x1c:
+               case 0x0d:
+               case 0x1d:
+               case 0x0e:
+               case 0x1e: ssp->RAM1[ssp->r1[t&3]++] = d; return;
+               case 0x0f: ssp->RAM1[1] = d; return;
+               // mod=2 (10), "-"
+               case 0x10:
+               case 0x11:
+               case 0x12: ssp->RAM0[ssp->r0[t&3]--] = d; return;
+               case 0x13: ssp->RAM0[2] = d; return;
+               case 0x14:
+               case 0x15:
+               case 0x16: ssp->RAM1[ssp->r1[t&3]--] = d; return;
+               case 0x17: ssp->RAM1[2] = d; return;
+               // mod=3 (11)
+               case 0x1b: ssp->RAM0[3] = d; return;
+               case 0x1f: ssp->RAM1[3] = d; return;
+       }
+}
+
+static u32 ptr2_read(int op)
+{
+       int mv = 0, t = (op&3) | ((op>>6)&4) | ((op<<1)&0x18);
+       switch (t)
+       {
+               // mod=0 (00)
+               case 0x00:
+               case 0x01:
+               case 0x02: mv = ssp->RAM0[ssp->r0[t&3]]++; break;
+               case 0x03: mv = ssp->RAM0[0]++; break;
+               case 0x04:
+               case 0x05:
+               case 0x06: mv = ssp->RAM1[ssp->r1[t&3]]++; break;
+               case 0x07: mv = ssp->RAM1[0]++; break;
+               // mod=1 (01)
+               case 0x0b: mv = ssp->RAM0[1]++; break;
+               case 0x0f: mv = ssp->RAM1[1]++; break;
+               // mod=2 (10)
+               case 0x13: mv = ssp->RAM0[2]++; break;
+               case 0x17: mv = ssp->RAM1[2]++; break;
+               // mod=3 (11)
+               case 0x1b: mv = ssp->RAM0[3]++; break;
+               case 0x1f: mv = ssp->RAM1[3]++; break;
+               default:   elprintf(EL_SVP|EL_ANOMALY, "invalid mod in ((rX))? @ %04x", GET_PPC_OFFS());
+                          return 0;
+       }
+
+       return ((unsigned short *)svp->iram_rom)[mv];
+}
+
+
+// -----------------------------------------------------
+
 void ssp1601_reset(ssp1601_t *l_ssp)
 {
        ssp = l_ssp;
        ssp->emu_status = 0;
        ssp->gr[SSP_GR0].v = 0xffff0000;
        rPC = 0x400;
-       rSTACK = 6; // ? using descending stack
+       rSTACK = 0; // ? using ascending stack
 }
 
 
-void ssp1601_run(int cycles)
+static void debug_dump(void)
 {
-       int op;
+       printf("GR0:   %04x    X: %04x    Y: %04x  A: %08x\n", ssp->gr[SSP_GR0].h, rX, rY, ssp->gr[SSP_A].v);
+       printf("PC:    %04x  (%04x)                P: %08x\n", GET_PC(), GET_PC() << 1, ssp->gr[SSP_P].v);
+       printf("PM0:   %04x  PM1: %04x  PM2: %04x\n", rPM0, rPM1, rPM2);
+       printf("XST:   %04x  PM4: %04x  PMC: %08x\n", rXST, rPM4, ssp->gr[SSP_PMC].v);
+       printf(" ST:   %04x  %c%c%c%c,  GP0_0 %i,  GP0_1 %i\n", rST, rST&FLAG_N?'N':'n', rST&FLAG_V?'V':'v',
+               rST&FLAG_Z?'Z':'z', rST&FLAG_L?'L':'l', (rST>>5)&1, (rST>>6)&1);
+       printf("STACK: %i %04x %04x %04x %04x %04x %04x\n", rSTACK, ssp->stack[0], ssp->stack[1],
+               ssp->stack[2], ssp->stack[3], ssp->stack[4], ssp->stack[5]);
+       printf("r0-r2: %02x %02x %02x  r4-r6: %02x %02x %02x\n", rIJ[0], rIJ[1], rIJ[2], rIJ[4], rIJ[5], rIJ[6]);
+       elprintf(EL_SVP, "cycles: %i, emu_status: %x", g_cycles, ssp->emu_status);
+}
 
+static void debug_dump_mem(void)
+{
+       int h, i;
+       printf("RAM0\n");
+       for (h = 0; h < 32; h++)
+       {
+               if (h == 16) printf("RAM1\n");
+               printf("%03x:", h*16);
+               for (i = 0; i < 16; i++)
+                       printf(" %04x", ssp->RAM[h*16+i]);
+               printf("\n");
+       }
+}
+
+static int bpts[10] = { 0, };
+
+static void debug(unsigned int pc, unsigned int op)
+{
+       static char buffo[64] = {0,};
+       char buff[64] = {0,};
+       int i;
+
+       if (running) {
+               for (i = 0; i < 10; i++)
+                       if (pc != 0 && bpts[i] == pc) {
+                               printf("breakpoint %i\n", i);
+                               running = 0;
+                               break;
+                       }
+       }
+       if (running) return;
+
+       printf("%04x (%02x) @ %04x\n", op, op >> 9, pc<<1);
+
+       while (1)
+       {
+               printf("dbg> ");
+               fflush(stdout);
+               fgets(buff, sizeof(buff), stdin);
+               if (buff[0] == '\n') strcpy(buff, buffo);
+               else strcpy(buffo, buff);
+
+               switch (buff[0]) {
+                       case   0: exit(0);
+                       case 'c':
+                       case 'r': running = 1; return;
+                       case 's':
+                       case 'n': return;
+                       case 'x': debug_dump(); break;
+                       case 'm': debug_dump_mem(); break;
+                       case 'b': {
+                               char *baddr = buff + 2;
+                               i = 0;
+                               if (buff[3] == ' ') { i = buff[2] - '0'; baddr = buff + 4; }
+                               bpts[i] = strtol(baddr, NULL, 16) >> 1;
+                               printf("breakpoint %i set @ %04x\n", i, bpts[i]<<1);
+                               break;
+                       }
+                       case 'd': {
+                               FILE *f = fopen("dump.bin", "wb");
+                               unsigned short *p = (unsigned short *)svp->iram_rom;
+                               int i;
+                               if (f) {
+                                       for (i = 0; i < 0x10000; i++) p[i] = (p[i]<<8) | (p[i]>>8);
+                                       fwrite(svp->iram_rom, 1, 0x20000, f);
+                                       fclose(f);
+                                       for (i = 0; i < 0x10000; i++) p[i] = (p[i]<<8) | (p[i]>>8);
+                                       printf("dumped to dump.bin\n");
+                               }
+                               else
+                                       printf("dump failed\n");
+                               break;
+                       }
+                       default:  printf("unknown command\n"); break;
+               }
+       }
+}
+
+void ssp1601_run(int cycles)
+{
        SET_PC(rPC);
        g_cycles = cycles;
+//running = 0;
 
        while (g_cycles > 0)
        {
-               op = *PC;
+               int op;
+               u32 tmpv;
+
+               op = *PC++;
+               debug(GET_PC()-1, op);
                switch (op >> 9)
                {
                        // ld d, s
-                       case 0:
+                       case 0x00:
                                if (op == 0) break; // nop
                                if (op == ((SSP_A<<4)|SSP_P)) { // A <- P
                                        // not sure. MAME claims that only hi word is transfered.
                                        read_P(); // update P
                                        ssp->gr[SSP_A].v = ssp->gr[SSP_P].v;
-                                       break;
                                }
+                               else
                                {
-                                       u32 d = REG_READ(op & 0x0f);
-                                       REG_WRITE((op & 0xf0) >> 4, d);
+                                       tmpv = REG_READ(op & 0x0f);
+                                       REG_WRITE((op & 0xf0) >> 4, tmpv);
+                               }
+                               break;
+
+                       // ld d, (ri)
+                       case 0x01: tmpv = ptr1_read(op); REG_WRITE((op & 0xf0) >> 4, tmpv); break;
+
+                       // ld (ri), s
+                       case 0x02: tmpv = REG_READ((op & 0xf0) >> 4); ptr1_write(op, tmpv); break;
+
+                       // ldi d, imm
+                       case 0x04: tmpv = *PC++; REG_WRITE((op & 0xf0) >> 4, tmpv); break;
+
+                       // ld d, ((ri))
+                       case 0x05: tmpv = ptr2_read(op); REG_WRITE((op & 0xf0) >> 4, tmpv); break;
+
+                       // ldi (ri), imm
+                       case 0x06: tmpv = *PC++; ptr1_write(op, tmpv); break;
+
+                       // ld adr, a
+                       case 0x07: ssp->RAM[op & 0x1ff] = rA; break;
+
+                       // ld d, ri
+                       case 0x09: tmpv = rIJ[(op&3)|((op>>6)&4)]; REG_WRITE((op & 0xf0) >> 4, tmpv); break;
+
+                       // ld ri, s
+                       case 0x0a: rIJ[(op&3)|((op>>6)&4)] = REG_READ((op & 0xf0) >> 4); break;
+
+                       // ldi ri, simm
+                       case 0x0c:
+                       case 0x0d:
+                       case 0x0e:
+                       case 0x0f: rIJ[(op>>8)&7] = op; break;
+
+                       // call cond, addr
+                       case 0x24: {
+                               int cond = 0;
+                               COND_CHECK
+                               if (cond) { int new_PC = *PC++; write_STACK(GET_PC()); write_PC(new_PC); }
+                               else PC++;
+                               break;
+                       }
+
+                       // ld d, (a)
+                       case 0x25: tmpv = ((unsigned short *)svp->iram_rom)[rA]; REG_WRITE((op & 0xf0) >> 4, tmpv); break;
+
+                       // bra cond, addr
+                       case 0x26: {
+                               int cond = 0;
+                               COND_CHECK
+                               if (cond) { int new_PC = *PC++; write_PC(new_PC); }
+                               else PC++;
+                               break;
+                       }
+
+                       // mod cond, op
+                       case 0x48: {
+                               int cond = 0;
+                               COND_CHECK
+                               if (cond) {
+                                       switch (op & 7) {
+                                               case 2: rA32 >>= 1; break; // shr
+                                               case 3: rA32 <<= 1; break; // shl
+                                               case 6: rA32 = -(int)rA32; break; // neg
+                                               case 7: if ((int)rA32 < 0) rA32 = -(int)rA32; break; // abs
+                                               default: elprintf(EL_SVP, "ssp16: unhandled mod %i @ %04x", op&7, GET_PPC_OFFS());
+                                       }
+                                       UPD_ACC_ZN
                                }
-                               // flags?
                                break;
+                       }
+
+                       // mpya (rj), (ri), b
+                       case 0x4b:
+                               // dunno if this is correct. What about b?
+                               read_P(); // update P
+                               ssp->gr[SSP_A].v += ssp->gr[SSP_P].v; // maybe only upper word?
+                               rX = ptr1_read_(op&3, 0, (op<<1)&0x18); // ri (maybe rj?)
+                               rY = ptr1_read_((op>>4)&3, 4, (op>>3)&0x18); // rj
+                               break;
+
+                       // mld (rj), (ri), b
+                       case 0x5b:
+                               // dunno if this is correct. What about b?
+                               ssp->gr[SSP_A].v = 0; // maybe only upper word?
+                               rX = ptr1_read_(op&3, 0, (op<<1)&0x18); // ri (maybe rj?)
+                               rY = ptr1_read_((op>>4)&3, 4, (op>>3)&0x18); // rj
+                               break;
+
+                       // OP a, s
+                       case 0x10: tmpv = REG_READ(op & 0x0f); OP_SUBA(tmpv); break;
+                       case 0x30: tmpv = REG_READ(op & 0x0f); OP_CMPA(tmpv); break;
+                       case 0x40: tmpv = REG_READ(op & 0x0f); OP_ADDA(tmpv); break;
+                       case 0x50: tmpv = REG_READ(op & 0x0f); OP_ANDA(tmpv); break;
+                       case 0x60: tmpv = REG_READ(op & 0x0f); OP_ORA (tmpv); break;
+                       case 0x70: tmpv = REG_READ(op & 0x0f); OP_EORA(tmpv); break;
+
+                       // OP a, (ri)
+                       case 0x11: tmpv = ptr1_read(op); OP_SUBA(tmpv); break;
+                       case 0x31: tmpv = ptr1_read(op); OP_CMPA(tmpv); break;
+                       case 0x41: tmpv = ptr1_read(op); OP_ADDA(tmpv); break;
+                       case 0x51: tmpv = ptr1_read(op); OP_ANDA(tmpv); break;
+                       case 0x61: tmpv = ptr1_read(op); OP_ORA (tmpv); break;
+                       case 0x71: tmpv = ptr1_read(op); OP_EORA(tmpv); break;
+
+                       // OP a, adr
+                       case 0x03: tmpv = ssp->RAM[op & 0x1ff]; OP_LDA (tmpv); break;
+                       case 0x13: tmpv = ssp->RAM[op & 0x1ff]; OP_SUBA(tmpv); break;
+                       case 0x33: tmpv = ssp->RAM[op & 0x1ff]; OP_CMPA(tmpv); break;
+                       case 0x43: tmpv = ssp->RAM[op & 0x1ff]; OP_ADDA(tmpv); break;
+                       case 0x53: tmpv = ssp->RAM[op & 0x1ff]; OP_ANDA(tmpv); break;
+                       case 0x63: tmpv = ssp->RAM[op & 0x1ff]; OP_ORA (tmpv); break;
+                       case 0x73: tmpv = ssp->RAM[op & 0x1ff]; OP_EORA(tmpv); break;
+
+                       // OP a, imm
+                       case 0x14: tmpv = *PC++; OP_SUBA(tmpv); break;
+                       case 0x34: tmpv = *PC++; OP_CMPA(tmpv); break;
+                       case 0x44: tmpv = *PC++; OP_ADDA(tmpv); break;
+                       case 0x54: tmpv = *PC++; OP_ANDA(tmpv); break;
+                       case 0x64: tmpv = *PC++; OP_ORA (tmpv); break;
+                       case 0x74: tmpv = *PC++; OP_EORA(tmpv); break;
+
+                       // OP a, ((ri))
+                       case 0x15: tmpv = ptr2_read(op); OP_SUBA(tmpv); break;
+                       case 0x35: tmpv = ptr2_read(op); OP_CMPA(tmpv); break;
+                       case 0x45: tmpv = ptr2_read(op); OP_ADDA(tmpv); break;
+                       case 0x55: tmpv = ptr2_read(op); OP_ANDA(tmpv); break;
+                       case 0x65: tmpv = ptr2_read(op); OP_ORA (tmpv); break;
+                       case 0x75: tmpv = ptr2_read(op); OP_EORA(tmpv); break;
+
+                       // OP a, ri
+                       case 0x19: tmpv = rIJ[IJind]; OP_SUBA(tmpv); break;
+                       case 0x39: tmpv = rIJ[IJind]; OP_CMPA(tmpv); break;
+                       case 0x49: tmpv = rIJ[IJind]; OP_ADDA(tmpv); break;
+                       case 0x59: tmpv = rIJ[IJind]; OP_ANDA(tmpv); break;
+                       case 0x69: tmpv = rIJ[IJind]; OP_ORA (tmpv); break;
+                       case 0x79: tmpv = rIJ[IJind]; OP_EORA(tmpv); break;
+
+                       // OP simm
+                       case 0x1c: OP_SUBA(op & 0xff); break;
+                       case 0x3c: OP_CMPA(op & 0xff); break;
+                       case 0x4c: OP_ADDA(op & 0xff); break;
+                       // MAME code only does LSB of top word, but this looks wrong to me.
+                       case 0x5c: OP_ANDA(op & 0xff); break;
+                       case 0x6c: OP_ORA (op & 0xff); break;
+                       case 0x7c: OP_EORA(op & 0xff); break;
 
                        default:
-                               elprintf(EL_ANOMALY|EL_SVP, "ssp16: unhandled op %04x @ %04x", op, GET_PC_OFFS());
+                               elprintf(EL_ANOMALY|EL_SVP, "ssp16: unhandled op %04x @ %04x", op, GET_PPC_OFFS());
                                break;
                }
                g_cycles--;
-               PC++;
        }
 
        read_P(); // update P
index 7b916ff..970ba42 100644 (file)
@@ -6,6 +6,7 @@ static void PicoSVPReset(void)
 {
        elprintf(EL_SVP, "SVP reset");
 
+       memcpy(svp->iram_rom + 0x800, Pico.rom + 0x800, 0x20000 - 0x800);
        ssp1601_reset(&svp->ssp1601);
 }
 
@@ -16,18 +17,17 @@ static void PicoSVPLine(void)
        // OSC_NTSC / 3.0 / 60.0 / 262.0 ~= 1139
        // OSC_PAL  / 3.0 / 50.0 / 312.0 ~= 1137
        ssp1601_run(100);
-       exit(1);
 }
 
 
-static int PicoSVPDma(unsigned int source, unsigned short **srcp, unsigned short **limitp)
+static int PicoSVPDma(unsigned int source, int len, unsigned short **srcp, unsigned short **limitp)
 {
        if ((source & 0xfe0000) == 0x300000)
        {
-               elprintf(EL_VDPDMA|EL_SVP, "SVP DmaSlow from %06x", source);
+               elprintf(EL_VDPDMA|EL_SVP, "SVP DmaSlow from %06x, len=%i", source, len);
                source &= 0x1fffe;
-               *srcp = (unsigned short *)(svp->ram + source);
-               *limitp = (unsigned short *)(svp->ram + sizeof(svp->ram));
+               *srcp = (unsigned short *)(svp->dram + source);
+               *limitp = (unsigned short *)(svp->dram + sizeof(svp->dram));
                return 1;
        }
 
index d26636a..0d9a526 100644 (file)
@@ -14,7 +14,8 @@
 
 #define mix_32_to_16l_stereo_lvl mix_32_to_16l_stereo
 
-#define EL_LOGMASK (EL_ANOMALY|EL_STATUS|EL_SRAMIO|EL_EEPROM|EL_UIO|EL_VDPDMA) // EL_VDPDMA|EL_ASVDP|EL_SR) // |EL_BUSREQ|EL_Z80BNK)
+#define EL_LOGMASK (EL_ANOMALY|EL_STATUS|EL_SRAMIO|EL_EEPROM|EL_UIO|EL_SVP)
+// EL_VDPDMA|EL_ASVDP|EL_SR) // |EL_BUSREQ|EL_Z80BNK)
 
 //#define dprintf(f,...) printf("%05i:%03i: " f "\n",Pico.m.frame_count,Pico.m.scanline,##__VA_ARGS__)
 #define dprintf(x...)