Browse Source

Last irixxxx's optimizations

root 2 years ago
parent
commit
ebc054b278
9 changed files with 141 additions and 202 deletions
  1. 1 0
      cpu/fame/famec_opcodes.h
  2. 1 1
      cpu/musashi/m68k_in.c
  3. 5 5
      cpu/musashi/m68kcpu.c
  4. 2 0
      cpu/musashi/m68kcpu.h
  5. 3 0
      cpu/musashi/m68kmake.c
  6. 0 176
      pico/misc.c
  7. 1 0
      pico/pico.c
  8. 4 3
      pico/pico_int.h
  9. 124 17
      pico/videoport.c

+ 1 - 0
cpu/fame/famec_opcodes.h

@@ -19318,6 +19318,7 @@ OPCODE(0x4E73)
 		AREG(7) = ASP;
 		ASP = res;
 	}
+	CHECK_BRANCH_EXCEPTION(res)
 	POST_IO
 	ctx->execinfo &= ~(FM68K_EMULATE_GROUP_0|FM68K_EMULATE_TRACE|FM68K_DO_TRACE);
 	CHECK_INT_TO_JUMP(20)

+ 1 - 1
cpu/musashi/m68k_in.c

@@ -389,7 +389,7 @@ addi      32  .     .     0000011010......  A+-DXWL...  U U U U  20  20   4   4
 addq       8  .     d     0101...000000...  ..........  U U U U   4   4   2   2
 addq       8  .     .     0101...000......  A+-DXWL...  U U U U   8   8   4   4
 addq      16  .     d     0101...001000...  ..........  U U U U   4   4   2   2
-addq      16  .     a     0101...001001...  ..........  U U U U   4   4   2   2
+addq      16  .     a     0101...001001...  ..........  U U U U   8   8   2   2
 addq      16  .     .     0101...001......  A+-DXWL...  U U U U   8   8   4   4
 addq      32  .     d     0101...010000...  ..........  U U U U   8   8   2   2
 addq      32  .     a     0101...010001...  ..........  U U U U   8   8   2   2

+ 5 - 5
cpu/musashi/m68kcpu.c

@@ -43,7 +43,7 @@ extern void m68040_fpu_op1(void);
 /* ================================= DATA ================================= */
 /* ======================================================================== */
 
-int  m68ki_initial_cycles;
+//int  m68ki_initial_cycles;
 //int  m68ki_remaining_cycles = 0;                     /* Number of clocks remaining */
 uint m68ki_tracing = 0;
 uint m68ki_address_space;
@@ -828,6 +828,10 @@ int m68k_execute(int num_cycles)
 			m68ki_instruction_jump_table[REG_IR]();
 			USE_CYCLES(CYC_INSTRUCTION[REG_IR]); // moving this up may cause a deadlock
 
+			/* ASG: update cycles */
+			USE_CYCLES(CPU_INT_CYCLES);
+			CPU_INT_CYCLES = 0;
+
 			/* Trace m68k_exception, if necessary */
 			m68ki_exception_if_trace(); /* auto-disable (see m68kcpu.h) */
 
@@ -839,10 +843,6 @@ int m68k_execute(int num_cycles)
 		/* set previous PC to current PC for the next entry into the loop */
 		REG_PPC = REG_PC;
 
-		/* ASG: update cycles */
-		USE_CYCLES(CPU_INT_CYCLES);
-		CPU_INT_CYCLES = 0;
-
 		/* return how many clocks we used */
 		return m68ki_initial_cycles - GET_CYCLES();
 	}

+ 2 - 0
cpu/musashi/m68kcpu.h

@@ -916,6 +916,7 @@ typedef struct
 	void (*instr_hook_callback)(void);                /* Called every instruction cycle prior to execution */
 
 	// notaz
+	sint cyc_initial_cycles;
 	sint cyc_remaining_cycles;
 	sint not_polling;
 } m68ki_cpu_core;
@@ -923,6 +924,7 @@ typedef struct
 // notaz
 extern m68ki_cpu_core *m68ki_cpu_p;
 #define m68ki_cpu (*m68ki_cpu_p)
+#define m68ki_initial_cycles m68ki_cpu_p->cyc_initial_cycles
 #define m68ki_remaining_cycles m68ki_cpu_p->cyc_remaining_cycles
 
 

+ 3 - 0
cpu/musashi/m68kmake.c

