--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+
+
+static FILE *f;
+
+#define bswap16(x) (x=(unsigned short)((x<<8)|(x>>8)))
+#define bswap32(x) (x=((x<<24)|((x<<8)&0xff0000)|((x>>8)&0x00ff00)|((unsigned)x>>24)))
+
+static void write_op(unsigned short op, unsigned short word0, unsigned short word1, unsigned short word2)
+{
+ bswap16(op);
+ bswap16(word0);
+ bswap16(word1);
+ bswap16(word2);
+
+ fwrite(&op, 1, sizeof(op), f);
+ fwrite(&word0, 1, sizeof(word0), f);
+ fwrite(&word1, 1, sizeof(word1), f);
+ fwrite(&word2, 1, sizeof(word2), f);
+}
+
+static void write32(unsigned int a)
+{
+ bswap32(a);
+ fwrite(&a, 1, sizeof(a), f);
+}
+
+static int op_check(unsigned short op)
+{
+ if ((op&0xf000) == 0x6000) return 0; // Bxx
+ if ((op&0xf0f8) == 0x50c8) return 0; // DBxx
+ if ((op&0xff80) == 0x4e80) return 0; // Jsr
+ if ((op&0xf000) == 0xa000) return 0; // a-line
+ if ((op&0xf000) == 0xf000) return 0; // f-line
+ if ((op&0xfff8)==0x4e70&&op!=0x4e71&&op!=0x4e76) return 0; // reset, rte, rts
+
+ if ((op&0x3f) >= 0x28) op = (op&~0x3f) | (rand() % 0x28);
+ return 1;
+}
+
+static unsigned short safe_rand(void)
+{
+ unsigned short op;
+
+ /* avoid branch opcodes */
+ do
+ {
+ op = rand();
+ }
+ while (!op_check(op));
+
+ return op;
+}
+
+int main()
+{
+ int i, op;
+
+ srand(time(0));
+
+ f = fopen("test_misc2.bin", "wb");
+ if (!f) return 1;
+
+ write32(0x00ff8000); // stack
+ write32(0x300); // IP
+
+ for (i=0x100/4-2; i; i--)
+ {
+ write32(0x200+i*4); // exception vectors
+ }
+
+ for (i=0x100/4; i; i--)
+ {
+ write32(0); // pad
+ }
+
+ for (i=0x100/4; i; i--)
+ {
+ write32(0x4e734e73); // fill with rte instructions
+ }
+
+ for (op = 0; op < 0x10000; op++)
+ {
+ if ((op&0xf000) == 0x6000) // Bxx
+ {
+ if ((op&0x00ff) == 0)
+ write_op(op, 6, 0, 0);
+ }
+ else if ((op&0xf0f8)==0x50c8) // DBxx
+ {
+ write_op(op, 6, 0, 0);
+ }
+ else if ((op&0xff80)==0x4e80) // Jsr
+ {
+ int addr = 0x300 + op*8 + 8;
+ if ((op&0x3f) == 0x39)
+ write_op(op, addr >> 16, addr & 0xffff, 0);
+ }
+ else if ((op&0xf000)==0xa000 || (op&0xf000)==0xf000) // a-line, f-line
+ {
+ if (op != 0xa000 && op != 0xf000) continue;
+ }
+ else if ((op&0xfff8)==0x4e70&&op!=0x4e71&&op!=0x4e76); // rte, rts, stop, reset
+ else
+ {
+ write_op(op, safe_rand(), safe_rand(), safe_rand());
+ }
+ }
+
+ // jump to the beginning
+ write_op(0x4ef8, 0x300, 0x4ef8, 0x300);
+ write_op(0x4ef8, 0x300, 0x4ef8, 0x300);
+
+ fclose(f);
+ return 0;
+}
+
--- /dev/null
+| Processor: 68K\r
+| Target Assembler: 680x0 Assembler by GNU project\r
+\r
+| ___________________________________________________________________________\r
+\r
+| Segment type: Pure code\r
+| segment "ROM"\r
+dword_0: .long 0 | DATA XREF: ROM:00007244\19r\r
+ | sub_764E+3E\19o ...\r
+ | initial interrupt stack pointer\r
+dword_4: .long _start | DATA XREF: ROM:00007248\19r\r
+ | ROM:000142C2\19w\r
+ | reset initial PC\r
+dword_8: .long 0x4DE | DATA XREF: sub_20050+B54\19w\r
+ .long 0x490\r
+ .long 0x4AA | illegal instruction\r
+ .long 0x4C4\r
+ .long 0x4DE\r
+ .long 0x4DE\r
+ .long 0x4DE\r
+ .long _trace | trace\r
+ .long 0x4DE\r
+ .long 0x4DE\r
+ .long 0x4DE\r
+ .long 0x4DE\r
+ .long 0x4DE\r
+ .long 0x4DE\r
+ .long 0x4DE\r
+ .long 0x4DE\r
+ .long 0x4DE\r
+ .long 0x4DE\r
+ .long 0x4DE\r
+ .long 0x4DE\r
+ .long 0x4DE\r
+ .long 0x4DE\r
+ .long 0x4DE\r
+ .long 0x548 | Level 1 Interrupt Autovector\r
+ .long 0x548 | 2 = ext interrupt\r
+ .long 0x548\r
+ .long 0x592 | 4 = horizontal interrupt?\r
+ .long 0x548\r
+ .long 0x594 | 6 = verticai interrupt?\r
+ .long 0x552\r
+dword_80: .long 0x45C | DATA XREF: ROM:00152F29\19o\r
+ | trap vector table? trap 0?\r
+ .long 0x1738\r
+ .long 0x171C\r
+ .long 0x1754\r
+ .long 0x1700\r
+ .long 0x556\r
+ .long 0x57A\r
+ .long 0x548\r
+ .long 0x548\r
+ .long 0x7CE | 9\r
+ .long 0x548\r
+ .long 0x548\r
+ .long 0x548\r
+ .long 0x548\r
+ .long 0x548\r
+ .long 0x548\r
+ .long 0x4DE\r
+ .long 0x4DE\r
+ .long 0x4DE\r
+ .long 0x4DE\r
+ .long 0x4DE\r
+ .long 0x4DE\r
+ .long 0x4DE\r
+ .long 0x4DE\r
+ .long 0x4DE\r
+ .long 0x4DE\r
+ .long 0x4DE\r
+ .long 0x4DE\r
+ .long 0x4DE\r
+ .long 0x4DE\r
+ .long 0x4DE\r
+ .long 0x4DE\r
+aSegaGenesis: .ascii "SEGA GENESIS " | DATA XREF: ROM:00045C6A\19o\r
+aCSega1994_jul: .ascii "(C)SEGA 1994.JUL"\r
+aDumpedByTsd: .ascii "Dumped By TSD "\r
+aShiningForce2: .ascii "SHINING FORCE 2 "\r
+aGmMk131500: .ascii "GM MK-1315 -00"\r
+ .word 0x8921 | checksum\r
+aJ: .ascii "J " | IO_Support\r
+ .long 0 | Rom_Start_Adress\r
+dword_1A4: .long 0x1FFFFF | DATA XREF: sub_28008+F66\19o\r
+ | Rom_End_Adress\r
+ .long 0xFF0000 | Ram_Start_Adress\r
+ .long 0xFFFFFF | Ram_End_Adress\r
+aRaa: .ascii "RA° "<0>" "<0><1><0>" ?"<0xFF> | Modem_Infos\r
+ .ascii " "\r
+ .byte 0x20 | \r
+ .byte 0x20 | \r
+ .byte 0x20 | \r
+ .byte 0x20 | \r
+ .byte 0x20 | \r
+ .byte 0x20 | \r
+ .byte 0x20 | \r
+ .byte 0x20 | \r
+ .byte 0x20 | \r
+ .byte 0x20 | \r
+ .byte 0x20 | \r
+ .byte 0x20 | \r
+aU: .ascii "U " | Countries\r
+ .byte 0x20 | \r
+ .byte 0x20 | \r
+ .byte 0x20 | \r
+ .byte 0x20 | \r
+ .byte 0x20 | \r
+ .byte 0x20 | \r
+ .byte 0x20 | \r
+ .byte 0x20 | \r
+ .byte 0x20 | \r
+ .byte 0x20 | \r
+ .byte 0x20 | \r
+ .byte 0x20 | \r
+ .byte 0x20 | \r
+_trace:\r
+ nop\r
+ nop\r
+ rte\r
+\r
+.globl _start\r
+_start:\r
+ move.l #0xFFFFFFFF, %d0\r
+ move.l #0xFFFFFFFF, %d1\r
+ move.w #0xa711, %sr\r
+ move.l #0x1, %d2\r
+ move.l #0x8000, %d3\r
+ negx.l %d0\r
+ negx.l %d1\r
+ move.w #0x270f, %sr\r
+ negx.b %d2\r
+ negx.w %d3\r
+_loop:\r
+ bra _loop\r
+\r
+ nop\r
+ nop\r
+ nop\r
+ nop\r
--- /dev/null
+
+void CycloneInitIdle(void);
+void CycloneFinishIdle(void);
--- /dev/null
+@ vim:filetype=armasm
+
+@ ranges/opcodes (idle, normal):
+@ 71xx, 73xx - bne.s (8bit offset)
+@ 75xx, 77xx - beq.s (8bit offset)
+@ 7dxx, 7fxx - bra.s (8bit offset)
+
+.data
+.align 2
+
+have_patches:
+ .word 0
+
+.equ patch_desc_table_size, 10
+
+patch_desc_table:
+ .word (0x71fa<<16) | 0x66fa, idle_detector_bcc8, idle_bne, Op6601 @ bne.s
+ .word (0x71f8<<16) | 0x66f8, idle_detector_bcc8, idle_bne, Op6601 @ bne.s
+ .word (0x71f6<<16) | 0x66f6, idle_detector_bcc8, idle_bne, Op6601 @ bne.s
+ .word (0x71f2<<16) | 0x66f2, idle_detector_bcc8, idle_bne, Op6601 @ bne.s
+ .word (0x75fa<<16) | 0x67fa, idle_detector_bcc8, idle_beq, Op6701 @ beq.s
+ .word (0x75f8<<16) | 0x67f8, idle_detector_bcc8, idle_beq, Op6701 @ beq.s
+ .word (0x75f6<<16) | 0x67f6, idle_detector_bcc8, idle_beq, Op6701 @ beq.s
+ .word (0x75f2<<16) | 0x67f2, idle_detector_bcc8, idle_beq, Op6701 @ beq.s
+ .word (0x7dfe<<16) | 0x60fe, idle_detector_bcc8, idle_bra, Op6001 @ bra.s
+ .word (0x7dfc<<16) | 0x60fc, idle_detector_bcc8, idle_bra, Op6001 @ bra.s
+
+
+.text
+.align 2
+
+
+.global CycloneInitIdle
+
+CycloneInitIdle:
+ ldr r3, =CycloneJumpTab
+ ldr r2, =patch_desc_table
+ mov r12,#patch_desc_table_size
+
+cii_loop:
+ ldrh r0, [r2]
+ ldr r1, [r2, #4] @ detector
+ str r1, [r3, r0, lsl #2]
+ ldrh r0, [r2, #2]
+ ldr r1, [r2, #8] @ idle
+ add r0, r3, r0, lsl #2
+ str r1, [r0]
+ ldr r1, [r2, #12] @ normal
+ str r1, [r0, #0x800]
+ add r2, r2, #16
+ subs r12,r12,#1
+ bgt cii_loop
+
+ ldr r0, =have_patches
+ mov r1, #1
+ str r1, [r0]
+ bx lr
+
+
+.global CycloneFinishIdle
+
+CycloneFinishIdle:
+ ldr r0, =have_patches
+ ldr r0, [r0]
+ tst r0, r0
+ bxeq lr
+
+ ldr r3, =CycloneJumpTab
+ ldr r2, =patch_desc_table
+ mov r12,#patch_desc_table_size
+
+cfi_loop:
+ ldrh r0, [r2]
+ ldr r1, [r2, #12] @ normal
+ str r1, [r3, r0, lsl #2]
+ ldrh r0, [r2, #2]
+ ldr r1, =Op____
+ add r0, r3, r0, lsl #2
+ str r1, [r0]
+ str r1, [r0, #0x800]
+ add r2, r2, #16
+ subs r12,r12,#1
+ bgt cfi_loop
+
+ ldr r0, =have_patches
+ mov r1, #0
+ str r1, [r0]
+ bx lr
+
+
+
+.macro inc_counter cond
+@ ldr\cond r0, [r7, #0x60]
+@ mov r11,lr
+@ sub r0, r4, r0
+@ sub r0, r0, #2
+@ bl\cond SekRegisterIdleHit
+@ mov lr, r11
+.endm
+
+idle_bra:
+ mov r5, #2
+ inc_counter
+ b Op6001
+
+idle_bne:
+ msr cpsr_flg, r10
+ movne r5, #2 @ 2 is intentional due to strange timing issues
+ inc_counter ne
+ b Op6601
+
+idle_beq:
+ msr cpsr_flg, r10 ;@ ARM flags = 68000 flags
+ moveq r5, #2
+ inc_counter eq
+ b Op6701
+
+
+@ @@@ @
+
+idle_detector_bcc8:
+ ldr r0, =(Pico+0x22208) @ Pico.m
+ ldr r1, =idledet_start_frame
+ ldr r0, [r0, #0x1c] @ ..frame_count
+ ldr r1, [r1]
+ cmp r0, r1
+ blt exit_detector @ not yet
+
+ mov r0, r8, asl #24 @ Shift 8-bit signed offset up...
+ add r0, r4, r0, asr #24 @ jump dest
+ bic r0, r0, #1
+
+ mov r1, #0
+ sub r1, r1, r8, lsl #24
+ mov r1, r1, lsr #24
+ sub r1, r1, #2
+ bic r1, r1, #1
+
+ bl SekIsIdleCode
+ tst r0, r0
+ and r2, r8, #0x00ff
+ orr r2, r2, #0x7100
+ orreq r2, r2, #0x0200
+ mov r0, r8, lsr #8
+ cmp r0, #0x66
+ orrgt r2, r2, #0x0400 @ 67xx (beq)
+ orrlt r2, r2, #0x0c00 @ 60xx (bra)
+
+ @ r2 = patch_opcode
+ sub r0, r4, #2
+ ldrh r1, [r0]
+ mov r11,r2
+ mov r3, r7
+ bl SekRegisterIdlePatch
+ cmp r0, #1 @ 0 - ok to patch, 1 - no patch, 2 - remove detector
+ strlth r11,[r4, #-2]
+ ble exit_detector
+
+ @ remove detector from Cyclone
+ mov r0, r8, lsr #8
+ cmp r0, #0x66
+ ldrlt r1, =Op6001
+ ldreq r1, =Op6601
+ ldrgt r1, =Op6701
+
+ ldr r3, =CycloneJumpTab
+ str r1, [r3, r8, lsl #2]
+ bx r1
+
+exit_detector:
+ mov r0, r8, lsr #8
+ cmp r0, #0x66
+ blt Op6001
+ beq Op6601
+ b Op6701
+