@@ -641,6 +641,9 @@ int get_oper_cycles(opcode_struct* op, int ea_mode, int cpu_type)
 			strcmp(op->name, "suba")   == 0))
 			return op->cycles[cpu_type] + g_ea_cycle_table[ea_mode][cpu_type][size] + 2;
 
+		if(cpu_type == CPU_TYPE_000 && ea_mode == EA_MODE_I && op->size == 8 && strcmp(op->name, "btst") == 0)
+			return op->cycles[cpu_type] + g_ea_cycle_table[ea_mode][cpu_type][size] + 2;
+
 		if(strcmp(op->name, "jmp") == 0)
 			return op->cycles[cpu_type] + g_jmp_cycle_table[ea_mode];
 		if(strcmp(op->name, "jsr") == 0)

+ 0 - 176
pico/misc.c

@@ -1,7 +1,6 @@
 /*
  * rarely used EEPROM code
  * (C) notaz, 2006-2008
- * (C) kub, 2020
  *
  * This work is licensed under the terms of MAME license.
  * See COPYING file in the top-level directory.
@@ -9,181 +8,6 @@
 
 #include "pico_int.h"
 
-// H-counter table for hvcounter reads in 40col mode, starting at HINT
-const unsigned char hcounts_40[] = {
-0xa5,0xa6,0xa7,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xae,0xaf,0xb0,0xb1,0xb2,
-0xb3,0xb4,0xb5,0xb5,0xe4,0xe5,0xe6,0xe7,0xe8,0xe8,0xe9,0xea,0xea,0xeb,0xec,0xed,
-0xed,0xee,0xef,0xef,0xf0,0xf1,0xf2,0xf2,0xf3,0xf4,0xf4,0xf5,0xf6,0xf7,0xf7,0xf8,
-0xf9,0xfa,0xfb,0xfc,0xfd,0xfd,0xfe,0xff,0x00,0x01,0x02,0x03,0x04,0x04,0x05,0x06,
-0x07,0x08,0x09,0x0a,0x0b,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x12,0x13,0x14,
-0x15,0x16,0x17,0x18,0x19,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x20,0x21,0x22,
-0x23,0x24,0x25,0x26,0x27,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2e,0x2f,0x30,
-0x31,0x32,0x33,0x34,0x35,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3c,0x3d,0x3e,
-0x3f,0x40,0x41,0x42,0x43,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4a,0x4b,0x4c,
-0x4d,0x4e,0x4f,0x50,0x51,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x58,0x59,0x5a,
-0x5b,0x5c,0x5d,0x5e,0x5f,0x5f,0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x66,0x67,0x68,
-0x69,0x6a,0x6b,0x6c,0x6d,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x74,0x75,0x76,
-0x77,0x78,0x79,0x7a,0x7b,0x7b,0x7c,0x7d,0x7e,0x7f,0x80,0x81,0x82,0x82,0x83,0x84,
-0x85,0x86,0x87,0x88,0x89,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,0x90,0x90,0x91,0x92,
-0x93,0x94,0x95,0x96,0x97,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9e,0x9f,0xa0,
-0xa1,0xa2,0xa3,0xa4,0xa5,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xac,0xad,0xae,
-};
-
-// H-counter table for hvcounter reads in 32col mode, starting at HINT
-const unsigned char hcounts_32[] = {
-0x85,0x86,0x86,0x87,0x88,0x88,0x89,0x8a,0x8a,0x8b,0x8c,0x8d,0x8d,0x8e,0x8f,0x8f,
-0x90,0x91,0x91,0x92,0x93,0xe9,0xe9,0xea,0xeb,0xeb,0xec,0xed,0xed,0xee,0xef,0xf0,
-0xf0,0xf1,0xf2,0xf2,0xf3,0xf4,0xf4,0xf5,0xf6,0xf7,0xf7,0xf8,0xf9,0xf9,0xfa,0xfb,
-0xfb,0xfc,0xfd,0xfe,0xfe,0xff,0x00,0x00,0x01,0x02,0x02,0x03,0x04,0x05,0x05,0x06,
-0x07,0x07,0x08,0x09,0x09,0x0a,0x0b,0x0c,0x0c,0x0d,0x0e,0x0e,0x0f,0x10,0x10,0x11,
-0x12,0x13,0x13,0x14,0x15,0x15,0x16,0x17,0x17,0x18,0x19,0x1a,0x1a,0x1b,0x1c,0x1c,
-0x1d,0x1e,0x1e,0x1f,0x20,0x21,0x21,0x22,0x23,0x23,0x24,0x25,0x25,0x26,0x27,0x28,
-0x28,0x29,0x2a,0x2a,0x2b,0x2c,0x2c,0x2d,0x2e,0x2f,0x2f,0x30,0x31,0x31,0x32,0x33,
-0x33,0x34,0x35,0x36,0x36,0x37,0x38,0x38,0x39,0x3a,0x3a,0x3b,0x3c,0x3d,0x3d,0x3e,
-0x3f,0x3f,0x40,0x41,0x41,0x42,0x43,0x44,0x44,0x45,0x46,0x46,0x47,0x48,0x48,0x49,
-0x4a,0x4b,0x4b,0x4c,0x4d,0x4d,0x4e,0x4f,0x4f,0x50,0x51,0x52,0x52,0x53,0x54,0x54,
-0x55,0x56,0x56,0x57,0x58,0x59,0x59,0x5a,0x5b,0x5b,0x5c,0x5d,0x5d,0x5e,0x5f,0x60,
-0x60,0x61,0x62,0x62,0x63,0x64,0x64,0x65,0x66,0x67,0x67,0x68,0x69,0x69,0x6a,0x6b,
-0x6b,0x6c,0x6d,0x6e,0x6e,0x6f,0x70,0x70,0x71,0x72,0x72,0x73,0x74,0x75,0x75,0x76,
-0x77,0x77,0x78,0x79,0x79,0x7a,0x7b,0x7c,0x7c,0x7d,0x7e,0x7e,0x7f,0x80,0x80,0x81,
-0x82,0x83,0x83,0x84,0x85,0x85,0x86,0x87,0x87,0x88,0x89,0x8a,0x8a,0x8b,0x8c,0x8c,
-};
-
-// VDP transfer slots for blanked and active display in 32col and 40col mode.
-// 1 slot is 488/171 = 2.8538 68k cycles in h32, and 488/210 = 2.3238 in h40
-// In blanked display, all slots but 5(h32) / 6(h40) are usable for transfers,
-// in active display only 16(h32) / 18(h40) slots can be used.
-
-// NB the cyc2sl tables should cover 2 slot into the next scanline, in case the
-// last insn in the old scanline is a 32 bit VDP access. That is currently not
-// the case for active display.
-
-// XXX inactive tables by slot#=cycles*maxslot#/488. should be through hv tables
-// VDP transfer slots in inactive (blanked) display 32col mode.
-// refresh slots: 250, 26, 58, 90, 122 -> 32, 64, 96, 128, 160
-const unsigned char vdpcyc2sl_32_bl[] = { // 68k cycles/2 to slot #
-//  0   2   4   6   8  10  12  14  16  18  20  22  24  26  28  30
-    0,  0,  1,  2,  2,  3,  4,  4,  5,  6,  6,  7,  8,  8,  9, 10,
-   10, 11, 12, 12, 13, 14, 14, 15, 16, 17, 17, 18, 19, 19, 20, 21,
-   21, 22, 23, 23, 24, 25, 25, 26, 27, 27, 28, 29, 29, 30, 31, 31,
-   32, 33, 34, 34, 35, 36, 36, 37, 38, 38, 39, 40, 40, 41, 42, 42,
-   43, 44, 44, 45, 46, 46, 47, 48, 48, 49, 50, 51, 51, 52, 53, 53,
-   54, 55, 55, 56, 57, 57, 58, 59, 59, 60, 61, 61, 62, 63, 63, 64,
-   65, 65, 66, 67, 68, 68, 69, 70, 70, 71, 72, 72, 73, 74, 74, 75,
-   76, 76, 77, 78, 78, 79, 80, 80, 81, 82, 83, 83, 84, 85, 85, 86,
-   87, 87, 88, 89, 89, 90, 91, 91, 92, 93, 93, 94, 95, 95, 96, 97,
-   97, 98, 99,100,100,101,102,102,103,104,104,105,106,106,107,108,
-  108,109,110,110,111,112,112,113,114,114,115,116,117,117,118,119,
-  119,120,121,121,122,123,123,124,125,125,126,127,127,128,129,129,
-  130,131,131,132,133,134,134,135,136,136,137,138,138,139,140,140,
-  141,142,142,143,144,144,145,146,146,147,148,148,149,150,151,151,
-  152,153,153,154,155,155,156,157,157,158,159,159,160,161,161,162,
-  163,163,164,165,166,166,167,168,168,169,170,170,171,172,172,173,
-};
-// VDP transfer slots in inactive (blanked) display 40col mode.
-// refresh slots: 250, 26, 58, 90, 122, 154 -> 40, 72, 104, 136, 168, 200
-const unsigned char vdpcyc2sl_40_bl[] = { // 68k cycles/2 to slot #
-//  0   2   4   6   8  10  12  14  16  18  20  22  24  26  28  30
-    0,  0,  1,  2,  3,  4,  5,  5,  6,  7,  8,  9, 10, 10, 11, 12,
-   13, 14, 15, 15, 16, 17, 18, 19, 20, 20, 21, 22, 23, 24, 25, 25,
-   26, 27, 28, 29, 30, 30, 31, 32, 33, 34, 35, 35, 36, 37, 38, 39,
-   40, 40, 41, 42, 43, 44, 45, 45, 46, 47, 48, 49, 50, 51, 51, 52,
-   53, 54, 55, 56, 56, 57, 58, 59, 60, 61, 61, 62, 63, 64, 65, 66,
-   66, 67, 68, 69, 70, 71, 71, 72, 73, 74, 75, 76, 76, 77, 78, 79,
-   80, 81, 81, 82, 83, 84, 85, 86, 86, 87, 88, 89, 90, 91, 91, 92,
-   93, 94, 95, 96, 96, 97, 98, 99,100,101,102,102,103,104,105,106,
-  107,107,108,109,110,111,112,112,113,114,115,116,117,117,118,119,
-  120,121,122,122,123,124,125,126,127,127,128,129,130,131,132,132,
-  133,134,135,136,137,137,138,139,140,141,142,142,143,144,145,146,
-  147,147,148,149,150,151,152,153,153,154,155,156,157,158,158,159,
-  160,161,162,163,163,164,165,166,167,168,168,169,170,171,172,173,
-  173,174,175,176,177,178,178,179,180,181,182,183,183,184,185,186,
-  187,188,188,189,190,191,192,193,193,194,195,196,197,198,198,199,
-  200,201,202,203,204,204,205,206,207,208,209,209,210,211,212,213,
-};
-// VDP transfer slots in active display 32col mode. Transfer slots (Hint=0):
-// 11,25,40,48,56,72,80,88,104,112,120,136,144,152,167,168
-const unsigned char vdpcyc2sl_32[] = { // 68k cycles/2 to slot #
-//  0   2   4   6   8  10  12  14  16  18  20  22  24  26  28  30
-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-    1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
-    1,  1,  1,  1,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-    2,  2,  2,  2,  2,  2,  2,  2,  3,  3,  3,  3,  3,  3,  3,  3,
-    3,  3,  3,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  5,
-    5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,
-    5,  5,  5,  5,  5,  5,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,
-    6,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  8,  8,  8,
-    8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
-    8,  8,  8,  8,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9, 10,
-   10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11,
-   11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
-   11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14,
-   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15,
-   16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
-};
-// VDP transfer slots in active display 40col mode. Transfer slots (Hint=0):
-// 21,47,55,63,79,87,95,111,119,127,143,151,159,175,183,191,206,207
-const unsigned char vdpcyc2sl_40[] = { // 68k cycles/2 to slot #
-//  0   2   4   6   8  10  12  14  16  18  20  22  24  26  28  30
-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, //   0
-    0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1,  1,  1,  1, //  32
-    1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, //  64
-    1,  1,  1,  1,  1,  1,  1,  2,  2,  2,  2,  2,  2,  2,  2,  2, //  96
-    3,  3,  3,  3,  3,  3,  3,  3,  3,  4,  4,  4,  4,  4,  4,  4, // 128
-    4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  5,  5,  5,  5, // 160
-    5,  5,  5,  5,  5,  6,  6,  6,  6,  6,  6,  6,  6,  6,  7,  7, // 192
-    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7, // 224
-    7,  8,  8,  8,  8,  8,  8,  8,  8,  8,  9,  9,  9,  9,  9,  9, // 256
-    9,  9,  9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, // 288
-   10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, // 320
-   12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, // 352
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, // 384
-   14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, // 416
-   16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 17, // 448
-   18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, // 480
-};
-
-// NB the sl2cyc tables must cover all slots present in the cyc2sl tables.
-
-// XXX inactive tables by cyc=slot#*488/maxslot#. should be through hv tables
-const unsigned short vdpsl2cyc_32_bl[] = { // slot # to 68k cycles/2
-    0,  2,  3,  5,  6,  8,  9, 11, 12, 14, 15, 17, 18, 20, 21, 23,
-   24, 25, 27, 28, 30, 31, 33, 34, 36, 37, 39, 40, 42, 43, 45, 46,
-   48, 49, 50, 52, 53, 55, 56, 58, 59, 61, 62, 64, 65, 67, 68, 70,
-   71, 73, 74, 75, 77, 78, 80, 81, 83, 84, 86, 87, 89, 90, 92, 93,
-   95, 96, 98, 99,100,102,103,105,106,108,109,111,112,114,115,117,
-  118,120,121,122,124,125,127,128,130,131,133,134,136,137,139,140,
-  142,143,145,146,147,149,150,152,153,155,156,158,159,161,162,164,
-  165,167,168,170,171,172,174,175,177,178,180,181,183,184,186,187,
-  189,190,192,193,195,196,197,199,200,202,203,205,206,208,209,211,
-  212,214,215,217,218,220,221,222,224,225,227,228,230,231,233,234,
-  236,237,239,240,242,243,244,246,247,249,250,252,253,255,256
-};
-const unsigned short vdpsl2cyc_40_bl[] = { // slot # to 68k cycles/2
-    0,  2,  3,  4,  5,  6,  8,  9, 10, 11, 12, 14, 15, 16, 17, 18,
-   20, 21, 22, 23, 24, 26, 27, 28, 29, 30, 32, 33, 34, 35, 36, 38,
-   39, 40, 41, 42, 44, 45, 46, 47, 48, 50, 51, 52, 53, 54, 56, 57,
-   58, 59, 60, 61, 63, 64, 65, 66, 67, 69, 70, 71, 72, 73, 75, 76,
-   77, 78, 79, 81, 82, 83, 84, 85, 87, 88, 89, 90, 91, 93, 94, 95,
-   96, 97, 99,100,101,102,103,105,106,107,108,109,111,112,113,114,
-  115,117,118,119,120,121,122,124,125,126,127,128,130,131,132,133,
-  134,136,137,138,139,140,142,143,144,145,146,148,149,150,151,152,
-  154,155,156,157,158,160,161,162,163,164,166,167,168,169,170,172,
-  173,174,175,176,178,179,180,181,182,183,185,186,187,188,189,191,
-  192,193,194,195,197,198,199,200,201,203,204,205,206,207,209,210,
-  211,212,213,215,216,217,218,219,221,222,223,224,225,227,228,229,
-  230,231,233,234,235,236,237,239,240,241,242,243,244,246,247,248,
-  249,250,252,253,254,255,257
-};
-const unsigned short vdpsl2cyc_32[] = { // slot # to 68k cycles/2
-    0, 16, 36, 56, 67, 79,102,113,125,148,159,171,194,205,217,239,
-  240,260,280
-};
-const unsigned short vdpsl2cyc_40[] = { // slot # to 68k cycles/2
-    0, 24, 55, 64, 73, 92,101,110,129,138,147,166,175,184,203,212,
-  221,239,240,268,299
-};
 
 #ifndef _ASM_MISC_C
 PICO_INTERNAL_ASM void memcpy16bswap(unsigned short *dest, void *src, int count)

+ 1 - 0
pico/pico.c

@@ -40,6 +40,7 @@ void PicoInit(void)
   Pico32xInit();
   PsndInit();
 
+  PicoVideoInit();
   PicoDrawInit();
   PicoDraw2Init();
 }

+ 4 - 3
pico/pico_int.h

@@ -102,16 +102,16 @@ extern m68ki_cpu_core PicoCpuMM68k, PicoCpuMS68k;
 #define SekSr     m68k_get_reg(&PicoCpuMM68k, M68K_REG_SR)
 #define SekSrS68k m68k_get_reg(&PicoCpuMS68k, M68K_REG_SR)
 #define SekSetStop(x) { \
-	if(x) { SET_CYCLES(0); PicoCpuMM68k.stopped=STOP_LEVEL_STOP; } \
+	if(x) { PicoCpuMM68k.cyc_remaining_cycles = 0; PicoCpuMM68k.stopped=STOP_LEVEL_STOP; } \
 	else PicoCpuMM68k.stopped=0; \
 }
 #define SekSetStopS68k(x) { \
-	if(x) { SET_CYCLES(0); PicoCpuMS68k.stopped=STOP_LEVEL_STOP; } \
+	if(x) { PicoCpuMS68k.cyc_remaining_cycles = 0; PicoCpuMS68k.stopped=STOP_LEVEL_STOP; } \
 	else PicoCpuMS68k.stopped=0; \
 }
 #define SekIsStoppedM68k() (PicoCpuMM68k.stopped==STOP_LEVEL_STOP)
 #define SekIsStoppedS68k() (PicoCpuMS68k.stopped==STOP_LEVEL_STOP)
-#define SekShouldInterrupt() (CPU_INT_LEVEL > FLAG_INT_MASK)
+#define SekShouldInterrupt() (PicoCpuMM68k.int_level > PicoCpuMM68k.int_mask)
 
 #define SekNotPolling     PicoCpuMM68k.not_polling
 #define SekNotPollingS68k PicoCpuMS68k.not_polling
@@ -878,6 +878,7 @@ void PicoVideoFIFOSync(int cycles);
 int PicoVideoFIFOHint(void);
 void PicoVideoFIFOMode(int active, int h40);
 int PicoVideoFIFOWrite(int count, int byte_p, unsigned sr_mask, unsigned sr_flags);
+void PicoVideoInit(void);
 void PicoVideoSave(void);
 void PicoVideoLoad(void);
 void PicoVideoCacheSAT(void);

+ 124 - 17
pico/videoport.c

@@ -2,7 +2,7 @@
  * PicoDrive
  * (c) Copyright Dave, 2004
  * (C) notaz, 2006-2009
- * (C) kub, 2020
+ * (C) kub, 2020,2021
  *
  * This work is licensed under the terms of MAME license.
  * See COPYING file in the top-level directory.
@@ -12,11 +12,118 @@
 #define NEED_DMA_SOURCE
 #include "memory.h"
 
-extern const unsigned char  hcounts_32[], hcounts_40[];
-extern const unsigned char  vdpcyc2sl_32_bl[], vdpcyc2sl_40_bl[];
-extern const unsigned char  vdpcyc2sl_32[], vdpcyc2sl_40[];
-extern const unsigned short vdpsl2cyc_32_bl[], vdpsl2cyc_40_bl[];
-extern const unsigned short vdpsl2cyc_32[], vdpsl2cyc_40[];
+
+enum { clkdiv = 2 };    // CPU clock granularity: one of 1,2,4,8
+
+// VDP Slot timing, taken from http://gendev.spritesmind.net/
+//     forum/viewtopic.php?f=22&t=851&sid=d5701a71396ee7f700c74fb7cd85cb09
+// Thank you very much for the great work, Nemesis!
+
+// 1 slot is 488/171 = 2.8538 68k cycles in h32, and 488/210 = 2.3238 in h40.
+
+// VDP has a slot counter running from 0x00 to 0xff every scanline, but it has
+// a gap depending on the video mode. The slot in which a horizontal interrupt
+// is generated also depends on the video mode.
+enum { hint32 = 0x84, gapstart32 = 0x94, gapend32 = 0xe9 };
+enum { hint40 = 0xa4, gapstart40 = 0xb7, gapend40 = 0xe5 };
+
+// number of slots in a scanline
+#define slots32	(0x100-(gapend32-gapstart32)) // 171
+#define slots40	(0x100-(gapend40-gapstart40)) // 210
+
+// In blanked display, all slots but the refresh slots are usable for transfers,
+// in active display only 16(h32) / 18(h40) slots can be used.
+
+// dma and refresh slots for active display, 16 for H32
+static u8 dmaslots32[] =
+    { 145,243, 2,10,18, 34,42,50, 66,74,82, 98,106,114, 129,130 };
+static u8 refslots32[] =
+    {        250,     26,       58,       90,         122 };
+// dma and refresh slots for active display, 18 for H40
+static u8 dmaslots40[] =
+    {     232, 2,10,18, 34,42,50, 66,74,82, 98,106,114, 130,138,146, 161,162 };
+static u8 refslots40[] =
+    {        250,     26,       58,       90,         122,         154 };
+
+// table sizes
+enum { cycsz = 488/clkdiv };
+enum { sl32blsz=slots32-sizeof(refslots32)+1, sl32acsz=sizeof(dmaslots32)+1 };
+enum { sl40blsz=slots40-sizeof(refslots40)+1, sl40acsz=sizeof(dmaslots40)+1 };
+
+// Tables must be considerably larger than one scanline, since 68k emulation
+// isn't stopping in the middle of an operation. If the last op is a 32 bit
+// VDP write 2 slots may need to be taken from the next scanline, which can be
+// more than 100 CPU cycles. For safety just cover 2 scanlines.
+
+// table for mapping hvcounter reads
+static u8  hcounts_32[2*cycsz], hcounts_40[2*cycsz];
+// tables mapping cycles to slots
+static u16 vdpcyc2sl_32_bl[2*cycsz],vdpcyc2sl_40_bl[2*cycsz];
+static u16 vdpcyc2sl_32_ac[2*cycsz],vdpcyc2sl_40_ac[2*cycsz];
+// tables mapping slots to cycles
+// NB the sl2cyc tables must cover all slots present in the cyc2sl tables.
+static u16 vdpsl2cyc_32_bl[2*sl32blsz],vdpsl2cyc_40_bl[2*sl40blsz];
+static u16 vdpsl2cyc_32_ac[2*sl32acsz],vdpsl2cyc_40_ac[2*sl40acsz];
+
+
+// calculate timing tables for one mode (H32 or H40)
+// NB tables aligned to HINT, since the main loop uses HINT as synchronization
+#define INITTABLES(s) { \
+  float factor = 488./slots##s;						\
+  int ax, bx, rx, ac, bc;						\
+  int i, n;								\
+									\
+  /* calculate internal VDP slot numbers */				\
+  for (i = 0; i < cycsz; i++) {						\
+    n = hint##s + i*clkdiv/factor;					\
+    if (n >= gapstart##s) n += gapend##s-gapstart##s;			\
+       hcounts_##s[i] = n % 256;					\
+  }									\
+  memcpy(hcounts_##s+cycsz, hcounts_##s, ARRAY_SIZE(hcounts_##s)-cycsz);\
+									\
+  ax = bx = ac = bc = rx = 0;						\
+  for (i = 0; i < cycsz; i++) {						\
+    n = hcounts_##s[i];							\
+    if (i == 0 || n != hcounts_##s[i-1]) {				\
+      /* fill slt <=> cycle tables, active scanline */			\
+      if (ax < ARRAY_SIZE(dmaslots##s) && dmaslots##s[ax] == n) {	\
+        vdpsl2cyc_##s##_ac[++ax]=i;					\
+        while (ac < i) vdpcyc2sl_##s##_ac[ac++] = ax-1;			\
+      }									\
+      /* fill slt <=> cycle tables, scanline off */			\
+      if (rx >= ARRAY_SIZE(refslots##s) || refslots##s[rx] != n) {	\
+        vdpsl2cyc_##s##_bl[++bx]=i;					\
+        while (bc < i) vdpcyc2sl_##s##_bl[bc++] = bx-1;			\
+      } else								\
+        ++rx;								\
+    }									\
+  }									\
+  /* fill up cycle to slot mappings for last slot */			\
+  while (ac < cycsz)							\
+    vdpcyc2sl_##s##_ac[ac] = ARRAY_SIZE(dmaslots##s),		ac++;	\
+  while (bc < cycsz)							\
+    vdpcyc2sl_##s##_bl[bc] = slots##s-ARRAY_SIZE(refslots##s),	bc++;	\
+  /* extend tables for 2nd scanline */					\
+  i = ARRAY_SIZE(dmaslots##s);						\
+  while (ac < ARRAY_SIZE(vdpcyc2sl_##s##_ac))				\
+    vdpcyc2sl_##s##_ac[ac] = vdpcyc2sl_##s##_ac[ac-cycsz]+i,	ac++;	\
+  while (ax < ARRAY_SIZE(vdpsl2cyc_##s##_ac)-1)			ax++,	\
+    vdpsl2cyc_##s##_ac[ax] = vdpsl2cyc_##s##_ac[ax-i]+cycsz;\
+  i = slots##s - ARRAY_SIZE(refslots##s);				\
+  while (bc < ARRAY_SIZE(vdpcyc2sl_##s##_bl))				\
+    vdpcyc2sl_##s##_bl[bc] = vdpcyc2sl_##s##_bl[bc-cycsz]+i,	bc++;	\
+  while (bx < ARRAY_SIZE(vdpsl2cyc_##s##_bl)-1)			bx++,	\
+    vdpsl2cyc_##s##_bl[bx] = vdpsl2cyc_##s##_bl[bx-i]+cycsz;		\
+}
+ 
+
+// initialize VDP timing tables
+void PicoVideoInit(void)
+{
+  INITTABLES(32);
+  INITTABLES(40);
+}
+
 
 static int blankline;           // display disabled for this line
 
@@ -69,16 +176,17 @@ static struct VdpFIFO { // XXX this must go into save file!
   unsigned short fifo_slot;   // last executed slot in current scanline
   unsigned short fifo_maxslot;// #slots in scanline
 
-  const unsigned char *fifo_cyc2sl;
+  const unsigned short *fifo_cyc2sl;
   const unsigned short *fifo_sl2cyc;
 } VdpFIFO;
 
 enum { FQ_BYTE = 1, FQ_BGDMA = 2, FQ_FGDMA = 4 }; // queue flags, NB: BYTE = 1!
 
-// NB must limit cyc2sl to table size in case 68k overdraws its aim. That can
-// happen if the last insn is a blocking acess to VDP, or for exceptions (e.g.irq)
-#define	Cyc2Sl(vf,lc)	((lc) < 256*2 ? vf->fifo_cyc2sl[(lc)>>1] : vf->fifo_cyc2sl[255])
-#define Sl2Cyc(vf,sl)   (vf->fifo_sl2cyc[sl]*2)
+
+// NB should limit cyc2sl to table size in case 68k overdraws its aim. That can
+// happen if the last op is a blocking acess to VDP, or for exceptions (e.g.irq)
+#define	Cyc2Sl(vf,lc)	(vf->fifo_cyc2sl[(lc)/clkdiv])
+#define Sl2Cyc(vf,sl)   (vf->fifo_sl2cyc[sl]*clkdiv)
 
 // do the FIFO math
 static __inline int AdvanceFIFOEntry(struct VdpFIFO *vf, struct PicoVideo *pv, int slots)
@@ -263,7 +371,7 @@ int PicoVideoFIFOWrite(int count, int flags, unsigned sr_mask,unsigned sr_flags)
 
     // update FIFO state if it was empty
     if (!(pv->status & PVS_FIFORUN)) {
-      vf->fifo_slot = Cyc2Sl(vf, lc+9); // FIFO latency ~3 vdp slots
+      vf->fifo_slot = Cyc2Sl(vf, lc+5); // FIFO latency ~3 vdp slots
       pv->status |= PVS_FIFORUN;
       pv->fifo_cnt = count << (flags & FQ_BYTE);
     }
@@ -300,10 +408,10 @@ int PicoVideoFIFOHint(void)
 // switch FIFO mode between active/inactive display
 void PicoVideoFIFOMode(int active, int h40)
 {
-  static const unsigned char *vdpcyc2sl[2][2] =
-        { {vdpcyc2sl_32_bl, vdpcyc2sl_40_bl} , {vdpcyc2sl_32, vdpcyc2sl_40} };
+  static const unsigned short *vdpcyc2sl[2][2] =
+      { {vdpcyc2sl_32_bl, vdpcyc2sl_40_bl},{vdpcyc2sl_32_ac, vdpcyc2sl_40_ac} };
   static const unsigned short *vdpsl2cyc[2][2] =
-        { {vdpsl2cyc_32_bl, vdpsl2cyc_40_bl} , {vdpsl2cyc_32, vdpsl2cyc_40} };
+      { {vdpsl2cyc_32_bl, vdpsl2cyc_40_bl},{vdpsl2cyc_32_ac, vdpsl2cyc_40_ac} };
 
   struct VdpFIFO *vf = &VdpFIFO;
   struct PicoVideo *pv = &Pico.video;
@@ -316,11 +424,10 @@ void PicoVideoFIFOMode(int active, int h40)
   vf->fifo_cyc2sl = vdpcyc2sl[active][h40];
   vf->fifo_sl2cyc = vdpsl2cyc[active][h40];
   // recalculate FIFO slot for new mode
-  vf->fifo_slot = Cyc2Sl(vf, lc)-1;
+  vf->fifo_slot = Cyc2Sl(vf, lc);
   vf->fifo_maxslot = Cyc2Sl(vf, 488);
 }
 
-
 // VDP memory rd/wr
 
 static __inline void AutoIncrement(void)