head	1.1;
access;
symbols;
locks
	hayakawa:1.1; strict;
comment	@# @;


1.1
date	2000.12.06.07.02.26;	author hayakawa;	state Exp;
branches;
next	;


desc
@@


1.1
log
@Initial revision
@
text
@/* -*- asm -*- */

/* implement $BCf(B
 * store05_io
 *
 * implement $B$,I,MW$J%k!<%A%s(B
 * load05_io
 * load05_5204, mmc5_5204_output
 */
		
#include <asm.h>
#include <regdef.h>
#include <PR/R4300.h>
#include "offset-rfc.inc"

/* asmrfc.s $B$N%l%8%9%?3d$jEv$F!#(Bni_debug.c $B$G;2>H$G$-$k$h$&$K(B ks_rfc.inc
 * $B$G$d$k$N$bNI$$$,!"%^%/%mL>$,C;$9$.$F=EJ#$N4m81$,$"$k$N$G(B $B$d$a$?!#(B
 * $B%U%i%0%l%8%9%?$N(B Reserved|B|D|I $B$O(B $B%a%b%j$K;}$D$N$_(B
 * JUMPTBLP $B$O(B $B:#=hM}Cf$N%8%c%s%W%F!<%V%k$N@@hF,HVCO(B - OFFSET_JUMPTBL
 * STORE_DONE $B$OL?Na$N=hM}3+;O$N$H$-$K(B next $B$,F~$k!#(B
 * PAGE_PTR $B$O(B loadfunc $B2<@@A$1$J$I$G;H$&!#(B
 * Z $B$O(B 0xff $B$r1[$($k$3$H$b$"$k$N$G(B 0 $B$+$I$&$+$NHf3S$O(B andi 0xff $B$r$7$F$+$i!#(B
 * C $B$O(B $BI,$:(B 0 or 1
 * N $B$O(B $BI,$:(B 0 or 0x80
 * SP $B$O(B 0x00..0xff $B$G!"FI$_=q$-$N$H$-(B OFFSET_WRAM + 0x100(xx) $B$H$9$k!#(B
 */
	
#define WORK fp
#define A    s0
#define X    s1
#define Y    s2
#define PC   s3
#define SP   s4
#define Z    s5
#define C    s6
#define V    s7
#define N    gp


/* push_v1 $B$rFI$s$G$$$k$N$G$H$j$"$($:(B STORE_DONE $B$O(B v1 $B$K$7$J$$$h$&$K!#(B
 * STORE_DONE $B$O(B t6 $B$K$7$?!#(Bt6 $B$O%o!<%/$G;H$C$F$$$k$H$3$m$b$"$k$,%;!<%U!#(B
 * store_sound $B$G$3$l$i$r(B save $B$7$F$$$k$H$3$m$,$"$k$N$GCm0U!#(B
 */
#define STORE_DONE  t6
#define JUMPTBLP    t7
#define PAGE_PTR    t8
#define LINECYCLE   t9

#ifndef KS_DEBUG
#undef KS_TRACE
#undef KS_HISTORY
#undef KS_DEBUG_REGS
#undef KS_TRAP_STORE_INVALID
#endif
	
/* R4300 stack frame offset
 * $B%9%?%C%/%U%l!<%`$O(B 8 bytes alignment 
 * OFFSET_STACK_CALLER_A[0-3] $B$O8F$P$l$?$H$-$N0z?t$N(B save $BNN0h(B
 * C $B%3%s%Q%$%i$N$*LsB+$G$O(B a0-a3 $B$O(B EMU_PGB_ASM_STACKSIZE+0x00 $B$+$i$G$h$$$,(B
 * $B$=$3$O;H$o$J$$!#JL$K;H$o$J$/$C$?$C$F$$$$$N$@@!#(B
 * $B0z?t(B 8 int $B$N4X?t$r8F$V$H$7$F!"(B+8 bytes $BM>M5$r$_$F!"@@hF,$N(B 40 bytes $B$O(B reserved
 */
#define EMU_RFC_ASM_STACKSIZE 0x100
#define OFFSET_STACK_CALLER_A0 0x28
#define OFFSET_STACK_CALLER_A1 0x2c
#define OFFSET_STACK_CALLER_A2 0x30
#define OFFSET_STACK_CALLER_A3 0x34

#define OFFSET_STACK_S0 0x40
#define OFFSET_STACK_S1 0x44
#define OFFSET_STACK_S2 0x48
#define OFFSET_STACK_S3 0x4c
#define OFFSET_STACK_S4 0x50
#define OFFSET_STACK_S5 0x54
#define OFFSET_STACK_S6 0x58
#define OFFSET_STACK_S7 0x5c
#define OFFSET_STACK_GP 0x60
#define OFFSET_STACK_FP 0x64
#define OFFSET_STACK_RA 0x68

#define OFFSET_STACK_T0 0x6c
#define OFFSET_STACK_T1 0x70
#define OFFSET_STACK_T2 0x74
#define OFFSET_STACK_T3 0x78
#define OFFSET_STACK_T4 0x7c
#define OFFSET_STACK_T5 0x80
#define OFFSET_STACK_T6 0x84
#define OFFSET_STACK_T7 0x88
#define OFFSET_STACK_T8 0x8c
#define OFFSET_STACK_T9 0x90
#define OFFSET_STACK_A0 0x94
#define OFFSET_STACK_A1 0x98
#define OFFSET_STACK_A2 0x9c
#define OFFSET_STACK_A3 0xa0
#define OFFSET_STACK_V0 0xa4
#define OFFSET_STACK_V1 0xa8
#define OFFSET_STACK_RA_SOUND 0xac

#define OFFSET_STACK_T6_PRINTF  0xb0
#define OFFSET_STACK_T7_PRINTF  0xb4
#define OFFSET_STACK_T8_PRINTF  0xb8
#define OFFSET_STACK_T9_PRINTF  0xbc
#define OFFSET_STACK_V0_PRINTF  0xc0
#define OFFSET_STACK_V1_PRINTF  0xc4
	
#define OFFSET_STACK_RA_PRINTF  0xc8
#define OFFSET_STACK_AT_PRINTF  0xcc
#define OFFSET_STACK_RA_PRINTF2 0xd0
#define OFFSET_STACK_GP_PRINTF  0xd4
#define OFFSET_STACK_FP_PRINTF  0xd8
#define OFFSET_STACK_COUNTER    0xdc /* debug $BMQ(B */
#define OFFSET_STACK_DEBUG_V0   0xe0 /* debug $BMQ(B */
#define OFFSET_STACK_DEBUG_REGS 0xe4 /* debug $BMQ(B */



#undef PRINTF
#ifdef KS_DEBUG_VERBOSE
#define COUNTER_BEGIN \
	.set	noreorder; \
	mfc0	$1, C0_COUNT; \
	sw	$1, OFFSET_STACK_COUNTER(sp); \
	.set	reorder

#define COUNTER_END \
	.set	noreorder; \
	mfc0	$1, C0_COUNT; \
	lw	v0, OFFSET_STACK_COUNTER(sp); \
	subu	v0, $1, v0; \
	.set	reorder
	
#define TRAP(msg) \
	.data; \
206:	.asciiz	msg; \
	.text; \
	.set	noreorder; \
	la	k0, 206b; \
	lui	k1, 0x8000; \
	sw	k0, 0(k1); \
	teq	zero, zero; \
	nop; \
	.set	reorder

/* $B$o$6$o$6(B move $1,a0; $B$H$+$7$F$k$N$O(B
 * $BD>@@\(B la $1, 205b; $B$H$+$9$k$H(B as $B$,(B
 * Warning: macro instruction used $at $B$H$$$C$F$&$k$5$$$+$i!#(B
 */
#define PRINTF(f) \
	.data; \
205:	.asciiz	f; \
	.text; \
	.set noreorder; \
	sw	$1, OFFSET_STACK_AT_PRINTF(sp); \
	move $1,a0; \
	sw	ra, OFFSET_STACK_RA_PRINTF(sp); \
	la	a0, 205b; \
	jal	save_ossync_restore; \
	sw	$1, OFFSET_STACK_A0(sp); \
	.set reorder
#undef GLOBAL()
#define GLOBAL(s) .globl s; .aent s
#else
#define COUNTER_BEGIN
#define COUNTER_END
#define TRAP(msg) /* msg */
#define PRINTF(f) /* f */
#define GLOBAL(s) /* s */
#endif

#ifdef KS_DEBUG_VERBOSE
	.data
	.align	4
static_debug_insttbl:
	.asciiz "brk        "
1:	.asciiz "ora %02x,x   "
2:	.asciiz "?02"
3:	.asciiz "?03"
4:	.asciiz "?04"
5:	.asciiz "ora %02x     "
6:	.asciiz "asl %02x     "
7:	.asciiz "?07"
8:	.asciiz "php        "
9:	.asciiz "ora #%02x    "
10:	.asciiz "asl        "
11:	.asciiz "?0b"
12:	.asciiz "?0c"
13:	.asciiz "ora %04x   "
14:	.asciiz "asl %04x   "
15:	.asciiz "?0f"
16:	.asciiz "bpl        "
17:	.asciiz "ora (%02x),y "
18:	.asciiz "?12"
19:	.asciiz "?13"
20:	.asciiz "?14"
21:	.asciiz "ora %02x,x   "
22:	.asciiz "asl %02x,x   "
23:	.asciiz "?17"
24:	.asciiz "clc        "
25:	.asciiz "ora %04x,y "
26:	.asciiz "?1a"
27:	.asciiz "?1b"
28:	.asciiz "?1c"
29:	.asciiz "ora %04x,x "
30:	.asciiz "asl %04x,x "
31:	.asciiz "?1f"
32:	.asciiz "jsr %04x   "
33:	.asciiz "and (%02x,x) "
34:	.asciiz "?22"
35:	.asciiz "?23"
36:	.asciiz "bit %02x     "
37:	.asciiz "and %02x     "
38:	.asciiz "rol %02x     "
39:	.asciiz "?27"
40:	.asciiz "plp        "
41:	.asciiz "and #%02x    "
42:	.asciiz "rol        "
43:	.asciiz "?2b"
44:	.asciiz "bit %04x   "
45:	.asciiz "and %04x   "
46:	.asciiz "rol %04x   "
47:	.asciiz "?2f"
48:	.asciiz "bmi        "
49:	.asciiz "and (%02x),y "
50:	.asciiz "?32"
51:	.asciiz "?33"
52:	.asciiz "?34"
53:	.asciiz "and %02x,x   "
54:	.asciiz "rol %02x,x   "
55:	.asciiz "?37"
56:	.asciiz "sec        "
57:	.asciiz "and %04x,y "
58:	.asciiz "?3a        "
59:	.asciiz "?3b"
60:	.asciiz "?3c"
61:	.asciiz "and %04x,x "
62:	.asciiz "rol %04x,x "
63:	.asciiz "?3f"
64:	.asciiz "rti        "
65:	.asciiz "eor (%02x,x) "
66:	.asciiz "?42        "
67:	.asciiz "?43"
68:	.asciiz "?44"
69:	.asciiz "eor %02x     "
70:	.asciiz "lsr %02x     "
71:	.asciiz "?47"
72:	.asciiz "pha        "
73:	.asciiz "eor #%02x    "
74:	.asciiz "lsr        "
75:	.asciiz "?4b"
76:	.asciiz "jmp %04x   "
77:	.asciiz "eor %04x   "
78:	.asciiz "lsr %04x   "
79:	.asciiz "?4f"
80:	.asciiz "bvc        "
81:	.asciiz "eor (%02x),y "
82:	.asciiz "?52"
83:	.asciiz "?53"
84:	.asciiz "?54"
85:	.asciiz "eor %02x,x   "
86:	.asciiz "lsr %02x,x   "
87:	.asciiz "?57"
88:	.asciiz "cli        "
89:	.asciiz "eor %04x,y "
90:	.asciiz "?5a"
91:	.asciiz "?5b"
92:	.asciiz "?5c"
93:	.asciiz "eor %04x,x "
94:	.asciiz "lsr %04x,x "
95:	.asciiz "?5f"
96:	.asciiz "rts        "
97:	.asciiz "adc (%02x,x) "
98:	.asciiz "?62"
99:	.asciiz "?63"
100:	.asciiz "?64"
101:	.asciiz "adc %02x     "
102:	.asciiz "ror %02x     "
103:	.asciiz "?67"
104:	.asciiz "pla        "
105:	.asciiz "adc #%02x    "
106:	.asciiz "ror        "
107:	.asciiz "?6b"
108:	.asciiz "jmp (%04x) "
109:	.asciiz "adc %04x   "
110:	.asciiz "ror %04x   "
111:	.asciiz "?6f"
112:	.asciiz "bvs        "
113:	.asciiz "adc (%02x),y "
114:	.asciiz "?72"
115:	.asciiz "?73"
116:	.asciiz "?74"
117:	.asciiz "adc %02x,x   "
118:	.asciiz "ror %02x,x   "
119:	.asciiz "?77"
120:	.asciiz "sei        "
121:	.asciiz "adc %04x,y "
122:	.asciiz "?7a"
123:	.asciiz "?7b"
124:	.asciiz "?7c"
125:	.asciiz "adc %04x,x "
126:	.asciiz "ror %04x,x "
127:	.asciiz "?7f"
128:	.asciiz "?80"
129:	.asciiz "sta (%02x,x) "
130:	.asciiz "?82"
131:	.asciiz "?83"
132:	.asciiz "sty %02x     "
133:	.asciiz "sta %02x     "
134:	.asciiz "stx %02x     "
135:	.asciiz "?87"
136:	.asciiz "dey        "
137:	.asciiz "?89"
138:	.asciiz "txa        "
139:	.asciiz "?8b"
140:	.asciiz "sty %04x   "
141:	.asciiz "sta %04x   "
142:	.asciiz "stx %04x   "
143:	.asciiz "?8f"
144:	.asciiz "bcc        "
145:	.asciiz "sta (%02x),y "
146:	.asciiz "?92"
147:	.asciiz "?93"
148:	.asciiz "sty %02x,x   "
149:	.asciiz "sta %02x,x   "
150:	.asciiz "stx %02x,y   "
151:	.asciiz "?97"
152:	.asciiz "tya        "
153:	.asciiz "sta %04x,y "
154:	.asciiz "txs        "
155:	.asciiz "?9b"
156:	.asciiz "?9c"
157:	.asciiz "sta %04x,x "
158:	.asciiz "?9e"
159:	.asciiz "?9f"
160:	.asciiz "ldy #%02x    "
161:	.asciiz "lda (%02x,x) "
162:	.asciiz "ldx #%02x    "
163:	.asciiz "?a3"
164:	.asciiz "ldy %02x     "
165:	.asciiz "lda %02x     "
166:	.asciiz "ldx %02x     "
167:	.asciiz "?a7"
168:	.asciiz "tay        "
169:	.asciiz "lda #%02x    "
170:	.asciiz "tax        "
171:	.asciiz "?ab"
172:	.asciiz "ldy %04x   "
173:	.asciiz "lda %04x   "
174:	.asciiz "ldx %04x   "
175:	.asciiz "?af"
176:	.asciiz "bcs        "
177:	.asciiz "lda (%02x),y "
178:	.asciiz "?b2"
179:	.asciiz "?b3"
180:	.asciiz "ldy %02x,x   "
181:	.asciiz "lda %02x,x   "
182:	.asciiz "ldx %02x,y   "
183:	.asciiz "?b7"
184:	.asciiz "clv        "
185:	.asciiz "lda %04x,y "
186:	.asciiz "tsx        "
187:	.asciiz "?bb"
188:	.asciiz "ldy %04x,x "
189:	.asciiz "lda %04x,x "
190:	.asciiz "ldx %04x,y "
191:	.asciiz "?bf"
192:	.asciiz "cpy #%02x    "
193:	.asciiz "cmp (%02x,x) "
194:	.asciiz "?c2"
195:	.asciiz "?c3"
196:	.asciiz "cpy %02x     "
197:	.asciiz "cmp %02x     "
198:	.asciiz "dec        "
199:	.asciiz "?c7"
200:	.asciiz "iny        "
201:	.asciiz "cmp #%02x    "
202:	.asciiz "dex        "
203:	.asciiz "?cb"
204:	.asciiz "cpy %04x   "
205:	.asciiz "cmp %04x   "
206:	.asciiz "dec %04x   "
207:	.asciiz "?cf"
208:	.asciiz "bne        "
209:	.asciiz "cmp (%02x),y "
210:	.asciiz "?d2"
211:	.asciiz "?d3"
212:	.asciiz "?d4"
213:	.asciiz "cmp %02x,x   "
214:	.asciiz "dec %02x,x   "
215:	.asciiz "?d7"
216:	.asciiz "cld        "
217:	.asciiz "cmp %04x,y "
218:	.asciiz "?da"
219:	.asciiz "?db"
220:	.asciiz "?dc"
221:	.asciiz "cmp %04x,x "
222:	.asciiz "dec %04x,x "
223:	.asciiz "?df"
224:	.asciiz "cpx #%02x    "
225:	.asciiz "sbc (%02x,x) "
226:	.asciiz "?e2"
227:	.asciiz "?e3"
228:	.asciiz "cpx %02x     "
229:	.asciiz "sbc %02x     "
230:	.asciiz "inc %02x     "
231:	.asciiz "?e7"
232:	.asciiz "inx        "
233:	.asciiz "sbc #%02x    "
234:	.asciiz "nop        "
235:	.asciiz "?eb"
236:	.asciiz "cpx %04x   "
237:	.asciiz "sbc %04x   "
238:	.asciiz "inc %04x   "
239:	.asciiz "?ef"
240:	.asciiz "beq        "
241:	.asciiz "sbc (%02x),y "
242:	.asciiz "?f2"
243:	.asciiz "?f3"
244:	.asciiz "?f4"
245:	.asciiz "sbc %02x,x   "
246:	.asciiz "inc %02x,x   "
247:	.asciiz "?f7"
248:	.asciiz "sed        "
249:	.asciiz "sbc %04x,y "
250:	.asciiz "?fa"
251:	.asciiz "?fb"
252:	.asciiz "?fc"
253:	.asciiz "sbc %04x,x "
254:	.asciiz "inc %04x,x "
255:	.asciiz "?ff"

	.align	4
static_debug_insttbl_ptr:
	.word	static_debug_insttbl,
	.word	1b,2b,3b,4b,5b,6b,7b,8b,9b
	.word	10b,11b,12b,13b,14b,15b,16b,17b,18b,19b
	.word	20b,21b,22b,23b,24b,25b,26b,27b,28b,29b
	.word	30b,31b,32b,33b,34b,35b,36b,37b,38b,39b
	.word	40b,41b,42b,43b,44b,45b,46b,47b,48b,49b
	.word	50b,51b,52b,53b,54b,55b,56b,57b,58b,59b
	.word	60b,61b,62b,63b,64b,65b,66b,67b,68b,69b
	.word	70b,71b,72b,73b,74b,75b,76b,77b,78b,79b
	.word	80b,81b,82b,83b,84b,85b,86b,87b,88b,89b
	.word	90b,91b,92b,93b,94b,95b,96b,97b,98b,99b
	.word	100b,101b,102b,103b,104b,105b,106b,107b,108b,109b
	.word	110b,111b,112b,113b,114b,115b,116b,117b,118b,119b
	.word	120b,121b,122b,123b,124b,125b,126b,127b,128b,129b
	.word	130b,131b,132b,133b,134b,135b,136b,137b,138b,139b
	.word	140b,141b,142b,143b,144b,145b,146b,147b,148b,149b
	.word	150b,151b,152b,153b,154b,155b,156b,157b,158b,159b
	.word	160b,161b,162b,163b,164b,165b,166b,167b,168b,169b
	.word	170b,171b,172b,173b,174b,175b,176b,177b,178b,179b
	.word	180b,181b,182b,183b,184b,185b,186b,187b,188b,189b
	.word	190b,191b,192b,193b,194b,195b,196b,197b,198b,199b
	.word	200b,201b,202b,203b,204b,205b,206b,207b,208b,209b
	.word	210b,211b,212b,213b,214b,215b,216b,217b,218b,219b
	.word	220b,221b,222b,223b,224b,225b,226b,227b,228b,229b
	.word	230b,231b,232b,233b,234b,235b,236b,237b,238b,239b
	.word	240b,241b,242b,243b,244b,245b,246b,247b,248b,249b
	.word	250b,251b,252b,253b,254b,255b
	
	.text
	.align	4
	.set	reorder
	.set	macro
	.set	nobopt
	.set	noat

save_ossync_restore:
	sw	ra, OFFSET_STACK_RA_PRINTF2(sp)
	sw	v0, OFFSET_STACK_V0_PRINTF(sp)
	sw	v1, OFFSET_STACK_V1_PRINTF(sp)
	sw	a1, OFFSET_STACK_A1(sp)
	sw	a2, OFFSET_STACK_A2(sp)
	sw	a3, OFFSET_STACK_A3(sp)
	sw	t0, OFFSET_STACK_T0(sp)
	sw	t1, OFFSET_STACK_T1(sp)
	sw	t2, OFFSET_STACK_T2(sp)
	sw	t3, OFFSET_STACK_T3(sp)
	sw	t4, OFFSET_STACK_T4(sp)
	sw	t5, OFFSET_STACK_T5(sp)
	sw	t6, OFFSET_STACK_T6_PRINTF(sp)
	sw	t7, OFFSET_STACK_T7_PRINTF(sp)
	sw	t8, OFFSET_STACK_T8_PRINTF(sp)
	sw	t9, OFFSET_STACK_T9_PRINTF(sp)
	sw	gp, OFFSET_STACK_GP_PRINTF(sp)
	sw	fp, OFFSET_STACK_FP_PRINTF(sp)
	
	jal	osSyncPrintf
	
	lw	$1, OFFSET_STACK_AT_PRINTF(sp)
	lw	v0, OFFSET_STACK_V0_PRINTF(sp)
	lw	v1, OFFSET_STACK_V1_PRINTF(sp)
	lw	a0, OFFSET_STACK_A0(sp)
	lw	a1, OFFSET_STACK_A1(sp)
	lw	a2, OFFSET_STACK_A2(sp)
	lw	a3, OFFSET_STACK_A3(sp)
	lw	t0, OFFSET_STACK_T0(sp)
	lw	t1, OFFSET_STACK_T1(sp)
	lw	t2, OFFSET_STACK_T2(sp)
	lw	t3, OFFSET_STACK_T3(sp)
	lw	t4, OFFSET_STACK_T4(sp)
	lw	t5, OFFSET_STACK_T5(sp)
	lw	t6, OFFSET_STACK_T6_PRINTF(sp)
	lw	t7, OFFSET_STACK_T7_PRINTF(sp)
	lw	t8, OFFSET_STACK_T8_PRINTF(sp)
	lw	t9, OFFSET_STACK_T9_PRINTF(sp)
	lw	gp, OFFSET_STACK_GP_PRINTF(sp)
	lw	fp, OFFSET_STACK_FP_PRINTF(sp)
	lw	ra, OFFSET_STACK_RA_PRINTF2(sp)

	.set	noreorder
	jr	ra
	lw	ra, OFFSET_STACK_RA_PRINTF(sp)
	.set	reorder
#endif

/* $B5/F0;~$N(B load, store func $B4X?t%]%$%s%?(B */
	.data
	.align	4
nes_initial_functbl:
	.word	store_2000,  store_ppu_ram, store_ignore, store_ppu_ram
	.word	store_2004, store_2005, store_2006, store_2007_chrrom
/* 4000-4026(4027) storefunc */
	.word	store_sound, store_sound, store_sound, store_sound
	.word	store_sound, store_sound, store_sound, store_sound
	.word	store_sound, store_sound, store_sound, store_sound
	.word	store_sound, store_sound, store_sound, store_sound

#define store_4010 store_sound
#define store_4015 store_sound
	.word	store_4010,  store_sound, store_sound, store_sound
	.word	store_4014,  store_4015,  store_4016,  store_4017
	.word	store_invalid, store_invalid, store_invalid, store_invalid
	.word	store_invalid, store_invalid, store_invalid, store_invalid

	.word	storeqd_4020, storeqd_4021, storeqd_4022, storeqd_4023
	.word	storeqd_4024, storeqd_4025, storeqd_4026, store_invalid

/* 0000-, 2000-, ..., e000- storefunc */
	.word	store_internal_wram, store_ppu, store_io, store_invalid
	.word	store_invalid, store_invalid, store_invalid, store_invalid
	.word	store_internal_wram /* a0 > 0xffff $B$NBP:v(B - $B$^$:Mh$J$$$@@$m$&$1$I(B u64 alignment $B$b$"$k$7(B */
/* 0000-, 2000-, ..., e000- loadfunc */
	.word	load_internal_wram, load_ppu, load_io, load_invalid
	.word	load_6000, load_6000, load_6000, load_6000
	.word	load_internal_wram_10000 /* a0 > 0xffff $B$NBP:v(B */
/* 4000-4017 loadfunc */
	.word	load_invalid, load_invalid, load_invalid, load_invalid
	.word	load_invalid, load_invalid, load_invalid, load_invalid
	.word	load_invalid, load_invalid, load_invalid, load_invalid
	.word	load_invalid, load_invalid, load_invalid, load_invalid

	.word	load_invalid, load_invalid, load_invalid, load_invalid
	.word	load_invalid, load_4015,    load_4016,    load_4017

	.data
	.align	4
mmc5_store_functbl_org:
/*  MMC5 $B$N$H$-(B 5100-5131 $B$N(B storefunc
 * 5104: exram mode
 * 5105: vram bank
 * 5106: vram3 chr no
 * 5107: vram3 area code
 */
	.word	store05_5100, store05_5101, store05_5102, store05_5103
	.word	store05_5104, store05_5105, store05_5106, store05_5107
	.word	store_invalid, store_invalid, store_invalid, store_invalid
	.word	store_invalid, store_invalid, store_invalid, store_invalid
/* 5115: br5 */
	.word	store_invalid, store_invalid, store_invalid, store05_5113
	.word	store05_5114, store05_5115, store05_5116, store05_5117
	.word	store_invalid, store_invalid, store_invalid, store_invalid
	.word	store_invalid, store_invalid, store_invalid, store_invalid
/* 5120-27,28-2b: pbr0-7, 4'-7' */
	.word	store05_5120, store05_5120, store05_5120, store05_5120
	.word	store05_5120, store05_5120, store05_5120, store05_5120
	.word	store05_5120, store05_5120, store05_5120, store05_5120
	.word	store_invalid, store_invalid, store_invalid, store_invalid
	
	.word	store05_5130, store_invalid, store_invalid, store_invalid

/* $B%^%C%Q!<0MB8$N(B load/store func table
 * $B:G=i$K(B $B$=$N%^%C%Q!<$N=i4|2=$N$?$a$K!"FCJL$J%3!<%I$r8F$V$J$i$=$N%"%I%l%9$r!"(B
 * $BHFMQ$N=i4|2=$G$$$$$J$i(B 0 $B$r!#(B
 * $B<!$K!"(B0x8000-, 0xa000-, 0xc000-, 0xe000- $B$N=g$K(B store func
 * mapper 0..255 $B$^$G!#(B
 */
	.data
	.align	4
store_functbl_mapper0:
/*  0(0x00)=NONE           */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*  1(0x01)=MMC1           */.word init01, store01_8000, store01_8000, store01_8000, store01_8000
/*  2(0x02)=PRG1M, fixC000 */.word init02, store02_8000, store02_8000, store02_8000, store02_8000
/*  3(0x03)=CHR128/256     */.word init03, store03_6000, store03_6000, store03_6000, store03_6000
/*  4(0x04)=MMC3           */.word init04, store04_8000, store04_a000, store04_c000, store04_e000
/*  5(0x05)=MMC5           */.word init05, store_invalid, store_invalid, store_invalid, store_invalid
/*  6(0x06)=FFE F4xxx      */.word init06, store06_8000, store_invalid, store_invalid, store_invalid
/*  7(0x07)=Rare           */.word init07, store07_8000, store07_8000, store07_8000, store07_8000
/*  8(0x08)=FFE-F3         */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*  9(0x09)=MMC2           */.word init09, store_invalid, store09_a000, store09_c000, store09_e000
/* 10(0x0a)=MMC4           */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 11(0x0b)=ColorDreams    */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 12(0x0c)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 13(0x0d)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 14(0x0e)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 15(0x0f)=100-in-1       */.word init0f, store0f_8000, store_invalid, store_invalid, store_invalid
/* 16(0x10)=Bandai         */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 17(0x11)=FFE-F8         */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 18(0x12)=Jaleco ss8806  */.word init12, store12_8000, store12_a000, store12_a000, store12_e000
/* 19(0x13)=Namcot 106     */.word init13, store13_8000, store13_a000, store13_c000, store13_e000
/* 20(0x14)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 21(0x15)=VRC4           */.word init15, store19_8000, store19_a000, store19_b000, store19_e000
/* 22(0x16)=VRC2-Shift     */.word init16, store16_8000, store16_a000, store16_b000, store16_b000
/* 23(0x17)=VRC2/4-Odd     */.word init17, store16_8000, store17_a000, store17_b000, store17_e000
/* 24(0x18)=VRC6-A         */.word init18, store18_8000, store18_a000, store18_c000, store18_e000
/* 25(0x19)=VRC2/4 Even    */.word init19, store19_8000, store19_a000, store19_b000, store19_e000
/* 26(0x1a)=VRC6-B         */.word init1a, store18_8000, store18_a000, store18_c000, store18_e000
/* 27(0x1b)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 28(0x1c)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 29(0x1d)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 30(0x1e)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 31(0x1f)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 32(0x20)=Irem G-101     */.word init20, store20_8000, store20_a000, store_invalid, store_invalid
/* 33(0x21)=Taito tc190    */.word init21, store21_8000, store21_a000, store21_c000, store_invalid
/* 34(0x22)=Nina-1         */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 35(0x23)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 36(0x24)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 37(0x25)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 38(0x26)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 39(0x27)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 40(0x28)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 41(0x29)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 42(0x2a)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 43(0x2b)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 44(0x2c)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 45(0x2d)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 46(0x2e)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 47(0x2f)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 48(0x30)=FlintStone     */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 49(0x31)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 50(0x32)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 51(0x33)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 52(0x34)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 53(0x35)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 54(0x36)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 55(0x37)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 56(0x38)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 57(0x39)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 58(0x3a)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 59(0x3b)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 60(0x3c)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 61(0x3d)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 62(0x3e)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 63(0x3f)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 64(0x40)=Tengen Rambo-1 */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 65(0x41)=Irem h-3001    */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 66(0x42)=GNROM          */.word init42, store42_8000, store42_8000, store42_8000, store42_8000
/* 67(0x43)=Sunsoft 3      */.word init43, store44_8000, store44_8000, store43_c000, store44_e000
/* 68(0x44)=Sunsoft 4      */.word init44, store44_8000, store44_8000, store44_c000, store44_e000
/* 69(0x45)=Sunsoft 5      */.word init45, store45_8000, store45_a000, store_invalid, store_invalid
/* 70(0x46)=Kitarou2       */.word init46, store46_8000, store46_8000, store46_8000, store46_8000
/* 71(0x47)=Camerica       */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 72(0x48)=PinballQuest   */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 73(0x49)=VRC3           */.word init49, store_ignore, store49_a000, store49_c000, store02_8000
/* 74(0x4a)=Taiwan MMC3    */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 75(0x4b)=Jale 8805/VRC1 */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 76(0x4c)=Namcot 108/109 */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 77(0x4d)=NapoleonSenki  */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 78(0x4e)=Irem 74hc161   */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 79(0x4f)=AmericanVideo  */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 80(0x50)=Taito X-005    */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 81(0x51)=Taito C075     */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 82(0x52)=Taito X1-17    */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 83(0x53)=PC-Cony Mapper */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 84(0x54)=PC-SMB2J       */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 85(0x55)=VRC7           */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 86(0x56)=Jaleco Moepro  */.word init56, store_invalid, store_invalid, store_invalid, store_invalid
/* 87(0x57)=Hyp_tono       */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 88(0x58)=Namco 118      */.word init58, store58_8000, store_invalid, store_invalid, store_invalid
/* 89(0x59)=Mitokoumon     */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 90(0x5a)=PC-JY-??       */.word init5a, store5a_8000, store5a_a000, store5a_c000, store_invalid
/* 91(0x5b)=HK-SF3         */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 92(0x5c)=Jaleco Moepr88 */.word init5c, store5c_8000, store_invalid, store_invalid, store_invalid
#ifdef KS_RFC_MAPPER_EXTENSION
/* 93(0x5d)=FantasyZone    */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 94(0x5e)=Senjono Okami  */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 95(0x5f)=Namco Dbuster  */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 96(0x60)=Anpanman Hirag */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 97(0x61)=KaiketsuYancha */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 98(0x62)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/* 99(0x63)=VS UniSystem   */.word init63, store_invalid, store_invalid, store_invalid, store_invalid
/*100(0x64)=Hacked BugMMC3 */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*101(0x65)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*102(0x66)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*103(0x67)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*104(0x68)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*105(0x69)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*106(0x6a)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*107(0x6b)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*108(0x6c)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*109(0x6d)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*110(0x6e)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*111(0x6f)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*112(0x70)=PC-Asder       */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*113(0x71)=Sachen/Hacker  */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*114(0x72)=PC-SuperGames  */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*115(0x73)=PC-CartSaint   */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*116(0x74)=AV beauty fght */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*117(0x75)=Sangokushi 4   */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*118(0x76)=Alumagiro J    */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*119(0x77)=TQROM pinbot   */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*120(0x78)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*121(0x79)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*122(0x7a)=MadulaNoTubasa */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*123(0x7b)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*124(0x7c)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*125(0x7d)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*126(0x7e)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*127(0x7f)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*128(0x80)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*129(0x81)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*130(0x82)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*131(0x83)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*132(0x84)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*133(0x85)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*134(0x86)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*135(0x87)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*136(0x88)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*137(0x89)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*138(0x8a)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*139(0x8b)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*140(0x8c)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*141(0x8d)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*142(0x8e)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*143(0x8f)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*144(0x90)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*145(0x91)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*146(0x92)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*147(0x93)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*148(0x94)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*149(0x95)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*150(0x96)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*151(0x97)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*152(0x98)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*153(0x99)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*154(0x9a)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*155(0x9b)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*156(0x9c)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*157(0x9d)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*158(0x9e)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*159(0x9f)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*160(0xa0)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*161(0xa1)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*162(0xa2)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*163(0xa3)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*164(0xa4)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*165(0xa5)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*166(0xa6)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*167(0xa7)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*168(0xa8)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*169(0xa9)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*170(0xaa)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*171(0xab)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*172(0xac)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*173(0xad)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*174(0xae)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*175(0xaf)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*176(0xb0)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*177(0xb1)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*178(0xb2)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*179(0xb3)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*180(0xb4)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*181(0xb5)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*182(0xb6)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*183(0xb7)=AltantisNoNazo */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*184(0xb8)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*185(0xb9)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*186(0xba)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*187(0xbb)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*188(0xbc)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*189(0xbd)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*190(0xbe)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*191(0xbf)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*192(0xc0)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*193(0xc1)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*194(0xc2)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*195(0xc3)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*196(0xc4)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*197(0xc5)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*198(0xc6)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*199(0xc7)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*200(0xc8)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*201(0xc9)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*202(0xca)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*203(0xcb)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*204(0xcc)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*205(0xcd)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*206(0xce)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*207(0xcf)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*208(0xd0)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*209(0xd1)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*210(0xd2)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*211(0xd3)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*212(0xd4)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*213(0xd5)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*214(0xd6)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*215(0xd7)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*216(0xd8)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*217(0xd9)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*218(0xda)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*219(0xdb)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*220(0xdc)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*221(0xdd)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*222(0xde)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*223(0xdf)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*224(0xe0)=?              */.word inite0, storee0_8000, storee0_8000, storee0_8000, storee0_8000
/*225(0xe1)=58in1/64in1    */.word inite1, storee1_8000, storee1_8000, storee1_8000, storee1_8000
/*226(0xe2)=76in1          */.word inite2, storee2_8000, storee2_8000, storee2_8000, storee2_8000
/*227(0xe3)=1200in1        */.word inite3, storee3_8000, storee3_8000, storee3_8000, storee3_8000
/*228(0xe4)=Action52       */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*229(0xe5)=31in1          */.word inite5, storee5_8000, storee5_8000, storee5_8000, storee5_8000
/*230(0xe6)=22in1          */.word inite6, storee6_8000, storee6_8000, storee6_8000, storee6_8000
/*231(0xe7)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*232(0xe8)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*233(0xe9)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*234(0xea)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*235(0xeb)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*236(0xec)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*237(0xed)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*238(0xee)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*239(0xef)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*240(0xf0)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*241(0xf1)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*242(0xf2)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*243(0xf3)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*244(0xf4)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*245(0xf5)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*246(0xf6)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*247(0xf7)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*248(0xf8)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*249(0xf9)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*250(0xfa)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*251(0xfb)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*252(0xfc)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*253(0xfd)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*254(0xfe)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
/*255(0xff)=?              */.word 0, store_invalid, store_invalid, store_invalid, store_invalid
store_functbl_mapper256: /* $B%F!<%V%k$N%P%$%H?t%A%'%C%/MQ%7%s%\%k(B */
#else
/* 253(0xfd)=disksys by myself $B$N$_(B $BDI2C(B */
store_functbl_mapper253:
	.word	initqd, storeqd_8000, storeqd_8000, storeqd_8000, store_invalid
#endif


/* $BL?Na=hM}%F!<%V%k!#(B
 * 16bytes/inst $B$G(B {func1.w, func2.w, func3.w, nbytes.b, 0.b, cycles.h} $B$H$9$k!#(B
 * $B>CHq(B CPU cycle $B$O:G9b$G(B 8 $B$G$"$k!#$J$N$G(B 8 -> 0x800 $B$H$J$k$h$&$K(B 0x100 $BG\$G;}$A!"(B
 * $B@@:L)$J(B cycle $B7W;;$rL\;X$9!#(B
 * tools/0055.c $B$G%F!<%V%k:n@@.(B ($BJQ99$9$k$H$-$O(B 0055.c $B$rJQ$($k(B!)
 * ... $B$H;W$C$?$1$I!"$b$&(B wdm_42 $B0J30(B fix $B$7$F$$$k$N$G!"$3$3$rD>@@\JQ$($F$$$k!#(B
 */
#define nop_ea next
	.data
	.align	4
inst_jumptbl:
/*brk_00*/.word brk_00,0,0;                     .byte 2,0xff,7,0 /*brk_00*/
/*ora_01*/.word load8_dxi,ora_01,0;             .byte 2,0xff,6,0 /*ora_01*/
/*cop_02*/.word undef_op,0,0;                   .byte 2,0xff,8,0 /*cop_02*/
/*ora_03*/.word undef_op,0,0;                   .byte 2,0xff,4,0 /*ora_03*/
/*tsb_04*/.word undef_op,0,0;                   .byte 2,0xff,5,0 /*tsb_04*/
/*ora_05*/.word load8_zerop,ora_05,0;           .byte 2,0xff,3,0 /*ora_05*/
/*asl_06*/.word load8_zerop,asl_06,0;           .byte 2,0xff,5,0 /*asl_06*/
/*ora_07*/.word undef_op,0,0;                   .byte 2,0xff,6,0 /*ora_07*/
/*php_08*/.word php_08,0,0;                     .byte 1,0xff,3,0 /*php_08*/
/*ora_09*/.word load8_imm,ora_09,0;             .byte 2,0xff,2,0 /*ora_09*/
/*asl_0a*/.word asl_0a,0,0;                     .byte 1,0xff,2,0 /*asl_0a*/
/*phd_0b*/.word undef_op,0,0;                   .byte 1,0xff,4,0 /*phd_0b*/
/*tsb_0c*/.word undef_op,0,0;                   .byte 3,0xff,6,0 /*tsb_0c*/
/*ora_0d*/.word load8_abs,ora_0d,0;             .byte 3,0xff,4,0 /*ora_0d*/
/*asl_0e*/.word load8_abs,asl_0e,0;             .byte 3,0xff,6,0 /*asl_0e*/
/*ora_0f*/.word undef_op,0,0;                   .byte 4,0xff,5,0 /*ora_0f*/
/*bpl_10*/.word load8_imm,bpl_10,0;             .byte 2,0xff,3,0 /*bpl_10*/
/*ora_11*/.word load8_dyi,ora_11,0;             .byte 2,0xff,5,0 /*ora_11*/
/*ora_12*/.word undef_op,0,0;                   .byte 2,0xff,5,0 /*ora_12*/
/*ora_13*/.word undef_op,0,0;                   .byte 2,0xff,7,0 /*ora_13*/
/*trb_14*/.word undef_op,0,0;                   .byte 2,0xff,5,0 /*trb_14*/
/*ora_15*/.word load8_dx,ora_15,0;              .byte 2,0xff,4,0 /*ora_15*/
/*asl_16*/.word load8_dx,asl_16,0;              .byte 2,0xff,6,0 /*asl_16*/
/*ora_17*/.word undef_op,0,0;                   .byte 2,0xff,6,0 /*ora_17*/
/*clc_18*/.word clc_18,0,0;                     .byte 1,0xff,2,0 /*clc_18*/
/*ora_19*/.word load8_absy,ora_19,0;            .byte 3,0xff,4,0 /*ora_19*/
/*inc_1a*/.word undef_op,0,0;                   .byte 1,0xff,2,0 /*inc_1a*/
/*tcs_1b*/.word undef_op,0,0;                   .byte 1,0xff,2,0 /*tcs_1b*/
/*trb_1c*/.word undef_op,0,0;                   .byte 3,0xff,6,0 /*trb_1c*/
/*ora_1d*/.word load8_absx,ora_1d,0;            .byte 3,0xff,4,0 /*ora_1d*/
/*asl_1e*/.word load8_absx,asl_1e,0;            .byte 3,0xff,7,0 /*asl_1e*/
/*ora_1f*/.word undef_op,0,0;                   .byte 4,0xff,5,0 /*ora_1f*/
/*jsr_20*/.word load16_imm,jsr_20,0;            .byte 3,0xff,6,0 /*jsr_20*/
/*and_21*/.word load8_dxi,and_21,0;             .byte 2,0xff,6,0 /*and_21*/
/*jsl_22*/.word undef_op,0,0;                   .byte 4,0xff,8,0 /*jsl_22*/
/*and_23*/.word undef_op,0,0;                   .byte 2,0xff,4,0 /*and_23*/
/*bit_24*/.word load8_zerop,bit_24,0;           .byte 2,0xff,3,0 /*bit_24*/
/*and_25*/.word load8_zerop,and_25,0;           .byte 2,0xff,3,0 /*and_25*/
/*rol_26*/.word load8_zerop,rol_26,0;           .byte 2,0xff,5,0 /*rol_26*/
/*and_27*/.word undef_op,0,0;                   .byte 2,0xff,6,0 /*and_27*/
/*plp_28*/.word plp_28,0,0;                     .byte 1,0xff,4,0 /*plp_28*/
/*and_29*/.word load8_imm,and_29,0;             .byte 2,0xff,2,0 /*and_29*/
/*rol_2a*/.word rol_2a,0,0;                     .byte 1,0xff,2,0 /*rol_2a*/
/*pld_2b*/.word undef_op,0,0;                   .byte 1,0xff,5,0 /*pld_2b*/
/*bit_2c*/.word load8_abs,bit_2c,0;             .byte 3,0xff,4,0 /*bit_2c*/
/*and_2d*/.word load8_abs,and_2d,0;             .byte 3,0xff,4,0 /*and_2d*/
/*rol_2e*/.word load8_abs,rol_2e,0;             .byte 3,0xff,6,0 /*rol_2e*/
/*and_2f*/.word undef_op,0,0;                   .byte 4,0xff,5,0 /*and_2f*/
/*bmi_30*/.word load8_imm,bmi_30,0;             .byte 2,0xff,3,0 /*bmi_30*/
/*and_31*/.word load8_dyi,and_31,0;             .byte 2,0xff,5,0 /*and_31*/
/*and_32*/.word undef_op,0,0;                   .byte 2,0xff,5,0 /*and_32*/
/*and_33*/.word undef_op,0,0;                   .byte 2,0xff,7,0 /*and_33*/
/*bit_34*/.word undef_op,0,0;                   .byte 2,0xff,4,0 /*bit_34*/
/*and_35*/.word load8_dx,and_35,0;              .byte 2,0xff,4,0 /*and_35*/
/*rol_36*/.word load8_dx,rol_36,0;              .byte 2,0xff,6,0 /*rol_36*/
/*and_37*/.word undef_op,0,0;                   .byte 2,0xff,6,0 /*and_37*/
/*sec_38*/.word sec_38,0,0;                     .byte 1,0xff,2,0 /*sec_38*/
/*and_39*/.word load8_absy,and_39,0;            .byte 3,0xff,4,0 /*and_39*/
/*dec_3a*/.word undef_op,0,0;                   .byte 1,0xff,2,0 /*dec_3a*/
/*tsc_3b*/.word undef_op,0,0;                   .byte 1,0xff,2,0 /*tsc_3b*/
/*bit_3c*/.word undef_op,0,0;                   .byte 3,0xff,4,0 /*bit_3c*/
/*and_3d*/.word load8_absx,and_3d,0;            .byte 3,0xff,4,0 /*and_3d*/
/*rol_3e*/.word load8_absx,rol_3e,0;            .byte 3,0xff,7,0 /*rol_3e*/
/*and_3f*/.word undef_op,0,0;                   .byte 4,0xff,5,0 /*and_3f*/
/*rti_40*/.word rti_40,0,0;                     .byte 1,0xff,6,0 /*rti_40*/
/*eor_41*/.word load8_dxi,eor_41,0;             .byte 2,0xff,6,0 /*eor_41*/
/*wdm_42*/.word wdm_42,0,0;                     .byte 2,0xff,2,0 /*wdm_42*/
/*eor_43*/.word undef_op,0,0;                   .byte 2,0xff,4,0 /*eor_43*/
/*mvp_44*/.word undef_op,0,0;                   .byte 3,0xff,7,0 /*mvp_44*/
/*eor_45*/.word load8_zerop,eor_45,0;           .byte 2,0xff,3,0 /*eor_45*/
/*lsr_46*/.word load8_zerop,lsr_46,0;           .byte 2,0xff,5,0 /*lsr_46*/
/*eor_47*/.word undef_op,0,0;                   .byte 2,0xff,6,0 /*eor_47*/
/*pha_48*/.word pha_48,0,0;                     .byte 1,0xff,3,0 /*pha_48*/
/*eor_49*/.word load8_imm,eor_49,0;             .byte 2,0xff,2,0 /*eor_49*/
/*lsr_4a*/.word lsr_4a,0,0;                     .byte 1,0xff,2,0 /*lsr_4a*/
/*phk_4b*/.word undef_op,0,0;                   .byte 1,0xff,3,0 /*phk_4b*/
/*jmp_4c*/.word load16_imm,jmp_4c,0;            .byte 3,0xff,3,0 /*jmp_4c*/
/*eor_4d*/.word load8_abs,eor_4d,0;             .byte 3,0xff,4,0 /*eor_4d*/
/*lsr_4e*/.word load8_abs,lsr_4e,0;             .byte 3,0xff,6,0 /*lsr_4e*/
/*eor_4f*/.word undef_op,0,0;                   .byte 4,0xff,5,0 /*eor_4f*/
/*bvc_50*/.word load8_imm,bvc_50,0;             .byte 2,0xff,3,0 /*bvc_50*/
/*eor_51*/.word load8_dyi,eor_51,0;             .byte 2,0xff,5,0 /*eor_51*/
/*eor_52*/.word undef_op,0,0;                   .byte 2,0xff,5,0 /*eor_52*/
/*eor_53*/.word undef_op,0,0;                   .byte 2,0xff,7,0 /*eor_53*/
/*mvn_54*/.word undef_op,0,0;                   .byte 3,0xff,7,0 /*mvn_54*/
/*eor_55*/.word load8_dx,eor_55,0;              .byte 2,0xff,4,0 /*eor_55*/
/*lsr_56*/.word load8_dx,lsr_56,0;              .byte 2,0xff,6,0 /*lsr_56*/
/*eor_57*/.word undef_op,0,0;                   .byte 2,0xff,6,0 /*eor_57*/
/*cli_58*/.word cli_58,0,0;                     .byte 1,0xff,2,0 /*cli_58*/
/*eor_59*/.word load8_absy,eor_59,0;            .byte 3,0xff,4,0 /*eor_59*/
/*phy_5a*/.word undef_op,0,0;                   .byte 1,0xff,3,0 /*phy_5a*/
/*tcd_5b*/.word undef_op,0,0;                   .byte 1,0xff,2,0 /*tcd_5b*/
/*jmp_5c*/.word undef_op,0,0;                   .byte 4,0xff,4,0 /*jmp_5c*/
/*eor_5d*/.word load8_absx,eor_5d,0;            .byte 3,0xff,4,0 /*eor_5d*/
/*lsr_5e*/.word load8_absx,lsr_5e,0;            .byte 3,0xff,7,0 /*lsr_5e*/
/*eor_5f*/.word undef_op,0,0;                   .byte 4,0xff,5,0 /*eor_5f*/
/*rts_60*/.word rts_60,0,0;                     .byte 1,0xff,6,0 /*rts_60*/
/*adc_61*/.word load8_dxi,adc_61,0;             .byte 2,0xff,6,0 /*adc_61*/
/*per_62*/.word undef_op,0,0;                   .byte 3,0xff,6,0 /*per_62*/
/*adc_63*/.word undef_op,0,0;                   .byte 2,0xff,4,0 /*adc_63*/
/*stz_64*/.word undef_op,0,0;                   .byte 2,0xff,3,0 /*stz_64*/
/*adc_65*/.word load8_zerop,adc_65,0;           .byte 2,0xff,3,0 /*adc_65*/
/*ror_66*/.word load8_zerop,ror_66,0;           .byte 2,0xff,5,0 /*ror_66*/
/*adc_67*/.word undef_op,0,0;                   .byte 2,0xff,6,0 /*adc_67*/
/*pla_68*/.word pla_68,0,0;                     .byte 1,0xff,4,0 /*pla_68*/
/*adc_69*/.word load8_imm,adc_69,0;             .byte 2,0xff,2,0 /*adc_69*/
/*ror_6a*/.word ror_6a,0,0;                     .byte 1,0xff,2,0 /*ror_6a*/
/*rtl_6b*/.word undef_op,0,0;                   .byte 1,0xff,6,0 /*rtl_6b*/
/*jmp_6c*/.word load16_imm,jmp_6c,0;            .byte 3,0xff,5,0 /*jmp_6c*/
/*adc_6d*/.word load8_abs,adc_6d,0;             .byte 3,0xff,4,0 /*adc_6d*/
/*ror_6e*/.word load8_abs,ror_6e,0;             .byte 3,0xff,6,0 /*ror_6e*/
/*adc_6f*/.word undef_op,0,0;                   .byte 4,0xff,5,0 /*adc_6f*/
/*bvs_70*/.word load8_imm,bvs_70,0;             .byte 2,0xff,3,0 /*bvs_70*/
/*adc_71*/.word load8_dyi,adc_71,0;             .byte 2,0xff,5,0 /*adc_71*/
/*adc_72*/.word undef_op,0,0;                   .byte 2,0xff,5,0 /*adc_72*/
/*adc_73*/.word undef_op,0,0;                   .byte 2,0xff,7,0 /*adc_73*/
/*stz_74*/.word undef_op,0,0;                   .byte 2,0xff,4,0 /*stz_74*/
/*adc_75*/.word load8_dx,adc_75,0;              .byte 2,0xff,4,0 /*adc_75*/
/*ror_76*/.word load8_dx,ror_76,0;              .byte 2,0xff,6,0 /*ror_76*/
/*adc_77*/.word undef_op,0,0;                   .byte 2,0xff,6,0 /*adc_77*/
/*sei_78*/.word sei_78,0,0;                     .byte 1,0xff,2,0 /*sei_78*/
/*adc_79*/.word load8_absy,adc_79,0;            .byte 3,0xff,4,0 /*adc_79*/
/*ply_7a*/.word undef_op,0,0;                   .byte 1,0xff,4,0 /*ply_7a*/
/*tdc_7b*/.word undef_op,0,0;                   .byte 1,0xff,2,0 /*tdc_7b*/
/*jmp_7c*/.word undef_op,0,0;                   .byte 3,0xff,6,0 /*jmp_7c*/
/*adc_7d*/.word load8_absx,adc_7d,0;            .byte 3,0xff,4,0 /*adc_7d*/
/*ror_7e*/.word load8_absx,ror_7e,0;            .byte 3,0xff,7,0 /*ror_7e*/
/*adc_7f*/.word undef_op,0,0;                   .byte 4,0xff,5,0 /*adc_7f*/
/*bra_80*/.word undef_op,0,0;                   .byte 2,0xff,2,0 /*bra_80*/
/*sta_81*/.word load8_dx,sta_81,0;              .byte 2,0xff,6,0 /*sta_81*/
/*brl_82*/.word undef_op,0,0;                   .byte 3,0xff,4,0 /*brl_82*/
/*sta_83*/.word undef_op,0,0;                   .byte 2,0xff,4,0 /*sta_83*/
/*sty_84*/.word load8_imm,sty_84,0;             .byte 2,0xff,3,0 /*sty_84*/
/*sta_85*/.word load8_imm,sta_85,0;             .byte 2,0xff,3,0 /*sta_85*/
/*stx_86*/.word load8_imm,stx_86,0;             .byte 2,0xff,3,0 /*stx_86*/
/*sta_87*/.word undef_op,0,0;                   .byte 2,0xff,6,0 /*sta_87*/
/*dey_88*/.word dey_88,0,0;                     .byte 1,0xff,2,0 /*dey_88*/
/*bit_89*/.word undef_op,0,0;                   .byte 2,0xff,2,0 /*bit_89*/
/*txa_8a*/.word txa_8a,0,0;                     .byte 1,0xff,2,0 /*txa_8a*/
/*phb_8b*/.word undef_op,0,0;                   .byte 1,0xff,3,0 /*phb_8b*/
/*sty_8c*/.word load16_imm,sty_8c,0;            .byte 3,0xff,4,0 /*sty_8c*/
/*sta_8d*/.word load16_imm,sta_8d,0;            .byte 3,0xff,4,0 /*sta_8d*/
/*stx_8e*/.word load16_imm,stx_8e,0;            .byte 3,0xff,4,0 /*stx_8e*/
/*sta_8f*/.word undef_op,0,0;                   .byte 4,0xff,5,0 /*sta_8f*/
/*bcc_90*/.word load8_imm,bcc_90,0;             .byte 2,0xff,3,0 /*bcc_90*/
/*sta_91*/.word load8_zerop,sta_91,0;           .byte 2,0xff,6,0 /*sta_91*/
/*sta_92*/.word undef_op,0,0;                   .byte 2,0xff,5,0 /*sta_92*/
/*sta_93*/.word undef_op,0,0;                   .byte 2,0xff,7,0 /*sta_93*/
/*sty_94*/.word load8_imm,sty_94,0;             .byte 2,0xff,4,0 /*sty_94*/
/*sta_95*/.word load8_imm,sta_95,0;             .byte 2,0xff,4,0 /*sta_95*/
/*stx_96*/.word load8_imm,stx_96,0;             .byte 2,0xff,4,0 /*stx_96*/
/*sta_97*/.word undef_op,0,0;                   .byte 2,0xff,6,0 /*sta_97*/
/*tya_98*/.word tya_98,0,0;                     .byte 1,0xff,2,0 /*tya_98*/
/*sta_99*/.word load16_imm,sta_99,0;            .byte 3,0xff,5,0 /*sta_99*/
/*txs_9a*/.word txs_9a,0,0;                     .byte 1,0xff,2,0 /*txs_9a*/
/*txy_9b*/.word undef_op,0,0;                   .byte 1,0xff,2,0 /*txy_9b*/
/*stz_9c*/.word undef_op,0,0;                   .byte 3,0xff,4,0 /*stz_9c*/
/*sta_9d*/.word load16_imm,sta_9d,0;            .byte 3,0xff,5,0 /*sta_9d*/
/*stz_9e*/.word undef_op,0,0;                   .byte 3,0xff,5,0 /*stz_9e*/
/*sta_9f*/.word undef_op,0,0;                   .byte 4,0xff,5,0 /*sta_9f*/
/*ldy_a0*/.word load8_imm,ldy_a0,0;             .byte 2,0xff,2,0 /*ldy_a0*/
/*lda_a1*/.word load8_dxi,lda_a1,0;             .byte 2,0xff,6,0 /*lda_a1*/
/*ldx_a2*/.word load8_imm,ldx_a2,0;             .byte 2,0xff,2,0 /*ldx_a2*/
/*lda_a3*/.word undef_op,0,0;                   .byte 2,0xff,4,0 /*lda_a3*/
/*ldy_a4*/.word load8_zerop,ldy_a4,0;           .byte 2,0xff,3,0 /*ldy_a4*/
/*lda_a5*/.word load8_zerop,lda_a5,0;           .byte 2,0xff,3,0 /*lda_a5*/
/*ldx_a6*/.word load8_zerop,ldx_a6,0;           .byte 2,0xff,3,0 /*ldx_a6*/
/*lda_a7*/.word undef_op,0,0;                   .byte 2,0xff,6,0 /*lda_a7*/
/*tay_a8*/.word tay_a8,0,0;                     .byte 1,0xff,2,0 /*tay_a8*/
/*lda_a9*/.word load8_imm,lda_a9,0;             .byte 2,0xff,2,0 /*lda_a9*/
/*tax_aa*/.word tax_aa,0,0;                     .byte 1,0xff,2,0 /*tax_aa*/
/*plb_ab*/.word undef_op,0,0;                   .byte 1,0xff,4,0 /*plb_ab*/
/*ldy_ac*/.word load8_abs,ldy_ac,0;             .byte 3,0xff,4,0 /*ldy_ac*/
/*lda_ad*/.word load8_abs,lda_ad,0;             .byte 3,0xff,4,0 /*lda_ad*/
/*ldx_ae*/.word load8_abs,ldx_ae,0;             .byte 3,0xff,4,0 /*ldx_ae*/
/*lda_af*/.word undef_op,0,0;                   .byte 4,0xff,5,0 /*lda_af*/
/*bcs_b0*/.word load8_imm,bcs_b0,0;             .byte 2,0xff,3,0 /*bcs_b0*/
/*lda_b1*/.word load8_dyi,lda_b1,0;             .byte 2,0xff,5,0 /*lda_b1*/
/*lda_b2*/.word undef_op,0,0;                   .byte 2,0xff,5,0 /*lda_b2*/
/*lda_b3*/.word undef_op,0,0;                   .byte 2,0xff,7,0 /*lda_b3*/
/*ldy_b4*/.word load8_dx,ldy_b4,0;              .byte 2,0xff,4,0 /*ldy_b4*/
/*lda_b5*/.word load8_dx,lda_b5,0;              .byte 2,0xff,4,0 /*lda_b5*/
/*ldx_b6*/.word load8_imm,ldx_b6,0;             .byte 2,0xff,4,0 /*ldx_b6*/
/*lda_b7*/.word undef_op,0,0;                   .byte 2,0xff,6,0 /*lda_b7*/
/*clv_b8*/.word clv_b8,0,0;                     .byte 1,0xff,2,0 /*clv_b8*/
/*lda_b9*/.word load8_absy,lda_b9,0;            .byte 3,0xff,4,0 /*lda_b9*/
/*tsx_ba*/.word tsx_ba,0,0;                     .byte 1,0xff,2,0 /*tsx_ba*/
/*tyx_bb*/.word undef_op,0,0;                   .byte 1,0xff,2,0 /*tyx_bb*/
/*ldy_bc*/.word load8_absx,ldy_bc,0;            .byte 3,0xff,4,0 /*ldy_bc*/
/*lda_bd*/.word load8_absx,lda_bd,0;            .byte 3,0xff,4,0 /*lda_bd*/
/*ldx_be*/.word load8_absy,ldx_be,0;            .byte 3,0xff,4,0 /*ldx_be*/
/*lda_bf*/.word undef_op,0,0;                   .byte 4,0xff,5,0 /*lda_bf*/
/*cpy_c0*/.word load8_imm,cpy_c0,0;             .byte 2,0xff,2,0 /*cpy_c0*/
/*cmp_c1*/.word load8_dxi,cmp_c1,0;             .byte 2,0xff,6,0 /*cmp_c1*/
/*rep_c2*/.word undef_op,0,0;                   .byte 2,0xff,3,0 /*rep_c2*/
/*cmp_c3*/.word undef_op,0,0;                   .byte 2,0xff,4,0 /*cmp_c3*/
/*cpy_c4*/.word load8_zerop,cpy_c4,0;           .byte 2,0xff,3,0 /*cpy_c4*/
/*cmp_c5*/.word load8_zerop,cmp_c5,0;           .byte 2,0xff,3,0 /*cmp_c5*/
/*dec_c6*/.word load8_zerop,dec_c6,0;           .byte 2,0xff,5,0 /*dec_c6*/
/*cmp_c7*/.word undef_op,0,0;                   .byte 2,0xff,6,0 /*cmp_c7*/
/*iny_c8*/.word iny_c8,0,0;                     .byte 1,0xff,2,0 /*iny_c8*/
/*cmp_c9*/.word load8_imm,cmp_c9,0;             .byte 2,0xff,2,0 /*cmp_c9*/
/*dex_ca*/.word dex_ca,0,0;                     .byte 1,0xff,2,0 /*dex_ca*/
/*wai_cb*/.word undef_op,0,0;                   .byte 1,0xff,3,0 /*wai_cb*/
/*cpy_cc*/.word load8_abs,cpy_cc,0;             .byte 3,0xff,4,0 /*cpy_cc*/
/*cmp_cd*/.word load8_abs,cmp_cd,0;             .byte 3,0xff,4,0 /*cmp_cd*/
/*dec_ce*/.word load8_abs,dec_ce,0;             .byte 3,0xff,6,0 /*dec_ce*/
/*cmp_cf*/.word undef_op,0,0;                   .byte 4,0xff,5,0 /*cmp_cf*/
/*bne_d0*/.word load8_imm,bne_d0,0;             .byte 2,0xff,3,0 /*bne_d0*/
/*cmp_d1*/.word load8_dyi,cmp_d1,0;             .byte 2,0xff,5,0 /*cmp_d1*/
/*cmp_d2*/.word undef_op,0,0;                   .byte 2,0xff,5,0 /*cmp_d2*/
/*cmp_d3*/.word undef_op,0,0;                   .byte 2,0xff,7,0 /*cmp_d3*/
/*pei_d4*/.word undef_op,0,0;                   .byte 2,0xff,6,0 /*pei_d4*/
/*cmp_d5*/.word load8_dx,cmp_d5,0;              .byte 2,0xff,4,0 /*cmp_d5*/
/*dec_d6*/.word load8_dx,dec_d6,0;              .byte 2,0xff,6,0 /*dec_d6*/
/*cmp_d7*/.word undef_op,0,0;                   .byte 2,0xff,6,0 /*cmp_d7*/
/*cld_d8*/.word cld_d8,0,0;                     .byte 1,0xff,2,0 /*cld_d8*/
/*cmp_d9*/.word load8_absy,cmp_d9,0;            .byte 3,0xff,4,0 /*cmp_d9*/
/*phx_da*/.word undef_op,0,0;                   .byte 1,0xff,3,0 /*phx_da*/
/*stp_db*/.word undef_op,0,0;                   .byte 1,0xff,3,0 /*stp_db*/
/*jml_dc*/.word undef_op,0,0;                   .byte 3,0xff,6,0 /*jml_dc*/
/*cmp_dd*/.word load8_absx,cmp_dd,0;            .byte 3,0xff,4,0 /*cmp_dd*/
/*dec_de*/.word load8_absx,dec_de,0;            .byte 3,0xff,7,0 /*dec_de*/
/*cmp_df*/.word undef_op,0,0;                   .byte 4,0xff,5,0 /*cmp_df*/
/*cpx_e0*/.word load8_imm,cpx_e0,0;             .byte 2,0xff,2,0 /*cpx_e0*/
/*sbc_e1*/.word load8_dxi,sbc_e1,0;             .byte 2,0xff,6,0 /*sbc_e1*/
/*sep_e2*/.word undef_op,0,0;                   .byte 2,0xff,3,0 /*sep_e2*/
/*sbc_e3*/.word undef_op,0,0;                   .byte 2,0xff,4,0 /*sbc_e3*/
/*cpx_e4*/.word load8_zerop,cpx_e4,0;           .byte 2,0xff,3,0 /*cpx_e4*/
/*sbc_e5*/.word load8_zerop,sbc_e5,0;           .byte 2,0xff,3,0 /*sbc_e5*/
/*inc_e6*/.word load8_zerop,inc_e6,0;           .byte 2,0xff,5,0 /*inc_e6*/
/*sbc_e7*/.word undef_op,0,0;                   .byte 2,0xff,6,0 /*sbc_e7*/
/*inx_e8*/.word inx_e8,0,0;                     .byte 1,0xff,2,0 /*inx_e8*/
/*sbc_e9*/.word load8_imm,sbc_e9,0;             .byte 2,0xff,2,0 /*sbc_e9*/
/*nop_ea*/.word nop_ea,0,0;                     .byte 1,0xff,2,0 /*nop_ea*/
/*xba_eb*/.word undef_op,0,0;                   .byte 1,0xff,3,0 /*xba_eb*/
/*cpx_ec*/.word load8_abs,cpx_ec,0;             .byte 3,0xff,4,0 /*cpx_ec*/
/*sbc_ed*/.word load8_abs,sbc_ed,0;             .byte 3,0xff,4,0 /*sbc_ed*/
/*inc_ee*/.word load8_abs,inc_ee,0;             .byte 3,0xff,6,0 /*inc_ee*/
/*sbc_ef*/.word undef_op,0,0;                   .byte 4,0xff,5,0 /*sbc_ef*/
/*beq_f0*/.word load8_imm,beq_f0,0;             .byte 2,0xff,3,0 /*beq_f0*/
/*sbc_f1*/.word load8_dyi,sbc_f1,0;             .byte 2,0xff,5,0 /*sbc_f1*/
/*sbc_f2*/.word undef_op,0,0;                   .byte 2,0xff,5,0 /*sbc_f2*/
/*sbc_f3*/.word undef_op,0,0;                   .byte 2,0xff,7,0 /*sbc_f3*/
/*pea_f4*/.word undef_op,0,0;                   .byte 3,0xff,5,0 /*pea_f4*/
/*sbc_f5*/.word load8_dx,sbc_f5,0;              .byte 2,0xff,4,0 /*sbc_f5*/
/*inc_f6*/.word load8_dx,inc_f6,0;              .byte 2,0xff,6,0 /*inc_f6*/
/*sbc_f7*/.word undef_op,0,0;                   .byte 2,0xff,6,0 /*sbc_f7*/
/*sed_f8*/.word sed_f8,0,0;                     .byte 1,0xff,2,0 /*sed_f8*/
/*sbc_f9*/.word load8_absy,sbc_f9,0;            .byte 3,0xff,4,0 /*sbc_f9*/
/*plx_fa*/.word undef_op,0,0;                   .byte 1,0xff,4,0 /*plx_fa*/
/*xce_fb*/.word undef_op,0,0;                   .byte 1,0xff,2,0 /*xce_fb*/
/*jsr_fc*/.word undef_op,0,0;                   .byte 3,0xff,6,0 /*jsr_fc*/
/*sbc_fd*/.word load8_absx,sbc_fd,0;            .byte 3,0xff,4,0 /*sbc_fd*/
/*inc_fe*/.word load8_absx,inc_fe,0;            .byte 3,0xff,7,0 /*inc_fe*/
/*sbc_ff*/.word undef_op,0,0;                   .byte 4,0xff,5,0 /*sbc_ff*/
	
	.text
	.align	4
	.set	reorder
	.set	macro
	.set	nobopt
	.set	noat

/* extern int ks_reset_rfcstate_asm(rfcstate_object *p);
 * $B2?2s8F$s$G$bNI$$!#(B
 * $B$?$@@$7!"(Bwram $B$r(B 0xff $B%/%j%"$9$k$N$G(B HotStart $B$O$G$-$J$$!#(B
 * $BOC$O$=$l$k$,(B 0 $B$G=i4|2=$9$k$H(B HotStart $B$H4*0c$$$9$k%@@%a%=%U%H$,(B
 * $B$"$C$?$h$&$J!#(Bd_bowl.nes
 */
	.globl	ks_reset_rfcstate_asm
	.ent	ks_reset_rfcstate_asm
	.frame	sp, EMU_RFC_ASM_STACKSIZE, ra
ks_reset_rfcstate_asm:
	addiu	sp, sp, -EMU_RFC_ASM_STACKSIZE
	sw	s0, OFFSET_STACK_S0(sp)
	sw	s1, OFFSET_STACK_S1(sp)
	sw	s2, OFFSET_STACK_S2(sp)
	sw	s3, OFFSET_STACK_S3(sp)
	sw	s4, OFFSET_STACK_S4(sp)
	sw	s5, OFFSET_STACK_S5(sp)
	sw	s6, OFFSET_STACK_S6(sp)
	sw	s7, OFFSET_STACK_S7(sp)
	sw	gp, OFFSET_STACK_GP(sp)
	sw	fp, OFFSET_STACK_FP(sp)
	sw	ra, OFFSET_STACK_RA(sp)

	move	WORK, a0

	sw	zero, OFFSET_EMUFRAME(WORK)
	sb	zero, OFFSET_PC_HIST_OFFSET(WORK)
/* line (H-blank) $B3+;O$+$i(B H-blank $B=*N;$^$G$K$O(B $BLs(B 28 cpu cycle
 *                $B=*N;$+$i(B line end $B$^$G$K$O(B    $BLs(B 85 cpu cycle
 * $B$3$l$r(B 28+85.75 $B$H$9$k$H(B
 * 28    * 0x100 = 0x1c00
 * 85.75 * 0x100 = 0x55c0
 * H-blank $B$N=*N;$r%A%'%C%/$9$k$?$a$K(B line $B3+;O;~$K(B LINECYCLE $B$N(B d0=1 $B$K(B
 * $B$7$F$*$/!#(B
 */

#define LINECYCLE_CONST0 (-0x1c00 | 0x01)
#define LINECYCLE_CONST1 (-0x55c0)

	li	t0, LINECYCLE_CONST0
	sw	t0, OFFSET_THREAD_LINECYCLE(WORK)
	sh	zero, OFFSET_LINECNT(WORK)

/* $B:G=i$N<B9T%"%I%l%9$O(B emu_line0 */
	la	t0, emu_line0
	sw	t0, OFFSET_THREAD_PC(WORK)
	
/* clear wram, trainer, oam = 0xff
 * t0 = dst for wram
 * t1 = dst for trainer
 * t2 = dst for wram end
 * t3 = const
 * t4 = dst for oam
 * 0x80 $B2s(B repeat
 */
	move	t0, WORK
	move	t1, WORK
	move	t4, WORK
	addiu	t2, t0, 0x800
	li	t3, -1
1:
	sw	t3, OFFSET_WRAM(t0)
	sw	t3, OFFSET_WRAM + 4(t0)
	sw	t3, OFFSET_WRAM + 8(t0)
	sw	t3, OFFSET_WRAM + 0xc(t0)
	sw	t3, OFFSET_BBRAM + 0x1000(t1)
	sh	t3, OFFSET_OAM(t4)
	addiu	t0, t0, 0x10
	addiu	t1, t1, 0x4
	addiu	t4, t4, 0x2
	bne	t0, t2, 1b

/* 0xd3 $BHVCO$O(B < 0x80 $B$K$7$F$*$/(B
 * sun/metafght.nes $B$,$=$3$r%/%j%"$7$J$$$G(B MMC1 $B%l%8%9%?$K=q$-9~$s$G$$$k$N$G(B
 * d7=1 $B$G$O%l%8%9%?%j%;%C%H$K$J$C$F$7$^$&(B
 */
	li	t0, 0x7f
	sb	t0, OFFSET_WRAM + 0xd3(WORK)
	
/* clear vram, draw vram */
	move	t0, WORK
	addiu	t1, t0, SIZEOF_DRAW_VRAM
1:
	sd	zero, OFFSET_GFXBUF + OFFSET_GFXBUF_DRAW_VRAM + 0(t0)
	sd	zero, OFFSET_GFXBUF + OFFSET_GFXBUF_DRAW_VRAM + 8(t0)
	addiu	t0, t0, 0x10
	bne	t0, t1, 1b

/* VRAM mirror
 * header[6] $B$N(B d0 $B$,(B 0 $B$J$i(B $B=D;}$A(B
 *                    1 $B$J$i(B $B2#;}$A(B
 * $B$G=i4|2=$7$F$*$/(B
 */
	lw	t0, OFFSET_HEADERP(WORK)
	lbu	t1, 6(t0)
	andi	t1, t1, 0x01
	li	t2, 0x400    /* $B2#;}$A(B */
	bne	t1, zero, 1f
	li	t2, 0x800    /* $B=D;}$A(B */
1:
	sh	t2, OFFSET_VRAM_MIRROR_MASK_AND(WORK)
	sh	zero, OFFSET_VRAM_MIRROR_MASK_OR(WORK)

#if 0
/* chr touch flag $B$O(B all dirty $B$H$9$k!#(B*/
	move	t0, WORK
	addiu	t1, t0, SIZEOF_CHR_TOUCH_FLAG
1:
	sw	zero, OFFSET_GFXBUF + OFFSET_GFXBUF_CHR_TOUCH_FLAG(t0)
	addiu	t0, t0, 4
	bne	t0, t1, 1b
#endif

/* serial $B=i4|2=(B
 */
	sd	zero, OFFSET_SERIAL4016D1(WORK)
	sd	zero, OFFSET_SERIAL4017D5(WORK)
	sd	zero, OFFSET_SERIAL4017D3(WORK)
	sd	zero, OFFSET_SERIAL4017D1(WORK)
	sd	zero, OFFSET_WORK_4016D1(WORK)
	sd	zero, OFFSET_WORK_4017D5(WORK)
	sd	zero, OFFSET_WORK_4017D3(WORK)
	sd	zero, OFFSET_WORK_4017D1(WORK)
	sb	zero, OFFSET_WORK_4016H(WORK)
/* V ext mode $B$J$I(B $B3d$j9~$_6X;_(B */
	li	t0, 0x40
	sb	t0, OFFSET_WORK_4017H(WORK)
	sb	zero, OFFSET_IRQ_CAUSE(WORK)
	sb	zero, OFFSET_WORK_4015H_OUTPUT(WORK)

	li	t0, 0xffff
	sh	t0, OFFSET_WORK_4010H_OUTPUT(WORK)
	
/* BBRAM $B$b(B 0xff $B$G%/%j%"!#(B
 * - chrram $B$H6&$K!"(B hot start $B$K$OL$BP1~!#(B
 */
	move	t0, WORK
	li	t1, OFFSET_BBRAM
	li	t2, OFFSET_BBRAM + 0x2000
	addu	t1, t1, t0
	addu	t2, t2, t0
	li	t3, -1
1:
	sw	t3, 0(t1)
	sw	t4, 4(t1)
	addiu	t1, t1, 8
	bne	t1, t2, 1b
	
/* $B$^$:!"(Bnormal NES $B$H$7$F(B $B3F<o=i4|2=!#(B
 * store_ppu, store_io, storefunc, loadfunc, load_io $B$N=gHV!#(B
 * page table
 * ppu2000h output
 * ppu2000h
 * qd4030h
 */
	la	t0, nes_initial_functbl
	addiu	t1, t0, OFFSET_LOAD_IO_FUNCTBL + 4 * 0x18 - OFFSET_STORE_PPU_FUNCTBL
	move	t2, WORK
1:
	ld	t3, 0(t0)
	sd	t3, OFFSET_STORE_PPU_FUNCTBL(t2)

#if 0
/* debug */
	lw	a1, 0(t0)
	lw	a2, 4(t0)
	addiu	a3, t2, OFFSET_STORE_PPU_FUNCTBL
	PRINTF("%08x %08x at %08x\n");
#endif
	
	addiu	t0, t0, 8
	addiu	t2, t2, 8
	bne	t0, t1, 1b

/* chrbank $B@@_Dj4X?t$J$I(B */
	la	t0, chrbank_func_normal
	sw	t0, OFFSET_CHRBANK_FUNCP(WORK)
	sb	zero, OFFSET_DRAW_BG_CHRBANK_COUNT(WORK)
	sb	zero, OFFSET_DRAW_OBJ_CHRBANK_COUNT(WORK)

/* page table
 * 0000-5fff $B$O%@@%_!<!#(BWORK $B$G$bF~$l$H$1!#(B
 * 6000-7fff $B$O(B bbram - 0x6000
 * 8000-9fff $B$O(B prgrom - 0x8000 (rombank 0)
 * a000-bfff $B$O(B prgrom - 0x8000 (rombank 1)
 * c000-dfff $B$O(B prgrom + prgsize - 0x4000 - 0xc000 (rombank last-1)
 * e000-ffff $B$O(B prgrom + prgsize - 0x4000 - 0xc000 (rombank last)
 * pbank_mask $B$b@@_Dj!#(B(0x2000 bytes $BC10L(B)
 */
	sw	WORK, OFFSET_PAGE_TABLE + 0x00(WORK)
	sw	WORK, OFFSET_PAGE_TABLE + 0x04(WORK)
	sw	WORK, OFFSET_PAGE_TABLE + 0x08(WORK)

	addiu	t1, WORK, OFFSET_BBRAM - 0x6000
	sw	t1, OFFSET_PAGE_TABLE + 0x0c(WORK)
	lw	t2, OFFSET_HEADERP(WORK)
	lbu	t3, 6(t2)

	andi	t4, t3, 0x04 | 0x02
	beq	t4, zero, 1f
/* trainer or BBRAM */
	la	t0, store_bbram_64k
	sw	t0, OFFSET_STOREFUNC_TBL + 0x0c(WORK)
	la	t0, load_6000
	sw	t0, OFFSET_LOADFUNC_TBL + 0x0c(WORK)
	
	andi	t3, t3, 0x04
	beq	t3, zero, 1f
/* trainer */
/* headerp $B$N8e$K(B prgrom, chrrom $B$,$/$C$D$/$N$O(B $B$d$a$?!#(B
 * $B$=$N(B 1/2
 */
	la	t2, ks_nes_nesromstartp
	lw	t2, 0(t2)

	addiu	t3, t2, 0x200

	move	t5, WORK
2:
	lw	t4, 0x10(t2)
	sw	t4, OFFSET_BBRAM + 0x1000(t5)
	addiu	t2, t2, 4
	addiu	t5, t5, 4
	bne	t2, t3, 2b

1:
#if 0
/* headerp $B$N8e$K(B prgrom, chrrom $B$,$/$C$D$/$N$O(B $B$d$a$?!#(B
 * $B$=$N(B 2/2
 */
	addiu	t2, t2, 0x10
	sw	t2, OFFSET_PRGROM(WORK)
#endif
/* prgrom $B$O(B extern $B$G!#(B
 * $B@@hF,$O(B NES^Z $B$d$7!#(B
 */
	la	t2, ks_nes_nesromstartp
	lw	t2, 0(t2)
	addiu	t2, t2, 0x10
/* trainer $BBP1~(B */
	lw	t1, OFFSET_HEADERP(WORK)
	lbu	t3, 6(t1)
	andi	t3, t3, 0x04
	beq	t3, zero, 4f
	addiu	t2, t2, 0x200
4:
	sw	t2, OFFSET_PRGROM(WORK)

	lw	t3, OFFSET_PRGSIZE(WORK)
	addu	t4, t2, t3
	addiu	t2, t2, -0x8000
	sw	t2, OFFSET_PAGE_TABLE + 0x10(WORK)
	sw	t2, OFFSET_PAGE_TABLE + 0x14(WORK)
	addiu	t2, t2, -0x8000  /* $B$3$l$G(B t2 = prgrom - 0x4000 - 0xc000 */
	addu	t2, t2, t3
	sw	t2, OFFSET_PAGE_TABLE + 0x18(WORK)
	sw	t2, OFFSET_PAGE_TABLE + 0x1c(WORK)
/* pbank_mask = (prgsize / 0x2000) - 1 */
	srl	t1, t3, 13
	addiu	t1, t1, -1
	sb	t1, OFFSET_PBANK_MASK(WORK)

/* chr offset mask $B$O(B byte $BC10L!#(B*/
	lw	t2, OFFSET_CHRSIZE(WORK)
	sw	t4, OFFSET_CHRROM(WORK)
	sb	zero, OFFSET_MMC1_IGNORE_CHRBANK(WORK)
	bne	t2, zero, 1f
/* chrram $B$J$i(B storefunc $B$bJQ99!#(B*/
	li	t2, 0xff
	sb	t2, OFFSET_MMC1_IGNORE_CHRBANK(WORK)
	la	t2, store_2007_chrram
	sw	t2, OFFSET_STORE_PPU_FUNCTBL + 7 * 4(WORK)
	li	t2, 0x2000
1:
	addiu	t2, t2, -1
	sw	t2, OFFSET_CHR_OFFSET_MASK(WORK)

/* chr data $B$N(B conversion
 * chrram $B$J$i(B $BL5;k!#(B
 */
	lw	a0, OFFSET_CHRROM(WORK)
	lw	a2, OFFSET_UCODE_WORKP(WORK)
	lw	a3, OFFSET_CHRSIZE(WORK)
	
	addiu	a2, a2, OFFSET_UCODEWK_DRAW_CHR
	bne	a3, zero, 1f
/* chrram $B$J$i(B 0 $B%/%j%"(B
 * - hot start $B$K$OL$BP1~(B
 */
	addiu	a3, a2, 0x2000
2:
	sd	zero, 0(a2)
	sd	zero, 8(a2)
	addiu	a2, a2, 0x10
	bne	a2, a3, 2b
	
	j	10f
1:
	li	a1, 0
/* $B0z?t(B (keep $B$5$l$k(B)
 * a0: chrrom top
 * a1: chrrom offset
 * a2: dst top
 * (a3: chrrom offset end)
 * 1 char $B$:$D(B  convert $B$5$l$k!#(B
 */
1:
	jal	convert_chrdata
	addiu	a1, a1, 0x10
	bne	a1, a3, 1b

10:
/* $B%^%$%/%m%3!<%I$G(B chrram/chrrom $B6&DL=hM}$r$7$F$$$k$N$G(B
 * ucode work chrrom $B@@hF,(B $B$N(B 0x2000 bytes $B$O(B draw chrrom $B$K$b(B copy.
 * goemon1j.nes $BBP:v$G(B 0x4000 bytes $B$K$7$F$_$k!#(B
 */
	addiu	a0, WORK, OFFSET_GFXBUF
	lw	a1, OFFSET_UCODE_WORKP(WORK)
	addiu	a2, a0, 0x4000
1:
	ld	t0, OFFSET_UCODEWK_DRAW_CHR + 0(a1)
	ld	t1, OFFSET_UCODEWK_DRAW_CHR + 8(a1)
	sd	t0, OFFSET_GFXBUF_DRAW_CHR + 0(a0)
	sd	t1, OFFSET_GFXBUF_DRAW_CHR + 8(a0)
	addiu	a0, a0, 0x10
	addiu	a1, a1, 0x10
	bne	a0, a2, 1b
	
/* ppu2000h output */
	li	t0, 0x20202020
	sw	t0, OFFSET_PPU2000H_OUTPUT + 0(WORK)
	sw	t0, OFFSET_PPU2000H_OUTPUT + 4(WORK)
/* draw scch, sccv */
	sb	zero, OFFSET_DRAW_SCCH(WORK)
	sh	zero, OFFSET_DRAW_SCCV_NEW(WORK)
/* ppu2000h */
	sd	zero, OFFSET_PPU2000H(WORK)
/* qd output */
/*	li	t0, 0x000047ff */
/* debug
 * disksys
 * qd not inserted
 */
	li	t0, 0x0000fa80
	sw	t0, OFFSET_QD4030H(WORK)
	li	t0, 0x27
	sb	t0, OFFSET_QD4020H + 5(WORK)
	sb	t0, OFFSET_QD4025H_BAK(WORK)
/* QD dirty flag $B$r>C$7$F$*$/!#(B
 */
	sb	t0, OFFSET_QD_DIRTY(WORK)

/* strikef */
	li	t1, 0xff
	sb	t1, OFFSET_STRIKEF_LINE(WORK)

/* inst_jumptbl -> jumptbl $B$X(B copy */
	la	t0, inst_jumptbl
	move	t1, WORK
	addiu	t2, t0, 0x100 * 0x10
1:
	ld	t3, 0(t0)
	ld	t4, 8(t0)
	sd	t3, OFFSET_JUMPTBL + 0(t1)
	sd	t4, OFFSET_JUMPTBL + 8(t1)
	addiu	t0, t0, 0x10
	addiu	t1, t1, 0x10
	bne	t0, t2, 1b

/* A=X=Y=0
 * SP=0xff
 * P= 0x04 (Reserved|B|D|I) = (0|0|0|1)
 */
	sb	zero, OFFSET_A(WORK)
	sb	zero, OFFSET_X(WORK)
	sb	zero, OFFSET_Y(WORK)
	li	t0, 0xff
	sb	t0, OFFSET_SP(WORK)
	sb	zero, OFFSET_WORK_Z(WORK)
	sb	zero, OFFSET_WORK_C(WORK)
	sb	zero, OFFSET_WORK_V(WORK)
	sb	zero, OFFSET_WORK_N(WORK)
	li	t0, 0x04
	sb	t0, OFFSET_WORK_RBDI(WORK)

/* $B5/F0;~(B PC
 * (0xfffc,0xfffd) $B$O(B prgrom + prgsize - (4,3) $B$NHVCO$NFbMF$+$i!#(B
 */
	lw	t1, OFFSET_PRGROM(WORK)
	lw	t2, OFFSET_PRGSIZE(WORK)
	addu	t1, t1, t2
	lbu	t3, -4(t1)
	lbu	t4, -3(t1)
	sll	t4, t4, 8
	or	t3, t3, t4
	sh	t3, OFFSET_PC(WORK)
	move	v0, t3

/* chr bank register $B$N@@_Dj(B
 * (chrrom read $B$J$I!"(Bbank $B@@Z$jBX$($J$7$G$bI,MW(B)
 * 0000, 0001, ..., 0007
 */
	move	t0, WORK
	addiu	t1, t0, 2 * 8
	li	t2, 0
1:
	sh	t2, OFFSET_CHRBANK_REG0000(t0)
	addiu	t0, t0, 2
	addiu	t2, t2, 1
	bne	t0, t1, 1b

/* chrrom read $B;~$K(B chr seg $B;2>H$7$F$$$k$N$G(B bank $B@@Z$jBX$($J$7$G$b(B
 * $B$3$N=i4|2=$OI,MW!#(B
 * sun4_vrom $B$N=i4|2=$bI,MW!#(B
 * MMC5_BR7 >= 0x80 $B$G$"$k$3$H$rMxMQ$7$F(B MMC5 $B$+$I$&$+H=JL$9$k!#(B
 */
	sh	zero, OFFSET_CHRSEG_FOR_READ(WORK)
	sb	zero, OFFSET_SUN4(WORK)
	sb	zero, OFFSET_MMC5_BR7(WORK)

/* $B%i%$%s3d$j9~$_$N6X;_(B */
	li	t0, 0x8000
	sh	t0, OFFSET_LINECNT_IRQ(WORK)
	sh	t0, OFFSET_VRC4_LINECNT_SAVE(WORK)
	sh	zero, OFFSET_LINECNT_IRQ_PRESET(WORK)
	sb	zero, OFFSET_LINECNT_IRQ_ENABLED(WORK)
	la	t1, linecnt_over00
	sw	t1, OFFSET_LINECNT_OVER_FUNCP(WORK)
	
/* $B%^%C%Q!<0MB8$N(B $B=i4|2=(B
 * $B%F!<%V%k$N%P%$%H?t$O(B $B$:$l$F$$$J$$$+(B ?
 * header[7] $B$N(B upper 4bits + header[6] $B$N(B upper 4bits $B$,%^%C%Q!<HV9f!#(B
 */
	lw	t2, OFFSET_HEADERP(WORK)
	la	a0, store_functbl_mapper0
#ifdef KS_RFC_MAPPER_EXTENSION
	la	t1, store_functbl_mapper256
	subu	t1, t1, a0
	addiu	t1, t1, -(4 * 5 * 0x100)
	beq	t1, zero, 1f
	TRAP("MAPPER TBL BROKEN (T1)");
1:
#endif
	lbu	t1, 7(t2)
	lbu	t0, 6(t2)
	andi	t1, t1, 0xf0
	srl	t0, t0, 4
	or	t0, t0, t1
	mul	t1, t0, 4 * 5
	beq	t0, zero, 10f  /* mapper none */

	addu	a0, a0, t1
#ifndef KS_RFC_MAPPER_EXTENSION
/* mapper 0xfd $B$O(B disksys by myself
 */
	xori	t2, t0, 0xfd
	bne	t2, zero, 1f
	la	a0, store_functbl_mapper253
1:
#endif
/* t0-t3 $B$O8GDj!#Ht$S@@h$G;2>H$9$k$3$H$b$"$k(B */
	lw	t4, 0(a0)
	lw	t0, 4(a0)
	lw	t1, 8(a0)
	lw	t2, 0xc(a0)
	lw	t3, 0x10(a0)
	sw	t0, OFFSET_STOREFUNC_TBL + 0x10(WORK)
	sw	t1, OFFSET_STOREFUNC_TBL + 0x14(WORK)
	sw	t2, OFFSET_STOREFUNC_TBL + 0x18(WORK)
	sw	t3, OFFSET_STOREFUNC_TBL + 0x1c(WORK)
	beq	t4, zero, 10f
	jalr	t4
mapper_init_func_done:
10:
	
#if 0
/* debug
 * set watchpoint
 * address &= 0xfffff8;
 * d1=1: read watch, d0=1: write watch
 */
	.set	noreorder
	addiu	t0, WORK, OFFSET_MMC1_BIGROM
	li	t1, 0xfffff8
	and	t0, t0, t1
	ori	t0, t0, 1
	mtc0	t0, C0_WATCHLO
	.set	reorder
#endif

/* PPU $B%Q%l%C%H%G!<%?=i4|CM$r(B $B9u(B (0x0f) $B$K(B
 */
	move	t0, WORK
	addiu	t1, t0, 0x20
	li	t2, 0x0f0f0f0f
/*	li	t2, 0x01010101*/
/*	li	t2, 0x0e0e0e0e*/
1:
	sw	t2, OFFSET_PALETTE_BUF(t0)
	addiu	t0, t0, 4
	bne	t0, t1, 1b

/* $B:G8e$K!"%G%k%?%b%8%e%l!<%7%g%s(B $B%F!<%V%k%"%I%l%9@@_Dj(B
 * page table for 0xc000 + 0xc000
 */
	lw	t0, OFFSET_PAGE_TABLE + 0x18(WORK)
	li	t1, 0xc000
	addu	a0, t0, t1
	jal	Sound_SetC000

	lw	s0, OFFSET_STACK_S0(sp)
	lw	s1, OFFSET_STACK_S1(sp)
	lw	s2, OFFSET_STACK_S2(sp)
	lw	s3, OFFSET_STACK_S3(sp)
	lw	s4, OFFSET_STACK_S4(sp)
	lw	s5, OFFSET_STACK_S5(sp)
	lw	s6, OFFSET_STACK_S6(sp)
	lw	s7, OFFSET_STACK_S7(sp)
	lw	gp, OFFSET_STACK_GP(sp)
	lw	fp, OFFSET_STACK_FP(sp)
	lw	ra, OFFSET_STACK_RA(sp)

	addiu	sp, sp, EMU_RFC_ASM_STACKSIZE
	jr	ra

	GLOBAL(init01)
init01:
/* MMC1
 * r0-r3 $B=i4|CM$O(B 0x3f $B$H$$$&$3$H$G!"DL>o$K=q$-9~$s$@@CM$HF1$8$K$J$i$J$$!#(B
 * ... $B$"$+$s!"=i4|CM0MB8$N(B hal/satsui_k.nes $B$,(B ...
 * BBRAM $B$r;H$($k$h$&$K$7$F$*$/(B (kid_icar.nes)
 * dq4j.nes type (prgsize == 0x80000) $B$N>l9g!"(Bpage table $B$,68$&$N$G(B
 * c000-, e000- $B$N(B page table $B$O(B -0x40000 $B$9$k!#(B
 * $B7h$a$&$A$G$$$$$h$M!#(B
 */
	li	t0, 5
	sb	t0, OFFSET_MMC1_SHIFTCOUNT(WORK)
	li	t0, 0x0f
	sb	t0, OFFSET_MMC1_R0(WORK)
	li	t0, 0x00
	sb	t0, OFFSET_MMC1_R1(WORK)
	sb	t0, OFFSET_MMC1_R2(WORK)
	sb	t0, OFFSET_MMC1_R3(WORK)
	sb	zero, OFFSET_MMC1_ROMBANK(WORK)
	sb	zero, OFFSET_MMC1_RAMBANK(WORK)
	sw	zero, OFFSET_MMC1_BIGROM(WORK)
	la	t0, chrbank_func04
	sw	t0, OFFSET_CHRBANK_FUNCP(WORK)
	la	t0, store_bbram_64k
	sw	t0, OFFSET_STOREFUNC_TBL + 0x0c(WORK)
	la	t0, load_6000
	sw	t0, OFFSET_LOADFUNC_TBL + 0x0c(WORK)
	lw	t1, OFFSET_PRGSIZE(WORK)
	li	t2, 0x80000
	bne	t2, t1, 1f
/* MMC1 $B%j%;%C%H$N;~$N$3$H$,$"$k$N$G!"(Bprgsize $B$r(B 0x40000 $B$K$9$k(B */
	li	t2, 0xff
	sb	t2, OFFSET_MMC1_DQ4_MODE(WORK)
	li	t2, 0x40000
	sw	t2, OFFSET_PRGSIZE(WORK)
	lw	t1, OFFSET_PAGE_TABLE + 0x18(WORK)
	subu	t0, t1, t2
	sw	t0, OFFSET_PAGE_TABLE + 0x18(WORK)
	sw	t0, OFFSET_PAGE_TABLE + 0x1c(WORK)
1:
/* chr bank table $B$N=i4|2=(B */
	move	t0, WORK
	addiu	t1, t0, 2 * 8
	li	t2, 0
1:
	sh	t2, OFFSET_CHRBANK_REG0000(t0)
	addiu	t2, t2, 1
	addiu	t0, t0, 2
	bne	t0, t1, 1b

	jr	ra
	
	GLOBAL(init02)
init02:
/* PRG1M, fixC000
 * 8000-ffff $B$N=q$-9~$_$G(B 8000-bfff $B$N(B pbank
 * 2Mbit $B$b$"$k!#(B
 * BBRAM $B$r;H$($k$h$&$K$7$F$*$/(B (salaman0.nes)
 */
	la	t0, store_bbram_64k
	sw	t0, OFFSET_STOREFUNC_TBL + 0x0c(WORK)
	la	t0, load_6000
	sw	t0, OFFSET_LOADFUNC_TBL + 0x0c(WORK)
	jr	ra
	
	GLOBAL(init03)
init03:
/* CHR128/256
 * 6000-ffff $B$N=q$-9~$_$G(B d0,d1 $B$,(B chr bank $B$K$J$k!#(B
 */
	sw	t0, OFFSET_STOREFUNC_TBL + 0xc(WORK)
	la	t0, chrbank_func03
	sw	t0, OFFSET_CHRBANK_FUNCP(WORK)
	jr	ra

	GLOBAL(init04)
init04:
/* MMC3
 * $B%X%C%@@$K4X78$J$/(B BBRAM $B$O;H$($k$h$&$K$7$F$*$/(B (smario3.nes)
 */
	la	t0, store_bbram_64k
	sw	t0, OFFSET_STOREFUNC_TBL + 0x0c(WORK)
	la	t0, load_6000
	sw	t0, OFFSET_LOADFUNC_TBL + 0x0c(WORK)
	sb	zero, OFFSET_MMC3_POINTER(WORK)
	sw	zero, OFFSET_MMC3_R0(WORK)
	sh	zero, OFFSET_MMC3_R6(WORK)
	la	t1, chrbank_func04
	sw	t1, OFFSET_CHRBANK_FUNCP(WORK)
	la	t1, linecnt_over04
	sw	t1, OFFSET_LINECNT_OVER_FUNCP(WORK)
	jr	ra

	GLOBAL(init05)
init05:
/* MMC5
 * amode=3
 * (pamode $B$O(B $BITDj(B)
 * br7=0xff
 * pbrex=0
 * $B%X%C%@@$K4X78$J$/(B BBRAM $B$O;H$($k$h$&$K$7$F$*$/(B (o/koei/sangok2j.nes)
 * linecnt_irq cause bit $B$N%/%j%"(B
 */
	sb	zero, OFFSET_MMC5_EXRAM + 0x400 + 4(WORK)
	la	t0, store_bbram_64k
	sw	t0, OFFSET_STOREFUNC_TBL + 0x0c(WORK)
	la	t0, load_6000
	sw	t0, OFFSET_LOADFUNC_TBL + 0x0c(WORK)
/* debug for ohotsuku.nes (converted for MMC5)
 */
	la	t0, store_verbose
	sw	t0, OFFSET_STOREFUNC_TBL + 0x10(WORK)
	sw	t0, OFFSET_STOREFUNC_TBL + 0x14(WORK)
	sw	t0, OFFSET_STOREFUNC_TBL + 0x18(WORK)
	
	li	t1, 0x0300
	sh	t1, OFFSET_MMC5_AMODE_PAMODE(WORK)
/* amode 3 $B$N(B mapping $B@@_Dj(B */

	li	t1, 0xff
	sb	t1, OFFSET_MMC5_BR7(WORK)

	sh	zero, OFFSET_MMC5_PBREX(WORK)
	
	la	t0, store05_io
	sw	t0, OFFSET_STOREFUNC_TBL + 0x08(WORK)

/* storefunc $B$N=i4|2=(B */
	la	t0, mmc5_store_functbl_org
	addiu	t1, WORK, OFFSET_MMC5_STOREFUNC_TBL
	addiu	t2, t0, 4 * 0x34
1:
	ld	t3, 0(t0)
	ld	t4, 8(t0)
	sd	t3, 0(t1)
	sd	t4, 8(t1)
	addiu	t0, t0, 0x10
	addiu	t1, t1, 0x10
	bne	t0, t2, 1b

	la	t1, chrbank_func05
	sw	t1, OFFSET_CHRBANK_FUNCP(WORK)
	la	t1, linecnt_over05
	sw	t1, OFFSET_LINECNT_OVER_FUNCP(WORK)
	jr	ra
	
	GLOBAL(init06)
init06:
/* FFE F4xxx
 * debug $B$H$j$"$($:!#(B
 * goemon1j.nes $BBP:v$J$N$@@$,(B restart address $B$O(B rom offset +0x1e210
 * $B$N$h$&$@@!#(B
 * $B$H$j$"$($:(B prgrom + 0x1e000 $B$r(B e000-ffff $B$N(B page table $B$K!#(B
 *                   + 0x1c000 $B$r(B c000-dfff $B$N(B page table $B$K!#(B
 */
#if 0
/* mappers.nfo $B$^$C$?$/$&$=$d$s!#(B*/
	la	t0, store06_4000
	sw	t0, OFFSET_STOREFUNC_TBL + 0x08(WORK)
#endif
	
	lw	t1, OFFSET_PRGROM(WORK)
	li	t2, 0x1c000 - 0xc000
	addu	t0, t1, t2
	la	t3, chrbank_func03
	sw	t3, OFFSET_CHRBANK_FUNCP(WORK)
	j	inite3_setfffc_common

	GLOBAL(init07)
init07:
/* Rare
 * 1 $B2hLL%b!<%I$@@$1(B ?
 * first 32K ROM bank is swapped into $8000 when the cart is started or reset.
 */
	lw	t1, OFFSET_PRGROM(WORK)
	addiu	t1, t1, -0x8000
	sw	t1, OFFSET_PAGE_TABLE + 0x10(WORK)
	sw	t1, OFFSET_PAGE_TABLE + 0x14(WORK)
	sw	t1, OFFSET_PAGE_TABLE + 0x18(WORK)
	sw	t1, OFFSET_PAGE_TABLE + 0x1c(WORK)
	sh	zero, OFFSET_VRAM_MIRROR_MASK_AND(WORK)
	jr	ra
	
	GLOBAL(init09)
init09:
/* MMC2
 * a000-ffff $B$,(B $B8GDj(B
 * a000-bfff $B$O(B prgrom + prgsize - 0x6000 - 0xa000 (rombank last - 2)
 * $B$&$_$e!<$3$l$OL5M}$d!#$F$$$&$+%Q%s%A%"%&%H$@@$1$d$7!#(B
 * $B%G%b8+$F$?$i(B 8000H $B$K(B store $B$7$F$k$>!#(B(PC=b0a5)
 */
	lw	t0, OFFSET_PRGROM(WORK)
	lw	t1, OFFSET_PRGSIZE(WORK)
	li	t2, 0x6000 + 0xa000
	addu	t0, t0, t1
	subu	t0, t0, t2
	sw	t0, OFFSET_PAGE_TABLE + 0x14(WORK)

	sb	zero, OFFSET_MMC3_POINTER(WORK)
	la	t1, chrbank_func04 /* $B$H$j$"$($:(B */
	sw	t1, OFFSET_CHRBANK_FUNCP(WORK)
	jr	ra

	GLOBAL(init0f)
init0f:
/* 100 in 1
 *  Notes: - The first 32K of ROM is loaded into $8000 on reset. There is
 *            8K of VRAM at PPU $0000.
 */
	lw	t0, OFFSET_PAGE_TABLE + 0x10(WORK)
	j	inite3_setfffc_common

	GLOBAL(init12)
init12:
/* Jaleco SS8806
 * BBRAM $B;HMQ2DG=$K(B (toppro.nes)
 */
	la	t0, chrbank_func04
	sw	t0, OFFSET_CHRBANK_FUNCP(WORK)
	la	t1, linecnt_over12
	sw	t1, OFFSET_LINECNT_OVER_FUNCP(WORK)
	sh	zero, OFFSET_SS_PBANK0 + 0x0(WORK)
	sh	zero, OFFSET_SS_PBANK0 + 0x2(WORK)
	sh	zero, OFFSET_SS_PBANK0 + 0x4(WORK)
	sh	zero, OFFSET_SS_CHRBANK0 + 0x0(WORK)
	sh	zero, OFFSET_SS_CHRBANK0 + 0x2(WORK)
	sh	zero, OFFSET_SS_CHRBANK0 + 0x4(WORK)
	sh	zero, OFFSET_SS_CHRBANK0 + 0x6(WORK)
	sh	zero, OFFSET_SS_CHRBANK0 + 0x8(WORK)
	sh	zero, OFFSET_SS_CHRBANK0 + 0xa(WORK)
	sh	zero, OFFSET_SS_CHRBANK0 + 0xc(WORK)
	sh	zero, OFFSET_SS_CHRBANK0 + 0xe(WORK)
	la	t0, store_bbram_64k
	sw	t0, OFFSET_STOREFUNC_TBL + 0x0c(WORK)
	la	t0, load_6000
	sw	t0, OFFSET_LOADFUNC_TBL + 0x0c(WORK)
	jr	ra

	GLOBAL(init13)
init13:
/* Namcot 106 */
	la	t0, chrbank_func04
	sw	t0, OFFSET_CHRBANK_FUNCP(WORK)
	la	t1, linecnt_over13
	sw	t1, OFFSET_LINECNT_OVER_FUNCP(WORK)
	la	t0, store13_io
	sw	t0, OFFSET_STOREFUNC_TBL + 0x08(WORK)
#if 0
/* 7800 $B$K(B $B=q$-9~$s$G$$$k(B namco/fcirc91.nes - BBRAM */
	la	t0, store_verbose
	sw	t0, OFFSET_STOREFUNC_TBL + 0x0c(WORK)
#endif
/* $B2#;}$A$G(B $B=i4|2=(B */
	li	t0, 0x0001
	sh	t0, OFFSET_SS_PBANK0(WORK)
	sh	t0, OFFSET_SS_PBANK0 + 2(WORK)
#if 0
/* n_clasic.nes, mindseek.nes $B$,;_$^$k$N$O4X78$J$$!#(B*/
	la	t0, store_bbram_64k
	sw	t0, OFFSET_STOREFUNC_TBL + 0x0c(WORK)
	la	t0, load_6000
	sw	t0, OFFSET_LOADFUNC_TBL + 0x0c(WORK)
#endif
	jr	ra

	GLOBAL(init16)
init16:
/* mapper 0x16=Konami VRC2-Shift
 * BBRAM $B;HMQ2DG=$K$7$F$*$/(B ?
 */
	la	t0, chrbank_func04
	sw	t0, OFFSET_CHRBANK_FUNCP(WORK)
	jr	ra

	GLOBAL(init19)
init19:
init17:
init15:
/* mapper 0x19=VRC2/4 Even
 * mapper 0x18=VRC6-A $B$+$i$bMh$k!#(B
 * mapper 0x17=VRC2/4 Odd
 * mapper 0x15=VRC4
 * BBRAM $B$O;H$($k$h$&$K$7$F$*$3$&!#(B
 * linecnt irq $B$O(B $BC1H/$N$_(B
 */
	la	t1, linecnt_over19
	sw	t1, OFFSET_LINECNT_OVER_FUNCP(WORK)
init19_common:
	la	t0, chrbank_func04
	sw	t0, OFFSET_CHRBANK_FUNCP(WORK)
	la	t0, store_bbram_64k
	sw	t0, OFFSET_STOREFUNC_TBL + 0x0c(WORK)
	la	t0, load_6000
	sw	t0, OFFSET_LOADFUNC_TBL + 0x0c(WORK)
	sb	zero, OFFSET_VRC4_MAPMODE(WORK)
	sb	zero, OFFSET_VRC4_PBANK(WORK)
	jr	ra

	GLOBAL(init18)
init18:
/* mapper 0x18=VRC6-A
 *        0x1a=VRC6-B
 */
	sb	zero, OFFSET_VRC6_REG_SWAP(WORK)
	sb	zero, OFFSET_VRC6_IRQ_SELECT(WORK)
	li	t0, 1
	sb	t0, OFFSET_VRC6_IRQ_REG(WORK)
	GLOBAL(init18_common)
init18_common:
	la	t1, linecnt_over18
	sw	t1, OFFSET_LINECNT_OVER_FUNCP(WORK)
	sb	zero, OFFSET_VRC6_IRQ(WORK)
	j	init19_common

	GLOBAL(init1a)
init1a:
	li	t0, 0x03
	sb	t0, OFFSET_VRC6_REG_SWAP(WORK)
	li	t1, 0x01
	sb	t1, OFFSET_VRC6_IRQ_SELECT(WORK)
	li	t0, 2
	sb	t0, OFFSET_VRC6_IRQ_REG(WORK)
	j	init18_common

	GLOBAL(init20)
init20:
/* Irem G-101
 * ss_pbank0 $B$r(B pbank, + 1 $B$r(B mapmode $B$,$o$j$K!#(B
 */
	sh	zero, OFFSET_SS_PBANK0(WORK)
	la	t0, chrbank_func04
	sw	t0, OFFSET_CHRBANK_FUNCP(WORK)
	jr	ra
	
	GLOBAL(init21)
init21:
/* Taito TC0190
 */
	la	t0, chrbank_func04
	sw	t0, OFFSET_CHRBANK_FUNCP(WORK)
	la	t1, linecnt_over21
	sw	t1, OFFSET_LINECNT_OVER_FUNCP(WORK)
	jr	ra
	
	GLOBAL(init42)
init42:
/* GNROM
 * xxPPCCCC
 * PP: pbank @@ 8000-ffff
 * CC: cbank @@ 0000-1fff
 * c000-ffff $B$N(B page table $B$r(B 8000-bfff $B$HF1$8$b$N$K$7$F$*$/!#(B
 * jaleco/yokaiclb.nes $B$,(B 6000 $B$K=q$-9~$s$G$$$k$,F1Ey$K07$&!#(B
 * jaleco/dan.nes $B$O(B chrrom 0x20000 bytes.
 */
	lw	t2, OFFSET_PAGE_TABLE + 0x10(WORK)
	sw	t2, OFFSET_PAGE_TABLE + 0x18(WORK)
	sw	t2, OFFSET_PAGE_TABLE + 0x1c(WORK)
	la	t1, chrbank_func04
	sw	t1, OFFSET_CHRBANK_FUNCP(WORK)
	sw	t0, OFFSET_STOREFUNC_TBL + 0x0c(WORK)
	jr	ra

	GLOBAL(init43)
init43:
/* Sunsoft 3
 * fantasy zone 2 $B$@@$1(B ?
 *
 */
	la	t1, chrbank_func04
	sw	t1, OFFSET_CHRBANK_FUNCP(WORK)
	la	t1, linecnt_over43
	sw	t1, OFFSET_LINECNT_OVER_FUNCP(WORK)
	jr	ra
	
	GLOBAL(init44)
init44:
/* Sunsoft 4
 * BBRAM $B$O;H$($k$h$&$K$7$F$*$/(B
 * VROM $BBP:v$G(B internal format attr data $B$r(B convert $B$9$k!#(B
 * (chrrom 00000-3ffff $B$N(B attr $B$r(B 40000-7ffff $B$K(B)
 * sun4 $B$r(B 0x40 $B$K$7$F$*$/!#(B
 */
	la	t0, chrbank_func44
	sw	t0, OFFSET_CHRBANK_FUNCP(WORK)
	la	t0, store_bbram_64k
	sw	t0, OFFSET_STOREFUNC_TBL + 0x0c(WORK)
	la	t0, load_6000
	sw	t0, OFFSET_LOADFUNC_TBL + 0x0c(WORK)
	li	t0, 0x40
	sb	t0, OFFSET_SUN4(WORK)
	sb	zero, OFFSET_SUN4_VROM_ENABLED(WORK)

/* t3: chrrom src
 * t4: chrrom src true end
 * t5:
 * t6: chrrom dst base
 * t7: src offset 0..0x40
 * t8: chrrom dst work
 */
	lw	t3, OFFSET_CHRROM(WORK)
	li	t0, 0x40000
	addu	t4, t3, t0
	addu	t6, t3, t0
2:
	li	t7, 0
1:
	lbu	t2, 0x3c0(t3)
	andi	t1, t7, 0x07
	sll	t1, t1, 2     /* 0x07 -> 0x1c */

	andi	t0, t7, 0x38
	sll	t0, t0, 4     /* 0x38 -> 0x380 */
	or	t0, t0, t1
	addu	t8, t6, t0
/* (d7,d6) -> draw vram + (0x40 $B$H(B 0x60) + (2 $B$H(B 3) */
	andi	t1, t2, 0xc0
	sb	t1, 0x42(t8)
	sb	t1, 0x43(t8)
	sb	t1, 0x62(t8)
	sb	t1, 0x63(t8)
/* (d5,d4) -> draw vram + (0x40 $B$H(B 0x60) + (0 $B$H(B 1) */
	andi	t0, t2, 0x30
	sll	t0, t0, 2
	sb	t0, 0x40(t8)
	sb	t0, 0x41(t8)
	sb	t0, 0x60(t8)
	sb	t0, 0x61(t8)
/* (d3,d2) -> draw vram + (0x00 $B$H(B 0x20) + (2 $B$H(B 3) */
	andi	t1, t2, 0x0c
	sll	t1, t1, 4
	sb	t1, 0x02(t8)
	sb	t1, 0x03(t8)
	sb	t1, 0x22(t8)
	sb	t1, 0x23(t8)
/* (d1,d0) -> draw vram + (0x00 $B$H(B 0x20) + (0 $B$H(B 1) */
	sll	t1, t2, 6
	sb	t1, 0x00(t8)
	sb	t1, 0x01(t8)
	sb	t1, 0x20(t8)
	sb	t1, 0x21(t8)

	addiu	t7, t7, 1
	addiu	t3, t3, 1
	sltiu	t0, t7, 0x40
	bne	t0, zero, 1b

	addiu	t3, t3, 0x3c0
	addiu	t6, t6, 0x400
	bne	t3, t4, 2b
	
	jr	ra
		
	GLOBAL(init45)
init45:
/* Sunsoft 5
 */
	la	t0, chrbank_func04
	sw	t0, OFFSET_CHRBANK_FUNCP(WORK)
	la	t1, linecnt_over45
	sw	t1, OFFSET_LINECNT_OVER_FUNCP(WORK)
	la	t0, store_bbram_64k
	sw	t0, OFFSET_STOREFUNC_TBL + 0x0c(WORK)
	la	t0, load_6000
	sw	t0, OFFSET_LOADFUNC_TBL + 0x0c(WORK)
	jr	ra

	GLOBAL(init46)
init46:
/* Kitarou2 mapper
 * taito/arkanoi2.nes $B$J$I!#(B
 */
	la	t1, chrbank_func04
	sw	t1, OFFSET_CHRBANK_FUNCP(WORK)
	jr	ra
	
	GLOBAL(init49)
init49:
/* Konami VRC3 (salamder.nes)
 * $B$3$N%2!<%`(B WRAM $B:\$;$F$k$h!#(B
 * 8000,9000 $B$O(B chrbank $B$G$7$g$&!#(Bchrram $B$J$N$GL5;k!#(B
 * f000 $B$,(B pbank @@ 8000-bfff $B$/$5$$!#(B
 */
	la	t1, linecnt_over49
	sw	t1, OFFSET_LINECNT_OVER_FUNCP(WORK)
	jr	ra
	
	GLOBAL(init56)
init56:
/* Jaleco Moepro
 * prg $B$OF0$$$?!#(B
 * chr $B$bF0$$$?!#(B
 */
	la	t1, store56_6000
	sw	t1, OFFSET_STOREFUNC_TBL + 0x0c(WORK)
	
	la	t0, store_verbose
	sw	t0, OFFSET_STOREFUNC_TBL + 0x10(WORK)
	sw	t0, OFFSET_STOREFUNC_TBL + 0x14(WORK)
	sw	t0, OFFSET_STOREFUNC_TBL + 0x18(WORK)
	sw	t0, OFFSET_STOREFUNC_TBL + 0x1c(WORK)

	la	t0, chrbank_func03
	sw	t0, OFFSET_CHRBANK_FUNCP(WORK)
	
	jr	ra

	GLOBAL(init58)
init58:
/* Namcot 118
 * $B$+$J$j(B MMC3 $B$K;w$F$$$k!#(B
 * c000=0 $B=q$-9~$_(B (devilman.nes)
 */
	la	t0, store_verbose
	sw	t0, OFFSET_STOREFUNC_TBL + 0x18(WORK)
	
	sb	zero, OFFSET_MMC3_POINTER(WORK)
	sw	zero, OFFSET_MMC3_R0(WORK)
	sh	zero, OFFSET_MMC3_R6(WORK)
	la	t1, chrbank_func04
	sw	t1, OFFSET_CHRBANK_FUNCP(WORK)
	la	t1, linecnt_over04
	sw	t1, OFFSET_LINECNT_OVER_FUNCP(WORK)
	jr	ra

	
	GLOBAL(init5a)
init5a:
/* PC-JY-? mapper
 * o/cracked/tekken2.nes, o/cracked/samuspi2.nes
 */
	la	t0, store_verbose
	sw	t0, OFFSET_STOREFUNC_TBL + 0x1c(WORK)
	la	t0, chrbank_func04
	sw	t0, OFFSET_CHRBANK_FUNCP(WORK)
	la	t1, linecnt_over5a
	sw	t1, OFFSET_LINECNT_OVER_FUNCP(WORK)
	jr	ra

	GLOBAL(init5c)
init5c:
/* Jaleco Moepro88, MoeproSoccer
 */
	la	t0, store_verbose
	sw	t0, OFFSET_STOREFUNC_TBL + 0x10(WORK)
	sw	t0, OFFSET_STOREFUNC_TBL + 0x14(WORK)
	sw	t0, OFFSET_STOREFUNC_TBL + 0x18(WORK)
	sw	t0, OFFSET_STOREFUNC_TBL + 0x1c(WORK)
	jr	ra
	
	GLOBAL(init63)
init63:
/* VS Unisystem
 * debug $B$H$j$"$($:(B vspack/iceclimv.nes $B$G<B83!#(B
 * scroll $B$r(B V $B$K!#(B
 */
	li	t0, 0x800
	sh	t0, OFFSET_VRAM_MIRROR_MASK_AND(WORK)
	la	t0, store63_4020
	sw	t0, OFFSET_STORE_IO_FUNCTBL + 0x20 * 4(WORK)
	jr	ra

	GLOBAL(inite0)
inite0:
/* 72 in 1
 * 110 in 1 $B$N4J0WHG(B
 */
	li	t0, 0x400
	sh	t0, OFFSET_VRAM_MIRROR_MASK_AND(WORK)
	la	t0, chrbank_func04
	sw	t0, OFFSET_CHRBANK_FUNCP(WORK)
	lw	t0, OFFSET_PAGE_TABLE + 0x10(WORK)
	j	inite3_setfffc_common

	GLOBAL(inite1)
inite1:
/* 110 in 1
 * reset $B;~(B $B2#;}$A!"(B0x8000 bytes/bank, prg bank 0, chr bank 0,
 * 5800-5803 = 0x0f, 0x00, 0x0f, 0x00
 * 4bit register files x 4 $BFbB"$H$$$&$3$H$J$N$G!"$=$l$O(B BBRAM $B$r;H$&!#(B
 */
	li	t0, 0x400
	sh	t0, OFFSET_VRAM_MIRROR_MASK_AND(WORK)

	li	t2, 0x0f000f00
	sw	t2, OFFSET_BBRAM(WORK)
	
	la	t0, chrbank_func04
	sw	t0, OFFSET_CHRBANK_FUNCP(WORK)

	la	t1, storee1_io
	sw	t1, OFFSET_STOREFUNC_TBL + 0x08(WORK)
	la	t2, loade1_io
	sw	t2, OFFSET_LOADFUNC_TBL + 0x08(WORK)
	
	lw	t0, OFFSET_PAGE_TABLE + 0x10(WORK)
	j	inite3_setfffc_common

	GLOBAL(inite2)
inite2:
inite5:
/* 0xe2 = 76 in 1
 * 0xe5 = 31 in 1
 */
	la	t0, chrbank_func04
	sw	t0, OFFSET_CHRBANK_FUNCP(WORK)
	sh	zero, OFFSET_SS_PBANK0(WORK)
	lw	t0, OFFSET_PAGE_TABLE + 0x10(WORK)
	j	inite3_setfffc_common

	GLOBAL(inite3)
inite3:
/* 1200in1
 * reset $B;~(B $B2#;}$A!"(Bchrram, 8000-, c000- $B$H$b$K(B rombank 0
 */
	lw	t0, OFFSET_PAGE_TABLE + 0x10(WORK)
	addiu	t0, t0, -0x4000

	GLOBAL(inite3_setfffc_common)
inite3_setfffc_common:
/* t0: page table @@ e000-
 */
	sw	t0, OFFSET_PAGE_TABLE + 0x18(WORK)
	sw	t0, OFFSET_PAGE_TABLE + 0x1c(WORK)
	li	t2, 0xfffc
	addu	t3, t0, t2
	lbu	t0, 0(t3)
	lbu	t1, 1(t3)
	sll	t1, t1, 8
	or	v0, t0, t1
	sh	v0, OFFSET_PC(WORK)
	
	jr	ra

	GLOBAL(inite6)
inite6:
/* 22 in 1
 * $B:G=i(B contra mode $B$G!"(B power off $B$K$h$C$F(B
 * 21 in 1/contra mode $B$,(B swap $B$9$k$i$7$$!#(B
 */
	la	t0, chrbank_func04
	sw	t0, OFFSET_CHRBANK_FUNCP(WORK)
	sh	zero, OFFSET_SS_PBANK0(WORK)
	lw	t0, OFFSET_PAGE_TABLE + 0x10(WORK)
	j	inite3_setfffc_common

	GLOBAL(initqd)
initqd:
/* disksys by myself (mapper 0xfd)
 * BBRAM $B$O;H$($k$h$&$K$7$F$*$/!#(B
 * prgrom $BNN0h$K$b=q$-9~$a$k!#(B
 */
	la	t0, store_bbram_64k
	sw	t0, OFFSET_STOREFUNC_TBL + 0x0c(WORK)
	la	t0, load_6000
	sw	t0, OFFSET_LOADFUNC_TBL + 0x0c(WORK)

	la	t1, linecnt_overqd
	sw	t1, OFFSET_LINECNT_OVER_FUNCP(WORK)
	jr	ra

/* $B%j%;%C%H%k!<%A%s=*N;(B */
	.end	ks_reset_rfcstate_asm


	
/* extern int ks_emu_rfc_asm(rfcstate_object *p);
 */
	.globl	ks_emu_rfc_asm
	.ent	ks_emu_rfc_asm
	.frame	sp, EMU_RFC_ASM_STACKSIZE, ra
ks_emu_rfc_asm:
	addiu	sp, sp, -EMU_RFC_ASM_STACKSIZE
	sw	s0, OFFSET_STACK_S0(sp)
	sw	s1, OFFSET_STACK_S1(sp)
	sw	s2, OFFSET_STACK_S2(sp)
	sw	s3, OFFSET_STACK_S3(sp)
	sw	s4, OFFSET_STACK_S4(sp)
	sw	s5, OFFSET_STACK_S5(sp)
	sw	s6, OFFSET_STACK_S6(sp)
	sw	s7, OFFSET_STACK_S7(sp)
	sw	gp, OFFSET_STACK_GP(sp)
	sw	fp, OFFSET_STACK_FP(sp)
	sw	ra, OFFSET_STACK_RA(sp)

	move	WORK, a0

/* $B%Q%C%I%G!<%?$NJQ49(B ... famicom.c $B$G$d$C$F$$$?!#(B */

/* SP $B$,(B ucode_wk $B$X(B DMA copy $B$7=*$o$C$F$$$J$1$l$PBT$D!#(B
 */
	lw	t1, OFFSET_WORK_RSPSIGNAL(WORK)
	bne	t1, zero, 1f  /* $B%O%s%I%7%'%$%/$r(B skip */
	lui	t0, 0xa404
2:
	.set	noreorder
	andi	t2, t1, 0x0400
	beq	t2, zero, 2b
	lw	t1, 0x10(t0)
	.set	reorder
/* IO_WRITE(SP_STATUS_REG, SP_CLR_RSPSIGNAL); */
	ori	t1, zero, 0x8000
	sw	t1, 0x10(t0)
	sw	t2, OFFSET_WORK_RSPSIGNAL(WORK) /* t2 != 0 */
1:

	lhu	PC, OFFSET_PC(WORK)
	lbu	A, OFFSET_A(WORK)
	lbu	X, OFFSET_X(WORK)
	lbu	Y, OFFSET_Y(WORK)
	lbu	SP, OFFSET_SP(WORK)
	lbu	Z, OFFSET_WORK_Z(WORK)
	lbu	C, OFFSET_WORK_C(WORK)
	lbu	V, OFFSET_WORK_V(WORK)
	lbu	N, OFFSET_WORK_N(WORK)

	lw	STORE_DONE, OFFSET_THREAD_STORE_DONE(WORK)
	lw	JUMPTBLP, OFFSET_THREAD_JUMPTBLP(WORK)
	lw	PAGE_PTR, OFFSET_THREAD_PAGE_PTR(WORK)
	lw	LINECYCLE, OFFSET_THREAD_LINECYCLE(WORK)
	lw	ra, OFFSET_THREAD_RA(WORK)
	lw	a2, OFFSET_THREAD_PC(WORK)
	jr	a2

/* debug */
	GLOBAL(emu_line0)
emu_line0:
/* $B%i%Y%k$H$ON"J"$K!"$3$3$O(B line 0 $B$G$O$J$$!#(B
 * line -22 $B$G$"$k!#(B
 * palette change count, bg bank change count, obj bank change count,
 * oam change count $B$r(B 0 $B$K!#(B
 */
	sb	zero, OFFSET_PALETTE_CHANGE_COUNT(WORK)
	sb	zero, OFFSET_BG_CHRBANK_TOUCH_FLAG(WORK)
	sb	zero, OFFSET_OBJ_CHRBANK_TOUCH_FLAG(WORK)
	sb	zero, OFFSET_BG_CHRBANK_CHANGE_COUNT(WORK)
	sb	zero, OFFSET_OBJ_CHRBANK_CHANGE_COUNT(WORK)
	sb	zero, OFFSET_OAM_CHANGE_COUNT(WORK)

/* $B:#2s(B $B=q$-9~$`(B gfxbuf $B$r(B gfx_selbuf $B$+$i7hDj$9$k!#(B
 * $B%@@%V%k%P%C%U%!!#(B
 */
	lbu	t0, OFFSET_GFX_SELBUF(WORK)
	lbu	t2, OFFSET_GFX_SELBUF_NEXT(WORK)
	li	t1, OFFSET_GFXBUF
	bne	t0, zero, 1f
	li	t1, OFFSET_GFXBUF2
1:
	sb	t2, OFFSET_GFX_SELBUF(WORK)
	addu	t1, t1, WORK
	sw	t1, OFFSET_GFXPTR(WORK)

/* chr touch flag $B$r%/%j%"$9$k!#(B
 */
	move	t0, WORK
	addiu	t1, t0, SIZEOF_CHR_TOUCH_FLAG
	li	t2, -1  /* 0xffffffff */
1:
	sw	t2, OFFSET_GFXBUF + OFFSET_GFXBUF_CHR_TOUCH_FLAG(t0)
	addiu	t0, t0, 4
	bne	t0, t1, 1b

	j	mainloop_srlt0
	
	GLOBAL(line_240_done)
line_240_done:
/* PPU 2002H output $B$N(B d7 $B$r(B 1 $B$K$9$k$N$O!"(BNMI $B5/F0$h$j$[$s$N>/$7A0(B
 * $B$N$h$&$@@!#(B(ascii/castle_j.nes 0x816a $BHVCO(B)
 */
	lbu	t2, OFFSET_PPU2000H_OUTPUT + 2(WORK)
	ori	t2, t2, 0x80
/* strikef $B$N%/%j%"(B */
	andi	t2, t2, 0xbf
	sb	t2, OFFSET_PPU2000H_OUTPUT + 2(WORK)
	li	t1, 0xff
	sb	t1, OFFSET_STRIKEF_LINE(WORK)
	
	li	t1, -22
	sh	t1, OFFSET_LINECNT(WORK)
	lw	t0, OFFSET_EMUFRAME(WORK)
	addiu	t0, t0, 1
	sw	t0, OFFSET_EMUFRAME(WORK)

#if 0
/* debug */
	lw	a1, OFFSET_EMUFRAME(WORK)
	PRINTF("emuframe=%x\n");
#endif

/* draw list $B$N(B next line $B%Q%i%a%?$r%;%C%H$9$k!#(B
 * $B$3$l$O!"!VF1$8(B draw BG bank$B!W$,(B $B$"$H2?(B line $B8e$K8=$l$k$+$r(B
 * $B;XDj$9$k$b$N$G!"$J$1$l$P(B 0 $B$N$^$^!#(B
 * t0: draw BG bank master
 * t1:              work
 * t2: draw list offset top (-240,-239,-238, ..., 1)*8
 * t3: draw list offset work
 * t4: process count (240,239,...,0)
 * t5: gfxptr
 * t6: t5+t2 or t5+t3
 * Sunsoft 4 $B$J$i(B $BL5;k!#(B
 */
	lbu	t2, OFFSET_SUN4(WORK)
	lw	t5, OFFSET_GFXPTR(WORK)
	bne	t2, zero, set_draw_next_loop_done
#define DRAW_LIST_LOOP_BEGIN (240)*8
	li	t2, -(DRAW_LIST_LOOP_BEGIN)
	li	t4, 240
set_draw_next_loop_1:
	addu	t6, t5, t2
	lbu	t0, OFFSET_GFXBUF_DRAW_LIST + OFFSET_GFX_DRAW_BG_BANK + DRAW_LIST_LOOP_BEGIN(t6)
	addiu	t2, t2, 8
	move	t3, t2
set_draw_next_loop_2:
	addu	t6, t5, t3
	lbu	t1, OFFSET_GFXBUF_DRAW_LIST + OFFSET_GFX_DRAW_BG_BANK + DRAW_LIST_LOOP_BEGIN(t6)
	addiu	t3, t3, 8
	bgtz	t3, 2f

	bne	t1, t0, set_draw_next_loop_2
	j	1f
2:
/* $B$3$N(B draw BG bank $B$r;H$&(B line $B$O(B $B8e$K$O$J$+$C$?!#(B*/
	addiu	t4, t4, -1
	bne	t4, zero, set_draw_next_loop_1
	j	set_draw_next_loop_done
1:
	subu	t1, t3, t2
	srl	t1, t1, 3
/* $B$3$l$G(B $B2?%i%$%s8e$K(B $BF1$8(B draw BG bank $B$r;H$C$F$$$k$+$,=P$?!#(B
 * t2 $B$O$9$G$K(B +8 $B$5$l$F$$$k$N$G(B sb $B$N%*%U%;%C%H$GD4@@0!#(B
 */
	addu	t6, t5, t2
	sb	t1, OFFSET_GFXBUF_DRAW_LIST + OFFSET_GFX_NEXT_LINE + DRAW_LIST_LOOP_BEGIN - 8(t6)
	addiu	t4, t4, -1
	bne	t4, zero, set_draw_next_loop_1
set_draw_next_loop_done:
	
	
/* $B<!$O(B emu_line0 $B$+$i!#(B*/
	la	a2, emu_line0
	j	emuframe_done

/* fetch opcode
 * address < 0x6000 $B$J$i(B load $B4X?t!#(B
 */
	GLOBAL(mainloop_srlt0)
mainloop_srlt0:
	srl	t0, PC, 13
	
	GLOBAL(mainloop)
mainloop:
	sll	t1, t0, 2
	addu	PAGE_PTR, t1, WORK
	sltiu	t2, t0, 0x6000 >> 13
	beq	t2, zero, 1f
/* address < 0x6000 */
	lw	t0, OFFSET_LOADFUNC_TBL(PAGE_PTR)
	la	ra, 2f
	move	a0, PC
	jr	t0
1:
/* address >= 6000 */
	lw	t0, OFFSET_PAGE_TABLE(PAGE_PTR)
/* $B$I$C$A$_$A(B delay slot $B$J$N$G(B ... */
	andi	PC, PC, 0xffff
	addu	t3, t0, PC
	lbu	v0, 0(t3)
2:
	sll	t0, v0, 4
	addu	JUMPTBLP, t0, WORK
/* func1 $B$H(B nbytes, cycles $B$NFI$_=P$7(B */
	lw	t4, OFFSET_JUMPTBL + 0(JUMPTBLP)
	lbu	t5, OFFSET_JUMPTBL + 0xc(JUMPTBLP) /* nbytes */
	lhu	t6, OFFSET_JUMPTBL + 0xe(JUMPTBLP) /* cycles */

#if 0
#ifdef KS_HISTORY
/* debug history, $B%G%P%C%0(B debug PC history $B$3$N%V%m%C%/$O(B reorder $B$5$;$J$$(B */
1:
	lbu	v1, OFFSET_PC_HIST_OFFSET(WORK)
	li	a2, OFFSET_PC_HIST_BUF
	addu	a2, a2, v1
	addiu	v1, v1, 2
	sb	v1, OFFSET_PC_HIST_OFFSET(WORK)
	addu	a2, a2, WORK
	sh	PC, 0(a2)
1:
#endif
#endif

#if 0
/* debug */
	lw	a1, OFFSET_WRAM + 0x700(WORK)
	PRINTF("%08x\n");
#endif

#if 0
#ifdef KS_TRACE
/* debug trace
 * v0: opcode, t4: funcptr, t5: nbytes, t6: cycles
 * t3: opcode pointer (PC >= 0x6000 $B$N$H$-$N$_(B)
 * NV1BDIZC AXY=00 00 00  SP=1xx  00:0000 00 0000  lda #c000
 * CONT_R = 0x0010, CONT_L = 0x0020
 */

#if 0
/* exbike_.nes line 30-100 $B$r(B trace */
	lw	t0, OFFSET_EMUFRAME(WORK)
	sltiu	t1, t0, 600
	bne	t1, zero, 99f
	lh	t0, OFFSET_LINECNT(WORK)
	slti	t1, t0, 30
	bne	t1, zero, 99f
	slti	t1, t0, 100
	beq	t1, zero, 99f
#endif

#if 0
/* zelda.nes $B$G5/F0$;$:!#(Baudio routine $B$GK=Av$9$k!#(B
 * $B$*$=$i$/(B RSP $B$,(B audio $B$N%o!<%/$+%3!<%I$rGK2u$7$F$$$k$N$@@!#(B
 * $B4F;k!#(B
 */
	la	t0, debug_ptr
	lw	t1, 0(t0)
	lw	t0, 0(t1)
	tge	t0,zero
	lw	t0, OFFSET_TRACE_FLAG(WORK)
	beq	t0, zero, 99f
#endif

#if 0
/* zelda.nes $B$G5/F0$7$J$+$C$?$N$H!";w$?>I>u!#(B
 * $B:#2s(B($BF0J*$N?9BP1~$NESCf(B)$B!"(Bchrram $B$8$c$J$$$N$K(B cluclu.nes $B$GK=Av$9$k!#(B
 * EmuSound_Start(u8 *noise); $B$N(B $B0z?t(B a0 $B$,$$$D$N$^$K$+GK2u$5$l$F$$$k!#(B
 * ... $B:#2s$O!"(BEmuSound_Start() $B$rFs=E8F$S$7$F$$$?$N$,860x$@@$C$?!#(B
 */
	li	t0, 0x800397e8
	lw	t1, 0(t0)
	tne	zero, zero
	b	99f
#endif

#if 0
	lw	t0, OFFSET_TRACE_FLAG(WORK)
	bne	t0, zero, 90f
	xori	t0, PC, 0xe887
	bne	t0, zero, 99f
	sw	PC, OFFSET_TRACE_FLAG(WORK)
#endif
#if 0
/* smario3.nes check */

	addiu	t0, PC, 0x10000 - 0xd5e3
	srl	t1, t0, 16
	bne	t1, zero, 10f
	addiu	t0, t0, 0x50
	srl	t1, t0, 16
	bne	t1, zero, 90f

10:
	addiu	t0, WORK, OFFSET_WRAM + 0x270
	lbu	t1, 0(t0)
	andi	t1, t1, 0xc0
	beq	t1, zero, 10f

	addiu	t0, t0, 8
	lbu	t1, 0(t0)
	andi	t1, t1, 0xc0
	beq	t1, zero, 10f
	
	addiu	t0, t0, 8
	lbu	t1, 0(t0)
	andi	t1, t1, 0xc0
	beq	t1, zero, 10f
	
	addiu	t0, t0, 8
	lbu	t1, 0(t0)
	andi	t1, t1, 0xc0
	bne	t1, zero, 99f
10:
	lbu	t1, 1(t0)
	xori	t1, t1, 0x51
	bne	t1, zero, 99f
	

	TRAP("?");
#endif

#if 0
/* mario94.nes check */
	addiu	t0, PC, 0x8000
	sltiu	t1, t0, 0x8b9f - 0x8000
	bne	t1, zero, 99f
	sltiu	t1, t0, 0x8bde - 0x8000
	beq	t1, zero, 99f
#endif
	
90:
	li	a1, 0x4e /* 'N' */
	li	a2, 0x56 /* 'V' */
	li	a3, 0x31 /* '1' */
	andi	t0, N, 0x80
	bne	t0, zero, 1f
	li	a1, 0x2d /* '-' */
1:
	bne	V, zero, 1f
	li	a2, 0x2d /* '-' */
1:
	lbu	t1, OFFSET_WORK_RBDI(WORK)
	andi	t0, t1, 0x20
	bne	t0, zero, 1f
	li	a3, 0x2d /* '-' */
1:
	PRINTF("%c%c%c");

	li	a1, 0x42 /* 'B' */
	li	a2, 0x44 /* 'D' */
	li	a3, 0x49 /* 'I' */
	andi	t0, t1, 0x10
	bne	t0, zero, 1f
	li	a1, 0x2d /* '-' */
1:
	andi	t0, t1, 0x08
	bne	t0, zero, 1f
	li	a2, 0x2d /* '-' */
1:
	andi	t0, t1, 0x04
	bne	t0, zero, 1f
	li	a3, 0x2d /* '-' */
1:
	PRINTF("%c%c%c");

	li	a1, 0x5a /* 'Z' */
	li	a2, 0x43 /* 'C' */
	move	a3, A
	andi	t0, Z, 0xff
	beq	t0, zero, 1f
	li	a1, 0x2d /* '-' */
1:
	bne	C, zero, 1f
	li	a2, 0x2d /* '-' */
1:
	PRINTF("%c%c AXY=%02x ");

	move	a1, X
	move	a2, Y
	move	a3, SP
	PRINTF("%02x %02x  SP=1%02x  ");

	li	a1, 0
	move	a2, PC
	move	a3, v0
	PRINTF("%02x:%04x %02x ");

/* 2byte $BL\0J9_$NI=<($O(B address >= 0x6000 $B$G$J$$$H(B $B4V0c$$!#(B*/
	sltiu	t0, PC, 0x6000
	bne	t0, zero, 4f
6:
	addiu	t0, t5, -2
	bgtz	t0, 3f
	beq	t0, zero, 2f
	PRINTF("      ");
	li	a1, 0
	j	1f
4:
	sltiu	t0, PC, 0x2000
	beq	t0, zero, 5f
	andi	t3, PC, 0x7ff
#if OFFSET_WRAM
	addiu	t3, t3, OFFSET_WRAM
#endif
	addu	t3, t3, WORK
	j	6b	
5:
	PRINTF("????  ");
	li	a1, 0
	j	1f
2:
	lbu	a1, 1(t3)
	PRINTF("%02x    ");
	j	1f
3:
	lbu	a1, 1(t3)
	lbu	a2, 2(t3)
	PRINTF("%02x%02x  ");
	sll	a2, a2, 8
	or	a1, a1, a2
1:
	la	t0, static_debug_insttbl_ptr
	sll	t1, v0, 2
	addu	t0, t0, t1
	lw	a0, 0(t0)
/* $B$3$3$O(B PRINTF $B%^%/%m$O;H$($J$$!#(B*/
	sw	ra, OFFSET_STACK_RA_PRINTF(sp)
	jal	save_ossync_restore

	lw	a1, OFFSET_EMUFRAME(WORK)
	lh	a2, OFFSET_LINECNT(WORK)
	sra	a3, LINECYCLE, 8
	PRINTF("(%d:%03d.%+03d");
	
/* in H-blank ? */
	andi	t0, LINECYCLE, 0x01
	li	a1, 0x48 /* 'H' */
	bne	t0, zero, 1f
	li	a1, 0x5f /* '-' */
1:
	PRINTF("%c)\n");	
	
99:
	
#endif /* KS_TRACE */
#endif

	addu	LINECYCLE, LINECYCLE, t6
	addu	PC, PC, t5
#if 0
/* debug */
	teq	t5, 0x24
	teq	t4, zero
#endif

#if 0
#ifdef KS_DEBUG_VERBOSE
/* debug profile
 * $B;H$C$?$3$H$,$"$kL?Na$KBP1~$9$k(B jumptbl $B$K(B 0 $B$r!#(B
 */
	sb	zero, OFFSET_JUMPTBL + 0xd(JUMPTBLP)
#endif
#endif
	
	jalr	STORE_DONE, t4
	
	GLOBAL(next)
next:
	srl	t0, PC, 13
	bltz	LINECYCLE, mainloop

/* LINECYCLE $B$N(B d0=1 $B$J$i(B H-blank $B=*N;(B
 * set draw param
 */
	andi	t0, LINECYCLE, 0x01
	xor	LINECYCLE, LINECYCLE, t0
	beq	t0, zero, line_end
/* H-blank $B=*N;(B
 * linecnt < 0 $B$J$i(B draw param, H-line $B3d$j9~$_$O$J$7!#(B
 * line 240 $B$N(B H-blank $B=*N;$J$i(B draw param $B$O$J$7!#(B linecnt = -22; H-line $B3d$j9~$_%A%'%C%/$@@$1!#(B
 */
	addiu	LINECYCLE, LINECYCLE, LINECYCLE_CONST1

	lh	t4, OFFSET_LINECNT(WORK)
	addiu	t3, t4, -239

	bltz	t4, vblank    /* linecnt < 0 */

/* H-line $B3d$j9~$_%A%'%C%/(B $B$O(B $B$3$3$G$O$d$i$J$$!#(B*/

#if 0
	lbu	t0, OFFSET_STRIKEF_LINE(WORK)
	bgtz	t3, line_240_done

/* strikef */
	lbu	t1, OFFSET_PPU2000H_OUTPUT + 2(WORK)
	bne	t0, t4, 1f
	ori	t1, t1, 0x40
	sb	t1, OFFSET_PPU2000H_OUTPUT + 2(WORK)
1:
#endif
	lbu	t0, OFFSET_OAM + 0(WORK)
	bgtz	t3, line_240_done
#if 0
/* debug */
	lw	a0, OFFSET_EMUFRAME(WORK)
	sltiu	a0, a0, 420
	bne	a0, zero, 1f
	move	a1, t0
	move	a2, t4
	PRINTF("check strikef %x,%x\n");
1:
#endif
/* obj 0 $B$N(B ypos $B$H(B linecnt $B$,Ey$7$/$J$C$?$i(B strikef check
 * $B:#$N(B obj chr bank $B$r3d$j=P$7!"(Blinecnt + 1 + n $B$,(B strikef_line $B$K$J$k!#(B
 * t3: strikef_line ($B2<$GMxMQ(B)
 */
	lbu	t3, OFFSET_STRIKEF_LINE(WORK)
	bne	t0, t4, 4f
#if 0
/* debug */
	move	a1, t3
	PRINTF("strikef_line");
#endif
	lbu	$1, OFFSET_MMC3_POINTER(WORK)
	lbu	t3, OFFSET_OAM + 1(WORK)
	andi	$1, $1, 0x80
	srl	$1, $1, 4  /* 0x80 -> 0x08 */
	lbu	t1, OFFSET_PPU2000H(WORK)
	andi	t2, t1, 0x20
	xor	t1, t1, $1
	beq	t2, zero, 20f  /* OBJ 8x8 */
/* 8x16 $B$J$i(B OBJ seg $B$N(B xor $B$rLa$9!#(B
 * chr code & 0x01 $B$K$h$C$F(B 0 or 0x08
 * chr code &= 0xfe;
 */
	xor	t1, t1, $1
	andi	$1, t3, 0x01
	sll	$1, $1, 3    /* 0x01 -> 0x08 */
	xor	t1, t1, $1
	andi	t3, t3, 0xfe
	li	t2, 1
20:
/* 8x8 $B$J$i(B t2 = 0, 8x16 $B$J$i(B t2 = 1 */
	move	$1, t2
	andi	t1, t1, 0x08
	addu	t1, t1, WORK
	andi	t2, t3, 0xc0
	srl	t2, t2, 5    /* 0xc0 -> 0x06 */
	addu	t1, t1, t2
	lhu	t1, OFFSET_CHRBANK_REG0000(t1)
	lw	t2, OFFSET_CHRROM(WORK)
	andi	t3, t3, 0x3f
	mul	t3, t3, 0x10
	mul	t1, t1, 0x400
	addu	t2, t2, t3
	addu	t2, t2, t1
/* $1: OBJ size $B$K$h$C$F(B 0 or 1
 * t0,t1: work
 * t2: chr data src ptr
 * t3: sub loop counter
 * t4: keep
 * a0: work
 */
	li	t3, 0
2:
	lbu	t0, 0(t2)
	lbu	t1, 8(t2)
	addiu	t3, t3, 1
	sltiu	a0, t3, 0x07
	or	t0, t0, t1
	bne	t0, zero, 8f
	addiu	t2, t2, 1
	bne	a0, zero, 2b
	addiu	t2, t2, 8
	addiu	$1, $1, -1
	beq	$1, zero, 2b
/* $BF)L@@(B OBJ ?
 */
	addiu	t3, t4, 1
	j	5f
8:
/* linecnt + t3 $B$,!"(Bstrikef_linecnt $B$K$J$k!#(B*/
	addu	t3, t3, t4
5:
	sb	t3, OFFSET_STRIKEF_LINE(WORK)
#if 0
/* debug */
	move	a1, t3
	PRINTF("=%x\n");
#endif
4:
/* t3: strikef_line $B$G$"$k$3$H!#(B*/
	lbu	t1, OFFSET_PPU2000H_OUTPUT + 2(WORK)
	bne	t3, t4, 1f
	ori	t1, t1, 0x40
	
/* debug
 * itadaki.nes $B%V%lD4@@0(B
 * 0x6 * 0x100 $B$G$O%V%l$k$N$G(B 0x8 * 0x100 $B$K$7$?(B
 * twinbee3.nes $B$,%V%l$k(B ... 0x2 * 0x100 $B$J$i(B $B$3$C$A$O(B OK $B$J$s$@@$1$I!#(B
 */
#if 1
	addiu	LINECYCLE, LINECYCLE, 0x8 * 0x100
#endif
	
#if 0
/* debug */
	lw	t0, test_data
	addu	LINECYCLE, LINECYCLE, t0
#endif
	sb	t1, OFFSET_PPU2000H_OUTPUT + 2(WORK)
1:

/* draw param $B@@_Dj(B */
	sll	t4, t4, 3
	lw	t3, OFFSET_GFXPTR(WORK)
	addu	t4, t4, t3
/* PPU 2000H, 2001H $B$O$^$H$a$F=hM}!#(B
 * NEXT_LINE ($B=i4|CM(B 0) $B$H(B DRAW_SCCH $B$b$^$H$a$F!#(B
 * t4: gfxptr + linecnt * 8
 */
	lhu	t0, OFFSET_PPU2000H(WORK)
	lbu	t2, OFFSET_DRAW_SCCH(WORK)
	sh	t0, OFFSET_GFX_DRAW_2000H(t4)
	sh	t2, OFFSET_GFX_NEXT_LINE(t4)
/* t0: PPU 2000H, 2001H
 * debug: $BIT==J,!#(B
 * draw vram addr $B$O(B | wrap | 0 | vram page | addr4-0 |
 * addr4-0 $B$O(B * 0x20 $B$9$k$N$G(B vram [0x2000-0x23e0] $B$KAjEv!#(B
 * page $B$O(B * 0x400, wrap $B$O(B 1 $B$J$i(B ^ 0x400 $B$9$k!#(B
 * mirror mask and & 0x400 $B$J$i(B wrap = 1
 */
	lhu	t1, OFFSET_DRAW_SCCV(WORK)
	lhu	t2, OFFSET_VRAM_MIRROR_MASK_AND(WORK)
	lhu	t3, OFFSET_VRAM_MIRROR_MASK_OR(WORK)
	sll	t5, t1, 2
	and	t5, t5, t2
	or	t5, t5, t3
/* 0x800 or 0x400 -> 0x400 */
	srl	$1, t5, 1
	or	t5, t5, $1
	andi	t5, t5, 0x400
	srl	t5, t5, 5     /* 0x400 -> 0x20 */
	
	andi	$1, t2, 0x400
	srl	$1, $1, 3     /* 0x400 -> 0x80 */
	or	t5, t5, $1

	srl	t2, t1, 3     /* 0x3ff -> 0x7f */
	andi	t2, t2, 0x1f
	or	t5, t5, t2
	sb	t5, OFFSET_GFX_DRAW_VRAM_ADDR(t4)
#if 0
/* debug */
	lw	t5, OFFSET_EMUFRAME(WORK)
	sltiu	t5, t5, 300
	bne	t5, zero, 1f
	move	a1, t1
	lhu	a2, OFFSET_VRAM_MIRROR_MASK_AND(WORK)
	PRINTF("%x,%x\n");
1:
#endif
	
#if 0
/* debug */
	andi	t5, t5, 0x80
	tne	t5, zero
#endif
	andi	a1, t1, 0x07
	lw	t2, OFFSET_CHRBANK_FUNCP(WORK)
#if 0
	sb	a1, OFFSET_GFX_DRAW_BG_BANK(t4)
#endif
	
/* draw sccv $B$O(B 0x000-0x0ef, 0x200-0x2ef, 0x000-...
 *           or 0x100-0x1ef, 0x300-0x3ef, 0x100-...
 * $B$?$@@$7(B 0xff->0x100 $B$X$N7+$j>e$,$j$O(B $B$J$$!#(B(challeng.nes)
 */
	andi	$1, t1, 0x300
	addiu	t1, t1, 1
	andi	t1, t1, 0xff
	xori	t3, t1, 0xf0
	bne	t3, zero, 1f
	xori	$1, $1, 0x200
	li	t1, 0
#if 0
/* debug */
	PRINTF("xxxx\n");
#endif
1:
	or	t1, t1, $1
#if 0
/* debug */
	move	a2, a1
	lhu	t0, OFFSET_SERIAL4016D0(WORK)
	andi	t0, t0, 0x0010
	beq	t0, zero, 1f
	move	a1, t1
	PRINTF("SCCV=%x\n");
	move	a1, a2
1:
#endif
	sh	t1, OFFSET_DRAW_SCCV(WORK)

/* a1 $B$K(B draw_sccv & 7, t4 $B$K(B gfxptr, t2 $B$K(B funcp
 * t0 = 0xff
 * t5 $B$K(B bg_chrbank_touch_flag
 * chrbank $B@@_Dj4X?t$X!#(B
 * $B=*$o$C$?$i(B mainloop_srlt0 $B$X!#(B
 */
	lbu	t5, OFFSET_BG_CHRBANK_TOUCH_FLAG(WORK)
	li	t0, 0xff
	jr	t2

/* chrbank functions
 */
	GLOBAL(chrbank_func_normal)
chrbank_func_normal:
/* $B%N!<%^%k(B NES
 * BG chr bank $B$OJQ$o$C$?$+(B ?
 * chrbank $B@@Z$jBX$($O$J$$$N$G(B PPU 2000H d4=0 $B$J$i(B bg bank index=0 $B$H$9$k!#(B
 * $B$h$C$F(B $B:G9b@@Z$jBX$(?t%A%'%C%/$bL5;k!#(B
 */
	lbu	t3, OFFSET_BG_CHRBANK_CHANGE_COUNT(WORK)
	lbu	t1, OFFSET_PPU2000H(WORK)
	bne	t5, zero, 10f
	sb	t0, OFFSET_BG_CHRBANK_TOUCH_FLAG(WORK)
/*	sltiu	t2, t3, BG_BANK_CHANGE_COUNT_MAX * 8 */
/*	beq	t2, zero, 10f */
/*	addiu	t3, t3, 8 */
/*	sb	t3, OFFSET_BG_CHRBANK_CHANGE_COUNT(WORK) */

	andi	t2, t1, 0x10   /* BG chr seg */
	srl	t3, t2, 1      /* 0x10 -> 0x08 */
	sb	t3, OFFSET_BG_CHRBANK_CHANGE_COUNT(WORK)

/* bg chr bank table $B$b%;%C%H$9$k!#(B*/
	lw	t0, OFFSET_GFXPTR(WORK)
	addu	t0, t0, t3
	
	srl	t2, t2, 2      /* 0x10 -> 0x04 */
	sh	t2, OFFSET_GFXBUF_BG_CHRBANK_TBL + 0(t0)
	addiu	t2, t2, 1
	sh	t2, OFFSET_GFXBUF_BG_CHRBANK_TBL + 2(t0)
	addiu	t2, t2, 1
	sh	t2, OFFSET_GFXBUF_BG_CHRBANK_TBL + 4(t0)
	addiu	t2, t2, 1
	sh	t2, OFFSET_GFXBUF_BG_CHRBANK_TBL + 6(t0)
10:
	or	t3, t3, a1
	sb	t3, OFFSET_GFX_DRAW_BG_BANK(t4)

/* OBJ chr bank $B$OJQ$o$C$?$+(B ?
 * t1: PPU 2000H
 */
	li	t0, 0xff
/*	lbu	t2, OFFSET_OBJ_CHRBANK_CHANGE_COUNT(WORK) */
	lbu	t5, OFFSET_OBJ_CHRBANK_TOUCH_FLAG(WORK)
	bne	t5, zero, 20f
	sb	t0, OFFSET_OBJ_CHRBANK_TOUCH_FLAG(WORK)

#if 0
/* obj chr bank index $B8GDj3d$jEv$F$J$N$G(B $B$3$3$G(B OBJ chr seg $B$r8+$k$3$H$O$J$$(B */
	andi	t3, t1, 0x08  /* OBJ chr seg */
	sll	t2, t3, 1     /* 0x08 -> 0x10 */
	sb	t2, OFFSET_OBJ_CHRBANK_CHANGE_COUNT(WORK)
#endif

/* obj chr bank table $B$r%;%C%H$9$k(B */
	lw	t0, OFFSET_GFXPTR(WORK)
	li	t3, 0
	sh	t3, OFFSET_GFXBUF_OBJ_CHRBANK_TBL + 0x0(t0)
	addiu	t3, t3, 1
	sh	t3, OFFSET_GFXBUF_OBJ_CHRBANK_TBL + 0x2(t0)
	addiu	t3, t3, 1
	sh	t3, OFFSET_GFXBUF_OBJ_CHRBANK_TBL + 0x4(t0)
	addiu	t3, t3, 1
	sh	t3, OFFSET_GFXBUF_OBJ_CHRBANK_TBL + 0x6(t0)
	addiu	t3, t3, 1
	sh	t3, OFFSET_GFXBUF_OBJ_CHRBANK_TBL + 0x8(t0)
	addiu	t3, t3, 1
	sh	t3, OFFSET_GFXBUF_OBJ_CHRBANK_TBL + 0xa(t0)
	addiu	t3, t3, 1
	sh	t3, OFFSET_GFXBUF_OBJ_CHRBANK_TBL + 0xc(t0)
	addiu	t3, t3, 1
	sh	t3, OFFSET_GFXBUF_OBJ_CHRBANK_TBL + 0xe(t0)

20:
/* obj bank table entry $B$O(B 0x00 $B8GDj!#(B*/
	sb	zero, OFFSET_GFX_DRAW_OBJ_BANK(t4)

#if 0
/* debug */
	lw	a1, OFFSET_GFXPTR(WORK)
	subu	a1, t4, a1
	srl	a1, a1, 3
	PRINTF("line %x set done\n");
#endif
	j	mainloop_srlt0

	GLOBAL(chrbank_func03)
chrbank_func03:
/* CHR128/256
 * bank index $B$O8GDj3d$jEv$F!#(B
 * mapper 0x56 (moepro) $B$G$b;HMQ!#(B
 */
	lbu	t3, OFFSET_BG_CHRBANK_CHANGE_COUNT(WORK)
	lbu	t1, OFFSET_PPU2000H(WORK)
	bne	t5, zero, 10f
	sb	t0, OFFSET_BG_CHRBANK_TOUCH_FLAG(WORK)
/* chrbank change count $B$OKh%U%l!<%`(B 0 $B$K=i4|2=$5$l$k$N$G;H$($J$$!#(B*/
	lhu	t3, OFFSET_CHRBANK_REG0000(WORK)
	sll	t3, t3, 1     /* 0x00/0x08/0x10/0x18 * 2 */
	
	andi	t2, t1, 0x10  /* BG chr seg */
	srl	t2, t2, 1     /* 0x10 -> 0x08 */
#if 0
/* debug */
	beq	t3, zero, 1f
	move a1,t3
	PRINTF("03_bg chrbank=%x\n");
1:
#endif
	or	t3, t3, t2
	sb	t3, OFFSET_BG_CHRBANK_CHANGE_COUNT(WORK)
/* bg chr bank table $B$N%;%C%H(B */
	lw	t0, OFFSET_GFXPTR(WORK)
	addu	t0, t0, t3
	srl	t2, t3, 1     /* 0x08 -> 0x04 */
	sh	t2, OFFSET_GFXBUF_BG_CHRBANK_TBL + 0(t0)
	addiu	t2, t2, 1
	sh	t2, OFFSET_GFXBUF_BG_CHRBANK_TBL + 2(t0)
	addiu	t2, t2, 1
	sh	t2, OFFSET_GFXBUF_BG_CHRBANK_TBL + 4(t0)
	addiu	t2, t2, 1
	sh	t2, OFFSET_GFXBUF_BG_CHRBANK_TBL + 6(t0)
10:
	or	t3, t3, a1
#if 0
/* debug */
	lh	t0, OFFSET_LINECNT(WORK)
	bne	t0, zero, 1f
	move	a1, t3
	PRINTF("03_bg chrbank=%x\n");
1:
#endif
	sb	t3, OFFSET_GFX_DRAW_BG_BANK(t4)

/* OBJ chr bank $B$OJQ$o$C$?$+(B ?
 * t1: PPU 2000H
 */
	li	t0, 0xff
	lbu	t2, OFFSET_OBJ_CHRBANK_CHANGE_COUNT(WORK)
	lbu	t5, OFFSET_OBJ_CHRBANK_TOUCH_FLAG(WORK)
	bne	t5, zero, 20f
	sb	t0, OFFSET_OBJ_CHRBANK_TOUCH_FLAG(WORK)

/* chrbank change count $B$OKh%U%l!<%`(B 0 $B$K=i4|2=$5$l$k$N$G;H$($J$$!#(B
 * obj chr bank index $B8GDj3d$jEv$F$J$N$G(B $B$3$3$G(B OBJ chr seg $B$r8+$k$3$H$O$J$$(B
 */
	lhu	t2, OFFSET_CHRBANK_REG0000(WORK)
	sll	t2, t2, 1
	sb	t2, OFFSET_OBJ_CHRBANK_CHANGE_COUNT(WORK)
/* obj chr bank table $B$r%;%C%H$9$k(B
 * 0x00/0x08/0x10/0x18 -> $B$=$N$^$^(B
 */
#if 0
/* debug */
	move	a1, t2
	PRINTF("03_obj chrbank=%x\n");
#endif
	lw	t0, OFFSET_GFXPTR(WORK)
	addu	t0, t0, t2
	srl	t3, t2, 1
	sh	t3, OFFSET_GFXBUF_OBJ_CHRBANK_TBL + 0x0(t0)
	addiu	t3, t3, 1
	sh	t3, OFFSET_GFXBUF_OBJ_CHRBANK_TBL + 0x2(t0)
	addiu	t3, t3, 1
	sh	t3, OFFSET_GFXBUF_OBJ_CHRBANK_TBL + 0x4(t0)
	addiu	t3, t3, 1
	sh	t3, OFFSET_GFXBUF_OBJ_CHRBANK_TBL + 0x6(t0)
	addiu	t3, t3, 1
	sh	t3, OFFSET_GFXBUF_OBJ_CHRBANK_TBL + 0x8(t0)
	addiu	t3, t3, 1
	sh	t3, OFFSET_GFXBUF_OBJ_CHRBANK_TBL + 0xa(t0)
	addiu	t3, t3, 1
	sh	t3, OFFSET_GFXBUF_OBJ_CHRBANK_TBL + 0xc(t0)
	addiu	t3, t3, 1
	sh	t3, OFFSET_GFXBUF_OBJ_CHRBANK_TBL + 0xe(t0)
20:
	sb	t2, OFFSET_GFX_DRAW_OBJ_BANK(t4)
	j	mainloop_srlt0

	GLOBAL(chrbank_func04)
chrbank_func04:
/* MMC3
 * $1: pointer $B$N(B chr seg
 */
	lbu	$1, OFFSET_MMC3_POINTER(WORK)
	andi	$1, $1, 0x80
	lbu	t3, OFFSET_DRAW_BG_CHRBANK_COUNT(WORK)
	lbu	t1, OFFSET_PPU2000H(WORK)
	bne	t5, zero, 10f

	sb	t0, OFFSET_BG_CHRBANK_TOUCH_FLAG(WORK)
	srl	t0, $1, 3  /* 0x80 -> 0x10 */
	xor	t0, t0, t1
	andi	t0, t0, 0x10
/* t0 $B$,(B 0 $B$J$i(B chr bank for 0000-,
 *       1 $B$J$i(B chr bank for 1000-, $B$+$i!#(B
 */
	srl	t0, t0, 1
	addu	t0, t0, WORK
	lw	a0, OFFSET_CHRBANK_REG0000(t0)
	lw	t6, OFFSET_CHRBANK_REG0800(t0)
	lw	t0, OFFSET_GFXPTR(WORK)
	li	t3, 0
	lbu	t2, OFFSET_BG_CHRBANK_CHANGE_COUNT(WORK)
/* a0/t6 $B$HF1$8CM$,$9$G$K$"$l$P!"$=$l!#(B
 * a2/a3: $BHf3SBP>](B
 * t3: draw chrbank count
 * t2: chrbank change count. 0 $B$J$i:G=i$J$N$GL5>r7oEPO?!"0c$($P(B t3 $B$,$3$NCM$K$J$kD>A0$^$G%k!<%W(B
 * t0: gfxptr
 */
1:
	addu	t5, t0, t3
	beq	t2, t3, 2f  /* $BF1$8$b$N$O$J$+$C$?(B */
	lw	a2, OFFSET_GFXBUF_BG_CHRBANK_TBL + 0(t5)
	lw	a3, OFFSET_GFXBUF_BG_CHRBANK_TBL + 4(t5)

	xor	a2, a2, a0
	xor	a3, a3, t6
	or	a2, a2, a3
	beq	a2, zero, 3f  /* $BF1$8(B */
	
	sltiu	t5, t3, (BG_BANK_CHANGE_COUNT_MAX - 1) * 8
	addiu	t3, t3, 8
	bne	t5, zero, 1b
	addiu	t3, t3, -8
	j	3f  /* $B@@Z$jBX$(2s?t%*!<%P!<(B */
2:
/*	addu	t5, t0, t3 $B$$$i$s$h$J(B? */
	sw	a0, OFFSET_GFXBUF_BG_CHRBANK_TBL + 0(t5)
	sw	t6, OFFSET_GFXBUF_BG_CHRBANK_TBL + 4(t5)
	addiu	t2, t3, 8
	sb	t2, OFFSET_BG_CHRBANK_CHANGE_COUNT(WORK)
3:
	sb	t3, OFFSET_DRAW_BG_CHRBANK_COUNT(WORK)
	
10:
	or	t3, t3, a1
	sb	t3, OFFSET_GFX_DRAW_BG_BANK(t4)

/* OBJ chr bank $B$OJQ$o$C$?$+(B ?
 * t1: PPU 2000H
 */
	li	t0, 0xff
	lbu	t5, OFFSET_OBJ_CHRBANK_TOUCH_FLAG(WORK)
	lbu	t3, OFFSET_DRAW_OBJ_CHRBANK_COUNT(WORK)
	bne	t5, zero, 20f
	sb	t0, OFFSET_OBJ_CHRBANK_TOUCH_FLAG(WORK)
/* pointer $B$N(B chr seg $B$,(B 0 $B$N$H$-$O(B chr bank for 0000-, ..., 1000-, $B$G!"(B
 *                       1                       1000-, ..., 0000-, $B$r!#(B
 */
	srl	$1, $1, 4  /* 0x80 -> 0x08 */
	li	t3, 0
	lbu	t2, OFFSET_OBJ_CHRBANK_CHANGE_COUNT(WORK)
	lw	t0, OFFSET_GFXPTR(WORK)
/* {+0,+2,+4,...,+e} $B$N(B bank $B$NAH$O(B $B$9$G$K$"$k$b$N$+(B ?
 * $1: $BHf3S(B src offset (0 or 8)
 * t3: draw chrbank count (0x10 bytes $BC10L(B)
 * t2: chrbank change count. $B:G=i$J$i(B 0 $B$J$N$GL5>r7oEPO?!#(B
 *     $B0c$($P(B t3 $B$,$3$NCM$K$J$kD>A0$^$G%k!<%W(B
 * t0: gfxptr
 * a0,a2,a3: $BHf3S(B work
 */
1:
	addu	t5, t0, t3
	beq	t2, t3, 2f  /* $BF1$8$b$N$O$J$+$C$?(B */
/* $BHf3S(B src,dst $BFI$_9~$_(B */
	.set	noreorder
	addu	t6, $1, WORK
	lw	a2, OFFSET_CHRBANK_REG0000(t6)
	lw	a3, OFFSET_GFXBUF_OBJ_CHRBANK_TBL + 0(t5)
	xori	a0, $1, 0x08
	bne	a2, a3, 5f
	lw	a2, OFFSET_CHRBANK_REG0800(t6)
	lw	a3, OFFSET_GFXBUF_OBJ_CHRBANK_TBL + 4(t5)
	addu	t6, a0, WORK
	bne	a2, a3, 5f
	lw	a2, OFFSET_CHRBANK_REG0000(t6)
	lw	a3, OFFSET_GFXBUF_OBJ_CHRBANK_TBL + 8(t5)
	lw	a0, OFFSET_CHRBANK_REG0800(t6)
	bne	a2, a3, 5f
	lw	a3, OFFSET_GFXBUF_OBJ_CHRBANK_TBL + 0xc(t5)
	.set	reorder
	beq	a0, a3, 3f  /* $BF1$8(B */
5:
	sltiu	t5, t3, (OBJ_BANK_CHANGE_COUNT_MAX - 1) * 0x10
	addiu	t3, t3, 0x10
	bne	t5, zero, 1b
	addiu	t3, t3, -0x10
	j	3f  /* $B@@Z$jBX$(2s?t%*!<%P!<(B */
2:
	addu	t6, $1, WORK
	lw	a2, OFFSET_CHRBANK_REG0000(t6)
	lw	a3, OFFSET_CHRBANK_REG0800(t6)
	sw	a2, OFFSET_GFXBUF_OBJ_CHRBANK_TBL + 0(t5)
	sw	a3, OFFSET_GFXBUF_OBJ_CHRBANK_TBL + 4(t5)
	
	xori	t6, $1, 0x08
	addu	t6, t6, WORK
	lw	a2, OFFSET_CHRBANK_REG0000(t6)
	lw	a3, OFFSET_CHRBANK_REG0800(t6)
	sw	a2, OFFSET_GFXBUF_OBJ_CHRBANK_TBL + 8(t5)
	sw	a3, OFFSET_GFXBUF_OBJ_CHRBANK_TBL + 0xc(t5)
	
	addiu	t2, t3, 0x10
	sb	t2, OFFSET_OBJ_CHRBANK_CHANGE_COUNT(WORK)
3:
	sb	t3, OFFSET_DRAW_OBJ_CHRBANK_COUNT(WORK)
20:
	sb	t3, OFFSET_GFX_DRAW_OBJ_BANK(t4)
	j	mainloop_srlt0

	GLOBAL(chrbank_func05)
chrbank_func05:
/* MMC5
 * debug preliminary
 */
	lbu	t3, OFFSET_BG_CHRBANK_CHANGE_COUNT(WORK)
	lw	$1, OFFSET_GFXPTR(WORK)
	bne	t5, zero, 10f
	sltiu	t5, t3, BG_BANK_CHANGE_COUNT_MAX * 8
	sb	t0, OFFSET_BG_CHRBANK_TOUCH_FLAG(WORK)
	beq	t5, zero, 10f  /* $B@@Z$jBX$(2s?t%*!<%P!<(B */
	
	lbu	t1, OFFSET_PPU2000H(WORK)
	addiu	t3, t3, 0x08
	sb	t3, OFFSET_BG_CHRBANK_CHANGE_COUNT(WORK)
	addu	t5, t3, $1
	andi	t2, t1, 0x20
	bne	t2, zero, 1f
/* obj 8x8 $B$J$N$G(B pbr0-3 or pbr4-7 $B$r!#(B
 */
	andi	t2, t1, 0x10
	srl	t2, t2, 1    /* 0x10 -> 0x08 */
	addu	t2, t2, WORK
	lw	t1, OFFSET_MMC5_PBR0 + 0(t2)
	lw	t2, OFFSET_MMC5_PBR0 + 4(t2)
	j	2f
1:
/* obj 8x16 mode $B$J$N$G(B pbr4'-pbr7' $B$r(B 2 $B2s!#(B
 */
	lw	t1, OFFSET_MMC5_PBR0 + (8 + 0) * 2(WORK)
	lw	t2, OFFSET_MMC5_PBR0 + (8 + 2) * 2(WORK)
2:
	sw	t1, OFFSET_GFXBUF_BG_CHRBANK_TBL + 0(t5)
	sw	t2, OFFSET_GFXBUF_BG_CHRBANK_TBL + 4(t5)
10:
	or	t2, t3, a1
#if 0
/* debug */
	lhu	a1, OFFSET_LINECNT(WORK)
	move	a2, t3
	PRINTF("05_chrbank_func line=%x, count=%x\n");
#endif
	lbu	t5, OFFSET_OBJ_CHRBANK_TOUCH_FLAG(WORK)
	lbu	t3, OFFSET_OBJ_CHRBANK_CHANGE_COUNT(WORK)
	sb	t2, OFFSET_GFX_DRAW_BG_BANK(t4)
	bne	t5, zero, 20f
	sltiu	t5, t3, OBJ_BANK_CHANGE_COUNT_MAX * 0x10
	sb	t0, OFFSET_OBJ_CHRBANK_TOUCH_FLAG(WORK)
	beq	t5, zero, 20f  /* $B@@Z$jBX$(2s?t%*!<%P!<(B */
	addiu	t3, t3, 0x10
	sb	t3, OFFSET_OBJ_CHRBANK_CHANGE_COUNT(WORK)
	addu	t5, t3, $1
	lw	t0, OFFSET_MMC5_PBR0 + 0(WORK)
	lw	t1, OFFSET_MMC5_PBR0 + 4(WORK)
	lw	t2, OFFSET_MMC5_PBR0 + 8(WORK)
	lw	a3, OFFSET_MMC5_PBR0 + 0xc(WORK)
	sw	t0, OFFSET_GFXBUF_OBJ_CHRBANK_TBL + 0(t5)
	sw	t1, OFFSET_GFXBUF_OBJ_CHRBANK_TBL + 4(t5)
	sw	t2, OFFSET_GFXBUF_OBJ_CHRBANK_TBL + 8(t5)
	sw	a3, OFFSET_GFXBUF_OBJ_CHRBANK_TBL + 0xc(t5)
20:
	sb	t3, OFFSET_GFX_DRAW_OBJ_BANK(t4)
	j	mainloop_srlt0

	GLOBAL(chrbank_func44)
chrbank_func44:
/* Sunsoft4 - VROM
 * VROM $B%b!<%I$J$i(B
 *                 DRAW_VRAM_ADDR |= 0x40 $B$r!"(B
 *                 VROM_R   $B$K(B VROM bank (right) $B$r!"(B
 * VROM bank (left) $B$r(B D7-D0 $B$H$9$k$H(B
 * DRAW 2000H $B$N(B d7=D7, d6=D6,       d2-d0=D5-D3,
 * DRAW 2001H $B$N(B d7-d5=D2-D0
 * $B$K(B pack $B$9$k!#(B
 * NEXT_LINE $B$r;H$*$&$H;W$C$?$1$I$&$^$/9T$+$J$$!#K=Av$9$k(B...
 * t4: gfxptr
 * t5: keep
 * a1: keep
 * t0: keep
 * $B8e$O(B chrbank_func04 $B$KG$$;$k!#(B
 */
	lbu	$1, OFFSET_SUN4_VROM_ENABLED(WORK)
	lbu	t1, OFFSET_GFX_DRAW_VRAM_ADDR(t4)
	beq	$1, zero, chrbank_func04
	lhu	a0, OFFSET_GFX_DRAW_2000H(t4)
/* t1: draw vram addr
 * t1 & 0x20 $B$,!"(B0 $B$J$i(B left $B$K$O(B vrom0 $B$r!#(B
 *               0x20 $B$J$i(B        vrom1 $B$r!#(B
 * a2: left index (0 or 1)
 * t1 & 0x80 $B$,(B 0 $B$J$i(B right $B$K$O(B left $B$HF1$8$b$N$r!#(B
 *              0x80 $B$J$i(B         left $B$H0c$&$b$N$r!#(B
 * a3: right index (0 or 1)
 * t1 | 0x40 $B$7$F$*$/!#(B
 * $B$J$s$+!"(Baftrbrn2.nes $B$N(B chrrom (0x40000 bytes) $B$N!"(B
 * $B8eH>(B 0x20000 bytes $B$N;2>H$K$J$C$F$$$k$h$&$J$N$G(B
 * chrbank no $B$N(B d7 $B$r(B 1 $B$K$7$F$*$/!#(B
 */
	ori	t1, t1, 0x40
	sb	t1, OFFSET_GFX_DRAW_VRAM_ADDR(t4)
	andi	a2, t1, 0x20
	srl	a2, a2, 5     /* 0x20 -> 0x01 */
	andi	a3, t1, 0x80
	srl	a3, a3, 7     /* 0x80 -> 0x01 */
	xor	a3, a3, a2

	addu	a2, a2, WORK
	lbu	a2, OFFSET_SUN4_VROM0(a2)
	addu	a3, a3, WORK
	lbu	a3, OFFSET_SUN4_VROM1(a3)
	
	andi	a0, a0, 0x3800 | 0x001f
	ori	a2, a2, 0x80
	andi	t3, a2, 0xc0
	sll	t3, t3, 8      /* 0xc0 -> 0xc000 */
	or	a0, a0, t3
	andi	t3, a2, 0x3f
	sll	t3, t3, 1 + 4  /* 0x3f -> 0x07e0 */
	or	a0, a0, t3
	sh	a0, OFFSET_GFX_DRAW_2000H(t4)
	ori	a3, a3, 0x80
 	sb	a3, OFFSET_GFX_DRAW_VROM_R(t4)
	j	chrbank_func04
			

	
	GLOBAL(line_end)
line_end:
	lw	t2, OFFSET_SOUNDCYCLE(WORK)
	addiu	t2, t2, (-(LINECYCLE_CONST0 + LINECYCLE_CONST1) / 0x100)
	sw	t2, OFFSET_SOUNDCYCLE(WORK)
	lh	t1, OFFSET_LINECNT_IRQ(WORK)
	addiu	LINECYCLE, LINECYCLE, LINECYCLE_CONST0
	lh	t4, OFFSET_LINECNT(WORK)
	addiu	t4, t4, 1
	sh	t4, OFFSET_LINECNT(WORK)

	srl	t0, PC, 13
	bne	t1, t4, mainloop
/* $B%i%$%s%+%&%s%?%*!<%P!<!#(B
 * $B%^%C%Q!<$K$h$C$F(B $B%i%$%s%+%&%s%?%*!<%P!<4X?t$X!#(B
 * $B$=$N4X?t$O(B mainloop_srlt0 $B$X5"$k!#(B
 * t4: new linecnt
 * t3: linecnt_irq preset $BCM(B
 * t2: linecnt_irq enabled
 */
	lw	t0, OFFSET_LINECNT_OVER_FUNCP(WORK)
	lhu	t3, OFFSET_LINECNT_IRQ_PRESET(WORK)
	lbu	t2, OFFSET_LINECNT_IRQ_ENABLED(WORK)
#if 0
/* debug */
	move	a1, t4
	move	a2, t3
	move	a3, t2
	PRINTF("linecnt over %x,%x,%x\n");
#endif
	jr	t0

	GLOBAL(vblank)
vblank:
/* linecnt == -21 $B$J$i(B vblank start, vblank begin
 * linecnt == -1 $B$J$i(B  vblank end
 * t4: linecnt
 */
	addiu	t2, t4, 1
	addiu	t1, t4, 21
	bne	t1, zero, 1f
/* vblank start
 * PPU 2002H output $B$N(B d7 $B$r(B 1 $B$K(B 
 * NMI enabled $B$J$i(B activate
 * hudson/sforce.nes $B$N%9%/%m!<%k%V%lBP:v$G!"(Blinecycle $B$rD4@@0$9$k!#(B-(0x22*0x100) $B$G$O%V%l$k!#(B
 *  -(0x24*0x100) $B$@@$H(B devil.nes $B$,%V%l$k!#(B
 * $B:#(B -(0x28*0x100)
 */
	addiu	LINECYCLE, LINECYCLE, -(0x28 * 0x100)
	lb	t1, OFFSET_PPU2000H(WORK)  /* signed $B$GFI$`(B */
	bgez	t1, mainloop_srlt0

	la	STORE_DONE, mainloop_srlt0
	li	t0, 0xfffa
	j	activate_intr

1:
	srl	t0, PC, 13
	bne	t2, zero, mainloop
/* vblank end
 * PPU 2002H output $B$N(B d7,d6 $B$r(B 0 $B$K!#(B
 * 2002H strikef position $B$N7W;;!#(B
 * draw sccv new -> draw sccv
 * oam -> draw oam $B$X!#(B
 * palette -> draw palette
 * V ext mode $B3d$j9~$_%A%'%C%/(B
 */
#if 0
/* 2002H polling $B$H(B NMI $B$rJ;MQ$7$F$$$k$b$N$,$"$k!#(B(cloadrun.nes)
 * strikef $B$b!"(B read reset $B$J$N$+$J(B ?
 */
	lbu	t1, OFFSET_PPU2000H_OUTPUT + 2(WORK)
	andi	t1, t1, 0x3f
	sb	t1, OFFSET_PPU2000H_OUTPUT + 2(WORK)
#endif
#if 0
/* line 240 done $B$G9T$&(B */
/* 2002H strikef $B$O%/%j%"$7$h$&(B (romf1.nes) */
	lbu	t1, OFFSET_PPU2000H_OUTPUT + 2(WORK)
	andi	t1, t1, 0xbf
	sb	t1, OFFSET_PPU2000H_OUTPUT + 2(WORK)
	li	t1, 0xff
	sb	t1, OFFSET_STRIKEF_LINE(WORK)
#endif
#if 0
/* debug
 * strikef $B7W;;$,;(!#(B
 */
	lbu	t2, OFFSET_OAM(WORK)
	sb	t2, OFFSET_STRIKEF_LINE(WORK)
#endif
	
/* sccv = sccv new
 * PPU 2006H $B$K2?$+=q$-9~$`$H$5$"!"(Bsccv new $B$,JQ$o$C$F!"(B
 * $B$=$N$"$H(B PPU 2005H $B$K2?$b=q$+$J$1$l$P(B $B%9%/%m!<%k$O$=$N$^$^$J$s$@@$h$M!#(B
 * $B$G$b$3$3$G$O6/@@)E*$K(B SCCV $B$K$7$A$c$&$G$7$g!"@@5$7$/$J$$$s$8$c$s(B ?
 */
	lbu	t0, OFFSET_DRAW_SCCV_NEW + 1(WORK)
	
	lbu	t1, OFFSET_DRAW_SCCV_NEW(WORK)
#if 0
/* debug
 * cluclu.nes $B$H(B jaleco/ninjakun.nes $B$N8_49@@-$O(B ?
 * $B$3$l$rF~$l$k$H(B smario.nes $B$N>e$,%P%0$k!#(B
 * $B$J$/$F$b(B cluclu.nes, ninjakun.nes $B$A$c$s$H=P$k!#(B
 */
	lbu	t1, OFFSET_PPU2000H(WORK)
#endif
	andi	t1, t1, 0x03
#if 0
/* debug
 * jaleco/ninjakun.nes $B$O$3$l$GF0$/$1$I(B
 * $BB>$O$d$P$$$G$7$g$&!#$3$s$J$3$H$7$?$i!#(B
 * andi 0x03 $B$G$7$g(B? (cluclu.nes $B$,%P%0$k(B)
 */
	andi	t1, t1, 0x01
#endif
	sb	t1, OFFSET_DRAW_SCCV(WORK)
	sb	t0, OFFSET_DRAW_SCCV + 1(WORK)

#if 0
/* debug */
	lhu	a1, OFFSET_DRAW_SCCV(WORK)
	PRINTF("SCCV = SCCV_NEW = %x\n");
#endif
	
/* oam -> draw oam */
	lw	t0, OFFSET_GFXPTR(WORK)
	addiu	t1, t0, 0x100
	move	t2, WORK
1:
	lw	a0, OFFSET_OAM + 0(t2)
	lw	a1, OFFSET_OAM + 4(t2)
	lw	a2, OFFSET_OAM + 8(t2)
	lw	a3, OFFSET_OAM + 0xc(t2)

	sw	a0, OFFSET_GFXBUF_OAM0 + 0(t0)
	sw	a1, OFFSET_GFXBUF_OAM0 + 4(t0)
	sw	a2, OFFSET_GFXBUF_OAM0 + 8(t0)
	sw	a3, OFFSET_GFXBUF_OAM0 + 0xc(t0)
	
	addiu	t2, t2, 0x10
	addiu	t0, t0, 0x10
	bne	t0, t1, 1b
		
	ld	t2, OFFSET_PALETTE_BUF + 0x00(WORK)
	ld	t3, OFFSET_PALETTE_BUF + 0x08(WORK)
	ld	t4, OFFSET_PALETTE_BUF + 0x10(WORK)
	ld	t5, OFFSET_PALETTE_BUF + 0x18(WORK)
	lw	t0, OFFSET_GFXPTR(WORK)
	sd	t2, OFFSET_GFXBUF_PALETTE0 + 0x00(t0)
	sd	t3, OFFSET_GFXBUF_PALETTE0 + 0x08(t0)
	sd	t4, OFFSET_GFXBUF_PALETTE0 + 0x10(t0)
	sd	t5, OFFSET_GFXBUF_PALETTE0 + 0x18(t0)

#if 1
/* V int check (current code)
 * 4017H (d7,d6)=(0,0) $B$J$i(B V ext intr request.
 * cli $B$J$i3d$j9~$_$r$+$1$k!#(B
 */
	lbu	t0, OFFSET_WORK_4017H(WORK)
	lbu	t1, OFFSET_WORK_4015H_OUTPUT(WORK)
	bne	t0, zero, mainloop_srlt0

	lbu	t0, OFFSET_WORK_RBDI(WORK)
	andi	t2, t0, 0x04  /* I */
	ori	t1, t1, 0x40  /* V ext int req. */
	sb	t1, OFFSET_WORK_4015H_OUTPUT(WORK)
	
	lbu	t0, OFFSET_IRQ_CAUSE(WORK)
	andi	t0, t0, 0xff ^ 0x40
	sb	t0, OFFSET_IRQ_CAUSE(WORK)
	la	STORE_DONE, mainloop_srlt0
	beq	t2, zero, activate_intr_fffe
	
/* sei $B$J$i(B irq cause bit d6 $B$rN)$F$F$*$/(B */
#if 0
	ori	t0, t0, 0x40
	sb	t0, OFFSET_IRQ_CAUSE(WORK)
#endif
#endif

	j	mainloop_srlt0


/* loadfunc $B$N$*LsB+(B
 * a0: emu-cpu addr (keep!)
 * v0: result (unsigned)
 * v1: keep!
 * ra: $B2<@@A$14X?t$N(B return address
 * OFFSET_JUMPTBL+4(JUMPTBLP) $B$N%"%I%l%9$X5"$k!#(B
 * PAGE_PTR: WORK + ((emu-cpu addr >> 13) << 2)
 * (keep!)   $B2<@@A$14X?t$N%"%I%l%9$H!"(Bpage table $B$r;2>H$9$k$?$a$K;H$&(B
 * 
 * storefunc $B$N$*LsB+(B
 * a0: emu-cpu addr (keep!)
 * a1: data (d31-d8 $B$,(B 0 $B$G$J$$>l9g$b$"$k(B)
 * a2: temp (cycle for $B%5%&%s%I(B)
 * v0, v1: $B0l1~(B keep!
 * STORE_DONE(t6): return address
 */
	GLOBAL(store_bbram_64k)
store_bbram_64k:
#if 0
/* debug */
	move	a2, a0
	PRINTF("BBRAM %02x->%x\n");
#endif
	addu	t0, a0, WORK
	sb	a1, OFFSET_BBRAM - 0x6000(t0)
	jr	STORE_DONE

/* v1 $B$NCM(B (16bit) $B$r(B push $B$9$k!#(B
 * v1 $B$OGK2u$5$l$k!#(B
 * t0: temp
 */
	GLOBAL(push_v1)
push_v1:
	addiu	t0, SP, -1
	andi	t0, t0, 0xff
	addu	t0, t0, WORK
	sb	v1, OFFSET_WRAM + 0x100(t0) /* low */
	srl	v1, v1, 8
	addu	t0, SP, WORK
	sb	v1, OFFSET_WRAM + 0x100(t0) /* high */
	addiu	SP, SP, -2
	andi	SP, SP, 0xff
	jr	ra

	GLOBAL(store_verbose)
store_verbose:
#ifdef KS_DEBUG_VERBOSE
/* debug */
	move	a3, PC
	move	a2, a1
	move	a1, a0
	PRINTF("%04x=%02x at PC=%04x\n");
#endif
	jr	STORE_DONE
	
	
/* store_done $B$N(B delay slot $B$r=E$M$F$"$k(B */
	GLOBAL(store_done)
store_done:
store_ignore:
	.set	noreorder
	jr	STORE_DONE
	GLOBAL(store_internal_wram)
store_internal_wram:
	andi	t0, a0, 0x7ff
	.set	reorder
	addu	t0, t0, WORK
	sb	a1, OFFSET_WRAM(t0)
#if 0
/* debug */
	move a2,a1
	move a1,a0
	PRINTF("%x=%x\n");
#endif
	jr	STORE_DONE

/* load_done $B$N(B delay slot $B$r=E$M$F$"$k(B */
	GLOBAL(load_done)
load_done:
	.set	noreorder
	jr	ra
	GLOBAL(load_internal_wram)
load_internal_wram:
/* 0000-1fff, address $B$K(B mask $B$,I,MW!#(B*/
	andi	t0, a0, 0x7ff
	.set	reorder
	addu	t0, t0, WORK
	lbu	v0, OFFSET_WRAM(t0)
	jr	ra
	
	GLOBAL(load_6000)
load_6000:
/* 6000-7fff, 8000-ffff
 * PAGE_PTR $B$r;2>H!#(B
 */
	lw	t0, OFFSET_PAGE_TABLE(PAGE_PTR)
	addu	t0, t0, a0
	lbu	v0, 0(t0)
	jr	ra

	GLOBAL(load8_imm)
load8_imm: /* $B%m!<%I8e(B func2 $B$X(B RMW $BBP1~ITMW(B */
	lw	ra, OFFSET_JUMPTBL + 4(JUMPTBLP)
	addiu a0,PC,-1; srl t0,a0,13; sll t0,t0,2; addu PAGE_PTR,t0,WORK; lw t1,OFFSET_LOADFUNC_TBL(PAGE_PTR); jr t1

	GLOBAL(load16_imm)
load16_imm: /* high, low $B%m!<%I8e(B func2 $B$X(B RMW $BBP1~ITMW(B jmp, jsr, sta, stx, sty $B$G;H$&(B $B$@@$1$@@$m$&!#(B jmp_6c, store $B7O(B $B$N$3$H$r9M$($F(B $B7k2L$O(B a0 $B$K!#(B*/
	addiu a0,PC,-1; srl t0,a0,13; sll t0,t0,2; addu PAGE_PTR,t0,WORK; lw t1,OFFSET_LOADFUNC_TBL(PAGE_PTR); jalr t1
	sll	v1, v0, 8
	addiu a0,PC,-2; srl t0,a0,13; sll t0,t0,2; addu PAGE_PTR,t0,WORK; lw t1,OFFSET_LOADFUNC_TBL(PAGE_PTR); jalr t1
	or	a0, v0, v1
	lw	ra, OFFSET_JUMPTBL + 4(JUMPTBLP)
	jr	ra

	GLOBAL(load8_zerop)
load8_zerop:
/* $B%m!<%I8e(B func2 $B$X(B
 * RMW $BBP1~I,MW$J$N$G(B a0 $B$K(B v0 $B$r!"(BPAGE_PTR $B$K(B WORK $B$rF~$l$k!#(B
 * sta_91 $B$G%l%8%9%?0MB8$7$F$$$k$N$GCm0U!#(B
 */
	addiu a0,PC,-1; srl t0,a0,13; sll t0,t0,2; addu PAGE_PTR,t0,WORK; lw t1,OFFSET_LOADFUNC_TBL(PAGE_PTR); jalr t1
	move	PAGE_PTR, WORK
	move	a0, v0
	addu	t0, a0, WORK
	lbu	v0, OFFSET_WRAM(t0)
	lw	ra, OFFSET_JUMPTBL + 4(JUMPTBLP)
	jr	ra

	GLOBAL(load8_abs)
load8_abs:
/* $B%m!<%I8e(B func2 $B$X(B
 * RMW $BBP1~I,MW!#(B
 */
	addiu a0,PC,-1; srl t0,a0,13; sll t0,t0,2; addu PAGE_PTR,t0,WORK; lw t1,OFFSET_LOADFUNC_TBL(PAGE_PTR); jalr t1
	sll	v1, v0, 8
	addiu a0,PC,-2; srl t0,a0,13; sll t0,t0,2; addu PAGE_PTR,t0,WORK; lw t1,OFFSET_LOADFUNC_TBL(PAGE_PTR); jalr t1
	or	a0, v0, v1
			srl t0,a0,13; sll t0,t0,2; addu PAGE_PTR,t0,WORK; lw t1,OFFSET_LOADFUNC_TBL(PAGE_PTR);
	lw	ra, OFFSET_JUMPTBL + 4(JUMPTBLP)
	jr	t1

	GLOBAL(load8_absx)
load8_absx:
/* $B%m!<%I8e(B func2 $B$X(B
 * RMW $BBP1~I,MW!#(B
 */
	addiu a0,PC,-1; srl t0,a0,13; sll t0,t0,2; addu PAGE_PTR,t0,WORK; lw t1,OFFSET_LOADFUNC_TBL(PAGE_PTR); jalr t1
	sll	v1, v0, 8
	addiu a0,PC,-2; srl t0,a0,13; sll t0,t0,2; addu PAGE_PTR,t0,WORK; lw t1,OFFSET_LOADFUNC_TBL(PAGE_PTR); jalr t1
	or	a0, v0, v1
	addu	a0, a0, X
			srl t0,a0,13; sll t0,t0,2; addu PAGE_PTR,t0,WORK; lw t1,OFFSET_LOADFUNC_TBL(PAGE_PTR);
	lw	ra, OFFSET_JUMPTBL + 4(JUMPTBLP)
	jr	t1

	GLOBAL(load8_dyi)
load8_dyi:
/* $B%m!<%I8e(B func2 $B$X(B
 * ($B$3$N%"%I%l%7%s%0%b!<%I$O(B RMW $B$,$J$$(B)
 */
	addiu a0,PC,-1; srl t0,a0,13; sll t0,t0,2; addu PAGE_PTR,t0,WORK; lw t1,OFFSET_LOADFUNC_TBL(PAGE_PTR); jalr t1
	addu	t0, v0, WORK
	addiu	a0, v0, 1
	lbu	v0, OFFSET_WRAM(t0)
	andi	a0, a0, 0xff
	addu	t0, a0, WORK
	lbu	v1, OFFSET_WRAM(t0)
	addu	v0, v0, Y
	sll	v1, v1, 8
	addu	a0, v0, v1
			srl t0,a0,13; sll t0,t0,2; addu PAGE_PTR,t0,WORK; lw t1,OFFSET_LOADFUNC_TBL(PAGE_PTR);
	lw	ra, OFFSET_JUMPTBL + 4(JUMPTBLP)
	jr	t1

	GLOBAL(load8_dx)
load8_dx:
/* $B%m!<%I8e(B func2 $B$X(B
 * RMW $BBP1~I,MW$J$N$G(B a0 $B$K(B (v0 + X) & 0xff $B$r!"(BPAGE_PTR $B$K(B WORK $B$rF~$l$k!#(B
 * sta_81 $B$G%l%8%9%?0MB8$7$F$$$k$N$GCm0U!#(B
 */
	addiu a0,PC,-1; srl t0,a0,13; sll t0,t0,2; addu PAGE_PTR,t0,WORK; lw t1,OFFSET_LOADFUNC_TBL(PAGE_PTR); jalr t1
	move	PAGE_PTR, WORK
	addu	a0, v0, X
	andi	a0, a0, 0xff
	addu	t0, a0, WORK
	lbu	v0, OFFSET_WRAM(t0)
	lw	ra, OFFSET_JUMPTBL + 4(JUMPTBLP)
	jr	ra

/* load8_dy $B$O(B ldx_b6 $B$@@$1$J$N$G(B $B3d0&(B
 * ldx_a2 $B$X!#(B
 */
ldx_b6: /* ldx z,y */
	addu	a0, v0, Y
	andi	a0, a0, 0xff
	addu	t0, a0, WORK
	lbu	v0, OFFSET_WRAM(t0)
	j	ldx_a2
		
	GLOBAL(load8_absy)
load8_absy:
/* $B%m!<%I8e(B func2 $B$X(B
 * ($B$3$N%"%I%l%7%s%0%b!<%I$O(B RMW $B$,$J$$(B)
 */
	addiu a0,PC,-1; srl t0,a0,13; sll t0,t0,2; addu PAGE_PTR,t0,WORK; lw t1,OFFSET_LOADFUNC_TBL(PAGE_PTR); jalr t1
	sll	v1, v0, 8
	addiu a0,PC,-2; srl t0,a0,13; sll t0,t0,2; addu PAGE_PTR,t0,WORK; lw t1,OFFSET_LOADFUNC_TBL(PAGE_PTR); jalr t1
	or	a0, v0, v1
	addu	a0, a0, Y
			srl t0,a0,13; sll t0,t0,2; addu PAGE_PTR,t0,WORK; lw t1,OFFSET_LOADFUNC_TBL(PAGE_PTR);
	lw	ra, OFFSET_JUMPTBL + 4(JUMPTBLP)
	jr	t1
	
	GLOBAL(load8_dxi)
load8_dxi:
/* $B%m!<%I8e(B func2 $B$X(B
 * ($B$3$N%"%I%l%7%s%0%b!<%I$O(B RMW $B$,$J$$(B)
 */
	addiu a0,PC,-1; srl t0,a0,13; sll t0,t0,2; addu PAGE_PTR,t0,WORK; lw t1,OFFSET_LOADFUNC_TBL(PAGE_PTR); jalr t1
	addu	a0, v0, X
	andi	a0, a0, 0xff
	addu	t0, a0, WORK
	lbu	v0, OFFSET_WRAM(t0)
	addiu	a0, a0, 1
	andi	a0, a0, 0xff
	addu	t0, a0, WORK
	lbu	v1, OFFSET_WRAM(t0)
	sll	v1, v1, 8
	or	a0, v0, v1
			srl t0,a0,13; sll t0,t0,2; addu PAGE_PTR,t0,WORK; lw t1,OFFSET_LOADFUNC_TBL(PAGE_PTR);
	lw	ra, OFFSET_JUMPTBL + 4(JUMPTBLP)
	jr	t1

/* func2 begins ... */
adc_61:
adc_65:
adc_69:
adc_6d:
adc_71:
adc_75:
adc_79:
adc_7d:
/* $BId9f3HD%$7$FB-$7!"(B-128..+127 $B$NHO0O!"$=$l$K(B +128 $B$7$F(B 0..255 $B$J$i(B
 * $B%*!<%P!<%U%m!<$J$7(B
 * RMW $B$G$O$J$$$N$G(B j next; $B$G5"$k(B
 */
	addu	t0, A, v0
	addu	t0, t0, C  /* t0 = next carry $B7W;;MQ(B */
	
	sll	A, A, 24
	sra	A, A, 24
	addu	A, A, C

	sll	v0, v0, 24
	sra	v0, v0, 24
	addu	Z, A, v0
	andi	N, Z, 0x80

	addiu	V, Z, 128
	srl	V, V, 8  /* A+v0+C+128 $B$,(B 0x100 $B0J>e$J$i(B V=1 */

	srl	C, t0, 8
	andi	A, t0, 0xff
	j	next

and_21:
and_25:
and_29:
and_2d:
and_31:
and_35:
and_39:
and_3d:
/*
 * RMW $B$G$O$J$$$N$G(B j next; $B$G5"$k(B
 */
	and	Z, A, v0
	andi	N, Z, 0x80
	andi	A, Z, 0xff
	j	next

asl_0a:
	sll	Z, A, 1
	andi	N, Z, 0x80
	srl	C, Z, 8
	andi	A, Z, 0xff
	j	next

asl_06:
asl_0e:
asl_16:
asl_1e:
/* RMW $B$J$N$G(B storefunc $B$X5"$k(B */
	lw	t0, OFFSET_STOREFUNC_TBL(PAGE_PTR)
	sll	Z, v0, 1
	andi	N, Z, 0x80
	srl	C, Z, 8
	andi	a1, Z, 0xff
	jr	t0

#if 0
/* $B$J$s$+(B $B%5%$%/%k?t7W;;(B $B$a$A$c$/$A$c$A$c$&(B ? */
bcc_90:	sll	t0, v0, 24;	bne	C, zero, next;	sra	t0, t0, 24;	addu	PC, PC, t0;	addiu	LINECYCLE, LINECYCLE, -0x100; j	next
bcs_b0:	sll	t0, v0, 24;	beq	C, zero, next;	sra	t0, t0, 24;	addu	PC, PC, t0;	addiu	LINECYCLE, LINECYCLE, -0x100; j	next
beq_f0:	andi	t1, Z, 0xff;	sll	t0, v0, 24;	sra	t0, t0, 24;	addu	PC, PC, t0;	beq	t1, zero, next;
	subu	PC, PC, t0;	addiu	LINECYCLE, LINECYCLE, -0x100; j	next
bne_d0:	andi	t1, Z, 0xff;	sll	t0, v0, 24;	sra	t0, t0, 24;	addu	PC, PC, t0;	bne	t1, zero, next;
	subu	PC, PC, t0;	addiu	LINECYCLE, LINECYCLE, -0x100; j	next
bpl_10:	                        sll	t0, v0, 24;	sra	t0, t0, 24;	addu	PC, PC, t0;	beq	N, zero, next;
	subu	PC, PC, t0;	addiu	LINECYCLE, LINECYCLE, -0x100; j	next
bmi_30:	                      	sll	t0, v0, 24;	sra	t0, t0, 24;	addu	PC, PC, t0;	bne	N, zero, next;
	subu	PC, PC, t0;	addiu	LINECYCLE, LINECYCLE, -0x100; j	next
bvc_50:	sll	t0, v0, 24;	bne	V, zero, next;	sra	t0, t0, 24;	addu	PC, PC, t0;	addiu	LINECYCLE, LINECYCLE, -0x100; j	next
bvs_70:	sll	t0, v0, 24;	beq	V, zero, next;	sra	t0, t0, 24;	addu	PC, PC, t0;	addiu	LINECYCLE, LINECYCLE, -0x100; j	next
#endif

bcc_90:				sll	t0, v0, 24;	sra	t0, t0, 24;	addu	PC, PC, t0;	beq	C, zero, next;
	subu	PC, PC, t0;	addiu	LINECYCLE, LINECYCLE, -0x100; j	next
bcs_b0:				sll	t0, v0, 24;	sra	t0, t0, 24;	addu	PC, PC, t0;	bne	C, zero, next;
	subu	PC, PC, t0;	addiu	LINECYCLE, LINECYCLE, -0x100; j	next
beq_f0:	andi	t1, Z, 0xff;	sll	t0, v0, 24;	sra	t0, t0, 24;	addu	PC, PC, t0;	beq	t1, zero, next;
	subu	PC, PC, t0;	addiu	LINECYCLE, LINECYCLE, -0x100; j	next
bne_d0:	andi	t1, Z, 0xff;	sll	t0, v0, 24;	sra	t0, t0, 24;	addu	PC, PC, t0;	bne	t1, zero, next;
	subu	PC, PC, t0;	addiu	LINECYCLE, LINECYCLE, -0x100; j	next
bpl_10:	                        sll	t0, v0, 24;	sra	t0, t0, 24;	addu	PC, PC, t0;	beq	N, zero, next;
	subu	PC, PC, t0;	addiu	LINECYCLE, LINECYCLE, -0x100; j	next
bmi_30:	                      	sll	t0, v0, 24;	sra	t0, t0, 24;	addu	PC, PC, t0;	bne	N, zero, next;
	subu	PC, PC, t0;	addiu	LINECYCLE, LINECYCLE, -0x100; j	next
bvc_50:	                        sll	t0, v0, 24;	sra	t0, t0, 24;	addu	PC, PC, t0;	beq	V, zero, next;
	subu	PC, PC, t0;	addiu	LINECYCLE, LINECYCLE, -0x100; j	next
bvs_70:	                        sll	t0, v0, 24;	sra	t0, t0, 24;	addu	PC, PC, t0;	bne	V, zero, next;
	subu	PC, PC, t0;	addiu	LINECYCLE, LINECYCLE, -0x100; j	next
	
bit_24:
bit_2c:
/* RMW $B$G$O$J$$$N$G(B j next; $B$G5"$k(B */
	and	Z, A, v0
	andi	N, v0, 0x80
	andi	V, v0, 0x40
	j	next

clc_18:
	li	C, 0
	j	next
	
cld_d8:
	lbu	t0, OFFSET_WORK_RBDI(WORK)
	andi	t0, t0, 0xff ^ 0x08
	sb	t0, OFFSET_WORK_RBDI(WORK)
	j	next
	
cli_58:
	lbu	t0, OFFSET_WORK_RBDI(WORK)
	andi	t1, t0, 0xff ^ 0x04
/* $B$9$G$K(B $B3d$j9~$_5v2D>uBV$J$i(B $B%A%'%C%/$7$J$$(B */
	beq	t0, t1, next
/* t1 $B$K$O(B $B:#$N(B Reserved|B|D|I $B$r!#(B*/
#if 0
/* debug */
	move	a1, PC
	lhu	a2, OFFSET_LINECNT(WORK)
	PRINTF("CLI at PC=%x, line=%x\n");
#endif
	sb	t1, OFFSET_WORK_RBDI(WORK)  /* Reserved|B|D|I */
#if 0
/* check_intr_common $B$O(B $B$&$^$/F0$$$F$$$J$$!#(B
 * $BB?=E3d$j9~$_=hM}$K<:GT$7$FK=Av$9$k(B (cv3j.nes)
 */
	j	check_intr_common
#endif
	j	next

clv_b8:
	li	V, 0
	j	next

cmp_c1:
cmp_c5:
cmp_c9:
cmp_cd:
cmp_d1:
cmp_d5:
cmp_d9:
cmp_dd:
/* RMW $B$G$O$J$$$N$G(B j next; $B$G5"$k(B
 * (A - M) >= 0 $B$J$i(B C = 1
 * unsigned $B$G(B (A - M) < 256 $B$J$i(B C = 1
 */
	subu	Z, A, v0
	andi	N, Z, 0x80
	sltiu	C, Z, 0x100
	j	next
	
cpx_e0:
cpx_e4:
cpx_ec:
	subu	Z, X, v0
	andi	N, Z, 0x80
	sltiu	C, Z, 0x100
	j	next

cpy_c0:
cpy_c4:
cpy_cc:
	subu	Z, Y, v0
	andi	N, Z, 0x80
	sltiu	C, Z, 0x100
	j	next

dec_c6:
dec_ce:
dec_d6:
dec_de:
/* RMW $B$J$N$G(B storefunc $B$X5"$k(B */
	lw	t0, OFFSET_STOREFUNC_TBL(PAGE_PTR)
	addiu	Z, v0, -1
	andi	N, Z, 0x80
	andi	a1, Z, 0xff
	jr	t0

dex_ca:
	addiu	Z, X, -1
	andi	N, Z, 0x80
	andi	X, Z, 0xff
	j	next
	
dey_88:
	addiu	Z, Y, -1
	andi	N, Z, 0x80
	andi	Y, Z, 0xff
	j	next

eor_41:
eor_45:
eor_49:
eor_4d:
eor_51:
eor_55:
eor_59:
eor_5d:
/* RMW $B$G$O$J$$!#(B*/
	xor	Z, A, v0
	andi	N, Z, 0x80
	andi	A, Z, 0xff
	j	next

inc_e6:
inc_ee:
inc_f6:
inc_fe:
/* RMW $B$J$N$G(B storefunc $B$X5"$k(B */
	lw	t0, OFFSET_STOREFUNC_TBL(PAGE_PTR)
	addiu	Z, v0, 1
	andi	N, Z, 0x80
	andi	a1, Z, 0xff
	jr	t0

inx_e8:
	addiu	Z, X, 1
	andi	N, Z, 0x80
	andi	X, Z, 0xff
	j	next
	
iny_c8:
	addiu	Z, Y, 1
	andi	N, Z, 0x80
	andi	Y, Z, 0xff
	j	next

jmp_4c:
/* a0 $B$K(B 16bit $B$G(B operand $B$,F~$C$F$$$k!#(B*/
	move	PC, a0
	j	next

jsr_20:
/* a0 $B$K(B 16bit $B$G(B operand $B$,F~$C$F$$$k!#(B*/
	addiu	v1, PC, -1
	move	PC, a0
	move	ra, STORE_DONE  /* next */
	j	push_v1

rts_60:
	addiu	SP, SP, 2
	andi	SP, SP, 0xff
	addu	t0, SP, WORK
	lbu	PC, OFFSET_WRAM + 0x100(t0)
	sll	PC, PC, 8
	addiu	t0, SP, -1
	andi	t0, t0, 0xff
	addu	t0, t0, WORK
	lbu	t0, OFFSET_WRAM + 0x100(t0)
	or	PC, PC, t0
	addiu	PC, PC, 1
	andi	PC, PC, 0xffff
	jr	STORE_DONE  /* rti_40 $B$+$i8F$P$l$k$+$b(B */
	
lda_a1:
lda_a5:
lda_a9:
lda_ad:
lda_b1:
lda_b5:
lda_b9:
lda_bd:
/* RMW $B$G$O$J$$!#(B*/
	move	Z, v0
	andi	N, Z, 0x80
	move	A, v0
	j	next

/* ldx_b6 $B$+$i$b(B ldx_a2 $B$X$d$C$FMh$k!#(B*/
ldx_a2:
ldx_a6:
ldx_ae:
ldx_be:
	move	Z, v0
	andi	N, Z, 0x80
	move	X, v0
	j	next

ldy_a0:
ldy_a4:
ldy_ac:
ldy_b4:
ldy_bc:
	move	Z, v0
	andi	N, Z, 0x80
	move	Y, v0
	j	next

lsr_4a:
	andi	C, A, 0x01
	srl	Z, A, 1
	andi	N, Z, 0x80
	andi	A, Z, 0xff
	j	next
	
lsr_46:
lsr_4e:
lsr_56:
lsr_5e:
/* RMW $B$J$N$G(B storefunc $B$X5"$k(B */
	lw	t0, OFFSET_STOREFUNC_TBL(PAGE_PTR)
	andi	C, v0, 0x01
	srl	Z, v0, 1
	andi	N, Z, 0x80
	andi	a1, Z, 0xff
	jr	t0

ora_01:
ora_05:
ora_09:
ora_0d:
ora_11:
ora_15:
ora_19:
ora_1d:
/* RMW $B$G$O$J$$!#(B*/
	or	Z, A, v0
	andi	N, Z, 0x80
	andi	A, Z, 0xff
	j	next

rol_2a:
	sll	Z, A, 1
	or	Z, Z, C
	andi	N, Z, 0x80
	srl	C, Z, 8
	andi	A, Z, 0xff
	j	next
	
rol_26:
rol_2e:
rol_36:
rol_3e:
/* RMW $B$J$N$G(B storefunc $B$X5"$k!#(B*/
	lw	t0, OFFSET_STOREFUNC_TBL(PAGE_PTR)
	sll	Z, v0, 1
	or	Z, Z, C
	andi	N, Z, 0x80
	srl	C, Z, 8
	andi	a1, Z, 0xff
	jr	t0

ror_6a:
	sll	C, C, 8
	or	Z, A, C
	andi	C, A, 0x01
	srl	Z, Z, 1
	andi	N, Z, 0x80
	andi	A, Z, 0xff
	j	next

ror_66:
ror_6e:
ror_76:
ror_7e:
/* RMW $B$J$N$G(B storefunc $B$X5"$k!#(B*/
	lw	t0, OFFSET_STOREFUNC_TBL(PAGE_PTR)
	sll	C, C, 8
	or	Z, v0, C
	andi	C, v0, 0x01
	srl	Z, Z, 1
	andi	N, Z, 0x80
	andi	a1, Z, 0xff
	jr	t0

sbc_e1:
sbc_e5:
sbc_e9:
sbc_ed:
sbc_f1:
sbc_f5:
sbc_f9:
sbc_fd:
/* $BId9f3HD%$7$F0z$-!"(B-128..+127 $B$NHO0O!"$=$l$K(B +128 $B$7$F(B 0..255 $B$J$i(B
 * $B%*!<%P!<%U%m!<$J$7(B
 * RMW $B$G$O$J$$$N$G(B j next; $B$G5"$k(B
 */

	xori	t0, C, 1    /* t0 = C ^ 1 */
	subu	t1, A, v0
	subu	t1, t1, t0  /* t1 = next carry $B7W;;MQ(B */

	sll	A, A, 24
	srl	A, A, 24
	subu	A, A, t0

	sll	v0, v0, 24
	sra	v0, v0, 24
	subu	Z, A, v0
	andi	N, Z, 0x80

	addiu	V, Z, 128
	srl	V, V, 8  /* A-C-v0+128 $B$,(B 0x100 $B0J>e$J$i(B V=1 */

	sltiu	C, t1, 0x100   /* unsigned $B$G(B t1 $B$,(B 256 $BL$K~$J$i(B C=1 */
	andi	A, t1, 0xff
	j	next

sec_38:
	li	C, 1
	j	next

	GLOBAL(sed_f8)
sed_f8:
	lbu	t0, OFFSET_WORK_RBDI(WORK)
	ori	t0, t0, 0x08
	sb	t0, OFFSET_WORK_RBDI(WORK)
	j	next

	GLOBAL(sei_78)
sei_78:
	lbu	t0, OFFSET_WORK_RBDI(WORK)
	ori	t0, t0, 0x04
	sb	t0, OFFSET_WORK_RBDI(WORK)
	j	next

	GLOBAL(sta_85)
sta_85:
/* v0 $B$K(B store $B$9$k$Y$-(B $B%<%m%Z!<%8(B emu-cpu address $B$,F~$C$F$$$k!#(B
 * $B5"$k$N$O(B j next; $B$GNI$$!#(B
 */
#if 0
/* debug
 * 2 or 3 $B$r(B trap
 */
	andi	t1, v0, 0xfe
	xori	t1, t1, 2
	bne	t1, zero, 1f
	lw	t0, OFFSET_EMUFRAME(WORK)
	sltiu	t0, t0, 629
	bne	t0, zero, 1f
	move	a1, v0
	move	a2, A
	move	a3, PC
	PRINTF("%x=%x,%x\n");

#if 0
/* $B$*$^$1$K(B
 * PC=d5c1 $B$J$i(B 0x20 $B$r(B or $B$7$FF($2$k!#(B
 */
	xori	a3, a3, 0xd5c1
	bne	a3, zero, 1f
	lbu	a3, OFFSET_WRAM + 0x3(WORK)
	ori	a3, a3, 0x20
	sb	a3, OFFSET_WRAM + 0x3(WORK)
	j	next
#endif
	
1:
#endif
	addu	t0, v0, WORK
	sb	A, OFFSET_WRAM(t0)
	j	next

	GLOBAL(sta_91)
sta_91:
/* v0 $B$K(B indirect $B$9$k$Y$-(B $B%<%m%Z!<%8(B emu-cpu address $B$,(B
 * load8_zerop $B$K$h$C$FFI$^$l$F$$$k!#(B
 * a0 $B$,;D$C$F$$$k$N$G$=$l$rMxMQ!#(B
 */
	addiu	a0, a0, 1
	andi	a0, a0, 0xff
	addu	t0, a0, WORK
	lbu	v1, OFFSET_WRAM(t0)
	addu	v0, v0, Y
	GLOBAL(sta_indirect_common)
sta_indirect_common:
	sll	v1, v1, 8
	addu	a0, v0, v1
	GLOBAL(sta_8d)
sta_8d: /* a0 $B$K(B store $B$9$k$Y$-(B emu-cpu address $B$,(B 16bit $B$GF~$C$F$$$k!#(B*/
sta_indirect_common2:
	srl	t0, a0, 13
	sll	t0, t0, 2
	addu	PAGE_PTR, t0, WORK
	lw	t1, OFFSET_STOREFUNC_TBL(PAGE_PTR)
	move	a1, A
	jr	t1

	GLOBAL(sta_95)	
sta_95:
/* v0 $B$K(B $B%<%m%Z!<%8(B emu-cpu address $B$,F~$C$F$$$k!#(B
 * $B$3$l$K(B X $B$r2C$($F(B andi 0xff $B$7$?(B emu-cpu address $B$X(B store.
 * $B5"$k$N$O(B j next; $B$GNI$$!#(B
 */
	addu	a0, v0, X
	andi	a0, a0, 0xff
	addu	t0, a0, WORK
	sb	A, OFFSET_WRAM(t0)
	j	next

	GLOBAL(sta_81)
sta_81:
/* v0 $B$K(B indirect $B$9$k$Y$-(B emu-cpu address L $B$,(B
 * load8_dx $B$K$h$C$FFI$^$l$F$$$k!#(B
 * a0 $B$,;D$C$F$$$k$N$G$=$l$rMxMQ!#(B
 */
	addiu	a0, a0, 1
	andi	a0, a0, 0xff
	addu	t0, a0, WORK
	lbu	v1, OFFSET_WRAM(t0)
	j	sta_indirect_common
	
sta_99:
/* a0 $B$K(B emu-cpu address $B$,(B 16bit $B$GF~$C$F$$$k!#(B
 * $B$3$l$K(B Y $B$r2C$($?$b$N$,(B store $B$9$k$Y$-(B emu-cpu address.
 */
	addu	a0, a0, Y
#if 0
/* debug */
	xori	t0, a0, 0x28a
	bne	t0, zero, 1f
	PRINTF("028a=%x\n");
1:
#endif
	j	sta_indirect_common2
	
sta_9d:
	addu	a0, a0, X
#if 0
/* debug */
	move	a2, a0
	PRINTF("sta_9d watch %x,%x\n");
	teq	a2, 0x6060
#endif

#if 0
/* debug */
	xori	t0, a0, 0x67e
	bne	t0, zero, 1f
	lw	t0, OFFSET_EMUFRAME(WORK)
	sltiu	t0, t0, 600
	bne	t0, zero, 1f
	move	a2, PC
	PRINTF("67e=%x at PC=%x\n");
	sw	PC, OFFSET_TRACE_FLAG(WORK)
1:
#endif
	
	j	sta_indirect_common2

stx_86:
/* v0 $B$K(B store $B$9$k$Y$-(B $B%<%m%Z!<%8(B emu-cpu address $B$,F~$C$F$$$k!#(B
 * $B5"$k$N$O(B j next; $B$GNI$$!#(B
 */
	addu	t0, v0, WORK
	sb	X, OFFSET_WRAM(t0)
	j	next

stx_8e:
/* a0 $B$K(B store $B$9$k$Y$-(B emu-cpu address $B$,(B 16bit $B$GF~$C$F$$$k!#(B*/
	srl	t0, a0, 13
	sll	t0, t0, 2
	addu	PAGE_PTR, t0, WORK
	lw	t1, OFFSET_STOREFUNC_TBL(PAGE_PTR)
	move	a1, X
	jr	t1

stx_96:
/* v0 $B$K(B $B%<%m%Z!<%8(B emu-cpu address $B$,F~$C$F$$$k!#(B
 * $B$3$l$K(B Y $B$r2C$($F(B andi 0xff $B$7$?(B emu-cpu address $B$X(B store.
 * $B5"$k$N$O(B j next; $B$GNI$$!#(B
 */
	addu	a0, v0, Y
	andi	a0, a0, 0xff
	addu	t0, a0, WORK
	sb	X, OFFSET_WRAM(t0)
	j	next

sty_84:
/* v0 $B$K(B store $B$9$k$Y$-(B $B%<%m%Z!<%8(B emu-cpu address $B$,F~$C$F$$$k!#(B
 * $B5"$k$N$O(B j next; $B$GNI$$!#(B
 */
	addu	t0, v0, WORK
	sb	Y, OFFSET_WRAM(t0)
	j	next

sty_8c:
/* a0 $B$K(B store $B$9$k$Y$-(B emu-cpu address $B$,(B 16bit $B$GF~$C$F$$$k!#(B*/
	srl	t0, a0, 13
	sll	t0, t0, 2
	addu	PAGE_PTR, t0, WORK
	lw	t1, OFFSET_STOREFUNC_TBL(PAGE_PTR)
	move	a1, Y
	jr	t1

sty_94:
/* v0 $B$K(B $B%<%m%Z!<%8(B emu-cpu address $B$,F~$C$F$$$k!#(B
 * $B$3$l$K(B X $B$r2C$($F(B andi 0xff $B$7$?(B emu-cpu address $B$X(B store.
 * $B5"$k$N$O(B j next; $B$GNI$$!#(B
 */
	addu	a0, v0, X
	andi	a0, a0, 0xff
	addu	t0, a0, WORK
	sb	Y, OFFSET_WRAM(t0)
	j	next

tax_aa:
	move	Z, A
	andi	N, Z, 0x80
	move	X, A
	j	next
	
tay_a8:
	move	Z, A
	andi	N, Z, 0x80
	move	Y, A
	j	next
	
tsx_ba:
	move	Z, SP
	andi	N, Z, 0x80
	move	X, SP
	j	next
	
txa_8a:
	move	Z, X
	andi	N, Z, 0x80
	move	A, X
	j	next
	
txs_9a:
	move	SP, X
	j	next
	
tya_98:
	move	Z, Y
	andi	N, Z, 0x80
	move	A, Y
	j	next

pha_48:
	addu	t0, SP, WORK
	sb	A, OFFSET_WRAM + 0x100(t0)
	addiu	SP, SP, -1
	andi	SP, SP, 0xff
	j	next

pla_68:
	addiu	SP, SP, 1
	andi	SP, SP, 0xff
	addu	t0, SP, WORK
	lbu	A, OFFSET_WRAM + 0x100(t0)
	move	Z, A
	andi	N, Z, 0x80
	j	next

brk_00:
/* PC, P $B$r(B push $B$7$F!"(B(t0) $B$N(B emu-cpu addr $B$X(B PC $B$r%;%C%H!#(B
 * B $B%U%i%0$rN)$F$k$H$$$&$3$H$@@$,!"<B5!$GN)$C$F$J$$$h$&$J(B ...?
 * $B$=$l$J$i(B thru $B$8$c$s(B?
 */
	
	GLOBAL(activate_intr_fffe)
activate_intr_fffe:
	li	t0, 0xfffe
/* thru */
	GLOBAL(activate_intr)
activate_intr:
/* PC, P $B$r(B push $B$7$F!"(B(t0) $B$N(B emu-cpu addr $B$X(B PC $B$r%;%C%H!#(B
 * STORE_DONE $B$X5"$k!#(B
 * plp_28 $B$+$i$b8F$P$l$k!#(B
 * t4 $B2u$5$J$$$G$M(B ($B$3$3$r8F$s$G$$$k85$N4X78$G(B)
 */
	move	v1, PC
	lw	t1, OFFSET_PAGE_TABLE + 0x1c(WORK)
	addu	t1, t1, t0
	lbu	t2, 1(t1)  /* new PC high */
	lbu	t1, 0(t1)  /* new PC low  */
	sll	t2, t2, 8
	or	PC, t1, t2
#if 0
/* debug */
	move	a1, t0
	move	a2, PC
	lhu	a3, OFFSET_LINECNT(WORK)
	PRINTF("intr(%x) newPC=%x at line=%x\n");
#endif
#if 0
/* gradius2.nes $B$,%V%l$k$N$G$3$3$G$O$d$i$J$$(B */
	addiu	LINECYCLE, LINECYCLE, 6 * 0x100
#endif
	jal	push_v1
	li	t2, 0x04
/* thru!! */
	GLOBAL(php_common)
php_common:
/* php_08 $B$+$i$b8F$P$l$k!#(B
 * t2: $B%U%i%0(B push $B8e(B SEI $B$9$k$J$i(B 4, $B$7$J$$$J$i(B 0
 */
	lbu	t0, OFFSET_WORK_RBDI(WORK)
	or	t2, t2, t0
	sb	t2, OFFSET_WORK_RBDI(WORK)
	andi	t1, Z, 0xff
	sltiu	t1, t1, 1
	sll	t1, t1, 1     /* Z */
	or	t1, t1, N     /* N|Z */
	or	t1, t1, C     /* N|Z|C */
	or	t1, t1, t0    /* N|-|Reserved|B|D|I|Z|C */
	beq	V, zero, 1f
	ori	t1, t1, 0x40  /* N|V|Reserved|B|D|I|Z|C */
1:
	addu	t0, SP, WORK
	sb	t1, OFFSET_WRAM + 0x100(t0)
	addiu	SP, SP, -1
	andi	SP, SP, 0xff
	jr	STORE_DONE  /* j next; $B$G$O%@@%a(B */

	GLOBAL(php_08)
php_08:
	li	t2, 0
	j	php_common
	
plp_28:
/* N=1 $B$+$D(B Z=1 $B$H$$$&$N$O(B $B$"$j$($kOC$G!"(B
 * NZ $B$G$OBP1~$G$-$J$$!#(B
 * $B$G$b!"$=$s$J$3$H(B $B$7$J$$$h$M(B...
 * $B$7$F$?!#(Bbit, exbike.nes
 * $B3d$j9~$_I|5"=hM}$N:G=i$K$b8F$P$l$k$N$G(B j next; $B$G5"$C$A$c%@@%a!#(B
 */
	addiu	SP, SP, 1
	andi	SP, SP, 0xff
	addu	t0, SP, WORK
	lbu	t0, OFFSET_WRAM + 0x100(t0)
	andi	t1, t0, 0x3c
	lbu	t3, OFFSET_WORK_RBDI(WORK)  /* Reserved|B|D|I */
	sb	t1, OFFSET_WORK_RBDI(WORK)  /* Reserved|B|D|I */
	andi	C, t0, 0x01                 /* C */
	andi	V, t0, 0x40                 /* V */
	andi	Z, t0, 0x02
	xori	Z, Z, 0x02                  /* Z */
	andi	N, t0, 0x80                 /* N */
/* I $B$,(B 1->0 $B$K$J$C$?$i(B $B3d$j9~$_%A%'%C%/$9$k(B */
	xor	t4, t3, t1
	and	t4, t4, t3
	andi	t4, t4, 0x04
	beq	t4, zero, store_done
	
	GLOBAL(check_intr_common)
check_intr_common:
	jr	STORE_DONE
#if 0
/* $B$&$^$/5!G=$7$F$$$J$$!#(B
 * $BB?=E3d$j9~$_=hM}$K<:GT$7$FK=Av$9$k(B (cv3j.nes)
 */
/* $B3d$j9~$_%A%'%C%/(B
 * irq cause $B$,(B 0 $B$G$J$1$l$P(B hit, $B3:Ev(B bit $B$r2<$m$9(B
 * cli_58 $B$+$i$bMh$k!#(B
 */
	lbu	t0, OFFSET_IRQ_CAUSE(WORK)
	li	t1, 0x80
	beq	t0, zero, store_done
1:
	and	t2, t0, t1
	srl	t1, t1, 1
	beq	t2, zero, 1b

	xor	t0, t0, t2
	sb	t0, OFFSET_IRQ_CAUSE(WORK)
	j	activate_intr_fffe  /* STORE_DONE $B$X5"$k(B */
#endif
	
	
jmp_6c:
/* a1 $B$N(B emu-cpu addr $B$+$i(B 2bytes $B$r(B $BFI$`!#(B
 * $BFI$s$@@=V4V$K3d$j9~$_$,$+$+$k$h$&$J(B I/O port $B$O$J$$$+$i(B PC $B$O(B $B$D$V$7$F$bNI$$!#(B
 */
			srl t0,a0,13; sll t0,t0,2; addu PAGE_PTR,t0,WORK; lw t1,OFFSET_LOADFUNC_TBL(PAGE_PTR); jalr t1
	addiu	a0, a0, 1
	move	PC, v0
			srl t0,a0,13; sll t0,t0,2; addu PAGE_PTR,t0,WORK; lw t1,OFFSET_LOADFUNC_TBL(PAGE_PTR); jalr t1
	sll	v0, v0, 8
	or	PC, PC, v0
	j	next

rti_40:
/* P, PC $B$NI|5"!#(B
 */
	la	STORE_DONE, 1f
	j	plp_28
1:
	la	STORE_DONE, 1f
	j	rts_60
1:
	addiu	PC, PC, -1
	andi	PC, PC, 0xffff
	j	next
			
	GLOBAL(load_ppu)
load_ppu:
/* 2002 $B$J$i(B read reset. debug $B$"$H!"I=<(%i%$%s$b$:$l$k$h$M(B ...
 * 2007 $B$J$i(B $B=hM}B?$$!#(B
 */
	andi	t0, a0, 0x07
	xori	t1, t0, 0x07
	addu	t0, t0, WORK
	beq	t1, zero, 1f
	lbu	v0, OFFSET_PPU2000H_OUTPUT(t0)
#if 0
/* debug */
	move	a1, a0
	PRINTF("%04xR\n");
#endif
	li	t2, 0x20
	sb	t2, OFFSET_PPU2000H_OUTPUT(t0) /* 2002H read reset */
	jr	ra
1:
#if 0
/* debug */
	move	a1, PC
	lhu	a2, OFFSET_LINECNT(WORK)
	PRINTF("2007R at PC=%x,line=%x");
#endif

/* debug
 * $BI=<(4|4VCf$NFI$_=P$7$J$i(B draw sccv ++;
 * $B$I$&$;(B $B=D$N(B $B6-3&1[$($O$J$$$h$M!#(B
 */
	lh	t2, OFFSET_LINECNT(WORK)
	lhu	t3, OFFSET_DRAW_SCCV(WORK)
	bltz	t2, 7f

	andi	$1, t3, 0x300
	addiu	t3, t3, 1
	andi	t3, t3, 0xff
	xori	t2, t3, 0xf0
	bne	t2, zero, 1f
	xori	$1, $1, 0x200
	li	t3, 0
1:
	or	t3, t3, $1
	sh	t3, OFFSET_DRAW_SCCV(WORK)
	
7:
/* 2007 read mode $B$,(B 0 $B$J$i(B 0 $B$G$J$/$7$F(B $B6uFI$_!#(B
 */
	lhu	t0, OFFSET_PPU_ADDR(WORK)
	lbu	t1, OFFSET_PPU2000H + 7(WORK) /* 2007 read mode $B$H$7$F;HMQ(B */
	bne	t1, zero, 1f
2:
/* $B6uFI$_(B/$BFI$_=P$7L58z(B
 * read mode $B$r(B 1 $B$K!#(B
 * a0 $B$N2<0L$OL@@$i$+$K(B 0 $B$G$O$J$$!#(B
 */
	li	v0, 0
	sb	a0, OFFSET_PPU2000H + 7(WORK) /* 2007 read mode $B$H$7$F;HMQ(B */
	jr	ra
1:
/* ppu_addr < 0x2000 $B$J$i(B chrrom/chrram
 *          < 0x3000 $B$J$i(B vram
 * $BB>$O(B $BL5;k(B
 */
	sltiu	t1, t0, 0x2000
	sltiu	t4, t0, 0x3000
	bne	t1, zero, 1f    /* chrrom/chrram */
	
	lhu	t2, OFFSET_VRAM_MIRROR_MASK_AND(WORK)
	lhu	t3, OFFSET_VRAM_MIRROR_MASK_OR(WORK)
	beq	t4, zero, load_2007_done
/* vram */
	and	t2, t2, t0
	or	t2, t2, t3
	srl	t3, t2, 1
	or	t2, t2, t3

	andi	t2, t2, 0x400
	andi	t0, t0, 0x3ff
	or	t0, t0, t2
	addu	t0, t0, WORK
	lbu	v0, OFFSET_GFXBUF + OFFSET_GFXBUF_DRAW_VRAM(t0)
#if 0
/* debug */
	move	a1, v0
	PRINTF("val=%x\n");
#endif
	
load_2007_done:
	move	STORE_DONE, ra
	j	store_2007_done  /* $B=q$-9~$_$8$c$J$$$1$I(B */

1:
/* chrrom/chrram
 * t0: ppu_addr
 * $BFI$_=P$7;~$K$b(B MMC3 pointer $B$N(B chr seg $B$,4X78$9$k!#(B(motherj.nes, chrrom $B$K%W%m%0%i%`(B)
 */
	lhu	t1, OFFSET_CHRSEG_FOR_READ(WORK)
	andi	t2, t0, 0x1c00
	xor	t2, t2, t1
	srl	t2, t2, 9      /* (/ 0x400) * 2 */
	addu	t2, t2, WORK
	lhu	t2, OFFSET_CHRBANK_REG0000(t2)
#if 0
/* debug */
	move	a1, t0
	move	a2, t2
	PRINTF("chrbank for %x=%x, ");
#endif
	lw	t1, OFFSET_CHRROM(WORK)
	andi	t3, t0, 0x03ff
	mul	t2, t2, 0x400
	addu	t2, t2, t3
	addu	t1, t1, t2
	lbu	v0, 0(t1)
#if 0
/* debug */
	move	a1, v0
	PRINTF("value=%x\n");
#endif
	j	load_2007_done


	GLOBAL(loade1_io)
loade1_io:
/* 110 in 1
 */
	addiu	t0, a0, -0x5800
	andi	t1, a0, 0x0003
	bltz	t0, load_io
	addu	t1, t1, WORK
	lbu	v0, OFFSET_BBRAM(t1)
	jr	ra
		
	GLOBAL(load_io)
load_io:
/* 4000-5fff
 * 4000-4013, 4015: sound
 * 4016: joypad
 * 4017: V ext mode
 * 4097 $B$^$G$O(B disksys $B%5%&%s%I4X78$,$"$k!#(B
 * 4030-4033: QD
 */
	andi	t0, a0, 0x1fff
	sltiu	t1, a0, 0x4018
	beq	t1, zero, 1f
	sll	t0, t0, 2
	addu	t0, t0, WORK
	lw	t0, OFFSET_LOAD_IO_FUNCTBL(t0)
	.set	noreorder
	jr	t0
1:
/* 4018-402f $B$O(B invalid
 * $B>e$N(B jr t0 $B$N(B delay slot $B$KF~$C$F$b(B $B$+$^$o$J$$!#(B
 */
	addiu	t1, a0, -0x4030
	.set	reorder
	addiu	t2, a0, -0x4034
	bltz	t1, load_invalid
/* a0=4030 -> t2=-4 -> t1=0
 *    4031       -3       1
 *    4032       -2       2
 *    4033       -1       3
 */
	addu	t3, t1, WORK
	bgez	t2, load_sound
	lbu	v0, OFFSET_QD4030H(t3)
	bne	t1, zero, 1f
/* 4030 read reset */
	sb	zero, OFFSET_QD4030H(WORK)
	jr	ra
1:
	li	t0, 0x4031
	lhu	t2, OFFSET_QDOFFSET + 2(WORK)
	bne	t0, a0, load_done
	addiu	t2, t2, 1
	sh	t2, OFFSET_QDOFFSET + 2(WORK)
	jr	ra

	GLOBAL(store_ppu)
store_ppu:
/* 2001, 2003 $B$O=q$/$@@$1(B
 * t0 $B$K(B a0 & 7 (keep!)
 * t1 $B$K(B t0 + WORK
 * t3 $B$K(B latch order (d0 $B$N$_;H$&(B)
 * reorder $B$,%P%+$J$N$G<j$G!#(B
 */
	andi	t0, a0, 0x07
	sll	t1, t0, 2
	addu	t1, t1, WORK
	lw	t2, OFFSET_STORE_PPU_FUNCTBL(t1)
	lbu	t3, OFFSET_PPU2000H_OUTPUT + 2(WORK)
	.set	noreorder
	jr	t2
	addu	t1, t0, WORK
	.set	reorder
	
	GLOBAL(store_ppu_ram)
store_ppu_ram:
/* t0 $B$K(B a0 & 7
 * t1 $B$K(B t0 + WORK
 */
#if 0
/* debug */
	move	a2, a0
	lhu	a3, OFFSET_LINECNT(WORK)
	PRINTF("PPU_RAM(%x->%x)line=%x\n");
1:
#endif
	
	sb	a1, OFFSET_PPU2000H(t1)
	jr	STORE_DONE

	GLOBAL(store_2005)
store_2005:
/* latch order $B$K$h$j(B draw scroll counter $B$rJQ99$9$k!#(B
 * $B4q?t2sL\(B - DRAW_SCCH $B$rJQ99!#$9$0M-8z$K$J$k!#(B
 * $B6v?t2sL\(B - DRAW_SCCV_NEW (low) $B$rJQ99!#$3$l$O<!$N%U%l!<%`$+$i(B $BM-8z$K$J$k!#(B
 * t3 $B$K(B latch order
 */
	xori	t3, t3, 1
	andi	t1, t3, 1
	sb	t3, OFFSET_PPU2000H_OUTPUT + 2(WORK)
	beq	t1, zero, 1f
/* $B4q?t2sL\(B */
#if 0
/* debug */
	lhu	a3, OFFSET_SERIAL4016D0(WORK)
	andi	a3, a3, 0x2000
	beq	a3, zero, 20f
	lhu	a2, OFFSET_LINECNT(WORK)
	PRINTF("2005H scch=%x at line=%x\n");
20:
#endif
	sb	a1, OFFSET_DRAW_SCCH(WORK)
	jr	STORE_DONE
1:
/* $B6v?t2sL\(B */
#if 0
/* debug */
	lhu	a3, OFFSET_SERIAL4016D0(WORK)
	andi	a3, a3, 0x2000
	beq	a3, zero, 20f
	lhu	a2, OFFSET_LINECNT(WORK)
	PRINTF("2005H sccv new=%x at line=%x\n");
20:
#endif
	sb	a1, OFFSET_DRAW_SCCV_NEW + 1(WORK)
	jr	STORE_DONE

	GLOBAL(store_2006)
store_2006:
/* latch order $B$K$h$j(B
 * $B4q?t2sL\(B - ppu_addr high $B$rJQ99!#(B
 * $B6v?t2sL\(B - ppu_addr low $B$rJQ99!#(B
 * t3 $B$K(B latch order
 * a2: ppu_addr high
 * a1: ppu_addr low  $B$K$9$k(B
 * 2007 read mode $B$r(B 0 $B$K$9$k(B
 */
	sb	zero, OFFSET_PPU2000H + 7(WORK) /* 2007 read mode $B$H$7$F;HMQ(B */
	xori	t3, t3, 1
	andi	t1, t3, 1
	sb	t3, OFFSET_PPU2000H_OUTPUT + 2(WORK)
	beq	t1, zero, 1f
/* $B4q?t2sL\(B */
	andi	t0, a1, 0x3f
	lbu	a1, OFFSET_PPU_ADDR + 1(WORK)
	sb	t0, OFFSET_PPU_ADDR + 0(WORK)
	move	a2, t0
	j	2f
1:
	lbu	a2, OFFSET_PPU_ADDR + 0(WORK)
	sb	a1, OFFSET_PPU_ADDR + 1(WORK)
2:
#if 0
/* debug */
	lhu	a3, OFFSET_SERIAL4016D0(WORK)
	andi	a3, a3, 0x2000
	beq	a3, zero, 20f
	lhu	a3, OFFSET_LINECNT(WORK)
	PRINTF("ppu_addr L,H=%02x,%02x at line=%x\n");
20:
#endif
/* devil.nes $B$O!"(Bold code $B$G$J$$$H%P%0$k!#(B
 */
#ifdef CODE_DEVIL
/* old code */
/* draw scroll counter $B$rJQ99$9$k!#(B
 * $BJQ49<0(B:
 * ppu_addr = 00YYyyyy yyyXXXXX
 * draw scch = XXXXX * 8
 * draw sccv new (high, low) = (yyyy yyy) * 8 + YY
 * ... $B$@@$H;W$&$1$I!"(B low $B$OL5;k!#(B
 * draw sccv $B$K$bB(:B$KH?1G$5$;$k!#(B
 * a2: ppu_addr high
 * a1: ppu_addr low
 */
	sll	t0, a1, 3
	sb	t0, OFFSET_DRAW_SCCH(WORK)
	srl	t0, a2, 4
	andi	t0, t0, 0x03  /* YY */
	andi	t1, a2, 0x0f
	sll	t1, t1, 3 + 3 /* yyyy yyy $B$N(B yyyy */
	srl	t2, a1, 5 - 3 /* yyyy yyy $B$N(B yyy  */
	andi	t2, t2, 0x38
	or	t0, t0, t1
	or	t0, t0, t2
	sh	t0, OFFSET_DRAW_SCCV(WORK)
#endif

/* devil.nes $B$O!"(Bold code $B$G$J$$$H%P%0$k!#(B
 */
#ifndef CODE_DEVIL
/* new code */
/* draw scroll counter $B$rJQ99$9$k!#(B
 * $BJQ49<0(B:
 * ppu_addr = 00YYyyyy yyyZZZ00
 * draw scch = 0
 * draw sccv new (high, low) = (yyyy yyy) * 8 + YY + ZZZ
 * cv3j.nes $B$N=D%9%/%m!<%k$N$H$-(B
 * 28c0,28bc,28b8,28b4,28b0,28ac $B$H$+$7$F$k!#(B
 * draw sccv $B$K$bB(:B$KH?1G$5$;$k!#(B
 * a2: ppu_addr high
 * a1: ppu_addr low
 */
	sb	zero, OFFSET_DRAW_SCCH(WORK)
	srl	t0, a2, 4
	andi	t0, t0, 0x03  /* YY */
	andi	t1, a2, 0x0f
	sll	t1, t1, 3 + 3 /* yyyy yyy $B$N(B yyyy */
	srl	t2, a1, 5 - 3 /* yyyy yyy $B$N(B yyy  */
	andi	t2, t2, 0x38
	or	t0, t0, t1
	or	t0, t0, t2
	andi	t1, a1, 0x1c
	srl	t1, t1, 2
	addu	t0, t0, t1
	andi	t1, t0, 0xff
	sltiu	t1, t1, 0xf0
	bne	t1, zero, 1f
	andi	t1, t0, 0x200
	addiu	t0, t0, 0x10
	andi	t0, t0, 0xff
	or	t0, t0, t1
1:
	sh	t0, OFFSET_DRAW_SCCV(WORK)
#endif
	
/* debug
 * cluclu.nes, jaleco/ninjakun.nes $B<B83(B
 */
	sh	t0, OFFSET_DRAW_SCCV_NEW(WORK)

	jr	STORE_DONE


	GLOBAL(store_palette)
store_palette:
/* t0: ppu_addr
 * t2 $B$,(B 1 $B$J$i(B ppu_addr < 0x3f00 $B$J$N$GL58z!#(B
 *
 */
	sb	zero, OFFSET_PPU2000H + 7(WORK) /* 2007 read mode $B$H$7$F;HMQ(B */
	andi	t1, t0, 0x1f
	bne	t2, zero, store_2007_done
/* $B%Q%l%C%H(B
 * 3f00 or 3f10 $B$J$i(B background color
 */
	andi	t2, t1, 0x0f
	addu	t3, t1, WORK
	beq	t2, zero, 1f
/* 3f04,08,0c, 14,18,1c $B$OL5;k(B */
	andi	t2, t1, 0x03
	beq	t2, zero, store_2007_done
	andi	t0, a1, 0x3f
	sb	t0, OFFSET_PALETTE_BUF(t3)
	j	store_2007_done
1:
	andi	t0, a1, 0x3f
	sb	t0, OFFSET_PALETTE_BUF + 0x00(WORK)
	sb	t0, OFFSET_PALETTE_BUF + 0x04(WORK)
	sb	t0, OFFSET_PALETTE_BUF + 0x08(WORK)
	sb	t0, OFFSET_PALETTE_BUF + 0x0c(WORK)
	sb	t0, OFFSET_PALETTE_BUF + 0x10(WORK)
	sb	t0, OFFSET_PALETTE_BUF + 0x14(WORK)
	sb	t0, OFFSET_PALETTE_BUF + 0x18(WORK)
	sb	t0, OFFSET_PALETTE_BUF + 0x1c(WORK)
	j	store_2007_done

	GLOBAL(store_2007_chrram)
store_2007_chrram:
	lhu	t0, OFFSET_PPU_ADDR(WORK)
	sltiu	t1, t0, 0x2000
	sltiu	t3, t0, 0x3000
	beq	t1, zero, 7f
/* chrram $B$J$N$G!"(Boriginal format $B$H(B internal format $B$r%;%C%H!#(B
 * bank $B$O(B ... $BL5;k$G$-$J$$(B(goemon1j.nes)$B!#(B
 * $B$H$j$"$($:(B chrbank @@ 0000- $B$N(B $B%l%8%9%?$@@$1(B $B8+$h$&!#(B
 */
	lhu	t4, OFFSET_CHRBANK_REG0000(WORK)
	mul	t4, t4, 0x400
	lw	t2, OFFSET_CHRROM(WORK)
	addu	t2, t2, t0
	addu	t2, t2, t4
	sb	a1, 0(t2)
#if 0
/* debug */
	la	t1, debug_ptr
	lw	t3, 0(t1)
	lw	t1, 0(t3)
	tge	t1,zero
#endif
/* (ppu_addr & 0x07) -> dst. offset +0,+0x80,+0x100,...,+0x380
 * (ppu_addr & 0x3f0) -> dst. offset +0,+2,+4,...,+0x7e
 * (ppu_addr & 0x08) -> dst.offset +1,+0
 */
	andi	t1, t0, 0x07
	sll	t1, t1, 7    /* 0x01 -> 0x80 */
	andi	t2, t0, 0x3f0
	srl	t2, t2, 3    /* 0x3f0 -> 0x7e */
	addu	t1, t1, t2
	andi	t2, t0, 0x1c00
	addu	t1, t1, t2
	andi	t2, t0, 0x08
	srl	t2, t2, 3    /* 0x08 -> 0x01 */
	xori	t2, t2, 1
	addu	t1, t1, t2
	addu	t1, t1, WORK
	addu	t1, t1, t4
	sb	a1, OFFSET_GFXBUF + OFFSET_GFXBUF_DRAW_CHR(t1)

#if 0
/* debug */
	lw	a2, OFFSET_EMUFRAME(WORK)
	sltiu	a2, a2, 20
	bne	a2, zero, 10f
	xori	a2, a1, 0x70
	bne	a2, zero, 10f
	sw	a1,OFFSET_TRACE_FLAG(WORK)
10:
#endif
	j	store_2007_done
	
	GLOBAL(store_2007_chrrom)
store_2007_chrrom:
/*
 * ppu_addr < 0x2000 $B$J$i(B $BL5;k!#(B (debug chrram $BL$BP1~(B)
 * ppu_addr > 0x2fff $B$J$i(B palette $B$+$b!#(B
 * t0: ppu_addr
 */
	lhu	t0, OFFSET_PPU_ADDR(WORK)
	sltiu	t1, t0, 0x2000
	sltiu	t3, t0, 0x3000
	bne	t1, zero, store_2007_done
7: /* store_2007_chrram $B$+$i$bMh$k!#(B*/
	sltiu	t2, t0, 0x3f00
	beq	t3, zero, store_palette
	GLOBAL(store_vram)
store_vram:
#if 0
/* debug */
	move	a2, t0
	PRINTF("%x->vram[%x]\n");
#endif
/* t0: ppu_addr
 * mirror mask and $B$O(B 0x000 -> one screen mode
 *                    0x400 -> $B2#;}$A(B
 *                    0x800 -> $B=D;}$A(B
 *                    0xc00 -> $B$"$j$($J$$(B
 * mirror mask or  $B$O(B 0x000 -> $BDL>o%b!<%I(B or one screen mode @@ vram[0x000]
 *                    0x400 -> one screen mode @@ vram[0x400]
 *                    0x800 -> one screen mode @@ vram[0x800] ($BL$<BAu(B)
 *                    0xc00 -> $B$"$j$($J$$(B
 * ppu_addr $B$K(B mask and $B$7$F!"(B mask or $B$7$?$b$N$N(B 0xc00 $B$N0L$O(B
 * (0xc00 $B$OL$<BAu$J$N$G=|$/(B)
 * 0 or 0x400 or 0x800 $B$K$J$k!#(B
 * 0x400 or 0x800 $B$J$i(B vram[0x400] $B$+$i$K$7$?$$$N$G(B
 * >> 1 $B$7$?$b$N$H(B or $B$7$?(B 0x400 $B$N0L(B $B$r:NMQ$9$k!#(B
 */
	lhu	t2, OFFSET_VRAM_MIRROR_MASK_AND(WORK)
	lhu	t3, OFFSET_VRAM_MIRROR_MASK_OR(WORK)

	and	t2, t2, t0
	or	t2, t2, t3
	srl	t3, t2, 1
	or	t2, t2, t3

	andi	t2, t2, 0x400
	andi	t3, t0, 0x3ff
	or	t2, t2, t3
#if 0
/* debug */
	xori	a2, t2, 0x480
	bne	a2, zero, 1f
	xori	a2, a1, 0x88
	bne	a2, zero, 1f
	sw	a1, OFFSET_TRACE_FLAG(WORK)
1:
#endif
	addu	t1, t2, WORK
	sb	a1, OFFSET_GFXBUF + OFFSET_GFXBUF_DRAW_VRAM(t1)
/*
 * attr $B$J$i(B $B3:Ev(B draw vram attr $B$rJQ99$9$k!#(B
 * t0: ppu_addr
 * t2: vram mirror $B$r9MN8$7$?(B ppu_addr
 * t3: (ppu_addr & 0x3ff) -0x3c0
 */
	addiu	t3, t3, -0x3c0
	bltz	t3, store_2007_done
/* ppu_addr $B$N2<0L(B 0x3c0-0x3ff $B$K$D$$$F(B
 * 23c0-23c7: 2000-207f
 * 23c8-23cf: 2080-20ff
 * 23d0-23d7: 2100-217f
 * 23d8-23df: 2180-21ff
 * 23e0-23e7: 2200-227f
 * 23e8-23ef: 2280-22ff
 * 23f0-23f7: 2300-237f
 * 23f8-23ff: 2380-23ff
 * $B$N(B attr $B$,JQ$o$k!#(B
 * $B$D$^$j(B ppu_addr $B$N$5$i$K2<0L(B 0x3f $B$K$D$$$F(B
 * 00: 2000,2001, 2002,2003,
 *     2020,2021, 2022,2023,
 *
 *     2040,2041, 2042,2043,
 *     2060,2061, 2062,2063,
 *
 * $B$N%(%j%"$K1F6A$9$k!#(B(d1,d0) (d3,d2)
 *                     (d5,d4) (d7,d6)
 *
 * $B2<0L(B 0,1,...,7  -> 0,4,...,1c
 * $B2<0L(B 0,8,...,38 -> 0,80,...,380
 */
	andi	t1, t3, 0x07
	sll	t1, t1, 2
	
	andi	t0, t3, 0x38
	sll	t0, t0, 4
	or	t0, t0, t1

	andi	t2, t2, 0x400
	or	t0, t0, t2
	addu	t0, t0, WORK

/* (d7,d6) -> draw vram + (0x40 $B$H(B 0x60) + (2 $B$H(B 3) */
	andi	t1, a1, 0xc0
	sb	t1, OFFSET_GFXBUF + OFFSET_GFXBUF_DRAW_VRAM + KS_RFC_VRAM_SIZE + 0x42(t0)
	sb	t1, OFFSET_GFXBUF + OFFSET_GFXBUF_DRAW_VRAM + KS_RFC_VRAM_SIZE + 0x43(t0)
	sb	t1, OFFSET_GFXBUF + OFFSET_GFXBUF_DRAW_VRAM + KS_RFC_VRAM_SIZE + 0x62(t0)
	sb	t1, OFFSET_GFXBUF + OFFSET_GFXBUF_DRAW_VRAM + KS_RFC_VRAM_SIZE + 0x63(t0)
/* (d5,d4) -> draw vram + (0x40 $B$H(B 0x60) + (0 $B$H(B 1) */
	andi	t2, a1, 0x30
	sll	t2, t2, 2
	sb	t2, OFFSET_GFXBUF + OFFSET_GFXBUF_DRAW_VRAM + KS_RFC_VRAM_SIZE + 0x40(t0)
	sb	t2, OFFSET_GFXBUF + OFFSET_GFXBUF_DRAW_VRAM + KS_RFC_VRAM_SIZE + 0x41(t0)
	sb	t2, OFFSET_GFXBUF + OFFSET_GFXBUF_DRAW_VRAM + KS_RFC_VRAM_SIZE + 0x60(t0)
	sb	t2, OFFSET_GFXBUF + OFFSET_GFXBUF_DRAW_VRAM + KS_RFC_VRAM_SIZE + 0x61(t0)
/* (d3,d2) -> draw vram + (0x00 $B$H(B 0x20) + (2 $B$H(B 3) */
	andi	t3, a1, 0x0c
	sll	t3, t3, 4
	sb	t3, OFFSET_GFXBUF + OFFSET_GFXBUF_DRAW_VRAM + KS_RFC_VRAM_SIZE + 0x02(t0)
	sb	t3, OFFSET_GFXBUF + OFFSET_GFXBUF_DRAW_VRAM + KS_RFC_VRAM_SIZE + 0x03(t0)
	sb	t3, OFFSET_GFXBUF + OFFSET_GFXBUF_DRAW_VRAM + KS_RFC_VRAM_SIZE + 0x22(t0)
	sb	t3, OFFSET_GFXBUF + OFFSET_GFXBUF_DRAW_VRAM + KS_RFC_VRAM_SIZE + 0x23(t0)
/* (d1,d0) -> draw vram + (0x00 $B$H(B 0x20) + (0 $B$H(B 1) */
	sll	t4, a1, 6
	sb	t4, OFFSET_GFXBUF + OFFSET_GFXBUF_DRAW_VRAM + KS_RFC_VRAM_SIZE + 0x00(t0)
	sb	t4, OFFSET_GFXBUF + OFFSET_GFXBUF_DRAW_VRAM + KS_RFC_VRAM_SIZE + 0x01(t0)
	sb	t4, OFFSET_GFXBUF + OFFSET_GFXBUF_DRAW_VRAM + KS_RFC_VRAM_SIZE + 0x20(t0)
	sb	t4, OFFSET_GFXBUF + OFFSET_GFXBUF_DRAW_VRAM + KS_RFC_VRAM_SIZE + 0x21(t0)
	
/* thru!! */
	GLOBAL(store_2007_done)
store_2007_done:
/* $B=D=q$-$+!"2#=q$-$+$G(B ppu_addr $B$NA}$(J}$,JQ$o$k!#(B
 * load_ppu $B$+$i$bMh$k!#(B
 */
	lbu	t0, OFFSET_PPU2000H(WORK)
	lhu	t1, OFFSET_PPU_ADDR(WORK)
	andi	t0, t0, 0x04
	addiu	t1, t1, 1
	beq	t0, zero, 1f      /* $B2#=q$-(B */
	addiu	t1, t1, 0x20 - 1  /* $B=D=q$-(B */
1:
	andi	t1, t1, 0x3fff
	sh	t1, OFFSET_PPU_ADDR(WORK)
#if 0
/* debug */
	move	a1,t1
	PRINTF("next ppu_addr=%x\n");
#endif
	jr	STORE_DONE

	GLOBAL(store_4014)
store_4014:
/* oam DMA
 * a1: src emu-cpu addr high
 * a1 < 0x20 $B$J$i(B internal wram
 * a1 >= 0x60 $B$J$i(B page table $B;2>H!#(B
 * $BB>$O(B $BL5;k!#(B
 * t0: dst
 * t1: src
 * t2: src ptr end
 */
#if 0
/* debug */
	lhu	a2, OFFSET_LINECNT(WORK)
	PRINTF("DMA=%x at line %x\n");
#endif
	
	sltiu	t0, a1, 0x20
	andi	t1, a1, 0x07
	sll	t1, t1, 8
	addu	t1, t1, WORK
#if OFFSET_WRAM
	addiu	t1, t1, OFFSET_WRAM
#endif
	bne	t0, zero, 1f  /* internal wram */
	
	sltiu	t0, a1, 0x60
	sll	t1, a1, 8
	bne	t0, zero, store_done
	srl	t2, t1, 13
	sll	t2, t2, 2
	addu	t2, t2, WORK
	lw	t2, OFFSET_PAGE_TABLE(t2)
	addu	t1, t1, t2
1:
	move	t0, WORK
	addiu	t2, t0, 0x100
2:
	ld	t3, 0(t1)
	ld	t4, 8(t1)
	sd	t3, OFFSET_OAM + 0(t0)
	sd	t4, OFFSET_OAM + 8(t0)
	addiu	t1, t1, 0x10
	addiu	t0, t0, 0x10
	bne	t0, t2, 2b
/* OAM DMA $B$O(B 512 clock $B>CHq$9$k!#(B
 * $B$s$H$A$c$&$N(B ?
 */
	li	t0, 0x200 * 0x100
	addu	LINECYCLE, LINECYCLE, t0
	jr	STORE_DONE
	
	GLOBAL(store_2004)
store_2004:
/* oam $B$K=q$-9~$_(B - $B;H$o$J$$$H$O;W$&$1$I!"0l1~<BAu$7$H$+$J$$$H$M!#(B
 */
	lbu	t0, OFFSET_PPU2000H + 3(WORK)  /* oam addr */
	addu	t1, t0, WORK
	sb	a1, OFFSET_OAM(t1)
	addiu	t0, t0, 1
	sb	t0, OFFSET_PPU2000H + 3(WORK)
	jr	STORE_DONE

	GLOBAL(load_invalid)	
load_invalid:
#if 0
/* debug */
	TRAP("load invalid");
#endif
#if 0
/* debug */
	move	a1, a0
	move	a2, PC
	lhu	a3, OFFSET_LINECNT(WORK)
	PRINTF("invalid load(%x)PC=%x,line=%x\n");
#endif
	srl	v0, a0, 8
	jr	ra

	GLOBAL(store_invalid)
store_invalid:
#if 0
/* debug */
	TRAP("store invalid");
#endif
/*	j	store_verbose */
	jr	STORE_DONE

	GLOBAL(load_sound)
load_sound:
	sltiu	t0, a0, 0x40a0
	beq	t0, zero, load_invalid

/* kmar.rda, kaemario.fam $B$G(B 4015R $B$7$F$k$h!#(B
 */
#if 0
/* debug */
	TRAP("load sound");
#endif
	sw	LINECYCLE, OFFSET_THREAD_LINECYCLE(WORK)
	sw	STORE_DONE, OFFSET_THREAD_STORE_DONE(WORK)
	sw	gp, OFFSET_THREAD_GP(WORK)

	sw	ra, OFFSET_STACK_RA_SOUND(sp)
	sw	a0, OFFSET_STACK_A0(sp)
	sw	v1, OFFSET_STACK_V1(sp)
	sw	JUMPTBLP, OFFSET_THREAD_JUMPTBLP(WORK)
	sw	PAGE_PTR, OFFSET_THREAD_PAGE_PTR(WORK)

	jal	Sound_Read
	
	lw	LINECYCLE, OFFSET_THREAD_LINECYCLE(WORK)
	lw	STORE_DONE, OFFSET_THREAD_STORE_DONE(WORK)
	lw	gp, OFFSET_THREAD_GP(WORK)
	
	lw	ra, OFFSET_STACK_RA_SOUND(sp)
	lw	a0, OFFSET_STACK_A0(sp)
	lw	v1, OFFSET_STACK_V1(sp)
	lw	JUMPTBLP, OFFSET_THREAD_JUMPTBLP(WORK)
	lw	PAGE_PTR, OFFSET_THREAD_PAGE_PTR(WORK)
	jr	ra


	GLOBAL(store_2000)
store_2000:
/* t0 $B$K(B a0 & 7
 * t1 $B$K(B t0 + WORK
 * draw sccv new $B$K(B MSBV,H $B$r%;%C%H$9$k!#(B
 * draw sccv $B$N(B MSBH $B$@@$1$OB(H?1~(B ?
 * $BA02s$N(B 2000H $B$H(B d4 $B$,0c$($P(B BG, d3 $B$,0c$($P(B OBJ bank change.
 */
	lbu	t3, OFFSET_PPU2000H(WORK)
	sb	a1, OFFSET_PPU2000H(WORK)
	andi	t0, a1, 0x03  /* MSBV | MSBH */

/* debug
 * cluclu.nes $B$H(B jaleco/ninjakun.nes $B$N8_49@@-$O(B ?
 */
	sb	t0, OFFSET_DRAW_SCCV_NEW(WORK)


	lbu	t1, OFFSET_DRAW_SCCV(WORK)
	andi	t0, t0, 0x01  /* MSBH */
	andi	t1, t1, 0xfe
	or	t0, t0, t1
	sb	t0, OFFSET_DRAW_SCCV(WORK)

#if 0
/* debug */
	lhu	a2, OFFSET_LINECNT(WORK)
	move	a3, LINECYCLE
	PRINTF("2000=%x at line %x--%x\n");
#endif
#if 0
/* debug */
	lhu	t2, OFFSET_VRAM_MIRROR_MASK_AND(WORK)
	andi	t1, t2, 0x400
	teq	t1, zero
#endif
	xor	t3, t3, a1
	andi	t2, t3, 0x10
	andi	t1, t3, 0x08
	beq	t2, zero, 1f
	sb	zero, OFFSET_BG_CHRBANK_TOUCH_FLAG(WORK)
1:
	beq	t1, zero, store_done
	sb	zero, OFFSET_OBJ_CHRBANK_TOUCH_FLAG(WORK)
	jr	STORE_DONE

	GLOBAL(store05_io)
store05_io:
/* MMC5
 * < 0x5000 $B$J$i(B store_io $B$X!#(B
 * < 0x5016 $B$J$i(B store_sound $B$X!#(B
 * >= 5c00 $B$J$i(B exram $B=q$-9~$_(B
 * < 0x5100 $B$J$i(B ignore
 * < 0x5131 $B$J$i(B index jump
 * < 0x5200 $B$J$i(B ignore
 * >= 0x5207 $B$J$i(B ignore
 * 5200-5206 $B$O(B CPU ver, $B>h;;(B $B$J$I(B
 */
#if 0
/* debug */
	move	a2, a0
	PRINTF("05_io(%x->%x)\n");
#endif
	.set	noreorder
	sltiu	t0, a0, 0x5000
	bne	t0, zero, store_io
	sltiu	t0, a0, 0x5016
	bne	t0, zero, store_sound
	sltiu	t0, a0, 0x5c00
	beq	t0, zero, store05_5c00
	sltiu	t0, a0, 0x5100
	bne	t0, zero, store_invalid
	sltiu	t0, a0, 0x5131
	bne	t0, zero, 1f
	sltiu	t0, a0, 0x5200
	bne	t0, zero, store_invalid
	sltiu	t0, a0, 0x5207
	beq	t0, zero, store_ignore  /* o/enix/justbred.nes $B$,(B 5800 $B$K=q$-9~$s$G$$$k(B */
/* 5200-5202 $B$O(B RAM $B$H$7$F!#(B
 */
	addiu	t1, a0, -0x5203
	bltz	t1, store05_5c00_common
	addiu	t0, a0, -0x5200 + 0x400 /* $B$3$3$G(B 5c00-5fff $B$N8e$K$J$k$h$&(B offset $BD4@@0(B */

	addiu	t2, a0, -0x5205
	bltz	t2, 3f
/*
 * 5205 $B$O(B multiple trigger
 * 5206 $B$O(B multiple source
 */
	addiu	t2, a0, -0x5205
	bne	t2, zero, 2f
	lbu	t0, OFFSET_MMC5_MULT_SRC(WORK)
	mul	t0, t0, a1
	.set	reorder
/* 5205 multiple trigger
 * t0: src -> result
 */
	srl	t1, t0, 8
	sb	t0, OFFSET_MMC5_EXRAM + 0x400 + 0x05(WORK) /* result low */
	sb	t1, OFFSET_MMC5_EXRAM + 0x400 + 0x06(WORK) /* result high */
	jr	STORE_DONE
2: /* 5206 multiple source */
	sb	a1, OFFSET_MMC5_MULT_SRC(WORK)
	jr	STORE_DONE
1:
/* 5100-5131, index jump
 * t0 $B$K(B amode_pamode (fixed)
 * t1 $B$K(B $B2?$+F~$l$?$$!#(B
 */
	andi	t0, a0, 0x3f
	sll	t0, t0, 2
	addu	t0, t0, WORK
	lw	t2, OFFSET_MMC5_STOREFUNC_TBL(t0)
	lhu	t0, OFFSET_MMC5_AMODE_PAMODE(WORK)
	jr	t2
3:
/* 5203,5204
 * 5203: V $B0LCV3d$j9~$_(B
 * 5204: d7: $B3d$j9~$_(B enable
 * t1: a0 - 0x5203
 */
	andi	t0, a1, 0x80
	beq	t1, zero, 33f
	lbu	t1, OFFSET_SUN5_IRQ_L(WORK)
	sb	t0, OFFSET_LINECNT_IRQ_ENABLED(WORK)
	sh	t1, OFFSET_LINECNT_IRQ(WORK)
	jr	STORE_DONE
33:
	sb	a1, OFFSET_SUN5_IRQ_L(WORK)
	sh	a1, OFFSET_LINECNT_IRQ(WORK)
	jr	STORE_DONE

	GLOBAL(store05_5c00)
store05_5c00:
/* MMC5 exram
 */
	addiu	t0, a0, -0x5c00

	GLOBAL(store05_5c00_common)
store05_5c00_common:
	addu	t0, t0, WORK
	sb	a1, OFFSET_MMC5_EXRAM(t0)
	jr	STORE_DONE

	GLOBAL(store13_io)
store13_io:
/* Namcot 106
 * 5000-5fff $B$O(B IRQ
 */
	sltiu	t0, a0, 0x5000
	andi	t1, a0, 0x0800
	bne	t0, zero, store_io
	srl	t1, t1, 11
	j	store13_5000
	
	GLOBAL(storee1_io)
storee1_io:
/* 110 in 1
 * 5800-5fff $B$K(B 4 bytes $B$@@$1(B low 4bits $B$N(B RAM $B$,$"$k!#(B
 */
	addiu	t0, a0, -0x5800
	andi	t1, a0, 0x0003
	bltz	t0, store_io
	addu	t1, t1, WORK
	sb	a1, OFFSET_BBRAM(t1)
	jr	STORE_DONE
		
	GLOBAL(store_io)
store_io:
/* 4000-5fff
 * 4000-4013, 4015: sound
 * 4014: OAM DMA
 * 4016: joypad
 * 4017: V ext mode
 * 4097 $B$^$G$O(B disksys $B%5%&%s%I4X78$,$"$k!#(B
 * 4020-4026: QD
 * funcptr $B$r(B $BB?$a$KMQ0U$7$F(B 4027 $B0J9_$r(B $B%5%&%s%I$X!#(B
 */
	andi	t0, a0, 0x1fff
	sltiu	t1, a0, 0x4027
	beq	t1, zero, store_sound
	sll	t0, t0, 2
	addu	t0, t0, WORK
	lw	t0, OFFSET_STORE_IO_FUNCTBL(t0)
	jr	t0

/* a0 > 0xffff $B$N$H$-$NFC<l4X?t(B
 * $BE57?E*$K$O!"(B PC > 0xffff $B$K$J$C$?$H$-$H;W$o$l$k$N$G(B
 * PC $B$K(B mask $B$r$+$1$F(B $B$"$H$O(B internal wram $B$N=hM}$X!#(B
 */
	GLOBAL(load_internal_wram_10000)
load_internal_wram_10000:
	andi	PC, PC, 0xffff
	j	load_internal_wram

	GLOBAL(store_sound)
store_sound:
/* JUMPTBLP, PAGE_PTR $B$OJ]B8$7$J$/$F$h$$!#(B
 * store 16bit $B$J$s$F$J$$$7!#(B
 * LINECYCLE, STORE_DONE $B$r%;!<%V!#(B
 * a2 $B$K(B linecycle.
 */

#if 0
/* debug */
	xori	t0, a0, 0x4088
	bne	t0, zero, 1f
	sll	a1, a1, 1
	andi	a1, a1, 0x07
	PRINTF("<%02x>");
1:
#endif

	
#if 0
/* debug
 * disksys sound $B$X$N=q$-9~$_$r4F;k(B
 */
	xori	t0, a0, 0x4084
	beq	t0, zero, 4f
	xori	t0, a0, 0x4085
	bne	t0, zero, 9f
/* 4085 */
	beq	a1, zero, 8f
	j	8f

4:
/* 4084 */
	andi	t0, a1, 0xc0
	andi	t1, a1, 0x20
	andi	t2, a1, 0x1f
	sll	t2, t2, 1
	or	t1, t1, t2
	or	a1, t0, t1
8:
	andi	a2, a0, 0x000f
	PRINTF("<%02x-%x>");
9:
#endif

#if 0
/* debug */
	move	a2, a0
	PRINTF("sound(%x->%x)\n");
#endif
#if 1
	xori	t0, a0, 0x4010
	bne	t0, zero, 1f

/* 4010H patch test
 * $BA02s$HF1$8CM$J$iL5;k!#(B
 */
	lhu	t1, OFFSET_WORK_4010H_OUTPUT(WORK)
	sh	a1, OFFSET_WORK_4010H_OUTPUT(WORK)
	beq	t1, a1, store_done
1:
#endif
store_sound_4023:
	sw	LINECYCLE, OFFSET_THREAD_LINECYCLE(WORK)
	sw	STORE_DONE, OFFSET_THREAD_STORE_DONE(WORK)
	sw	gp, OFFSET_THREAD_GP(WORK)

/* div $B%^%/%m$O(B $B%Q%i%a%?$,(B 2 $B8D$J$i(B $B:G=i$N(B $B%l%8%9%?$K(B $B>!<j$K(B mflo $B$rIU$12C$($F$7$^$&(B !!
 * a2 = a2 / t0 $B$,(B $B$d$j$?$$$N$@@!#(B
 * $B%"%;%s%V%i$K$h$k(B $B6/@@)(B 0 $B=|;;%A%'%C%/$r>J$/$?$a$K$O(B
 * div[u] zero, a2, t0; mflo a2 $B$GNI$$!#(B
 */
	lw	a2, OFFSET_SOUNDCYCLE(WORK)
#if 0
/* debug $B$J$s$G2;$,JQ$K$J$k(B ?
 */
	sra	LINECYCLE, LINECYCLE, 8
	addu	a2, a2, LINECYCLE
	addiu	a2, a2, (-(LINECYCLE_CONST0 + LINECYCLE_CONST1) / 0x100)  /* linecycle $B$O(B $BIi$+$i;O$^$C$F$$$k(B */
#endif
	lbu	t0, OFFSET_SOUND_CYCLE_DIVIDER(WORK)
	divu	zero, a2, t0
	mflo	a2
#if 0
/* debug */
	move	a3, LINECYCLE
	PRINTF("Sound_Write(reg,%x,%x)cycle=%x\n");
#endif

	jal	Sound_Write

	lw	LINECYCLE, OFFSET_THREAD_LINECYCLE(WORK)
	lw	STORE_DONE, OFFSET_THREAD_STORE_DONE(WORK)
	lw	gp, OFFSET_THREAD_GP(WORK)
	jr	STORE_DONE
	
	GLOBAL(store_4016)
store_4016:
/* d0=1 $B$J$i(B serial -> work $B$X(B copy
 */
#if 0
/* debug */
	move	a2, PC
	PRINTF("4016=%x at PC=%x\n");
#endif
	sb	a1, OFFSET_WORK_4016H(WORK)
	andi	t0, a1, 0x01
	beq	t0, zero, store_done

	ld	t0, OFFSET_SERIAL4016D1(WORK)
	ld	t1, OFFSET_SERIAL4017D5(WORK)
	ld	t2, OFFSET_SERIAL4017D3(WORK)
	ld	t3, OFFSET_SERIAL4017D1(WORK)

	sd	t0, OFFSET_WORK_4016D1(WORK)
	sd	t1, OFFSET_WORK_4017D5(WORK)
	sd	t2, OFFSET_WORK_4017D3(WORK)
	sd	t3, OFFSET_WORK_4017D1(WORK)
	jr	STORE_DONE

	GLOBAL(store_4017)
store_4017:
/* d7: V ext mode $B$OFf!#(B
 * d6: /(V int en)
 * $BNI$/J,$+$i$s$N$G(B d7,d6=0,0 $B$N$H$-$N$_(B V ext int $BH/@@8$K$7$F$_$k!#(B
 */
#if 0
/* debug */
	move	a2, PC
	PRINTF("4017=%x at PC=%x\n");
#endif
#if 0
/* debug */
	PRINTF("4017=%x\n");
#endif
	andi	t0, a1, 0xc0
	sb	t0, OFFSET_WORK_4017H(WORK)
	jr	STORE_DONE
	
	GLOBAL(load_4016)
load_4016:
#if 0
/* debug */
	move	a1, PC
	PRINTF("4016R at PC=%x\n");
#endif
	lbu	t0, OFFSET_WORK_4016H(WORK)
	lw	t1, OFFSET_WORK_4016D1(WORK)
	lw	t2, OFFSET_WORK_4016D0(WORK)
	srl	t3, t1, 30   /* d31 -> d1 */
	andi	t3, t3, 0x02
	srl	t4, t2, 31   /* d31 -> d0 */
	andi	t4, t4, 0x01
	or	t3, t3, t4
	ori	v0, t3, 0x40
/* need to shift ? */
	andi	t0, t0, 0x01
	bne	t0, zero, load_done
	sll	t1, t1, 1
	sll	t2, t2, 1
	sw	t1, OFFSET_WORK_4016D1(WORK)
	sw	t2, OFFSET_WORK_4016D0(WORK)
	jr	ra

	GLOBAL(load_4017)
load_4017:
#if 0
/* debug */
	move	a1, PC
	PRINTF("4017R at PC=%x\n");
#endif
	lw	t4, OFFSET_WORK_4017D4(WORK)
	lw	t3, OFFSET_WORK_4017D3(WORK)
	lw	t2, OFFSET_WORK_4017D2(WORK)
	lw	t1, OFFSET_WORK_4017D1(WORK)
	lw	t0, OFFSET_WORK_4017D0(WORK)

	srl	$1, t4, 27  /* d31 -> d4 */
	andi	v0, $1, 0x10
	srl	$1, t3, 28  /* d31 -> d3 */
	andi	$1, $1, 0x08
	or	v0, v0, $1
	srl	$1, t2, 29  /* d31 -> d2 */
	andi	$1, $1, 0x04
	or	v0, v0, $1
	srl	$1, t1, 30  /* d31 -> d1 */
	andi	$1, $1, 0x02
	or	v0, v0, $1
	srl	$1, t0, 31  /* d31 -> d0 */
	andi	$1, $1, 0x01
	or	v0, v0, $1
	ori	v0, v0, 0x40
	lbu	$1, OFFSET_WORK_4016H(WORK)
	andi	$1, $1, 0x01
	bne	$1, zero, load_done
	sll	t4, t4, 1
	sll	t3, t3, 1
	sll	t2, t2, 1
	sll	t1, t1, 1
	sll	t0, t0, 1
	sw	t4, OFFSET_WORK_4017D4(WORK)
	sw	t3, OFFSET_WORK_4017D3(WORK)
	sw	t2, OFFSET_WORK_4017D2(WORK)
	sw	t1, OFFSET_WORK_4017D1(WORK)
	sw	t0, OFFSET_WORK_4017D0(WORK)
	jr	ra

	GLOBAL(load_4015)
load_4015:

	lbu	v0, OFFSET_WORK_4015H_OUTPUT(WORK)
#if 0
	sw	ra, OFFSET_THREAD_RA(WORK)
	sw	LINECYCLE, OFFSET_THREAD_LINECYCLE(WORK)
	sw	STORE_DONE, OFFSET_THREAD_STORE_DONE(WORK)
	sw	gp, OFFSET_THREAD_GP(WORK)
	jal	Sound_Read
	
	lw	ra, OFFSET_THREAD_RA(WORK)
	lw	LINECYCLE, OFFSET_THREAD_LINECYCLE(WORK)
	lw	STORE_DONE, OFFSET_THREAD_STORE_DONE(WORK)
	lw	gp, OFFSET_THREAD_GP(WORK)
	lbu	t0, OFFSET_WORK_4015H_OUTPUT(WORK)
	andi	t0, t0, 0xc0
	or	v0, v0, t0
#endif
	
#if 0
/* debug */
	move	a1, v0
	move	a2, PC
	PRINTF("4015R=%x at PC=%x\n");
#endif

/* d7,d6 $B$O(B read-reset */
	andi	t0, v0, 0x3f
	sb	t0, OFFSET_WORK_4015H_OUTPUT(WORK)
	jr	ra
		
/* mapper-dependent funcs...
 */
	GLOBAL(store01_8000)
store01_8000:
/* MMC1
 * 8000-ffff $B6&DLItJ,$,B?$=$&$J$N$G!#(B
 * $B=q$-9~$_%G!<%?(B d7=1 $B$G(B r0 $B$N=i4|2=(B -> d3,d2 $B$N$_(B 1 $B$K!#(B
 */
#if 0
/* debug */
	move	a2, a0
	move	a3, PC
	PRINTF("MMC1(%02x->%04x)PC=%x\n");
	bne	a1, zero, 1f
	sw	PC, OFFSET_TRACE_FLAG(WORK)
1:
#endif
	lbu	t1, OFFSET_MMC1_SHIFTCOUNT(WORK)
	andi	t0, a1, 0x80
	bne	t0, zero, 80f
	lbu	t2, OFFSET_MMC1_SHIFTREG(WORK)
	sll	t0, a1, 7  /* 0x01 -> 0x80 */
	srl	t2, t2, 1
	or	t2, t2, t0
	addiu	t1, t1, -1
	beq	t1, zero, 1f
	sb	t1, OFFSET_MMC1_SHIFTCOUNT(WORK)
	sb	t2, OFFSET_MMC1_SHIFTREG(WORK)
	jr	STORE_DONE
1:
/* 5bits $B=q$-9~$_40N;!#(B*/
	li	t1, 5
	sb	t1, OFFSET_MMC1_SHIFTCOUNT(WORK)
	srl	t0, t2, 3
	andi	t0, t0, 0x1f
#if 0
/* debug */
	move	a1, a0
	move	a2, t0
	PRINTF("MMC1 %04x=%02x\n");
#endif
	andi	t1, a0, 0x6000
	srl	t2, t1, 13
	addu	t2, t2, WORK
	lbu	t3, OFFSET_MMC1_R0(t2)
	sb	t0, OFFSET_MMC1_R0(t2)
	beq	t3, t0, store_done  /* $BF1$8CM$N=q$-9~$_$OL5;k(B */

	xori	t2, t1, 0x6000
	beq	t1, zero, store01_r0
	bne	t2, zero, 1f  /* chrbank $BJQ99(B */
/* rombank
 * d4=1 $B$J$i(B $B$b$H$N(B (rombank) d3 $B$OJ]B8!#(B
 *   ... $B$8$c$J$/$F!"(B bank change $B$rL5;k$7$F$_$k!#(B
 *   ... $B$G$b!"$d$C$QHt$V(B (sutte_ha.nes)
 */
	lbu	t3, OFFSET_MMC1_ROMBANK(WORK)
	andi	t1, t0, 0x10
	bne	t1, zero, 2f
	move	t3, t0
2:
/* debug rambank $B$OL$BP1~(B */
	andi	t3, t3, 0x08
	andi	t1, t0, 0x07
	or	t3, t3, t1
	lbu	t2, OFFSET_PBANK_MASK(WORK)
	srl	t2, t2, 1
	and	t3, t3, t2
	sb	t3, OFFSET_MMC1_ROMBANK(WORK)
	lw	t1, OFFSET_PRGROM(WORK)
	lw	$1, OFFSET_MMC1_BIGROM(WORK)
	addu	t1, t1, $1
/* r0 $B$N(B d3,d2 $B$K$h$C$F(B page table $B$N@@_Dj(B
 * t1: prgrom
 * t3: new rombank
 */
	lbu	t0, OFFSET_MMC1_R0(WORK)
	andi	t2, t0, 0x08
	beq	t2, zero, 8f
/* d3=1 $B$J$N$G(B 0x4000 bytes/bank, d2 $B$K$h$C$F(B c000- or 8000- $B$N$_JQ99(B */
	andi	t0, t0, 0x04
	xori	t0, t0, 0x04  /* $B>oCs$,(B 0x8000- $B$J$i(B $B2DJQ$O(B 0xc000- */
	addiu	t2, t0, 0x08  /* $B8e$N(B +0x8000 $B$KAjEv(B */
	sll	t2, t2, 12
	sll	t0, t0, 1
	addu	t0, t0, WORK
	mul	t3, t3, 0x4000
	addu	t3, t3, t1
	subu	t3, t3, t2
	sw	t3, OFFSET_PAGE_TABLE + 0x10(t0)
	sw	t3, OFFSET_PAGE_TABLE + 0x14(t0)
	jr	STORE_DONE
8:
/* d3=0 $B$J$N$G(B 0x8000 bytes/bank. rombank $B$K$h$C$F(B 8000-ffff $B$NJQ99(B */
	andi	t3, t3, 0x0e
	mul	t3, t3, 0x4000
	addu	t3, t3, t1
	addiu	t3, t3, -0x8000
	sw	t3, OFFSET_PAGE_TABLE + 0x10(WORK)
	sw	t3, OFFSET_PAGE_TABLE + 0x14(WORK)
	sw	t3, OFFSET_PAGE_TABLE + 0x18(WORK)
	sw	t3, OFFSET_PAGE_TABLE + 0x1c(WORK)
	jr	STORE_DONE
	
1:
/* chrbank $B$NJQ99(B
 * t0: new chrbank
 * t1: 0x2000 (r1) or 0x4000 (r2)
 * r0 $B$K$h$C$F(B bank size $B$,(B 0x2000 or 0x1000 $B$K$J$k!#(B
 */
	xori	t1, t1, 0x2000
	lbu	t3, OFFSET_MMC1_R0(WORK)
	andi	t3, t3, 0x10
	sb	zero, OFFSET_BG_CHRBANK_TOUCH_FLAG(WORK)
	sb	zero, OFFSET_OBJ_CHRBANK_TOUCH_FLAG(WORK)
	bne	t1, zero, 2f
/* r1 $B$N=q$-9~$_$@@$C$?!#(B
 * r0 $B$N(B d4=0 $B$J$i(B 0x2000 bytes/bank.
 *          1      0x1000 bytes/bank
 * t3: r0 $B$N(B d4
 */

/* chrram $B$J$i(B dq4j.nes type $B$+$b$h(B... */
	lbu	$1, OFFSET_MMC1_DQ4_MODE(WORK)
	beq	$1, zero, 10f
	lw	$1, OFFSET_MMC1_BIGROM(WORK)
	li	t1, 0x80000
	and	t1, t1, $1
	andi	t0, t0, 0x10
	sll	t0, t0, 2 + 12  /* 0x10 -> 0x40000 */
	or	t0, t0, t1
	j	11f
10:

	addiu	t2, WORK, 2 * 4
	bne	t3, zero, 3f
/* 0x2000 bytes/bank $B$J$N$G(B t0 $B$N(B d0 $B$OL5;k(B */
	andi	t0, t0, 0x1e
#if 1
/* $B$H$j$"$($:!"I,MW(B !!
 * zelda1j.nes $B$,(B BG chrbank reg. $B$KBg$-$9$.$kCM$r$$$l$F$$$k!#(B
 * $B$3$l$rF~$l$J$$$H!"(Bcode_default/force_bss.c $B$G3NJ]$7$F$$$kJ,$r1[$($k(B bss $B$X=q$-9~$^$l$k(B
 * ($B7k2L!"(Baudio routine $B$GK=Av$7$?$j$9$k(B)
 * $B%^%9%/$7$J$$$H$$$1$J$$$,!"(Bgoemon1j.nes $B$N$3$H$,$"$k$N$G!"8=:_$O(B zelda1j.nes $B$rHsBP1~$G!#(B
 * $B$$$d!"(Bgoemon1j.nes $B$O(B mask $B$7$F$bF0$$$F$$$=$&!#(B
 * chrram $B$G!"(Bbank $B@@Z$jBX$($9$k$b$N$,$"$k$1$I!"$=$NH=JLJ}K!$,F~$C$F$J$$(B ...
 */
        andi t0,t0,0x00
#endif
	addiu	t2, WORK, 2 * 8
3:
	move	t1, WORK
	sll	t0, t0, 2
1:
	sh	t0, OFFSET_CHRBANK_REG0000(t1)
#if 0
/* debug */
	move	a2, t0
	subu	a3, t1, WORK
	PRINTF("MMC1 R1 %x,%x,%x\n");
#endif
	addiu	t0, t0, 1
	addiu	t1, t1, 2
	bne	t1, t2, 1b
	jr	STORE_DONE
2:
/* r2 $B$N=q$-9~$_$@@$C$?!#(B
 * r0 $B$N(B d4=0 $B$J$iL5;k!#(B
 *          1 $B$J$i(B chr 1000- $B$NJQ99(B
 */

/* chrram $B$J$i(B dq4j.nes type $B$+$b$h(B... */
	lbu	$1, OFFSET_MMC1_DQ4_MODE(WORK)
	beq	$1, zero, 10f
	lw	$1, OFFSET_MMC1_BIGROM(WORK)
	li	t1, 0x40000
	and	t1, t1, $1
	andi	t0, t0, 0x10
	sll	t0, t0, 2 + 13  /* 0x10 -> 0x80000 */
	or	t0, t0, t1
	j	11f
10:

	beq	t3, zero, store_done
	sll	t0, t0, 2

	move	t1, WORK
	addiu	t2, t1, 2 * 4
1:
	sh	t0, OFFSET_CHRBANK_REG1000(t1)
#if 0
/* debug */
	move	a2, t0
	subu	a3, t1, WORK
	PRINTF("MMC1 R2 %x,%x,%x\n");
#endif
	addiu	t0, t0, 1
	addiu	t1, t1, 2
	bne	t1, t2, 1b
	jr	STORE_DONE
11:
/* dq4 type $B$N;~$K(B bigrom offset (0/0x40000/0x80000/0xc0000)
 * $B$,JQ$o$l$P(B page table $B$bJQ$($k!#(B
 * $1: orig bigrom offset
 * t0: new  bigrom offset
 * $1:0,t0:0x40000 $B$J$i(B $1=0x40000 $B$K$J$k$N$G$=$l$>$l2C$($k!#(B
 */
	beq	$1, t0, store_done
	sw	t0, OFFSET_MMC1_BIGROM(WORK)
	subu	$1, t0, $1
	lw	t0, OFFSET_PAGE_TABLE + 0x10(WORK)
	lw	t1, OFFSET_PAGE_TABLE + 0x18(WORK)
	addu	t0, t0, $1
	addu	t1, t1, $1
	sw	t0, OFFSET_PAGE_TABLE + 0x10(WORK)
	sw	t0, OFFSET_PAGE_TABLE + 0x14(WORK)
	sw	t1, OFFSET_PAGE_TABLE + 0x18(WORK)
	sw	t1, OFFSET_PAGE_TABLE + 0x1c(WORK)
#if 0
/* debug */
	move	a1, t0
	move	a2, t1
	move	a3, $1
	PRINTF("BIGROM %x,%x,%x\n");
#endif
	jr	STORE_DONE

80:
	li	t1, 5
	sb	t1, OFFSET_MMC1_SHIFTCOUNT(WORK)
	lbu	t0, OFFSET_MMC1_R0(WORK)
	ori	t0, t0, 0x0c
	GLOBAL(store01_r0)
store01_r0:
	sb	t0, OFFSET_MMC1_R0(WORK)
	lw	t3, OFFSET_PRGROM(WORK)
	lw	$1, OFFSET_MMC1_BIGROM(WORK)
	addu	t3, t3, $1
	lbu	t4, OFFSET_MMC1_ROMBANK(WORK)
/* d3 $B$O(B ? */
	andi	t1, t0, 0x08
	beq	t1, zero, 8f
/* d3=1. $B$D$^$j(B 0x4000 bytes/bank.
 * d2 $B$K$h$C$F(B $B>oCs%P%s%/(B 0x8000- or 0xc000-
 */
	andi	t1, t0, 0x04
	addiu	t2, t1, 0x08  /* $B8e$N(B +0x8000 $B$KAjEv(B */
	sll	t2, t2, 12
	subu	t2, t3, t2
	bne	t1, zero, 4f
/* $B>oCs%P%s%/(B 8000-, $B2DJQ%P%s%/(B c000- */
	sw	t2, OFFSET_PAGE_TABLE + 0x10(WORK)
	sw	t2, OFFSET_PAGE_TABLE + 0x14(WORK)
	addiu	t2, WORK, OFFSET_PAGE_TABLE + 0x18
	addiu	t3, t3, -0x4000 /* $B8e$N(B -0xc000 $B$KAjEv(B */
	j	5f
4:
/* $B>oCs%P%s%/(B c000-, $B2DJQ%P%s%/(B 8000- */
	lw	$1, OFFSET_PRGSIZE(WORK)
#if 0
/* debug */
	move	a1, $1
	move	a2, t2
	move	a3, t3
	PRINTF("BIGROM2 %x,%x,%x\n");
#endif
	addu	t2, t2, $1
	addiu	t2, t2, -0x4000
	sw	t2, OFFSET_PAGE_TABLE + 0x18(WORK)
	sw	t2, OFFSET_PAGE_TABLE + 0x1c(WORK)
	addiu	t2, WORK, OFFSET_PAGE_TABLE + 0x10
5:
/* $B2DJQ%P%s%/$N@@_Dj(B */
	addiu	t3, t3, -0x8000
	mul	t4, t4, 0x4000
	addu	t3, t3, t4
	sw	t3, 0(t2)
	sw	t3, 4(t2)
	j	6f
8:
/* d3=0. $B$D$^$j(B 0x8000 bytes/bank.
 * rombank & 0x0e $B$K$h$C$F(B 8000-ffff.
 */
	addiu	t3, t3, -0x8000
	andi	t4, t4, 0x0e
	mul	t4, t4, 0x4000
	addu	t3, t3, t4
	sw	t3, OFFSET_PAGE_TABLE + 0x10(WORK)
	sw	t3, OFFSET_PAGE_TABLE + 0x14(WORK)
	sw	t3, OFFSET_PAGE_TABLE + 0x18(WORK)
	sw	t3, OFFSET_PAGE_TABLE + 0x1c(WORK)
6:
/* mirror
 * d1 $B$K$h$C$F(B one screen or 4 screen
 */
	andi	t1, t0, 0x02
	andi	t2, t0, 0x01
	mul	t2, t2, 0x400
	bne	t1, zero, 2f
/* one screen. d0 $B$O(B ? */
	sh	zero, OFFSET_VRAM_MIRROR_MASK_AND(WORK)
	sh	t2, OFFSET_VRAM_MIRROR_MASK_OR(WORK)
	j	10f
2:
/* 4 screen. d0 $B$K$h$C$F(B $B2#;}$A(B or $B=D;}$A(B */
	addiu	t2, t2, 0x400  /* $B$b$H$N(B t2 $B$O(B 0 or 0x400 */
	sh	zero, OFFSET_VRAM_MIRROR_MASK_OR(WORK)
	sh	t2, OFFSET_VRAM_MIRROR_MASK_AND(WORK)
10:
/* chr bank size
 * d4 $B$K$h$C$F(B 0x2000 bytes/bank or 0x1000 bytes/bank
 */
#if 0
	lbu	t2, OFFSET_MMC1_IGNORE_CHRBANK(WORK)
	bne	t2, zero, store_done
#endif
	lbu	t2, OFFSET_MMC1_DQ4_MODE(WORK)
	bne	t2, zero, store_done
	
	andi	t1, t0, 0x10
	lbu	t2, OFFSET_MMC1_R1(WORK)
	bne	t1, zero, 20f
/* d4=0. $B$D$^$j(B 0x2000 bytes/bank
 * r1 & 0x1e $B$K$h$k!#(B
 * max check $B$OL5;k(B
 */
	andi	t2, t2, 0x1e
	sll	t2, t2, 2
	addiu	t3, t2, 4
	j	1f

20:
/* d4=1. $B$D$^$j(B 0x1000 bytes/bank
 * r1, r2 $B$K$h$k!#(B
 * max check $B$OL5;k(B
 */
	lbu	t3, OFFSET_MMC1_R2(WORK)
	sll	t3, t3, 2
	sll	t2, t2, 2
1:
	move	t0, WORK
	addiu	t1, t0, 2 * 4
2:
	sh	t2, OFFSET_CHRBANK_REG0000(t0)
	sh	t3, OFFSET_CHRBANK_REG1000(t0)
	addiu	t2, t2, 1
	addiu	t3, t3, 1
	addiu	t0, t0, 2
	bne	t0, t1, 2b

	sb	zero, OFFSET_BG_CHRBANK_TOUCH_FLAG(WORK)
	sb	zero, OFFSET_OBJ_CHRBANK_TOUCH_FLAG(WORK)
	jr	STORE_DONE

	
	GLOBAL(store02_8000)
store02_8000:
/* PRG1M, fixC000
 * 8000-bfff $B$N(B pbank
 */
#if 0
/* debug */
	move	a2, a0
	move	a3, PC
	PRINTF("02(%x->%x)PC=%x\n");
#endif
	lw	t2, OFFSET_PRGROM(WORK)
	lbu	t3, OFFSET_PBANK_MASK(WORK)
	srl	t3, t3, 1   /* 0x4000 bytes/bank */
	and	t3, t3, a1
	addiu	t3, t3, -2  /* $B8e$N(B -0x8000 $B$KAjEv(B */
	mul	t3, t3, 0x4000
	addu	t2, t2, t3
	sw	t2, OFFSET_PAGE_TABLE + 0x10(WORK)
	sw	t2, OFFSET_PAGE_TABLE + 0x14(WORK)
	jr	STORE_DONE
	
	GLOBAL(store03_6000)
store03_6000:
/* CHR128/256
 * 6000-ffff $B$N=q$-9~$_$G(B d0,d1 $B$,(B chr bank $B$K$J$k!#(B
 * chr bank $B$O(B 0..3 (* 0x2000) $B$J$N$G(B obj/bg chr bank index $B$r8GDj3d$jEv$F!#(B
 */
#if 0
/* debug */
	move	a2, PC
	PRINTF("03_6000=%x at PC=%x\n");
#endif
	andi	t0, a1, 0x03
	mul	t1, t0, 0x2000
	lw	t2, OFFSET_CHR_OFFSET_MASK(WORK)
	and	t2, t2, t1
	srl	t2, t2, 10  /* / 0x400 */
/* t2 $B$O(B 0, 8, 0x10, 0x18 */
	lhu	t3, OFFSET_CHRBANK_REG0000(WORK)
	move	t0, WORK
	beq	t3, t2, store_done
/* bg chr bank index $B$O(B 8 bytes  (2*4) $BC10L!"(B
 * ($B$G$b(B PPU 2000H BG chr seg $B$,$"$k$N$G(B 16 bytes $BC10L$G!#(B)
 * obj               $B$O(B 16 bytes (2*8) $BC10L!#(B
 */
#if 0
/* debug */
	move	a1, t2
	PRINTF("03_chrbank=%x\n");
#endif
	sll	t3, t2, 1
/*	sb	t3, OFFSET_BG_CHRBANK_CHANGE_COUNT(WORK) */
/*	sb	t3, OFFSET_OBJ_CHRBANK_CHANGE_COUNT(WORK) */
	sb	zero, OFFSET_BG_CHRBANK_TOUCH_FLAG(WORK)
	sb	zero, OFFSET_OBJ_CHRBANK_TOUCH_FLAG(WORK)
			
	addiu	t1, t0, 2 * 8
1:
	sh	t2, OFFSET_CHRBANK_REG0000(t0)
	addiu	t2, t2, 1
	addiu	t0, t0, 2
	bne	t0, t1, 1b
	
	jr	STORE_DONE

	GLOBAL(store04_8000)
store04_8000:
/* address & 1 $B$K$h$C$F(B pointer or $B%l%8%9%?@@_Dj(B */
#if 0
/* debug */
	move	a2, a0
	move	a3, PC
	PRINTF("MMC3 %x->%x,%x\n");
#endif
	lbu	$1, OFFSET_MMC3_POINTER(WORK)
	andi	t1, a0, 0x0001
	bne	t1, zero, 10f
/* MMC3 pointer - chr seg, map mode, chr bank reg $B@@_Dj(B
 */
	sb	a1, OFFSET_MMC3_POINTER(WORK)
/* chrrom $BFI$_=P$7MQ(B chr seg $B@@_Dj(B */
	andi	t2, a1, 0x80
	sll	t2, t2, 5  /* 0x80 -> 0x1000 */
	sh	t2, OFFSET_CHRSEG_FOR_READ(WORK)
	xor	t0, $1, a1

	andi	t1, t0, 0x80
	beq	t1, zero, 1f
/* chr seg $B$,JQ$o$C$?$N$G(B BG, OBJ bank $B$,JQ$o$C$?$H9M$($k!#(B*/
	sb	zero, OFFSET_BG_CHRBANK_TOUCH_FLAG(WORK)
	sb	zero, OFFSET_OBJ_CHRBANK_TOUCH_FLAG(WORK)
1:
	andi	t1, t0, 0x40
	beq	t1, zero, store_done
/* map mode $B$,JQ$o$C$?!#(B
 */
	lbu	t1, OFFSET_MMC3_R6(WORK)
	lw	t3, OFFSET_PRGROM(WORK)
	lw	t4, OFFSET_PRGSIZE(WORK)
	andi	t2, a1, 0x40
	bne	t2, zero, 41f
/* map mode 0 $B$O(B window 0 (R6) $B$,(B 8000-9fff. c000-dfff $B$O(B prgrom + prgsize - 0x4000 $B8GDj!#(B*/
	addiu	t1, t1, -4  /* $B8e$G(B -0x8000 $BAjEv$K$J$k(B */
	mul	t1, t1, 0x2000
	addu	t1, t1, t3
	sw	t1, OFFSET_PAGE_TABLE + 0x10(WORK)
	addu	t3, t3, t4
	li	t4, -0x4000 - 0xc000
	addu	t3, t3, t4
	sw	t3, OFFSET_PAGE_TABLE + 0x18(WORK)
	jr	STORE_DONE
41:
/* map mode 1 $B$O(B window 0 (R6) $B$,(B c000-dfff. 8000-9fff $B$O(B prgrom + prgsize - 0x4000 $B8GDj!#(B*/
	addiu	t1, t1, -6  /* $B8e$G(B -0xc000 $BAjEv$K$J$k(B */
	mul	t1, t1, 0x2000
	addu	t1, t1, t3
	sw	t1, OFFSET_PAGE_TABLE + 0x18(WORK)
	addu	t3, t3, t4
	li	t4, -0x4000 - 0x8000
	addu	t3, t3, t4
	sw	t3, OFFSET_PAGE_TABLE + 0x10(WORK)
	jr	STORE_DONE
	
10:
	
/* $B%l%8%9%?@@_Dj(B
 * $1: pointer
 * t0: pointer & 7
 * t1: t0 + WORK
 * t2: $BA02s=q$$$?CM(B
 */
	andi	t0, $1, 0x07
	
	addu	t1, t0, WORK
	lbu	t2, OFFSET_MMC3_R0(t1)
	beq	t2, a1, store_done     /* $BA02s$HF1$8CM(B */
/* R0,R1 $B$J$i(B d0 $B$rL5;k$7$F(B chr bank for 0000-, 0800- $B$r!#(B
 * R2-R5 $B$J$i(B chr bank for 1000-,1400-,1800-,1c00- $B$r!#(B
 * R6,R7 $B$J$i(B prg bank.
 */
	lbu	t2, OFFSET_PBANK_MASK(WORK)
	addiu	t3, t0, -6
	bgez	t3, 6f
	lw	t2, OFFSET_CHR_OFFSET_MASK(WORK)
	sb	zero, OFFSET_BG_CHRBANK_TOUCH_FLAG(WORK)
	sb	zero, OFFSET_OBJ_CHRBANK_TOUCH_FLAG(WORK)
	mul	t4, a1, 0x400
#if 0
/* debug */
	ori	a2, t4, 0x3ff
	and	a3, a2, t2
	tne	a2, a3
#endif
	and	t4, t4, t2
	srl	t4, t4, 10  /* / 0x400 */
	addiu	t3, t0, -2
	bgez	t3, 2f
/* R0,R1 - d0 $B$OL58z(B */
	andi	t4, t4, 0xfffe
	sb	t4, OFFSET_MMC3_R0(t1)
	sll	t0, t0, 2
	addu	t0, t0, WORK
	sh	t4, OFFSET_CHRBANK_REG0000(t0) /* 0000 or 0800 */
	addiu	t4, t4, 1
	sh	t4, OFFSET_CHRBANK_REG0400(t0) /* 0400 or 0c00 */
#if 0
/* debug */
	subu	a2, t0, WORK
	move	a3, t4
	PRINTF("R0,1 %x,%x,%x\n");

/* chr bank table $B$,GK2u$5$l$F$$$k!#(B
 * t0 $B$,(B 0 $B$N$H$-(B trace flag ON!
 * ... $B%G%P%C%0MQ(B PRINTF $B$G(B a0 $B$H$+0z?t$K$7$F$k$1$I!"(B64bit operation $B$N(B
 * $BESCf$@@$C$?$N$,$^$:$+$C$?!#(B32bit operation $B$K$7$?!#(B
 */
	bne	a2, zero, 11f
	sw	WORK, OFFSET_TRACE_FLAG(WORK)
11:
#endif
	
	jr	STORE_DONE
2:
/* R2-R5
 * chr bank for 1000-, 1400-, 1800-, 1c00- $B$r!#(B
 * t3: t0 - 2
 */
	sb	t4, OFFSET_MMC3_R0(t1)
	sll	t3, t3, 1
	addu	t3, t3, WORK
	sh	t4, OFFSET_CHRBANK_REG1000(t3)
	jr	STORE_DONE
6:
/* R6-R7 pbank.
 * R6 $B$J$i(B mapmode $B$K$h$C$F(B window $B$,0c$&!#(B
 * $1: pointer
 * t0: pointer & 7
 * t1: t0 + WORK
 * t2: pbank mask
 * t3: t0 - 6
 */
	lw	t0, OFFSET_PRGROM(WORK)
	and	t2, t2, a1
	sb	t2, OFFSET_MMC3_R0(t1)
	bne	t3, zero, 7f
/* R6 */
	andi	$1, $1, 0x40
	beq	$1, zero, 40f
/* map mode 1 - R6 $B$O(B c000-dfff */
	addiu	t2, t2, -6  /* $B8e$G(B -0xc000 $BAjEv$K$J$k(B */
	mul	t2, t2, 0x2000
	addu	t2, t2, t0
	sw	t2, OFFSET_PAGE_TABLE + 0x18(WORK)
	jr	STORE_DONE
40:
/* map mode 0 - R6 $B$O(B 8000-9fff */
	addiu	t2, t2, -4  /* $B8e$G(B -0x8000 $BAjEv$K$J$k(B */
	mul	t2, t2, 0x2000
	addu	t2, t2, t0
	sw	t2, OFFSET_PAGE_TABLE + 0x10(WORK)
	jr	STORE_DONE
7:
/* R7 - mapmode $B$K$+$+$o$i$:(B a000-bfff */
	addiu	t2, t2, -5  /* $B8e$G(B -0xa000 $BAjEv$K$J$k(B */
	mul	t2, t2, 0x2000
	addu	t2, t2, t0
	sw	t2, OFFSET_PAGE_TABLE + 0x14(WORK)
	jr	STORE_DONE

	GLOBAL(store04_a000)
store04_a000:
/* address & 1 $B$K$h$C$F(B mirror or bbram protect
 * debug bbram protect $B$OL5;k(B
 */
#if 0
/* debug */
	move	a2, a0
	PRINTF("MMC3 %x->%x\n");
#endif
	andi	t0, a0, 0x0001
	bne	t0, zero, store_done
/* mirror $B$O(B d0=0 $B$J$i(B $B2#;}$A!"(Bd0=1 $B$J$i(B $B=D;}$A(B */
	li	t2, 0x400
	andi	t0, a1, 0x01
	sllv	t2, t2, t0
	sh	t2, OFFSET_VRAM_MIRROR_MASK_AND(WORK)
	jr	STORE_DONE
	
	
	GLOBAL(store04_c000)
store04_c000:
/* address & 1 $B$K$h$C$F(B JAM or P&SIT */
#if 0
/* debug */
	move	a2, a0
	PRINTF("MMC3 %x->%x\n");
#endif
	lh	t1, OFFSET_LINECNT(WORK)
	addiu	t2, t1, -239
	andi	t0, a0, 0x0001
	bne	t0, zero, 10f
/* MMC3 JAM
 * linecnt_irq preset $B$,AjEv$9$k!#(B
 * line 0..239 $B$J$i(B $B@@_Dj$HF1;~$K(B linecnt_irq $B:F7W;;(B
 *   linecnt_irq = linecnt + a1 + 1
 */
	sh	a1, OFFSET_LINECNT_IRQ_PRESET(WORK)
	bltz	t1, store_done
	addiu	t3, a1, 1
	bgtz	t2, store_done
2:
/* $B2<$+$iMh$k!#(B*/
	addu	t3, t3, t1
3:
/* $B2<$+$iMh$k!#(B*/
	sh	t3, OFFSET_LINECNT_IRQ(WORK)
	jr	STORE_DONE

10:
/* P&SIT (Preset & Start Interval Timer)
 * linecnt_irq $B$,AjEv$9$k!#(B
 * line < 0 or line > 239 $B$J$i(B linecnt_irq = linecnt_irq preset $B$r!#(B
 * $B$=$l0J30(B, $B$D$^$j(B line 0..239 $B$O(B $B$d$C$F$[$7$/$J$$$1$I(B
 *   linecnt_irq = linecnt + linecnt_irq preset + 1 $B$+$J(B?
 */
	lhu	t3, OFFSET_LINECNT_IRQ_PRESET(WORK)
	bltz	t1, 3b
	bgtz	t2, 3b
	
	addu	t1, t1, 1
	j	2b

	GLOBAL(store04_e000)
store04_e000:
/* address & 1 $B$K$h$C$F(B DITIRQ or EITIRQ */
#if 0
/* debug */
	move	a2, a0
	PRINTF("MMC3 %x->%x\n");
#endif
	andi	t0, a0, 0x0001
	sb	t0, OFFSET_LINECNT_IRQ_ENABLED(WORK)
	jr	STORE_DONE

	GLOBAL(linecnt_over04)
linecnt_over04:
/* MMC3 $B%i%$%s%+%&%s%?%*!<%P!<(B
 * line 0..239 $B$J$i(B $B<+F0%W%j%;%C%H$J$N$G(B linecnt_irq $B:F7W;;(B
 *   linecnt_irq = linecnt + linecnt_irq preset + 1
 * $B$=$l0J30$J$i(B $B5/$3$C$F$O$$$1$J$$$,!"L5;k!#(B
 *   $B0J9_(B $B%+%&%s%?%*!<%P!<$,H/@@8$7$J$$$h$&$K$9$k!#(B
 * BG, OBJ $BN>J}$,%V%i%s%-%s%0$J$i(B $BL5;k!#(B
 *   $B0J9_(B $B%+%&%s%?%*!<%P!<$,H/@@8$7$J$$$h$&$K$9$k!#(B(smario3.nes)
 * DITIRQ $B$J$i(B $B%+%&%s%?%*!<%P!<$OL5;k!#(B
 *
 * t4: new linecnt
 * t3: linecnt_irq preset $BCM(B
 * t2: linecnt_irq enabled
 */
	addiu	t1, t4, -239
	bltz	t4, 2f
	addiu	t3, t3, 1
	bgtz	t1, 2f
	lbu	t0, OFFSET_PPU2000H + 1(WORK)
	addu	t3, t3, t4
	sh	t3, OFFSET_LINECNT_IRQ(WORK)
	beq	t2, zero, mainloop_srlt0

	andi	t0, t0, 0x18  /* BGBLK | OBJBLK */
	beq	t0, zero, 2f
	j	check_irq
2:
/* $B%+%&%s%?%*!<%P!<L5;k(B */
	li	t0, 0x8000
	sh	t0, OFFSET_LINECNT_IRQ(WORK)
	j	mainloop_srlt0

	GLOBAL(check_irq)
check_irq:
/* cli $B$J$i(B $B3d$j9~$_=hM}!#(B
 * sei $B$J$i(B irq cause bit d5 $B$rN)$F$F$*$/(B
 * mainloop_srlt0 $B$XLa$k!#(B
 */
	la	STORE_DONE, mainloop_srlt0
	lbu	t2, OFFSET_IRQ_CAUSE(WORK)
	andi	t2, t2, 0xff ^ 0x20
	sb	t2, OFFSET_IRQ_CAUSE(WORK)
	lbu	t0, OFFSET_WORK_RBDI(WORK)
	andi	t1, t0, 0x04  /* I */
	beq	t1, zero, activate_intr_fffe

	ori	t2, t2, 0x20	
	sb	t2, OFFSET_IRQ_CAUSE(WORK)
	j	mainloop_srlt0


	GLOBAL(store05_5100)
store05_5100:
/* 5100: amode
 * t0 $B$K(B amode_pamode $B$,F~$C$F$$$k!#(B
 * $B:#$HF1$8$J$i(B $BL5;k(B
 * br3: 6000-7fff (debug not yet)
 */
	sll	t3, a1, 8
	xor	t2, t3, t0
	andi	t2, t2, 0x0300
	andi	a2, t3, 0x0300
	beq	t2, zero, store_done
	lw	t1, OFFSET_PRGROM(WORK)
	addiu	t1, t1, -0x8000
	lbu	t2, OFFSET_PBANK_MASK(WORK)
	lbu	t3, OFFSET_MMC5_BR5(WORK)
	lbu	t4, OFFSET_MMC5_BR7(WORK)
	sb	a1, OFFSET_MMC5_AMODE_PAMODE(WORK)
	xori	$1, a2, 0x0100
	beq	a2, zero, store_invalid  /* amode 0 not yet */
	xori	a3, a2, 0x0200
	beq	$1, zero, 10f  /* amode 1 */
	beq	a3, zero, 20f  /* amode 2 */

	j	store_invalid
10:
/* amode 1
 * br5: 8000-bfff
 * br7: c000-ffff
 * bank no. $B$N(B d0 $B$OL5;k(B
 * br7 $B$N(B d7=1 ($B$K$5$l$F$$$k(B)
 * t0: temp
 * t1: prgrom - 0x8000
 * t2: pbank mask
 * t3: br5
 * t4: br7
 */
	and	t3, t3, t2
	andi	t3, t3, 0xfe
	mul	t3, t3, 0x2000
	addu	t3, t3, t1
	sw	t3, OFFSET_PAGE_TABLE + 0x10(WORK)
	sw	t3, OFFSET_PAGE_TABLE + 0x14(WORK)

	and	t4, t4, t2
	andi	t4, t4, 0xfe
	mul	t4, t4, 0x2000
	addu	t4, t4, t1
	addiu	t4, t4, -0x4000
	sw	t4, OFFSET_PAGE_TABLE + 0x18(WORK)
	sw	t4, OFFSET_PAGE_TABLE + 0x1c(WORK)

	jr	STORE_DONE

20:
/* amode 2
 * br5: 8000-bfff
 * br6: c000-dfff
 * br7: e000-ffff
 * t0: br6
 * t1: prgrom - 0x8000
 * t2: pbank mask
 * t3: br5
 * t4: br7
 */
	lbu	t0, OFFSET_MMC5_BR6(WORK)
	and	t3, t3, t2
	andi	t3, t3, 0xfe
	mul	t3, t3, 0x2000
	addu	t3, t3, t1
	sw	t3, OFFSET_PAGE_TABLE + 0x10(WORK)
	sw	t3, OFFSET_PAGE_TABLE + 0x14(WORK)

	and	t0, t0, t2
	mul	t0, t0, 0x2000
	addu	t0, t0, t1
	addiu	t0, t0, -0x4000
	sw	t0, OFFSET_PAGE_TABLE + 0x18(WORK)

	and	t4, t4, t2
	mul	t4, t4, 0x2000
	addu	t4, t4, t1
	addiu	t4, t4, -0x6000
	sw	t4, OFFSET_PAGE_TABLE + 0x1c(WORK)
	jr	STORE_DONE

	GLOBAL(store05_5101)
store05_5101:
/* pamode
 * t0 $B$K(B amode_pamode $B$,F~$C$F$$$k!#(B
 */
#if 0
	PRINTF("05_pamode(%x)\n");
#endif
	xor	t2, a1, t0
	andi	t2, t2, 0x0003
	andi	a2, a1, 0x0003
	beq	t2, zero, store_done

	sb	a1, OFFSET_MMC5_AMODE_PAMODE + 1(WORK)
	sb	zero, OFFSET_BG_CHRBANK_TOUCH_FLAG(WORK)
	sb	zero, OFFSET_OBJ_CHRBANK_TOUCH_FLAG(WORK)
	jr	STORE_DONE
	

	GLOBAL(store05_5102)
store05_5102:
store05_5103:
/* 5102,5103: exram gate
 * $BL5;k(B
 */
#if 0
	move	a2, a0
	PRINTF("05_exram_gate(%x->%x)ignored\n");
#endif
	jr	STORE_DONE

	GLOBAL(store05_5104)
store05_5104:
/* exram mode
 * 0: vram2
 * 1: at-vram
 * 2: cpu-wram
 * 3: write protect
 * $BL5;k!#(B
 */
#if 0
/* debug */
	PRINTF("05_exram_mode(%x)ignored\n");
#endif
	jr	STORE_DONE

	GLOBAL(store05_5105)
store05_5105:
/* vram bank
 * d7,d6=vbr 3
 * d5,d4=vbr 2
 * d3,d2=vbr 1
 * d1,d0=vbr 0
 * $B$&!<$s$3$l$C$F(B namcot 106 $B$G$b$"$C$?$1$I(B $BC1=c$K2#;}$A!"=D;}$A$G$O(B
 * $BBP1~$G$-$s$J$"!#(B
 * $B$7$+$b(B castlev3.nes $B$,(B $B$$$-$J$j(B VRAM2 $B$G(B 0x44 $B$r=q$$$F$$$k!#(B
 * $B$H$j$"$($:(B namcot 106 $B$N$h$&$K(B
 * 00 01 00 01 -> $B2#;}$A(B
 * 00 00 01 01 -> $B=D;}$A(B
 * 00 00 00 00 -> 1 $B2hLL(B 2000-
 * 01 01 01 01 ->        2400-
 */
#if 0
/* debug */
	PRINTF("05_vrambank(%x)ignored\n");
#endif
	jr	STORE_DONE

	GLOBAL(store05_5106)
store05_5106:
/* vram3 chr no
 * $BL5;k!#(B
 */
#if 0
/* debug */
	PRINTF("05_vram3chr(%x)ignored\n");
#endif
	jr	STORE_DONE

	GLOBAL(store05_5107)
store05_5107:
/* vram3 area code
 * $BL5;k!#(B
 */
#if 0
/* debug */
	PRINTF("05_vram3area(%x)ignored\n");
#endif
	jr	STORE_DONE

	GLOBAL(store05_5113)
store05_5113:
/* br3: 6000-7fff
 * 0x00-0x0f
 * $BL5;k(B
 */
#if 0
/* debug */
	PRINTF("05_br3(%x)ignored\n");
#endif
	andi	t0, a1, 0x0f
	sb	t0, OFFSET_MMC5_BR3(WORK)
	jr	STORE_DONE

	GLOBAL(store05_5114)
store05_5114:
/* br4: 8000-9fff
 * t0 $B$K(B amode_pamode
 * amode 3 $B$N$_M-8z(B
 */
	andi	t0, t0, 0x0300
	xori	t0, t0, 0x0300
	lbu	t3, OFFSET_PBANK_MASK(WORK)
	bne	t0, zero, store_done
	lw	t4, OFFSET_PRGROM(WORK)
	and	t3, t3, a1
	mul	t3, t3, 0x2000
	addu	t3, t3, t4
	addiu	t3, t3, -0x8000
	sw	t3, OFFSET_PAGE_TABLE + 0x10(WORK)
	jr	STORE_DONE
	
	GLOBAL(store05_5115)
store05_5115:
/* br5
 * t0 $B$K(B amode_pamode
 * amode 0 $B$J$iL5;k(B
 * amode 3 $B$J$i(B a000-bfff
 * $BB>$O(B 8000-bfff
 */
	andi	t2, t0, 0x0300
	xori	t3, t2, 0x0300
	beq	t2, zero, store_done
	lw	t2, OFFSET_PRGROM(WORK)
	lbu	t4, OFFSET_PBANK_MASK(WORK)
	and	t4, t4, a1
	sb	a1, OFFSET_MMC5_BR5(WORK)
	beq	t3, zero, 3f
/* amode 1 or 2 */
	andi	t0, t4, 0xfe
	mul	t0, t0, 0x2000
	addiu	t0, t0, -0x8000
	addu	t0, t0, t2
	sw	t0, OFFSET_PAGE_TABLE + 0x10(WORK)
	sw	t0, OFFSET_PAGE_TABLE + 0x14(WORK)
	jr	STORE_DONE
3:
/* amode 3 */
	addiu	t0, t4, -5  /* $B8e$N(B -0xa000 $B$KAjEv(B */
	mul	t0, t0, 0x2000
	addu	t0, t0, t2
	sw	t0, OFFSET_PAGE_TABLE + 0x14(WORK)
	jr	STORE_DONE

	GLOBAL(store05_5116)
store05_5116:
/* br6
 * t0 $B$K(B amode_pamode
 * amode 0,1 $B$J$iL5;k(B
 * amode 2,3 $B$J$i(B c000-dfff
 */
	andi	t2, t0, 0x0200
	lbu	t1, OFFSET_PBANK_MASK(WORK)
	beq	t2, zero, store_done
	lw	t2, OFFSET_PRGROM(WORK)
	sb	a1, OFFSET_MMC5_BR6(WORK)
	and	t1, t1, a1
	addiu	t1, t1, -6  /* $B8e$N(B -0xc000 $B$KAjEv(B */
	mul	t1, t1, 0x2000
	addu	t1, t1, t2
	sw	t1, OFFSET_PAGE_TABLE + 0x18(WORK)
	jr	STORE_DONE

	GLOBAL(store05_5117)
store05_5117:
/* br7
 * t0 $B$K(B amode_pamode
 * amode 0 $B$J$i(B 8000-ffff
 * amode 1 $B$J$i(B c000-ffff
 * amode 2,3 $B$J$i(B e000-ffff
 */
	andi	t2, t0, 0x0300
	andi	t0, t0, 0x0200
	lbu	t1, OFFSET_PBANK_MASK(WORK)
	lw	t3, OFFSET_PRGROM(WORK)
	and	t1, t1, a1
	beq	t2, zero, 1f  /* amode 0 */
	beq	t0, zero, 2f  /* amode 1 */
/* amode 2,3 */
	addiu	t1, t1, -7  /* $B8e$N(B -0xe000 $B$KAjEv(B */
	mul	t1, t1, 0x2000
	addu	t1, t1, t3
	sw	t1, OFFSET_PAGE_TABLE + 0x1c(WORK)
	jr	STORE_DONE
1:
/* amode 0 */
	andi	t1, t1, 0xfc
	mul	t1, t1, 0x2000
	addu	t1, t1, t3
	addiu	t1, t1, -0x8000
	sw	t1, OFFSET_PAGE_TABLE + 0x10(WORK)
	sw	t1, OFFSET_PAGE_TABLE + 0x14(WORK)
	sw	t1, OFFSET_PAGE_TABLE + 0x18(WORK)
	sw	t1, OFFSET_PAGE_TABLE + 0x1c(WORK)
	jr	STORE_DONE
2:
/* amode 1 */
	andi	t1, t1, 0xfe
	addiu	t1, t1, -6  /* $B8e$N(B -0xc000 $B$KAjEv(B */
	mul	t1, t1, 0x2000
	addu	t1, t1, t3
	sw	t1, OFFSET_PAGE_TABLE + 0x18(WORK)
	sw	t1, OFFSET_PAGE_TABLE + 0x1c(WORK)
	jr	STORE_DONE
	
	GLOBAL(store05_5120)
store05_5120:
/* pbr0-7, pbr4'-7'
 * pbr4'-7' $B$O(B $BL5;k(B
 * amode $B$K$h$k99?7$O(B $BL5;k(B
 */
#if 0
/* debug */
	move	a2, a0
	PRINTF("05_pbr(%x->%x)\n");
#endif
	lhu	t1, OFFSET_MMC5_PBREX(WORK)
	andi	t0, a0, 0x0f
	sll	t0, t0, 1
	addu	t0, t0, WORK
	lhu	t2, OFFSET_MMC5_PBR0(t0)
	or	t1, t1, a1
	sh	t1, OFFSET_MMC5_PBR0(t0)
	beq	t1, t2, store_done
	sb	zero, OFFSET_BG_CHRBANK_TOUCH_FLAG(WORK)
	sb	zero, OFFSET_OBJ_CHRBANK_TOUCH_FLAG(WORK)
	jr	STORE_DONE

	GLOBAL(store05_5130)
store05_5130:
/* pbrex */
	andi	t0, a1, 0x03
	sll	t0, t0, 8
	sh	t0, OFFSET_MMC5_PBREX(WORK)
	jr	STORE_DONE

	
	
#if 0
/* mappers.nfo $B$^$C$?$/$&$=$d$s!#(B*/
	GLOBAL(store06_4000)
store06_4000:
/* FFE F4xxx
 */
#if 0
/* debug */
	move	a2, a0
	move	a3, PC
	PRINTF("06(%x->%x),PC=%x\n");
#endif
	xori	t0, a0, 0x43fe
	bne	t0, zero, store_io
#if 0
/* debug */
	move	a2, a0
	move	a3, PC
	PRINTF("06(%x->%x),PC=%x\n");
#endif
	jr	STORE_DONE
#endif
	
	GLOBAL(store06_8000)
store06_8000:
/* FFE F4xxx
 * goemon1j.nes $BMQ!#(B
 * pbank for 8000-bfff $B$+$J$"(B? $BCM$,(B 0x14 $B$@@$+$i(B $B0c$&$C$]$$!#(B
 * d7-d2 $B$,(B pbank ?
 * d0 $B$,(B chrbank ? chrram $B$J$N$K(B ?
 * $B$=$&!#(Bd1-d0 $B$,(B chrbank
 */
#if 0
/* debug */
	move	a2, a0
	PRINTF("06(%x->%x),");
	move	a2,PC
	PRINTF("%x,PC=%x,");
	lhu	a2, OFFSET_LINECNT(WORK)
	PRINTF("%x,linecnt=%x\n");
#endif

	lw	t2, OFFSET_PRGROM(WORK)
	andi	t1, a1, 0x3c
	sll	t1, t1, 14 - 2  /* 1 << 14 = 0x4000 */
	addiu	t1, t1, -0x8000
	addu	t1, t1, t2
	sw	t1, OFFSET_PAGE_TABLE + 0x10(WORK)
	sw	t1, OFFSET_PAGE_TABLE + 0x14(WORK)

/* d1,d0 $B$+$i(B 0, 8, 0x10, 0x18 (* 0x400)
 */
	andi	t2, a1, 0x03
	sll	t2, t2, 3
#if 0
/* debug */
	move	a1, t2
	PRINTF("06_chrbank(%x)\n");
#endif
	lhu	t1, OFFSET_CHRBANK_REG0000(WORK)
	move	t0, WORK
	beq	t2, t1, store_done

	addiu	t1, t0, 2 * 8
1:
	sh	t2, OFFSET_CHRBANK_REG0000(t0)
	addiu	t2, t2, 1
	addiu	t0, t0, 2
	bne	t0, t1, 1b
	
	sb	zero, OFFSET_BG_CHRBANK_TOUCH_FLAG(WORK)
	sb	zero, OFFSET_OBJ_CHRBANK_TOUCH_FLAG(WORK)
	jr	STORE_DONE

	GLOBAL(store07_8000)
store07_8000:
/* Rare
 * d3-d0: pbank 0x8000 $BC10L(B
 * d4: One Screen Mirroring
 *   0=mirror pages from PPU $2000
 *   1=mirror pages from PPU $2400
 * $B$3$l$C$F(B 1 $B2hLL%b!<%I$7$+$J$$$C$F$3$H(B ?
 */
	andi	t0, a1, 0x10
	sll	t0, t0, 2 + 4  /* 0x10 -> 0x400 */
	sh	t0, OFFSET_VRAM_MIRROR_MASK_OR(WORK)

	lw	t1, OFFSET_PRGROM(WORK)
	andi	t0, a1, 0x0f
	mul	t0, t0, 0x8000
	addu	t0, t0, t1
	addiu	t0, t0, -0x8000
	sw	t0, OFFSET_PAGE_TABLE + 0x10(WORK)
	sw	t0, OFFSET_PAGE_TABLE + 0x14(WORK)
	sw	t0, OFFSET_PAGE_TABLE + 0x18(WORK)
	sw	t0, OFFSET_PAGE_TABLE + 0x1c(WORK)
	jr	STORE_DONE


	GLOBAL(store09_a000)
store09_a000:
/* MMC2
 * a000-afff: pbank at 8000-9fff - max check $B$OL5;k(B
 * b000-cfff: chr bank 0000-0fff
 */
	andi	t0, a0, 0x1000
	bne	t0, zero, store09_b000
	lw	t2, OFFSET_PRGROM(WORK)
	mul	t3, a1, 0x2000
	addiu	t3, t3, -0x8000
	addu	t2, t2, t3
	sw	t2, OFFSET_PAGE_TABLE + 0x10(WORK)
	jr	STORE_DONE

	GLOBAL(store09_c000)
store09_c000:
/* MMC2
 * b000-cfff: chr bank 0000-0fff
 * d000-dfff: chr bank 1000-1fff when latch selector is $fd
 */
#if 0
/* debug */
	move	a2, a0
	PRINTF("09(%x->%x)\n");
#endif
	andi	t0, a0, 0x1000
	bne	t0, zero, store09_d000
store09_b000:
#if 0
/* debug */
	beq	t0, zero, 1f
	move	a2, a0
	PRINTF("09(%x->%x)\n");
1:
#endif
	sll	t1, a1, 4  /* 0x1000 bytes/bank */
	sh	t1, OFFSET_CHRBANK_REG0000(WORK)
	addiu	t1, t1, 1
	sh	t1, OFFSET_CHRBANK_REG0400(WORK)
	addiu	t1, t1, 1
	sh	t1, OFFSET_CHRBANK_REG0800(WORK)
	addiu	t1, t1, 1
	sh	t1, OFFSET_CHRBANK_REG0C00(WORK)
	sb	zero, OFFSET_BG_CHRBANK_TOUCH_FLAG(WORK)
	sb	zero, OFFSET_OBJ_CHRBANK_TOUCH_FLAG(WORK)
	jr	STORE_DONE
	
store09_d000:
	sll	t1, a1, 4  /* 0x1000 bytes/bank */
	sh	t1, OFFSET_CHRBANK_REG1000(WORK)
	addiu	t1, t1, 1
	sh	t1, OFFSET_CHRBANK_REG1400(WORK)
	addiu	t1, t1, 1
	sh	t1, OFFSET_CHRBANK_REG1800(WORK)
	addiu	t1, t1, 1
	sh	t1, OFFSET_CHRBANK_REG1C00(WORK)
	sb	zero, OFFSET_BG_CHRBANK_TOUCH_FLAG(WORK)
	sb	zero, OFFSET_OBJ_CHRBANK_TOUCH_FLAG(WORK)

	jr	STORE_DONE

	GLOBAL(store09_e000)
store09_e000:
/* MMC2
 * e000-efff: chr bank 1000-1fff when latch selector is $fe
 * f000-ffff: d0=mirror 0=$B2#;}$A(B 1=$B=D;}$A(B
 */
#if 0
/* debug */
	move	a2, a0
	PRINTF("09(%x->%x)\n");
#endif
	andi	t0, a0, 0x1000
	bne	t0, zero, store09_f000

#if 0
/* debug */
	move	a2, a0
	PRINTF("09(%x->%x)\n");
#endif
	
	sll	t1, a1, 4  /* 0x1000 bytes/bank */
	sh	t1, OFFSET_CHRBANK_REG1000(WORK)
	addiu	t1, t1, 1
	sh	t1, OFFSET_CHRBANK_REG1400(WORK)
	addiu	t1, t1, 1
	sh	t1, OFFSET_CHRBANK_REG1800(WORK)
	addiu	t1, t1, 1
	sh	t1, OFFSET_CHRBANK_REG1C00(WORK)
	sb	zero, OFFSET_BG_CHRBANK_TOUCH_FLAG(WORK)
	sb	zero, OFFSET_OBJ_CHRBANK_TOUCH_FLAG(WORK)

	jr	STORE_DONE
store09_f000:
	li	t1, 0x400
	andi	t0, a1, 0x01
	beq	t0, zero, 1f
	li	t1, 0x800
1:
	sh	t1, OFFSET_VRAM_MIRROR_MASK_AND(WORK)
	jr	STORE_DONE

	GLOBAL(store0f_8000)
store0f_8000:
/* 100 in 1
 * 8000: SMPPPPPP
 * S: 0: swap 8000-/a000-
 *    1: swap c000-/e000
 * M: mirror $B2#;}$A!"=D;}$A(B
 * P: pbank @@ 8000-bfff, c000-ffff
 * bank $BHV9f$O(B 0x4000 bytes $BC10L(B ?
 *
 * 8001: SxPPPPPP
 * PPPPPP: pbank @@ c000-ffff
 * S: Swap c000-/e000-
 *
 * 8002: SxPPPPPP
 * PPPPPP: select 8K of a 16K segment at
 *         8000-/a000-/c000-/e000-
 * S: Segment selector 0 - select lower 8K of segment
 *                     1 -        upper
 *
 * 8003: SMPPPPPP
 * PPPPPP: select 16k rom bank @@ c000-ffff
 * M: mirror
 * S: swap 8K at c000-/e000-
 *
 * $B$J$s$8$c$3$j$c!<(B !?
 * $B<jH4$-$@@$1$I!"F0$$$F$$$=$&!#(B
 */
#if 0
/* debug */
	move	a2, a0
	move	a3, PC
	PRINTF("0f(%x->%x)PC=%x\n");
#endif

	.set	noreorder
	andi	t0, a0, 0x0003
	beq	t0, zero, 10f
	xori	t1, t0, 0x0002
	beq	t1, zero, 20f
	xori	t1, t0, 0x0003
	beq	t1, zero, 30f
	nop
	.set	reorder

/*
 * 8001 $B$O<BAu$7$F$J$$(B
 */
	jr	STORE_DONE
10:
/* 8000
 * swap $B$O<BAu$7$F$J$$(B
 */
	lw	t1, OFFSET_PRGROM(WORK)
	andi	t2, a1, 0x3f
	mul	t2, t2, 0x4000
	addu	t1, t1, t2
	addiu	t1, t1, -0x8000
	sw	t1, OFFSET_PAGE_TABLE + 0x10(WORK)
	sw	t1, OFFSET_PAGE_TABLE + 0x14(WORK)
	sw	t1, OFFSET_PAGE_TABLE + 0x18(WORK)
	sw	t1, OFFSET_PAGE_TABLE + 0x1c(WORK)
	
15:
/* $B2<$+$i$bMh$k(B */
	andi	t0, a1, 0x40
	sll	t0, t0, 4
	addiu	t0, t0, 0x400
	sh	t0, OFFSET_VRAM_MIRROR_MASK_AND(WORK)

	lw	a0, OFFSET_PAGE_TABLE + 0x18(WORK)
	li	t1, 0xc000
	addu	a0, a0, t1
	sw	LINECYCLE, OFFSET_THREAD_LINECYCLE(WORK)
	sw	STORE_DONE, OFFSET_THREAD_STORE_DONE(WORK)
	sw	gp, OFFSET_THREAD_GP(WORK)
	jal	Sound_SetC000
	lw	LINECYCLE, OFFSET_THREAD_LINECYCLE(WORK)
	lw	STORE_DONE, OFFSET_THREAD_STORE_DONE(WORK)
	lw	gp, OFFSET_THREAD_GP(WORK)
	jr	STORE_DONE

20:
/* 8002
 * $B$3$3$K=q$-9~$`$H!"(B8000-,a000-,c000-,e000- $B$I$l$bF1$8%P%s%/$N(B $B%$%a!<%8(B ?
 */
	lw	t1, OFFSET_PRGROM(WORK)
	andi	t2, a1, 0x3f
	mul	t2, t2, 0x4000
	andi	t3, a1, 0x80
	sll	t3, t3, 8 - 2
	addu	t2, t2, t3
	addu	t2, t2, t1

	addiu	t2, t2, -0x8000
	sw	t2, OFFSET_PAGE_TABLE + 0x10(WORK)
	addiu	t2, t2, -0x2000
	sw	t2, OFFSET_PAGE_TABLE + 0x14(WORK)
	addiu	t2, t2, -0x2000
	sw	t2, OFFSET_PAGE_TABLE + 0x18(WORK)
	addiu	t2, t2, -0x2000
	sw	t2, OFFSET_PAGE_TABLE + 0x1c(WORK)
	jr	STORE_DONE

30:
/* 8003
 * swap $B$O(B $BL5;k(B
 * $B%\%s%P!<%^%s$rA*$s$@@$H$-(B set c000 $B$7$J$$$HJQ(B
 * swap $B$O<BAu$7$F$J$$(B
 */
	lw	t1, OFFSET_PRGROM(WORK)
	andi	t2, a1, 0x3f
	addiu	t2, t2, -3      /* $B8e$N(B -0xc000 $B$KAjEv(B */
	mul	t2, t2, 0x4000
	addu	t2, t2, t1
	sw	t2, OFFSET_PAGE_TABLE + 0x18(WORK)
	sw	t2, OFFSET_PAGE_TABLE + 0x1c(WORK)
	j	15b

	
	
	GLOBAL(store12_8000)
store12_8000:
/* Jaleco SS8806
 * 8000,8001: pbank @@ 8000-9fff low, high
 * 8002,8003:         a000-bfff
 * 9000,9001:         c000-dfff
 * address & 0x1000 -> 0,+4
 * address & 0x0003 -> + $B$=$l(B
 * +6 $B0J>e$OL5;k(B
 * t0, t1: temp
 * t2: 0,1, 2,3, 4,5 -> 0, 1, 2 -> 0, 4, 8
 * t3: dst ptr
 * t4: other data ptr -> other data
 * t5: pbank mask
 */
#if 0
/* debug */
	move	a2, a0
	PRINTF("12(%x->%x),");
#endif
	andi	t0, a0, 0x1000
	srl	t0, t0, 12 - 2  /* 0x1000 -> 0x04 */
	andi	t1, a0, 0x0003
	addu	t2, t0, t1
	sltiu	t1, t2, 6
	addu	t3, t2, WORK
	beq	t1, zero, store_ignore /* shinmoe.nes $B$,(B 9002,9003 $B$K=q$-9~$s$G$$$k(B */

	andi	t0, a0, 0x0001
	xor	t4, t3, 1
	lbu	t4, OFFSET_SS_PBANK0(t4) /* $B:#2s@@_Dj$H5U$NJ}$rFI$s$G$/$k(B */
	andi	t1, a1, 0x0f
	beq	t0, zero, 1f
/* higher byte */
	sll	t1, t1, 4
1:
	lbu	t5, OFFSET_PBANK_MASK(WORK)
	sb	t1, OFFSET_SS_PBANK0(t3)
	or	t1, t1, t4
	and	t1, t1, t5
	
/* t1: new pbank */
	srl	t2, t2, 1
	subu	t4, t1, t2  /* -0x8000,-0xa000,-0xc000 $B$K$=$J$($F(B -0,-1,-2 $B$9$k(B */
	addiu	t4, t4, -4  /* $B8e$N(B -0x8000 $B$KAjEv(B */
	mul	t4, t4, 0x2000
	sll	t2, t2, 2   /* 0/1/2 -> 0/4/8 */
#if 0
/* debug */
	move	a1, t2
	move	a2, t1
	PRINTF("12_pbank(%x=%x)\n");
#endif
	lw	t5, OFFSET_PRGROM(WORK)
	addu	t5, t5, t4
	addu	t2, t2, WORK
	sw	t5, OFFSET_PAGE_TABLE + 0x10(t2)
	jr	STORE_DONE

	GLOBAL(store12_a000)
store12_a000:
/* Jaleco SS8806
 * a000,a001: chrbank @@ 0000- low, high
 * a002,a003:           0400-
 * b000,b001:           0800-
 * b002,b003:           0c00-
 * c000,c001:           1000-
 * c002,c003:           1400-
 * d000,d001:           1800-
 * d002,d003:           1c00-
 * address & 0x3000 -> xor 0x2000 -> 0000/1000/2000/3000
 *   -> 0/4/8/c $B$3$l$,(B dst offset $B$=$N(B 1.
 * address & 0x0003 -> + $B$=$l!#(Bdst offset $B$=$N(B 2.
 * $B$G!"(B (dst offset 1 + dst offset 2) & 0x0e $B$,(B chrbank reg0000 $B$+$i$N(B offset.
 * t0, t1: temp
 * t2: dst offset 1 -> (dst offset 1 + dst offset 2) & 0x0e
 * t3: dst offset 2 -> dst ptr
 * t4: other data ptr -> other data
 */
	andi	t0, a0, 0x3000
	xori	t0, t0, 0x2000
	srl	t2, t0, 12 - 2  /* 0x3000 -> 0x0c */
	andi	t3, a0, 0x0003
	addu	t2, t2, t3
	addu	t3, t2, WORK
	xori	t4, t3, 0x01
	lbu	t4, OFFSET_SS_CHRBANK0(t4)
	andi	t0, a1, 0x0f
	andi	t1, a0, 0x0001
	beq	t1, zero, 1f
/* higher byte */
	sll	t0, t0, 4
1:
	sb	t0, OFFSET_SS_CHRBANK0(t3)
	or	t0, t0, t4
/* t0: new chrbank */
	andi	t2, t2, 0x0e
	addu	t2, t2, WORK
	sh	t0, OFFSET_CHRBANK_REG0000(t2)
	sb	zero, OFFSET_BG_CHRBANK_TOUCH_FLAG(WORK)
	sb	zero, OFFSET_OBJ_CHRBANK_TOUCH_FLAG(WORK)
	jr	STORE_DONE
	
	GLOBAL(store12_e000)
store12_e000:
/* Jaleco SS8806
 * e000,e001: irq L l,h
 * e002,e003: irq H l,h
 * f000,f001: d0=1: enable irq
 * f002: d1=1: one screen @@ 2000-
 *       d1=0: d0 $B$K$h$C$F2#;}$A!"=D;}$A(B
 * f003: External I/O
 */
	andi	t0, a0, 0x1000
	andi	t1, a0, 0x0003
	bne	t0, zero, 10f
/* irq
 * address & 3 -> dst ptr
 */
#if 0
/* debug */
	move	a2,a0
	PRINTF("12_irq(%x->%x)\n");
#endif
	andi	t0, a0, 0x0003
	addu	t0, t0, WORK
	andi	t1, a1, 0x0f
	sb	t1, OFFSET_SS_IRQL(t0)
	jr	STORE_DONE
10:
	andi	t1, a0, 0x0002
	andi	t0, a1, 0x01
	bne	t1, zero, 2f
/* d0=1: enable irq */
	lbu	t1, OFFSET_SS_IRQH + 1(WORK)
	lbu	t2, OFFSET_SS_IRQH + 0(WORK)
	lbu	t3, OFFSET_SS_IRQL + 1(WORK)
	lbu	t4, OFFSET_SS_IRQL + 0(WORK)
	sll	t1, t1, 12
	sll	t2, t2, 8
	sll	t3, t3, 4
	or	t1, t1, t2
	or	t1, t1, t3
	or	t1, t1, t4
	sb	t0, OFFSET_LINECNT_IRQ_ENABLED(WORK)

	li	t0, (-(LINECYCLE_CONST0 + LINECYCLE_CONST1) / 0x100)
	divu	zero, t1, t0
	lh	t2, OFFSET_LINECNT(WORK)
	mflo	t0
	addu	t2, t2, t0
	sh	t2, OFFSET_LINECNT_IRQ(WORK)
	jr	STORE_DONE

2:
/* f003 $B$J$i(B voice (shinmoe.nes)
 */
	andi	t1, a0, 0x0001
	andi	t2, a1, 0x02
	bne	t1, zero, 5f
/* mirror
 */
	sh	zero, OFFSET_VRAM_MIRROR_MASK_OR(WORK)
	bne	t2, zero, 2f
	mul	t0, t0, 0x400
	sh	t0, OFFSET_VRAM_MIRROR_MASK_AND(WORK)
	jr	STORE_DONE
2:
/* one screen @@ 2000- */
	sh	zero, OFFSET_VRAM_MIRROR_MASK_AND(WORK)
	jr	STORE_DONE

5:
/* f003: shinmoe.nes voice
 * $B=q$-9~$`CM$O!"$*$=$i$/C}$C$F$$$k4V!"F1$8CM$r=q$-B3$1$k!#(B
 * 0x00: $B=i4|2=(B ?
 * 0x01: $BL52;(B ?
 *
 *
 * $B%\!<%k$rEj$2$k2;(B
 * 00,42,40....
 * $B%\!<%kJV5e(B
 * 00,4a,48....
 * $B4?@@<(B
 * 00,4e,4c...
 * $B%U%i%$%-%c%C%A(B ?
 * 00,46,44...
 * $B",2<$HF1;~$K$$$1$k(B ?
 * $B!V%"%&%H!W(B
 * 00,02,00...
 * $B!V%;!<%U!W(B
 * 00,06,04...
 * $B!V%U%!!<%k!W(B
 * 00,0a,08...
 * $B!V%U%'%"!W(B
 * 00,0e,0c...
 * $B!V%9%H%i%$%/!W(B
 * 00,12,10...,
 * $B!V%\!<%k!W(B
 * 00,16,14...., 
 * $B!V%?%$%`!W(B
 * 00,1a,18....
 * $B!V%P%C%?!<%"%&%H!W(B
 * 00,1e,1c...
 * $B!V%U%)%"%\!<%k!W(B
 * 00,22,20...
 * $B!V%[!<%`%i%s!W(B
 * 00,26,24...
 * $B!V%W%l%$%\!<%k!W(B
 * 00,2a,28...
 * $B!V%T%C%A%c!<8rBe!W(B
 * 00,2e,2c...
 * $B!VBeBG!W(B
 * 00,32,30...
 * $B!V%$%F!W(B
 * 00,36,34...
 * $B!V%+!<%s!W(B
 * 00,3a,38...
 * $BEv$C$?$H$-$N!"$b$&0l$D$N2;(B
 * 00,3e,3c...
 *
 * 0x40 $BBf$O(B $BL5;k!#(B
 * d1=1 $B$N$H$-!"(Bd5,d4,d3,d2 $B$K$h$C$F!#(B
 * 
 */
#if 0
/* debug */
	PRINTF("12(%x)\n");
#endif
	andi	t0, a1, 0x42
	xori	t2, a1, 0x4e
	beq	t2, zero, 10f
	xori	t0, t0, 0x02
	andi	t1, a1, 0x3c
	bne	t0, zero, store_ignore

	srl	t1, t1, 2
	
	.data
voice_id_table_12:
	.byte	0x4, 0x5, 0x6, 0x7, 0x1, 0x2, 0x3, 0x8
	.byte	0xa, 0xb, 0x9, 0xc, 0xe, 0xd, 0xf, 0xf
	.text
	
	la	t2, voice_id_table_12
	addu	t2, t2, t1
	lbu	a0, 0(t2)
9:
#if 0
/* debug */
	move	a2, a0
	PRINTF("12_voice(%x->%x)\n");
#endif

	sw	LINECYCLE, OFFSET_THREAD_LINECYCLE(WORK)
	sw	STORE_DONE, OFFSET_THREAD_STORE_DONE(WORK)
	sw	gp, OFFSET_THREAD_GP(WORK)
	jal	Sound_PlayMENUPCM
	lw	LINECYCLE, OFFSET_THREAD_LINECYCLE(WORK)
	lw	STORE_DONE, OFFSET_THREAD_STORE_DONE(WORK)
	lw	gp, OFFSET_THREAD_GP(WORK)
		
	jr	STORE_DONE
10:
/* $B4?@@<(B */
	li	a0, 0x10
	j	9b
	
	GLOBAL(store13_5000)
store13_5000:
/* Namcot 106
 * 5000-57ff: irq L
 * 5800-5fff: irq H
 * t1 $B$,(B 0 or 1 $B$G(B 5000-,5800- $B$,J,$+$k!#(B
 * 5800=80,5000=0 $B$r=q$$$F$$$k!#$&$4$+$s(B(kaijyu.nes)
 */
#if 0
/* debug */
	move	a2, a0
	PRINTF("13_irq(%x->%x)\n");
#endif
	addu	t0, t1, WORK
	sb	a1, OFFSET_SUN5_IRQ_L(t0)
	beq	t1, zero, store_done
/* High $B$N(B d7: 1=enable
 * $B%+%&%s%H%"%C%W$7$F(B 0x7fff $B$K$J$C$?$i(B IRQ
 */
	andi	t0, a1, 0x80
	sb	t0, OFFSET_LINECNT_IRQ_ENABLED(WORK)
	beq	t0, zero, store_done

	lbu	t0, OFFSET_SUN5_IRQ_L(WORK)
	lbu	t1, OFFSET_SUN5_IRQ_H(WORK)
	lh	t2, OFFSET_LINECNT(WORK)
	sll	t1, t1, 8
	or	t1, t1, t0
	andi	t1, t1, 0x7fff
	li	t3, 0x7fff
	subu	t3, t3, t1
/* (-(LINECYCLE_CONST0 + LINECYCLE_CONST1) / 0x100) $B$G3d$k$H(B
 * $B2<$,(B $B$A$g$s@@Z$l$k$s$@@$1$I!#(B(rollingj.nes)
 */
	li	t1, (-(LINECYCLE_CONST0 + LINECYCLE_CONST1) / 0x100)
	divu	zero, t3, t1
	mflo	t0
	addu	t2, t2, t0
	sh	t2, OFFSET_LINECNT_IRQ(WORK)
	jr	STORE_DONE
	
	GLOBAL(store13_8000)
store13_8000:
store13_a000:
/* Namcot 106
 * $8000-$87FF    Select a 1kB CHR-ROM page at $0000.
 * $8800-$8FFF    Select a 1kB CHR-ROM page at $0400.
 * $9000-$97FF    Select a 1kB CHR-ROM page at $0800.
 * $9800-$9FFF    Select a 1kB CHR-ROM page at $0C00.
 * $A000-$A7FF    Select a 1kB CHR-ROM page at $1000.
 * $A800-$AFFF    Select a 1kB CHR-ROM page at $1400.
 * $B000-$B7FF    Select a 1kB CHR-ROM page at $1800.
 * $B800-$BFFF    Select a 1kB CHR-ROM page at $1C00.
 */
	andi	t0, a0, 0x3800
	srl	t0, t0, 11 - 1
	addu	t0, t0, WORK
	sh	a1, OFFSET_CHRBANK_REG0000(t0)
	sb	zero, OFFSET_BG_CHRBANK_TOUCH_FLAG(WORK)
	sb	zero, OFFSET_OBJ_CHRBANK_TOUCH_FLAG(WORK)
	jr	STORE_DONE

	GLOBAL(store13_c000)
store13_c000:
/* Namcot 106
 * c000-c7ff,c800-cfff,d000-d7ff,d800-dfff $B$,(B
 * PPU addr 2000-,2400-,2800-,2c00- $B$N(B chrbank.
 * $B$D$^$j(B VROM $B$J$s$@@$1$I(B ...
 * $B$3$3$G(B VROM $B$OLLE]$$$N$G$d$i$J$$!#(B
 * $B=q$-9~$`CM$,(B 0xe0 $B0J>e$N;~$O(B VRAM $B$K@@\B3$9$k$h$&$@@!#(B
 * c000=e0,d000=e0,c800=e1,d800=e1 (n_clasic.nes) $B$N$H$-(B
 * c000- $B$H(B d000- $B$,F1$8(B $B$J$N$G(B $B2#;}$A$G$"$k!#(B
 * $B$7$+$b(B n_clasic.nes $B$O(B PPU $BFI$_=P$7$7$F$$$k$;$$$+!"$3$3$r(B
 * $B<BAu$7$J$$$HK=Av$9$k!#(B
 * c000,c800,d000,d800 $B$X=q$-9~$`CM$,(B
 * e0,  e1,  e0,  e1   -> $B2#;}$A(B
 * e0,  e0,  e1,  e1   -> $B=D;}$A(B
 * e0,  e0,  e0,  e0   -> 1 $B2hLL(B 2000-
 * e1,  e1,  e1,  e1   ->        2400-
 * $BB>$NAH$_9g$o$;$N;~$O(B $B$I$&$9$k(B?
 * c800-,d000- $B$NAH$_9g$o$;$@@$1$G(B $B7h$a$A$c$*$&!#(B
 * ss_pbank0,1 $B$r;H$&!#(B
 * fcirc91.nes $B$O(B $B$3$l$G$$$1$k$+$b!#(B($B=i4|CM(B $B2#;}$A(B)
 */
#if 0
/* debug */
	move	a2, a0
	PRINTF("13(%x->%x)\n");
#endif
	andi	t0, a0, 0x1800
	srl	t0, t0, 11  /* 0x1800 -> 3 */
	addu	t0, t0, WORK
	andi	t1, a1, 0x01
	sb	t1, OFFSET_SS_PBANK0(t0)

	lbu	t1, OFFSET_SS_PBANK0 + 1(WORK)
	lbu	t2, OFFSET_SS_PBANK0 + 2(WORK)
	beq	t1, t2, 2f  /* 1 $B2hLL(B */
	mul	t2, t2, 0x400  /* t2 $B$,(B 0 $B$J$i(B $B2#;}$A(B */
	addiu	t2, t2, 0x400
	sh	t2, OFFSET_VRAM_MIRROR_MASK_AND(WORK)
	sh	zero, OFFSET_VRAM_MIRROR_MASK_OR(WORK)
	jr	STORE_DONE
2:
	mul	t1, t1, 0x400
	addiu	t1, t1, 0x400
	sh	t1, OFFSET_VRAM_MIRROR_MASK_OR(WORK)
	sh	zero, OFFSET_VRAM_MIRROR_MASK_AND(WORK)
	jr	STORE_DONE

	
	GLOBAL(store13_e000)
store13_e000:
/* Namcot 106
 * e000-e7ff: pbank 8000-9fff
 * e800-efff:       a000-bfff
 * f000-f7ff:       c000-dfff
 * f800: wram address register
 */
#if 0
/* debug */
	move	a2, a0
	PRINTF("13(%x->%x)\n");
#endif
	lw	t2, OFFSET_PRGROM(WORK)
	lbu	t4, OFFSET_PBANK_MASK(WORK)
	andi	t0, a0, 0x1800
	xori	t1, t0, 0x1800
	beq	t1, zero, 8f
/* t0: 0 or 0x800 or 0x1000
 * t1: (0 or 0x2000 or 0x4000) - 0x8000
 * t2: prgrom
 * t3: 0 or 4 or 8
 * t4: bank * 0x2000
 */
	and	t4, t4, a1
	mul	t4, t4, 0x2000
	srl	t3, t0, 11 - 2
	sll	t1, t0, 2
	subu	t1, t2, t1
	addiu	t1, t1, -0x8000
	addu	t1, t1, t4
	addu	t3, t3, WORK

#if 0
/* debug */
	subu	a1, t1, t2
	subu	a2, t3, WORK
	move	a3, t1
	PRINTF("13(%x,%x,%x)\n");
#endif
	sw	t1, OFFSET_PAGE_TABLE + 0x10(t3)
	jr	STORE_DONE

8:
	jr	STORE_DONE

	GLOBAL(store16_8000)
store16_8000:
/* VRC2-Shift
 * 8000-8fff: pbank at 8000-9fff
 * 9000-9fff: mirror d1,d0
 *                    00=$B2#;}$A(B
 *                    01=$B=D;}$A(B
 *                    10=one screen 2000- ?
 *                    11            2400- ?
 */
#if 0
/* debug */
	move	a2, a0
	PRINTF("16(%x->%x)\n");
#endif
	lbu	t1, OFFSET_PBANK_MASK(WORK)
	andi	t0, a0, 0x1000
	bne	t0, zero, store16_9000
	lw	t0, OFFSET_PRGROM(WORK)
	and	t2, a1, t1
	mul	t2, t2, 0x2000
	addu	t0, t0, t2
	addiu	t0, t0, -0x8000
	sw	t0, OFFSET_PAGE_TABLE + 0x10(WORK)
	jr	STORE_DONE

	GLOBAL(store16_9000)
store16_9000:
/* mapper 0x19(VRC2/4 Even), mapper 0x44(Sunsoft 4)
 * $B$+$i$bMh$k(B
 * d1=1 $B$J$i(B one screen, d0 $B$K$h$C$F(B 2000- or 2400-
 * d1=0 $B$J$i(B d0 $B$K$h$C$F(B $B2#;}$A(B or $B=D;}$A(B
 */
	andi	t0, a1, 0x02
	andi	t1, a1, 0x01
	mul	t1, t1, 0x400
	bne	t0, zero, 2f
	sh	zero, OFFSET_VRAM_MIRROR_MASK_OR(WORK)
	addiu	t1, t1, 0x400
	sh	t1, OFFSET_VRAM_MIRROR_MASK_AND(WORK)
#if 0
/* debug */
	move	a2, t1
	PRINTF("16_mirror(%x,%x)\n");
#endif
	jr	STORE_DONE
2:
/* one screen */
	sh	zero, OFFSET_VRAM_MIRROR_MASK_AND(WORK)
	sh	t1, OFFSET_VRAM_MIRROR_MASK_OR(WORK)
	jr	STORE_DONE

	GLOBAL(store16_a000)
store16_a000:
/* a000-afff: pbank at a000-bfff
 * b000,b002,...,bffe: chrbank 0000-03ff
 */
#if 0
/* debug */
	move	a2, a0
	PRINTF("16(%x->%x)\n");
#endif
	lbu	t1, OFFSET_PBANK_MASK(WORK)
	andi	t0, a0, 0x1000
	bne	t0, zero, store16_b000
	GLOBAL(store16_a000_common)
store16_a000_common:
/* store19_a000, store17_a000 $B$+$i$bMh$k!#(B
 * t1: pbank mask
 */
	lw	t0, OFFSET_PRGROM(WORK)
	and	t2, a1, t1
	addiu	t2, t2, -5  /* $B8e$N(B -0xa000 $B$KAjEv(B */
	mul	t2, t2, 0x2000
	addu	t0, t0, t2
	sw	t0, OFFSET_PAGE_TABLE + 0x14(WORK)
	jr	STORE_DONE

	GLOBAL(store16_b000)
store16_b000:
/* b000,b001,c000,c001,d000,d001,e000,e001:
 * chrbank 0000-,0400-,..., 1c00-
 * (addr >> 10) $B$,(B 0x2c,0x30,0x34,0x38 $B$K$J$k$h$&$K$9$k!#(B
 *              -> 0x0c,0x10,0x14,0x18 $B$X!#(B
 * (addr & 1) -> 0 or 2
 * Shift this value right one bit
 * $B$H$$$&$3$H$@@!#(B
 * konami/twinbee3.nes $B$G$O(B
 * b000,b002; b001,b003; c000,c002; c001,c003; ... $B$N$h$&$K=q$-9~$s$G$$$F(B
 * b000 $B$N(B $B>e0L(B 4bits $B$,(B b002 $B$K=q$-9~$^$l$F$$$k$h$&$@@!#(B
 * $B$=$3$G!"(B address & 0x02 $B$,(B 0 $B$G$J$1$l$PL5;k$9$k!#(B
 */
#if 0
/* debug */
	move	a2, a0
	PRINTF("16(%x->%x)\n");
#endif
	srl	t0, a0, 10
	andi	t1, a0, 0x02
	bne	t1, zero, store_done
	andi	t0, t0, 0x1c
	andi	t1, a0, 0x0001
	sll	t1, t1, 1
	or	t0, t0, t1
	addu	t0, t0, WORK
	srl	t1, a1, 1
	sh	t1, OFFSET_CHRBANK_REG0000 - 0x0c(t0)
	sb	zero, OFFSET_BG_CHRBANK_TOUCH_FLAG(WORK)
	sb	zero, OFFSET_OBJ_CHRBANK_TOUCH_FLAG(WORK)
	jr	STORE_DONE

	GLOBAL(store17_a000)
store17_a000:
/* a000-afff: pbank at a000-bfff
 * b000,b001,b002,b003,...,bfff: chrbank 0000-03ff,0400-07ff
 * $B$G$b(B $B%P%s%/%l%8%9%?$N%"%I%l%93d$jIU$1$,0c$&$N$G(B mapper 0x16 $B$H$OJL!#(B
 */
	lbu	t1, OFFSET_PBANK_MASK(WORK)
	andi	t0, a0, 0x1000
	beq	t0, zero, store16_a000_common

	GLOBAL(store17_b000)
store17_b000:
/* b000,b001: chr @@ 0000- low, high
 * b002,b003:       0400-
 * c000,c001:       0800- low, high
 * c002,c003:       0c00-
 * d000,d001:       1000-
 * d002,d003:       1400-
 * e000,e001:       1800-
 * e002,e003:       1c00-
 * parodius.nes, kdracula.nes, crisis_f.nes $B$O(B
 * b000,b004, b008,b00c, $B$N%?%$%W!#(B
 *
 * address & (0x01 | 0x04) $B$K$h$C$F(B low or high
 * address & (0x02 | 0x08) $B$K$h$C$F(B 0000-, 0400-
 *                                  +0     +2
 * address >> 10 $B$,(B 0x2c,0x30,0x34,0x38
 *               -> 0x0c,0x10,0x14,0x18
 * t3: previous chrbank
 */
#if 0
/* debug */
	move	a2, a0
	PRINTF("17_chrbank(%x->%x)\n");
#endif
	srl	t0, a0, 10
	andi	t0, t0, 0x1c
	andi	t1, a0, 0x0002 | 0x0008
	beq	t1, zero, 2f
	addiu	t0, t0, 0x02
2:
	addu	t0, t0, WORK
	lhu	t3, OFFSET_CHRBANK_REG0000 - 0x0c(t0)
	andi	t1, a0, 0x0001 | 0x0004
	bne	t1, zero, store19_b000_common_high
	j	store19_b000_common_low

	GLOBAL(store17_e000)
store17_e000:
/* e000-efff: chrbank
 * f000-ffff: irq
 */
	andi	t0, a0, 0x0f
	andi	t1, a0, 0x1000
	beq	t1, zero, store17_b000
#if 0
/* debug */
	move	a2, a0
	PRINTF("17_irq(%x->%x)\n");
#endif
/* irq
 * parodius.nes $B$O(B
 * f000,f004: count L,H
 * f008 $B$,(B trigger
 * t0: addr & 0x0f
 */
	.set	noreorder
	beq	t0, zero, store19_f000_0
	andi	t1, t0, 0x04
	bne	t1, zero, store19_f002
	andi	t1, t0, 0x08
	bne	t1, zero, store19_f001
	nop
	.set	reorder
	jr	STORE_DONE

	
	GLOBAL(store18_8000)
store18_8000:
/* VRC6
 * 8000-ffff: pbank @@ 8000-bfff - bank no $B$H$NBP1~$O(B ?
 */
#if 0
/* debug */
	move	a2, a0
	PRINTF("18(%x->%x)\n");
#endif
	lbu	t1, OFFSET_PBANK_MASK(WORK)
	andi	t0, a0, 0x1000
	bne	t0, zero, store18_9000  /* sound */
/* $B6v?t$N$_=q$-9~$^$l$k$H2>Dj$7$h$&!#(B
 * $B0c$C$?!#4q?t$,=q$-9~$^$l$F$$$k!#(B
 */
	lw	t0, OFFSET_PRGROM(WORK)
	sll	t2, a1, 1
	and	t1, t1, t2
	mul	t1, t1, 0x2000
	addiu	t1, t1, -0x8000
	addu	t0, t0, t1
	sw	t0, OFFSET_PAGE_TABLE + 0x10(WORK)
	sw	t0, OFFSET_PAGE_TABLE + 0x14(WORK)
	jr	STORE_DONE

	GLOBAL(store18_9000)
store18_9000:
/* VRC6 sound
 *
 * 9000,a000,b000 ch1,ch2,ch3 Sound Control 1
 * 9001,a001,b001 ch1,ch2,ch3 Sound Control 2
 * 9002,a002,b002 ch1,ch2,ch3 Sound Control 3
 *
 * address & 0x3000 -> 1000,2000,3000
 *              nes $B$N(B 5000,5004,5008
 * address & 0x0001 -> 5003,5007,500b
 * address & 0x0002 -> 5002,5006,500a
 * $B$K$7$F$_$k!#(B
 * 
 */
#if 0
/* debug */
	move	a2, a0
	PRINTF("VRC6_SoundWrite(%x->%x)\n");
#endif
	lbu	t4, OFFSET_VRC6_REG_SWAP(WORK)
	andi	t0, a0, 0x3000
	addiu	t0, t0, -0x1000
	srl	t0, t0, 12 - 2  /* 0x2000 -> 0x08 */
	andi	t1, a0, 0x0003
	beq	t1, zero, 1f
	xor	t1, t1, t4
	addu	t0, t0, t1
	addiu	t0, t0, 1
	xori	t3, t1, 0x0003
	beq	t3, zero, store_done
1:
	ori	a0, t0, 0x5000
#if 0
	andi	t0, a0, 0x08
	beq	t0, zero, store_done
#endif
#if 0
/* debug */
	move	a2, a0
	PRINTF("18_sound(%x->%x)\n");
#endif
	
	lw	a2, OFFSET_SOUNDCYCLE(WORK)
	lbu	t3, OFFSET_SOUND_CYCLE_DIVIDER(WORK)
	divu	zero, a2, t3
	mflo	a2
	sw	LINECYCLE, OFFSET_THREAD_LINECYCLE(WORK)
	sw	STORE_DONE, OFFSET_THREAD_STORE_DONE(WORK)
	sw	gp, OFFSET_THREAD_GP(WORK)
	
	jal	Sound_Write

#if 0
/* debug */
	PRINTF("written\n");
#endif
	
	lw	LINECYCLE, OFFSET_THREAD_LINECYCLE(WORK)
	lw	STORE_DONE, OFFSET_THREAD_STORE_DONE(WORK)
	lw	gp, OFFSET_THREAD_GP(WORK)
	jr	STORE_DONE
	
	
	GLOBAL(store18_a000)
store18_a000:
/* VRC6
 * b003 $B0J30(B sound
 * b003 Mirror Setting
 * Bmmmmmmm
 * B: SRAM enable/disable 1:enable 0:disable
 * mmmmmmm: Mirroring
 *  #08 HHHH
 *  #20 VHVH
 *  #24 VVHH
 *  #28 VVVV
 *  #2C HHHH
 */
#if 0
/* debug */
	move	a2, a0
	lhu	a3, OFFSET_LINECNT(WORK)
	PRINTF("18(%x->%x)line=%x\n");
#endif

	xori	t0, a0, 0xb003
	bne	t0, zero, store18_9000
#if 0
/* debug */
	lhu	a2, OFFSET_LINECNT(WORK)
	PRINTF("18_mirror=%x at line=%x\n");
#endif
/* mirror
 * 0x2c $B$N0L$K$D$$$F(B
 * 20=$B2#;}$A(B
 * 24=$B=D;}$A(B
 * 28=one screen @@ 2000- $B$H$A$c$&(B ?
 * 2c=one screen @@ 2400- $B$H$A$c$&(B ? (cv3j.nes)
 * $BB>$O(B one screen @@ 2000-
 * 0x08 $B$N0L$,N)$C$F$$$?$i(B one screen
 * $B8e$O(B 0x04 $B$N0L$G8+$k!#(B
 */
	
	andi	t0, a1, 0x08
	andi	t1, a1, 0x04
	bne	t0, zero, 8f
/* $B2#;}$A$J$i(B t1=0
 * $B=D;}$A$J$i(B    4
 */
	sll	t1, t1, 8  /* 0x04 -> 0x400 */
	addiu	t1, t1, 0x400
	sh	t1, OFFSET_VRAM_MIRROR_MASK_AND(WORK)
	sh	zero, OFFSET_VRAM_MIRROR_MASK_OR(WORK)
	jr	STORE_DONE
8:
/* one screen
 * 0x2c $B$J$i(B 2400- $B$H$7$F$*$3$&!#(B
 * esperdr2.nes $B$,(B 0xac $B$r=q$-9~$s$G$$$k!#(B
 */
	andi	t0, a1, 0x2c
	xori	t0, t0, 0x2c
	li	t1, 0x400
	beq	t0, zero, 1f
	li	t1, 0
1:
	sh	t1, OFFSET_VRAM_MIRROR_MASK_OR(WORK)
	sh	zero, OFFSET_VRAM_MIRROR_MASK_AND(WORK)
	jr	STORE_DONE
	
	GLOBAL(store18_c000)
store18_c000:
/* c000-cfff: pbank @@ c000-dfff
 * d000,d001,d002,d003,e000,e001,e002,e003:
 * chrbank 0000-,0400-,..., 1c00-
 */
#if 0
/* debug */
	move	a2, a0
	PRINTF("18(%x->%x)\n");
#endif
	lbu	t1, OFFSET_PBANK_MASK(WORK)
	andi	t0, a0, 0x1000
	bne	t0, zero, 10f
	lw	t0, OFFSET_PRGROM(WORK)
	and	t1, t1, a1
	addiu	t1, t1, -6  /* $B8e$N(B -0xc000 $B$KAjEv(B */
	mul	t1, t1, 0x2000
	addu	t0, t0, t1
	sw	t0, OFFSET_PAGE_TABLE + 0x18(WORK)
	jr	STORE_DONE
10:
/* chrbank
 * addr & 0x1000 -> 0x1000 $B$J$i(B d000-d003 $B$N=q$-9~$_!#(B(+0)
 *                  0           e000-e003             (+0x8)
 * t0: addr & 0x1000
 * $B2<$+$i$bMh$k!#(B
 */
#if 0
/* debug */
	move	a2, a0
	lhu	a3, OFFSET_LINECNT(WORK)
	PRINTF("18_chrbank(%x->%x)line=%x\n");
#endif
	lbu	t2, OFFSET_VRC6_REG_SWAP(WORK)
	andi	t1, a0, 0x0003
	beq	t1, zero, 2f
	xori	t3, t1, 0x0003
	beq	t3, zero, 2f
	xor	t1, t1, t2
2:
	sll	t1, t1, 1
	bne	t0, zero, 1f
	addiu	t1, t1, 8
1:
	addu	t1, t1, WORK
	sh	a1, OFFSET_CHRBANK_REG0000(t1)
	sb	zero, OFFSET_BG_CHRBANK_TOUCH_FLAG(WORK)
	sb	zero, OFFSET_OBJ_CHRBANK_TOUCH_FLAG(WORK)
	jr	STORE_DONE

	GLOBAL(store18_e000)
store18_e000:
/* e000-efff: chrbank
 * t0: addr & 0x1000
 * f000-ffff: irq
 * f000 IRQ scanline($BK\Ev$O(Bclock) counter
 *  (#$100-i)*#$72 clock wait.
 * f001 IRQ enable/disable
 * f002 IRQ enable/disable
 *   ------AB
 *   A 0:IRQ disable
 *     1:IRQ enable
 *   B 0:f001 is IRQ disable
 *     1:f001 is IRQ enable
 */
#if 0
/* debug */
	move	a2, a0
	PRINTF("18(%x->%x)\n");
#endif

	andi	t1, a0, 0x03
	andi	t0, a0, 0x1000
	beq	t0, zero, 10b

#if 0
/* debug */
	move	a2, a0
	lhu	a3, OFFSET_LINECNT(WORK)
 	PRINTF("18_irq(%x->%x) line=%x\n");
#endif

#if 0
/* old code */
	.set	noreorder
	beq	t1, zero, 1f   /* f000 */
	andi	t1, a0, 0x02
	bne	t1, zero, 2f   /* f002 */
	nop
	.set	reorder
/* f001
 * IRQ enable/disable
 * f002 $B$N(B d0 $B$K$h$C$F(B IRQ enabled/disabled $B$,(B $BH?E>(B ?
 * $B$A$,$&!#(B
 * f002 $B$N(B d0 $B$,(B 0 or $B=i4|>uBV$J$i(B $B$3$3(B f001 $B$X$N=q$-9~$_(B $B$N(B d1 $B$,(B enable.
 */
	lbu	t0, OFFSET_VRC6_IRQ_SELECT(WORK)
	andi	t0, t0, 0x01
	beq	t0, zero, 3f
/* f002 $B$N(B d0 $B$,(B 1 $B$J$i(B f002 $B$N(B d1 $B$,(B enable ? */
	jr	STORE_DONE

1:
/* f000
 * IRQ count
 */
	sb	a1, OFFSET_VRC6_IRQ(WORK)
	jr	STORE_DONE
2:
/* f002
 * d1: 1=IRQ enable,0=disable
 * d0: $B2?$@@$m$&(B ...
 */
	sb	a1, OFFSET_VRC6_IRQ_SELECT(WORK)
3:
/* $B>e$+$i$bMh$k!#(B*/
	andi	t0, a1, 0x02
	sb	t0, OFFSET_LINECNT_IRQ_ENABLED(WORK)
	lbu	t1, OFFSET_VRC6_IRQ(WORK)
	lh	t2, OFFSET_LINECNT(WORK)
	li	t3, 0x100
	subu	t1, t3, t1
	addu	t2, t2, t1
	sh	t2, OFFSET_LINECNT_IRQ(WORK)
	jr	STORE_DONE
#endif

#if 1
/* new code
 *  Any value written here will
 *  reset the IRQ counter to zero.
 * $B$H$$$&$3$H$G!"(B
 * f002 $B$X$N=q$-9~$_$O(B IRQ $B6X;_$7$F$_$k!#(B
 */
	.set	noreorder
	beq	t1, zero, 1f   /* f000 */
	lbu	t3, OFFSET_VRC6_IRQ_REG(WORK)
	and	t1, a0, t3
	bne	t1, zero, 2f   /* f001 */
	nop
	.set	reorder
/* f002
 * IRQ restart ?
 */
	lbu	t0, OFFSET_VRC6_IRQ_SELECT(WORK)
	andi	t0, t0, 0x01
	bne	t0, zero, 22f
	li	t1, 0x8000
	sh	t1, OFFSET_LINECNT_IRQ(WORK)
	jr	STORE_DONE
2:
/* f001 */
	sb	a1, OFFSET_VRC6_IRQ_SELECT(WORK)
	andi	t0, a1, 0x02
22:
#if 0
/* debug */
	move	a2, t0
	PRINTF("xxx,%x,%x,");
#endif
	sb	t0, OFFSET_LINECNT_IRQ_ENABLED(WORK)
3:
/* $B2<$+$i$bMh$k(B $B$N$+(B? */
	lbu	t1, OFFSET_VRC6_IRQ(WORK)
	lh	t2, OFFSET_LINECNT(WORK)
	li	t3, 0x100
	subu	t1, t3, t1
	addu	t2, t2, t1
#if 0
/* debug */
	move	a2, t2
	PRINTF("%x,next=%x\n");
#endif
	sh	t2, OFFSET_LINECNT_IRQ(WORK)
	jr	STORE_DONE
1:
/* f000 */
	sb	a1, OFFSET_VRC6_IRQ(WORK)
	jr	STORE_DONE
#endif
	
	GLOBAL(store19_8000)
store19_8000:
/* VRC2/4 Even
 * 8000-8fff: pbank @@ 8000-9fff or c000-dfff (map mode $B$K$h$k(B)
 * 9000: mirror (mapper 0x16 $B$HF1$8(B)
 * 9002: d0: SRAM enable, d1: map mode 0=8000-9fff,1=c000-dfff
 */
	lbu	t1, OFFSET_VRC4_MAPMODE(WORK)
	andi	t0, a0, 0x1000
	bne	t0, zero, 9f
/* pbank at ... 8000-? c000-? */
	lw	t0, OFFSET_PRGROM(WORK)
	lbu	t2, OFFSET_PBANK_MASK(WORK)
	and	t2, t2, a1
	sb	t2, OFFSET_VRC4_PBANK(WORK)
	addiu	t2, t2, -4  /* $B8e$N(B -0x8000 $B$KAjEv(B */
	mul	t2, t2, 0x2000
	addu	t0, t0, t2
	andi	t1, t1, 0x02
	bne	t1, zero, 2f
8:
/* 8000-9fff
 * $B2<$+$i$bMh$k!#(B
 */
	sw	t0, OFFSET_PAGE_TABLE + 0x10(WORK)
	jr	STORE_DONE
	
9:
/* 9000 $B$J$i(B mirror
 * 9002 $B$J$i(B mapmode
 */
#if 0
/* debug */
	move	a2, a0
	PRINTF("19_9000(%x->%x)\n");
#endif
	lbu	t1, OFFSET_VRC4_MAPMODE(WORK)
	andi	t0, a0, 0x0002
	beq	t0, zero, store16_9000
	lbu	t2, OFFSET_VRC4_PBANK(WORK)
	sb	a1, OFFSET_VRC4_MAPMODE(WORK)
	xor	t1, t1, a1
	andi	t1, t1, 0x02
	beq	t1, zero, store_done
/* mapmode $B$,(B $BJQ$o$C$?!#(B*/
	lw	t0, OFFSET_PRGROM(WORK)
	addiu	t2, t2, -4  /* $B8e$N(B -0x8000 $B$KAjEv(B */
	mul	t2, t2, 0x2000
	addu	t0, t0, t2
	andi	t1, a1, 0x02
	beq	t1, zero, 8b
2:
/* c000-dfff */
	addiu	t0, t0, -0x4000  /* $B$9$G$K(B -0x8000 $B$5$l$F$$$k(B */
	sw	t0, OFFSET_PAGE_TABLE + 0x18(WORK)
	jr	STORE_DONE

	GLOBAL(store19_a000)
store19_a000:
/* VRC2/4 Even
 * a000-afff: pbank @@ a000-bfff
 */
	lbu	t1, OFFSET_PBANK_MASK(WORK)
	andi	t0, a0, 0x1000
	beq	t0, zero, store16_a000_common

	GLOBAL(store19_b000)
store19_b000:
/* chrbank $B$O(B low, high 4bits $B$:$D$N=q$-9~$_$G(B d3-d0 $B$,M-8z!#(B
 * b000: chrbank @@ 0000-03ff low
 * b002:                     high
 * b001/b004:      0400-07ff low
 * b003/b006:                high
 * $BF1MM$K(B c000,c002: 0800-0bff, c001/c004,c003/c006: 0c00-0fff,
 * d000,d002: 1000-13ff, d001/d004,d003/d006: 1400-17ff
 * e000,e002: 1800-1bff, e001/e004,e003/e006: 1c00-1bff
 * goemong2.nes $B$O(B
 * b000,b040, b080,b0c0, $B$N%?%$%W!#(B
 *
 * t1: addr & (0x02 | 0x40) $B$,(B low or high.
 * t2: addr & (0x01 | 0x04 | 0x80) $B$,(B 0 $B$+$I$&$+$G(B 0000-, 0400-.
 *                                              -> +0     +2
 * t0: (addr >> 10) $B$,(B 0x2c,0x30,0x34,0x38 $B$K$J$k$h$&$K$9$k!#(B
 *                  -> 0x0c,0x10,0x14,0x18 $B$X!#(B
 * t3: previous chrbank
 */
#if 0
/* debug */
	move	a2, a0
	PRINTF("19_chrbank(%x->%x)\n");
#endif
	srl	t0, a0, 10
	andi	t0, t0, 0x1c
	addu	t0, t0, WORK
	andi	t2, a0, 0x0001 | 0x0004 | 0x0080
	beq	t2, zero, 1f
	addiu	t0, t0, 2
1:
	lhu	t3, OFFSET_CHRBANK_REG0000 - 0x0c(t0)
	andi	t1, a0, 0x0002 | 0x0040
	beq	t1, zero, 2f
	GLOBAL(store19_b000_common_high)
store19_b000_common_high:
/* higher bit $B$N@@_Dj(B. store17_b000 $B$+$i$bMh$k(B */
	sll	t1, a1, 4
	andi	t3, t3, 0x0f
3:
/* $B2<$+$i$bMh$k!#(B*/
	or	t1, t1, t3
	andi	t1, t1, 0xff
	sh	t1, OFFSET_CHRBANK_REG0000 - 0x0c(t0)
	sb	zero, OFFSET_BG_CHRBANK_TOUCH_FLAG(WORK)
	sb	zero, OFFSET_OBJ_CHRBANK_TOUCH_FLAG(WORK)
	jr	STORE_DONE
	GLOBAL(store19_b000_common_low)
store19_b000_common_low:
2:
/* lower bit $B$N@@_Dj(B */
	andi	t1, a1, 0x0f
	andi	t3, t3, 0xf0
	j	3b

	GLOBAL(store19_e000)
store19_e000:
/* e000-efff: chrbank
 * f000,f002: d3-d0: LINECNT_IRQ ($B%V%i%s%-%s%0J,$b4^$`(B?) low, high
 * f001,f004: d2: IRQ enable
 * f003,f006: timer start?
 */
	andi	t0, a0, 0x1000
	beq	t0, zero, store19_b000

	GLOBAL(store19_f000)
store19_f000:
#if 0
/* debug */
	move	a2, a0
	PRINTF("19(%x->%x)\n");
#endif
/* f000: IRQ counter low
 * f002, f040:             high
 * f001, f080: d1: IRQ disabled/enabled
 *             d0: 1=timer restart ?
 * goemong2.nes $B$,(B f000,f040,f080 $B$r;H$C$F$k!#(B
 */
	.set	noreorder
	andi	t0, a0, 0x07 | 0x40 | 0x80
	beq	t0, zero, store19_f000_0
	xori	t1, t0, 0x02
	beq	t1, zero, store19_f002
	xori	t1, t0, 0x01
	beq	t1, zero, store19_f001
	xori	t1, t0, 0x04
	beq	t1, zero, store19_f001
	xori	t1, t0, 0x03
	beq	t1, zero, store19_f003
	andi	t1, t0, 0x40
	bne	t1, zero, store19_f002
	andi	t1, t0, 0x80
	bne	t1, zero, store19_f001
	nop
	.set	reorder

#if 0
/* debug */
	move	a2, a0
	PRINTF("19_irq(%x->%x)\n");
#endif
	
	jr	STORE_DONE

	GLOBAL(store19_f000_0)
store19_f000_0:
/* irq counter low
 * store17_e000 $B$+$i$bMh$k!#(B
 */
	andi	t1, a1, 0x0f
	sb	t1, OFFSET_VRC4_IRQ_L(WORK)
	jr	STORE_DONE

	GLOBAL(store19_f002)
store19_f002:
/* irq counter high
 * store17_e000 $B$+$i$bMh$k!#(B
 */
	sll	t1, a1, 4
	sb	t1, OFFSET_VRC4_IRQ_H(WORK)
	jr	STORE_DONE

	GLOBAL(store19_f001)
store19_f001:
/* d1=1: irq enabled
 * d0=1: timer start ?
 * gradius2.nes $B$G$O(B f001 $B$K$O(B 3 $B$r!"(B
 *                   f003 $B$K$O(B 0xa $B$r=q$$$F$$$k!#(B
 * f001 or f003 $B$N!"(Bd1 $B$O6&DL$H$7$F(B
 *                  d0 or d3 =1: timer start $B$K$7$F$_$k!#(B
 * $B0c$&$J$"(B.
 * d0$B$rL5;k$7$F6/@@)E*$K(B timer start $B$H$9$k$H(B romupa.nes $B%P%C%A%j!#(B
 *                                           gradisu2.nes $B$b!#(B
 *                                           kworld2.nes $B$b(B !
 * mini4ku.nes $B$b(B $BA0$h$j$O$h$/$J$C$?(B ($B%G%b$,$*$+$7$$$,(B ... chrbank?)
 *             $B%$%a!<%8ITNI$A$c$&(B ?
 * 
 * store17_e000 $B$+$i$bMh$k!#(B
 */
	andi	t0, a1, 0x02
	sb	t0, OFFSET_LINECNT_IRQ_ENABLED(WORK)
	andi	t1, a1, 0x01 | 0x08
	j	1f
	bne	t1, zero, 1f
/* timer stop */
	li	t0, 0x8000
	sh	t0, OFFSET_LINECNT_IRQ(WORK)
	jr	STORE_DONE
1:
/* timer start
 * 0x100 - (irq_l | irq_h) $B$r(B linecnt $B$K2C$($F$_$k!#(B
 *                            -> gradius2.nes $B%?%$%H%k!"%2!<%`2hLL6&$K(B OK!
 * $BESCf$N%W%m%_%M%s%9$G!"2hLL$N??$sCf(B 1 line $B$,$A$i$D$/!#(B0x101 $B$G$b!#(B
 *   -> linecnt_over19 $B$GBP:v$7$?!#(B
 * 0x101 - $B$K$7$?$[$&$,(B goemong2.nes, crisis_f.nes $BNI$/$J$C$?!#(B
 */
	lbu	t0, OFFSET_VRC4_IRQ_L(WORK)
	lbu	t1, OFFSET_VRC4_IRQ_H(WORK)
	lh	t3, OFFSET_LINECNT(WORK)
	sh	t3, OFFSET_VRC4_LINECNT_SAVE(WORK)
	or	t0, t0, t1
	li	t2, 0x101
	subu	t0, t2, t0
	addu	t3, t3, t0
	sh	t3, OFFSET_LINECNT_IRQ(WORK)
	jr	STORE_DONE

	GLOBAL(store19_f003)
store19_f003:
/* $BA02s$N(B f001 $B=q$-9~$_;~$N(B linecnt $B$r;H$C$F(B
 * timer restart ?
 */
	lbu	t0, OFFSET_VRC4_IRQ_L(WORK)
	lbu	t1, OFFSET_VRC4_IRQ_H(WORK)
	lh	t3, OFFSET_VRC4_LINECNT_SAVE(WORK)
	or	t0, t0, t1
	addu	t3, t3, t0
	sh	t3, OFFSET_LINECNT_IRQ(WORK)
	jr	STORE_DONE

	GLOBAL(store20_8000)
store20_8000:
/* 8fff: pbank @@ 8000- or c000-
 */
	lbu	t2, OFFSET_SS_PBANK0 + 1(WORK)
	andi	t0, a0, 0x1000
	bne	t0, zero, 10f
	lw	t3, OFFSET_PRGROM(WORK)
	andi	t2, t2, 0x02
	sll	t2, t2, 2      /* 0x02 -> 0x08 */
	addiu	t4, t2, 0x10   /* $B8e$N(B -0x8000 $B$KAjEv(B */
	sll	t4, t4, 3 + 8  /* 0x08 -> 0x4000 */
	addu	t2, t2, WORK
	subu	t3, t3, t4
	lbu	t1, OFFSET_PBANK_MASK(WORK)
	and	t1, t1, a1
	sb	t1, OFFSET_SS_PBANK0(WORK)
	mul	t1, t1, 0x2000
	addu	t3, t3, t1
	sw	t3, OFFSET_PAGE_TABLE + 0x10(t2)
	jr	STORE_DONE
10:
/* 9fff: mirror */
	andi	t0, a1, 0x01
	mul	t0, t0, 0x400
	addiu	t0, t0, 0x400
	sh	t0, OFFSET_VRAM_MIRROR_MASK_AND(WORK)
	
	xor	t1, t2, a1
	andi	t1, t1, 0x02
	beq	t1, zero, store_done

/* d1 $B$,(B mapmode. 8000- or c000- */
	lw	t0, OFFSET_PRGROM(WORK)
	lbu	t2, OFFSET_SS_PBANK0(WORK)
	sb	a1, OFFSET_SS_PBANK0 + 1(WORK)
	andi	t1, a1, 0x02
	bne	t1, zero, 2f
/* 8000- */
	addiu	t2, t2, -0x04  /* $B8e$N(B -0x8000 $B$KAjEv(B */
	addiu	t3, WORK, 0
	j	1f
2:
/* c000- */
	addiu	t2, t2, -0x06  /* $B8e$N(B -0xc000 $B$KAjEv(B */
	addiu	t3, WORK, 8
1:
	mul	t2, t2, 0x2000
	addu	t2, t2, t0
	sw	t2, OFFSET_PAGE_TABLE + 0x10(t3)
	jr	STORE_DONE

	GLOBAL(store20_a000)
store20_a000:
/* afff: pbank @@ a000-
 */
	lbu	t1, OFFSET_PBANK_MASK(WORK)
	andi	t0, a0, 0x1000
	bne	t0, zero, 10f
	lw	t2, OFFSET_PRGROM(WORK)
	and	t1, t1, a1
	addiu	t1, t1, -5   /* $B8e$N(B -0xa000 $B$KAjEv(B */
	mul	t1, t1, 0x2000
	addu	t1, t1, t2
	sw	t1, OFFSET_PAGE_TABLE + 0x14(WORK)
	jr	STORE_DONE
10:
/* bff0-bff7: chrbank @@ 0000-,0400-,...,1c00-
 */
	andi	t0, a0, 0x07
	sll	t0, t0, 1
	addu	t0, t0, WORK
	sh	a1, OFFSET_CHRBANK_REG0000(t0)
	sb	zero, OFFSET_BG_CHRBANK_TOUCH_FLAG(WORK)
	sb	zero, OFFSET_OBJ_CHRBANK_TOUCH_FLAG(WORK)
	jr	STORE_DONE
	
	
	GLOBAL(store21_8000)
store21_8000:
/* Taito TC0190
 * 8000: pbank @@ 8000-9fff
 * 8001: pbakk @@ a000-bfff
 * 8002: chrbank 0000-07ff
 * 8003: chrbank 0800-0fff
 */
	andi	t1, a0, 0x0002
	andi	t0, a0, 0x0001
	bne	t1, zero, 2f
/* pbank */
	lbu	t2, OFFSET_PBANK_MASK(WORK)
	lw	t3, OFFSET_PRGROM(WORK)
	sll	t1, t0, 2
	addu	t1, t1, WORK
	addiu	t0, t0, 4  /* $B8e$N(B -0x8000 $B$KAjEv(B */
	and	t2, t2, a1
	subu	t2, t2, t0
	mul	t2, t2, 0x2000
	addu	t2, t2, t3
	sw	t2, OFFSET_PAGE_TABLE + 0x10(t1)
	jr	STORE_DONE
2:
#if 0
/* debug */
	move	a2, a0
	PRINTF("21(%x->%x)\n");
#endif
	sll	t0, t0, 2
	addu	t0, t0, WORK
	sll	t1, a1, 1
	sh	t1, OFFSET_CHRBANK_REG0000(t0)
	addiu	t1, t1, 1
	sh	t1, OFFSET_CHRBANK_REG0400(t0)
	sb	zero, OFFSET_BG_CHRBANK_TOUCH_FLAG(WORK)
	sb	zero, OFFSET_OBJ_CHRBANK_TOUCH_FLAG(WORK)
	jr	STORE_DONE

	GLOBAL(store21_a000)
store21_a000:
/* a000-a003: chrbank @@ 1000-,1400-,1800-,1c00-
 */
#if 0
/* debug */
	move	a2, a0
	PRINTF("21(%x->%x)\n");
#endif
	andi	t0, a0, 0x0003
	sll	t0, t0, 1
	addu	t0, t0, WORK
	sh	a1, OFFSET_CHRBANK_REG1000(t0)
	sb	zero, OFFSET_BG_CHRBANK_TOUCH_FLAG(WORK)
	sb	zero, OFFSET_OBJ_CHRBANK_TOUCH_FLAG(WORK)
	jr	STORE_DONE

	GLOBAL(store21_c000)
store21_c000:
/* c000: irq counter - $B%+%&%s%H%"%C%W$7$F(B $B%*!<%P!<%U%m!<$G3d$j9~$_(B
 * c001,c002: enable/disable
 * $B$H$j$"$($:(B c000 $B$K(B 0 $B$G$J$$CM$J$i(B IRQ enable.
 */
#if 0
	move	a2, a0
	PRINTF("21_irq(%x->%x)\n");
#endif
	lh	t0, OFFSET_LINECNT(WORK)
	sb	a1, OFFSET_LINECNT_IRQ_ENABLED(WORK)
	li	t1, 0x100
	subu	t1, t1, a1
	addu	t0, t0, t1
	sh	t0, OFFSET_LINECNT_IRQ(WORK)
	
	jr	STORE_DONE
	
	GLOBAL(store42_8000)
store42_8000:
/* GNROM
 * xxPPCCCC
 * PP: pbank @@ 8000-ffff
 * CC: cbank @@ 0000-1fff
 */
#if 0
/* debug */
	move	a2, a0
	PRINTF("42(%x->%x)\n");
#endif
	lhu	t2, OFFSET_CHRBANK_REG0000(WORK)
	andi	t3, a1, 0x0f
	sll	t3, t3, 3    /* 0x400 bytes/bank -> 0x2000 bytes/bank */
	beq	t2, t3, 10f
	move	t0, WORK
	addiu	t1, t0, 0x10
1:
	sh	t3, OFFSET_CHRBANK_REG0000(t0)
	addiu	t3, t3, 1
	addiu	t0, t0, 2
	bne	t0, t1, 1b

	sb	zero, OFFSET_BG_CHRBANK_TOUCH_FLAG(WORK)
	sb	zero, OFFSET_OBJ_CHRBANK_TOUCH_FLAG(WORK)

10:	
	
	andi	t0, a1, 0x30
	lw	t1, OFFSET_PRGROM(WORK)
	sll	t0, t0, 15 - 4  /* 0x30 -> 0x18000 */
	addiu	t0, t0, -0x8000
	addu	t0, t0, t1
	sw	t0, OFFSET_PAGE_TABLE + 0x10(WORK)
	sw	t0, OFFSET_PAGE_TABLE + 0x14(WORK)
	sw	t0, OFFSET_PAGE_TABLE + 0x18(WORK)
	sw	t0, OFFSET_PAGE_TABLE + 0x1c(WORK)

	jr	STORE_DONE

	GLOBAL(store43_c000)
store43_c000:
/* Sunsoft 3
 * cfff: IRQ counter
 * dfff: d4=1 $B$G(B IRQ on
 */
#if 0
/* debug */
	move	a2, a0
	lhu	a3, OFFSET_LINECNT(WORK)
	PRINTF("43_irq(%x->%x)line=%x\n");
#endif

	andi	t0, a0, 0x1000
	bne	t0, zero, 10f
/* $B$J$s$+!"(Bcfff $B$K(B 16, a8 $B$H=q$-9~$s$G(B $B$+$i(B trigger $B$r$+$1$F$$$k!#(B
 * 0xdb - value $B$G!#(B
 * 0xa8 -> 0xdb - 0xa8 -> 0x33 $B$K$J$k$h$&$K!#(B
 */
	lh	t1, OFFSET_LINECNT(WORK)
	li	t2, 0xdb
	subu	t2, t2, a1
	addu	t1, t1, t2
	sh	t1, OFFSET_LINECNT_IRQ(WORK)
	jr	STORE_DONE

10:
	andi	t0, a1, 0x10
	sb	t0, OFFSET_LINECNT_IRQ_ENABLED(WORK)
	jr	STORE_DONE


	GLOBAL(store44_8000)
store44_8000:
/* Sunsoft 4
 * 8000-8fff: PPU 0000-07ff
 * 9000-9fff: PPU 0800-0fff
 * a000-afff: PPU 1000-17ff
 * b000-bfff: PPU 1800-1fff
 * address & 0x3000 -> 0,4,8,c $B$K$J$k$h$&$K!#(B
 * chrbank no $B$r(B << 1 $B$9$k!#(B
 */
	lw	t0, OFFSET_CHR_OFFSET_MASK(WORK)
	sb	zero, OFFSET_BG_CHRBANK_TOUCH_FLAG(WORK)
	sb	zero, OFFSET_OBJ_CHRBANK_TOUCH_FLAG(WORK)
	mul	t1, a1, 0x400 * 2
	and	t1, t1, t0
	srl	t1, t1, 10  /* / 0x400 */
	andi	t2, a0, 0x3000
	srl	t2, t2, 12 - 2  /* 0x3000 -> 0x0c */
	addu	t2, t2, WORK
	sh	t1, OFFSET_CHRBANK_REG0000(t2)
	addiu	t1, t1, 1
	sh	t1, OFFSET_CHRBANK_REG0400(t2)
	jr	STORE_DONE

	GLOBAL(store44_c000)
store44_c000:
/* Sunsoft 4
 * aftrbrn2.nes $B$,(B screen data $B$r(B chrrom $B$K;}$C$F(B bank $B@@Z$jBX$($7$F$$$k!#(B
 * C000: CHR page_number at NameTable(VRAM_A10=L) (page_size=index_size=1k)
 * D000: CHR page_number at NameTable(VRAM_A10=H) (page_size=index_size=1k)
 *
 */
#if 0
/* debug */
	move	a2, a0
	PRINTF("44_c000(%x->%x)\n");
#endif
	andi	t0, a0, 0x1000
	srl	t0, t0, 12     /* 0x1000 -> 0x01 */
	addu	t0, t0, WORK
	sb	a1, OFFSET_SUN4_VROM0(t0)
	jr	STORE_DONE
	
	GLOBAL(store44_e000)
store44_e000:
/* 
 * e000-efff: VRAM mirror d1,d0=00: $B2#;}$A(B 01: $B=D;}$A(B 10: 2000-, 11: 2400- 1 $B2hLL(B
 *            d4: 1=VRAM$B$NBe$o$j$K(B VROM $B$r;H$&(B
 * (store16_9000 $B$r;H$&(B)
 * f000-ffff: d3-d0?: prg rom @@ 8000-bfff
 * (nantbase.nes $B$O(B 0x10 $B$N(B bit $B$,(B SRAM enable)
 * prgbank << 1 $B$9$k!#(B
 */
#if 0
/* debug */
	andi	t0, a0, 0x1000
	bne	t0, zero, 1f
	move	a2, a0
	PRINTF("44_mirror(%x->%x)\n");
1:
#endif
	lbu	t1, OFFSET_PBANK_MASK(WORK)
	andi	t0, a0, 0x1000
	bne	t0, zero, 1f
	andi	t0, a1, 0x10
	sll	t0, t0, 2     /* 0x10 -> 0x40, VROM $B$r;H$&(B */
	sb	t0, OFFSET_SUN4_VROM_ENABLED(WORK)
	j	store16_9000
1:
	lw	t0, OFFSET_PRGROM(WORK)
	sll	t2, a1, 1
	and	t2, t2, t1
	mul	t2, t2, 0x2000
	addiu	t2, t2, -0x8000
	addu	t2, t2, t0
	sw	t2, OFFSET_PAGE_TABLE + 0x10(WORK)
	sw	t2, OFFSET_PAGE_TABLE + 0x14(WORK)
	jr	STORE_DONE
	
	GLOBAL(store45_8000)
store45_8000:
/* Sunsoft 5
 * 8000 = command #
 */
#if 0
/* debug */
	move	a2, PC
	PRINTF("SUN5 CMD=%x at PC=%x\n")
#endif
	sb	a1, OFFSET_SUN5_CMD(WORK)
	jr	STORE_DONE

	GLOBAL(store45_a000)
store45_a000:
#if 0
/* debug */
	move	a2, PC
	PRINTF("SUN5 ARG=%x at PC=%x\n")
#endif
/* Sunsoft 5
 * a000 = argument
 *  #0 : CHR page_number at $0000-$03FF
 *  #1 : CHR page_number at $0400-$07FF
 *  #2 : CHR page_number at $0800-$0bFF
 *  #3 : CHR page_number at $0c00-$0fFF
 *  #4 : CHR page_number at $1000-$13FF
 *  #5 : CHR page_number at $1400-$17FF
 *  #6 : CHR page_number at $1800-$1bFF
 *  #7 : CHR page_number at $1c00-$13FF
 *  #8 : PRG page_number at $6000-$7FFF
 *  #9 : PRG page_number at $8000-$9FFF
 *  #A : PRG page_number at $A000-$BFFF
 *  #B : PRG page_number at $C000-$DFFF
 *  #C : Mirror
 *     bit ------MM
 *     MM 0: VHVH
 *        1: VVHH
 *        2: VVVV
 *        3: HHHH
 *  #D : IRQ enable/disable
 *    #00: disable
 *    #81: enable
 *  #E : IRQ clock Lower 1 byte
 *  #F : IRQ clock Higher 1 byte
 *
 * $B9M;!(B IRQ$B$O(B1$B%o!<%I$NBT5!%/%m%C%/?t$rF~NO$9$k(B
 * 0$B$rF~NO$9$k$H!"<!$N%/%m%C%/$G(BIRQ$B$,H/@@8$9$k!#(B
 * i$B$rF~NO$9$k$H!"(Bi+1$B%/%m%C%/8e$K(BIRQ$B$,H/@@8$9$k!#(B
 */
	lbu	t0, OFFSET_SUN5_CMD(WORK)
	andi	t1, t0, 0x07
	addiu	t3, t0, -0x0c
	beq	t0, t1, 7f  /* chr bank */
	lw	t2, OFFSET_PRGROM(WORK)
	bgez	t3, 8f
/* pbank
 * t1 $B$,(B 0 $B$J$i(B 6000-7fff
 *       1      8000-9fff
 *       2      a000-bfff
 *       3      c000-dfff
 */
	mul	t3, t1, 0x2000
	addiu	t3, t3, 0x6000
	sll	t1, t1, 2
	addu	t1, t1, WORK
/* max check $B$O(B $BI,MW(B (hebereke.nes) */
	lbu	t0, OFFSET_PBANK_MASK(WORK)
	and	t0, t0, a1
	mul	t4, t0, 0x2000
	subu	t3, t4, t3
	addu	t3, t3, t2
#if 0
/* debug */
	move	a1, t3
	subu	a2, t1, WORK
	PRINTF("Sun5P=%x,%x\n");
#endif
	sw	t3, OFFSET_PAGE_TABLE + 0x0c(t1)
	jr	STORE_DONE
8:
	andi	t0, a1, 0x02
	bgtz	t3, 9f
/* cmd 0x0c=mirror
 */
#if 0
/* debug */
	PRINTF("Sun5M=%x\n");
#endif
	andi	t1, a1, 0x01
	beq	t0, zero, 1f
/* d1: 1=one screen mode
 *     d0=0 $B$J$i(B 2000-?
 */
	addiu	t1, t1, 1
	andi	t1, t1, 0x02
	sll	t1, t1, 3 + 4 + 2
	sh	t1, OFFSET_VRAM_MIRROR_MASK_OR(WORK)
	sh	zero, OFFSET_VRAM_MIRROR_MASK_AND(WORK)
	jr	STORE_DONE
1:
	li	t0, 0x400
	beq	t1, zero, 1f
	li	t0, 0x800
1:
	sh	t0, OFFSET_VRAM_MIRROR_MASK_AND(WORK)
	sh	zero, OFFSET_VRAM_MIRROR_MASK_OR(WORK)
	jr	STORE_DONE
7:
/* chr bank
 * t1 $B$,(B 0..7 $B$,(B 0x0000-,0x0400-,...,0x1c00- $B$KBP1~(B
 */
	sll	t1, t1, 1
#if 0
/* debug */
	move	a2, t1
	PRINTF("Sun5C=%x,%x\n");
#endif
	addu	t1, t1, WORK
	sh	a1, OFFSET_CHRBANK_REG0000(t1)
	sb	zero, OFFSET_BG_CHRBANK_TOUCH_FLAG(WORK)
	sb	zero, OFFSET_OBJ_CHRBANK_TOUCH_FLAG(WORK)
	jr	STORE_DONE

9:
/* t3 $B$,(B 1 $B$J$i(B IRA enable/disable
 *       2      IRQ counter low
 *       3      IRQ counter high
 */
	addiu	t0, t3, -2
	bltz	t0, 1f
/* IRQ counter low or high
 * $B%;%C%H8e(B linecnt_irq $B$K(B convert $B$9$k!#(B
 * $B%U%l!<%`$r$^$?$0$H!"(BIRQ $B$,$+$+$i$J$$(B ...
 */
	addu	t0, t0, WORK
	sb	a1, OFFSET_SUN5_IRQ_L(t0)
	lbu	t0, OFFSET_SUN5_IRQ_L(WORK)
	lbu	t1, OFFSET_SUN5_IRQ_H(WORK)
	lh	t3, OFFSET_LINECNT(WORK)
	sll	t1, t1, 8
	or	t0, t0, t1
	li	t2, (-(LINECYCLE_CONST0 + LINECYCLE_CONST1) / 0x100)
	divu	zero, t0, t2
	mflo	t0
	addu	t3, t3, t0
	sh	t3, OFFSET_LINECNT_IRQ(WORK)
	jr	STORE_DONE

1:
/* 0x81 $B$J$i(B IRQ enable */
	xori	t0, a1, 0x81
	sltiu	t0, t0, 1
	sb	t0, OFFSET_LINECNT_IRQ_ENABLED(WORK)
	jr	STORE_DONE

	GLOBAL(linecnt_over05)
linecnt_over05:
/* MMC5 $B%i%$%s%+%&%s%?%*!<%P!<(B
 * $B0lCW%U%i%0$r%;%C%H(B
 */
	lbu	t1, OFFSET_MMC5_EXRAM + 0x400 + 4(WORK)
	ori	t1, t1, 0x80
	sb	t1, OFFSET_MMC5_EXRAM + 0x400 + 4(WORK)
	
	li	t0, 0x8000
	sh	t0, OFFSET_LINECNT_IRQ(WORK)
	beq	t2, zero, mainloop_srlt0
	j	check_irq

	GLOBAL(linecnt_overqd)
linecnt_overqd:
/* disksys by myself
 * QD IRQ $B$+!"(Btimer IRQ $B$N!"$I$A$i$G$b$d$C$F$/$k!#(B
 * QD $BF0:nCf$J$i!"(BQD $B3d$j9~$_$K$7$F$7$^$&!*$($($d$m!#(B
 *
 * t4: new linecnt
 * t3: linecnt_irq preset $BCM(B
 * t2: linecnt_irq enabled
 *
 * QD
 * QD reset $B$5$l$F$J$/$F(B motor ON $B$G(B IRQ enable
 * $B$J$i(B QD $BFI$_=q$-(B IRQ
 */
	lbu	t0, OFFSET_QD4020H + 5(WORK)
	andi	t1, t0, 0x80
	andi	$1, t0, 0xe3
	xori	$1, $1, 0xe1
	beq	t1, zero, 9f  /* QD IRQ $B$G$O$J$$(B */
	bne	$1, zero, mainloop_srlt0  /* QD not active */
/* QD active !!
 * $B$3$N(B line $B$N=*N;;~!"$9$0$K(B linecnt over $B$9$k$h$&$K!#(B
 * $B$?$@@$7(B linecnt > 238 $B$J$i(B -20 $B$KLa$9!#(B
 */
	addiu	t3, t4, 1
	slti	t1, t3, 238
	bne	t1, zero, 1f
	li	t3, -20
1:
	lw	t1, OFFSET_QDIMAGE(WORK)
	lw	t2, OFFSET_QDOFFSET(WORK)
	addu	t1, t1, t2
	sh	t3, OFFSET_LINECNT_IRQ(WORK)

#if 0
/* debug */
	move a1,t3
PRINTF("OverQD=%x\n");
#endif
	
/* read? write? */
	andi	$1, t0, 0x04
	beq	$1, zero, check_irq  /* QD write - $B$3$3$G$O=q9~$;$:!"3d$j9~$_5/F0$N$_(B */
	lbu	t0, 0(t1)
	sb	t0, OFFSET_QD4030H + 1(WORK)
	j	check_irq

9:
/* check timer IRQ
 * $BO"B3(B ?
 */
	lbu	t0, OFFSET_QD4020H + 2(WORK)
	andi	t0, t0, 0x01
	li	t1, 0x8000
	beq	t0, zero, 1f  /* single */
	addu	t1, t3, t4
1:
	sh	t1, OFFSET_LINECNT_IRQ(WORK)
	sh	t1, OFFSET_VRC4_LINECNT_SAVE(WORK)
	li	t0, 0x01
	sb	t0, OFFSET_QD4030H(WORK)  /* timer overflow */
	beq	t2, zero, mainloop_srlt0
	j	check_irq

	GLOBAL(linecnt_over45)
linecnt_over45:
linecnt_over49:
linecnt_over12:
linecnt_over13:
linecnt_over5a:
linecnt_over21:
/* Sunsoft 5 $B%i%$%s%+%&%s%?%*!<%P!<(B
 * $B%j%T!<%H$J$7(B
 * t2: linecnt_irq enabled
 */
	li	t0, 0x8000
	sh	t0, OFFSET_LINECNT_IRQ(WORK)
	beq	t2, zero, mainloop_srlt0
	j	check_irq

	GLOBAL(linecnt_over19)
linecnt_over19:
/* VRC4 $B%i%$%s%+%&%s%?%*!<%P!<(B
 * $B%j%T!<%H$J$7(B
 * gradius2.nes $BBP:v(B
 */
	addiu	LINECYCLE, LINECYCLE, -(6 * 0x100)
	li	t0, 0x8000
	sh	t0, OFFSET_LINECNT_IRQ(WORK)
	beq	t2, zero, mainloop_srlt0
	j	check_irq

	GLOBAL(linecnt_over43)
linecnt_over43:
/* Sunsoft 3 $B%i%$%s%+%&%s%?%*!<%P!<(B
 * $B%9%/%m!<%k$:$l(B fantasz2.nes $BBP:v(B
 */
	addiu	LINECYCLE, LINECYCLE, 0x20 * 0x100
	li	t0, 0x8000
	sh	t0, OFFSET_LINECNT_IRQ(WORK)
	beq	t2, zero, mainloop_srlt0
	j	check_irq
		
	GLOBAL(linecnt_over18)
linecnt_over18:
/* VRC6
 * irq selector $B$N(B d0=1 $B$J$i(B repeat
 * $B%V%lBP:v(B
 */
	addiu	LINECYCLE, LINECYCLE, 6 * 0x100
	lbu	t0, OFFSET_VRC6_IRQ_SELECT(WORK)
	bne	t2, zero, 1f
	li	t0, 0x8000
	sh	t0, OFFSET_LINECNT_IRQ(WORK)
	j	mainloop_srlt0
1:
	andi	t0, t0, 0x01
	bne	t0, zero, 1f
	li	t0, 0x8000
	sh	t0, OFFSET_LINECNT_IRQ(WORK)
	j	check_irq
1:
	lbu	t1, OFFSET_VRC6_IRQ(WORK)
	li	t3, 0x100
	subu	t1, t3, t1
	addu	t1, t1, t4
	sh	t1, OFFSET_LINECNT_IRQ(WORK)
#if 0
/* debug */
	move	a1, t1
	PRINTF("overNext=%x\n");
	xori	t0, a1, 0x0d
	beq	t0, zero, 1f
	sw	PC, OFFSET_TRACE_FLAG(WORK)
1:
#endif
	j	check_irq

	GLOBAL(store46_8000)
store46_8000:
/* Kitarou2 mapper
 * taito/arkanoi2.nes $B$J$I!#(B
 * 8000-ffff: Mpppcccc
 * M: mirror 0=$B=D(B ?
 * ppp: chrbank @@ 8000-bfff, 0x4000 bytes/bank
 * cccc: chrbank @@ 0000-1fff, 0x2000 bytes/bank
 */
#if 0
/* debug */
	move	a2, a0
	lhu	a3, OFFSET_LINECNT(WORK)
	PRINTF("46(%x->%x)line=%x\n");
#endif
	lw	t1, OFFSET_PRGROM(WORK)
	lhu	t2, OFFSET_CHRBANK_REG0000(WORK)

/* d7=1 $B$N$H$-(B $B2#;}$A!"(Bd7=0 $B$N$H$-(B one screen @@ 2800- $B$G(B $B$$$$$N(B ?
 * taito/arkanoi2.nes $B$OF0$/!#(Bkitarou2.nes $B$b$$$1$F$=$&!#(B
 */
	li	t3, 0x400
	andi	t0, a1, 0x80
	xori	t0, t0, 0x80
	beq	t0, zero, 1f
	li	t3, 0
	li	t0, 0x800
1:
	sh	t3, OFFSET_VRAM_MIRROR_MASK_AND(WORK)
	sh	t0, OFFSET_VRAM_MIRROR_MASK_OR(WORK)

	andi	t0, a1, 0x70
	sll	t0, t0, 14 - 4
	addiu	t0, t0, -0x8000
	addu	t0, t0, t1
	sw	t0, OFFSET_PAGE_TABLE + 0x10(WORK)
	sw	t0, OFFSET_PAGE_TABLE + 0x14(WORK)

	andi	t3, a1, 0x0f
	sll	t3, t3, 3     /* 0x2000 bytes/bank */
	beq	t3, t2, store_done

	move	t0, WORK
	addiu	t1, t0, 0x10
1:
	sh	t3, OFFSET_CHRBANK_REG0000(t0)
	addiu	t0, t0, 2
	addiu	t3, t3, 1
	bne	t0, t1, 1b
	sb	zero, OFFSET_BG_CHRBANK_TOUCH_FLAG(WORK)
	sb	zero, OFFSET_OBJ_CHRBANK_TOUCH_FLAG(WORK)
	jr	STORE_DONE

	
	GLOBAL(store49_a000)
store49_a000:
/* a000-afff: VRC3 IRQ L ?
 * b000-bfff:          H ?
 */
#if 0
/* debug */
	move	a2, a0
	PRINTF("VRC3_irq(%x->%x)\n");
#endif
	andi	t1, a0, 0x1000
	andi	t0, a1, 0x0f
	beq	t1, zero, 1f
	sll	t0, t0, 4
	li	t1, 1
1:
	addu	t1, t1, WORK
	sb	t0, OFFSET_VRC4_IRQ_L(t1)
	jr	STORE_DONE

	GLOBAL(store49_c000)
store49_c000:
/* VRC3 IRQ trigger ?
 * d1 = start?
 */
#if 0
/* debug */
	move	a2, a0
	PRINTF("VRC3_irq_trig(%x->%x)\n");
#endif
	lbu	t1, OFFSET_VRC4_IRQ_L(WORK)
	lbu	t2, OFFSET_VRC4_IRQ_H(WORK)
	lh	t3, OFFSET_LINECNT(WORK)
	
	andi	t0, a1, 0x02
	sb	t0, OFFSET_LINECNT_IRQ_ENABLED(WORK)

	or	t1, t1, t2
	li	t2, 0x17a
	subu	t1, t2, t1
	addu	t1, t1, t3
	sh	t1, OFFSET_LINECNT_IRQ(WORK)
	jr	STORE_DONE

	GLOBAL(store56_6000)
store56_6000:
/* Jaleco Moepro
 * debug
 * 6000-6fff: d5-d4: 0x8000 bytes $BC10L$N(B pbank
 *            d7,d1,d0: 0x2000 bytes $BC10L$N(B cbank
 * 7000-7fff: voice
 */
#if 0
/* debug */
	move	a3, PC
	move	a2, a0
	PRINTF("56(%x->%x),PC=%x\n");
#endif
	andi	t0, a0, 0x1000
	bne	t0, zero, 70f
/* $B$^$:(B pbank */
	lw	t2, OFFSET_PRGROM(WORK)
	lbu	t3, OFFSET_PBANK_MASK(WORK)

	sll	t3, t3, 2  /* 0x8000 bytes $BC10L(B */
	and	t3, t3, a1
	andi	t3, t3, 0xf0
	addiu	t3, t3, -0x10  /* $B8e$N(B -0x8000 $B$KAjEv(B */
	mul	t3, t3, 0x8000 / 0x10

	addu	t3, t3, t2

#if 0
/* debug */
/* debug */
	move	a2, t3
	PRINTF("%x,%x\n");
#endif
	sw	t3, OFFSET_PAGE_TABLE + 0x10(WORK)
	sw	t3, OFFSET_PAGE_TABLE + 0x14(WORK)
	sw	t3, OFFSET_PAGE_TABLE + 0x18(WORK)
	sw	t3, OFFSET_PAGE_TABLE + 0x1c(WORK)

/* chr bank - max check $B$OL5;k(B */
	lhu	t0, OFFSET_CHRBANK_REG0000(WORK)

	andi	t2, a1, 0x40
	srl	t2, t2, 4
	andi	t1, a1, 0x03
	or	t1, t1, t2
	
	sll	t1, t1, 3
	beq	t0, t1, store_done

#if 0
/* debug */
	lhu	a2, OFFSET_LINECNT(WORK)
	PRINTF("56_cbank=%x at line=%x\n");
#endif

/* $BFI$_=P$7BP:v$G(B $BA4(B bank $B@@_Dj(B */
	move	t0, WORK
	addiu	t2, t0, 2 * 8
1:
	sh	t1, OFFSET_CHRBANK_REG0000(t0)
	addiu	t1, t1, 1
	addiu	t0, t0, 2
	bne	t0, t2, 1b
	sb	zero, OFFSET_BG_CHRBANK_TOUCH_FLAG(WORK)
	sb	zero, OFFSET_OBJ_CHRBANK_TOUCH_FLAG(WORK)
	
	jr	STORE_DONE

70:
/* voice $B$@@(B ...
 * moepro.nes $B$N>l9g(B (Sound_PlayMENUPCM $B$N0z?t(B)
 * 10,30 - $B=i4|2=(B ? $B:G=i$@@$1(B
 * (1)20,30 - $B%9%H%i%$%/(B
 * (2)21,31 - $B%\!<%k(B
 * (3)22,32 - $B%?!<%$%`(B
 * (4)23,33 - $B%"%&%H(B
 * (5)24,34 - $B%;!<%U(B
 * (6)25,35 - $B%U%!!<%k(B
 * (7)26,36 - $B%U%'%"(B
 * (8)27,37 - $B%P%C%?!<%"%&%H(B(0x37 $B$rO"BG$7$F$$$k(B)
 * (9)28,38 - $B%W%l%$%\!<%k(B
 * (a)29,39 - $B%U%)%"%\!<%k(B
 * (b)2a,3a - $B%[!<%`%i%s(B
 * (c)2b,3b - $B%T%C%A%c!<8rBe(B
 * (d)2c,3c - $B%$%F(B ($B%G%C%I%\!<%k(B)
 * (e)2d,3d - $B%"!<%[!<(B
 * (f)2e,3e - $BBG$C$?$H$-(B $B%+!<%s(B
 * (0x10)2f,3f - $B4?@@<(B on/off
 * 2x $B$r=q$-9~$s$@@$H$-$K(B Sound_PlayMENUPCM $B$r8F$V!#(B
 */
	andi	t0, a1, 0x10
	bne	t0, zero, store_done
#if 0
/* debug */
	move	a3, PC
	move	a2, a0
	PRINTF("56_voice(%x->%x),PC=%x\n");
#endif
	
	andi	a0, a1, 0x0f
	addiu	a0, a0, 1

	sw	LINECYCLE, OFFSET_THREAD_LINECYCLE(WORK)
	sw	STORE_DONE, OFFSET_THREAD_STORE_DONE(WORK)
	sw	gp, OFFSET_THREAD_GP(WORK)
#if 0
/* 0 $B$b$"$k!#(B*/
	beq	a0, zero, store_done  /* $BL$BP1~(B */
#endif
	jal	Sound_PlayMENUPCM
	
	lw	LINECYCLE, OFFSET_THREAD_LINECYCLE(WORK)
	lw	STORE_DONE, OFFSET_THREAD_STORE_DONE(WORK)
	lw	gp, OFFSET_THREAD_GP(WORK)
	
	jr	STORE_DONE

	GLOBAL(store58_8000)
store58_8000:
/* Namcot 118
 * MMC3 $B$H$[$H$s$IF1$8$@@$,(B R0 $B$N(B 0x20 $B$N0L$G(B mirror $B$7$F$$$k!#(B
 * (dbuster.nes)
 * map mode $B$H$+$O(B $B$J$5$=$&(B $B$@@$1$I(B $B$H$j$"$($:(B MMC3 $B$N%3%T!<!#(B
 */
#if 0
/* debug */
	move	a2, a0
	lhu	a3, OFFSET_LINECNT(WORK)
	PRINTF("58(%x->%x,%x)\n");
#endif
	lbu	$1, OFFSET_MMC3_POINTER(WORK)
	andi	t1, a0, 0x0001
	bne	t1, zero, 10f
/* MMC3 pointer - chr seg, map mode, chr bank reg $B@@_Dj(B
 */
	sb	a1, OFFSET_MMC3_POINTER(WORK)
/* chrrom $BFI$_=P$7MQ(B chr seg $B@@_Dj(B */
	andi	t2, a1, 0x80
	sll	t2, t2, 5  /* 0x80 -> 0x1000 */
	sh	t2, OFFSET_CHRSEG_FOR_READ(WORK)
	xor	t0, $1, a1

	andi	t1, t0, 0x80
	beq	t1, zero, 1f
/* chr seg $B$,JQ$o$C$?$N$G(B BG, OBJ bank $B$,JQ$o$C$?$H9M$($k!#(B*/
	sb	zero, OFFSET_BG_CHRBANK_TOUCH_FLAG(WORK)
	sb	zero, OFFSET_OBJ_CHRBANK_TOUCH_FLAG(WORK)
1:
	andi	t1, t0, 0x40
	beq	t1, zero, store_done
/* map mode $B$,JQ$o$C$?!#(B
 */
	lbu	t1, OFFSET_MMC3_R6(WORK)
	lw	t3, OFFSET_PRGROM(WORK)
	lw	t4, OFFSET_PRGSIZE(WORK)
	andi	t2, a1, 0x40
	bne	t2, zero, 41f
/* map mode 0 $B$O(B window 0 (R6) $B$,(B 8000-9fff. c000-dfff $B$O(B prgrom + prgsize - 0x4000 $B8GDj!#(B*/
	addiu	t1, t1, -4  /* $B8e$G(B -0x8000 $BAjEv$K$J$k(B */
	mul	t1, t1, 0x2000
	addu	t1, t1, t3
	sw	t1, OFFSET_PAGE_TABLE + 0x10(WORK)
	addu	t3, t3, t4
	li	t4, -0x4000 - 0xc000
	addu	t3, t3, t4
	sw	t3, OFFSET_PAGE_TABLE + 0x18(WORK)
	jr	STORE_DONE
41:
/* map mode 1 $B$O(B window 0 (R6) $B$,(B c000-dfff. 8000-9fff $B$O(B prgrom + prgsize - 0x4000 $B8GDj!#(B*/
	addiu	t1, t1, -6  /* $B8e$G(B -0xc000 $BAjEv$K$J$k(B */
	mul	t1, t1, 0x2000
	addu	t1, t1, t3
	sw	t1, OFFSET_PAGE_TABLE + 0x18(WORK)
	addu	t3, t3, t4
	li	t4, -0x4000 - 0x8000
	addu	t3, t3, t4
	sw	t3, OFFSET_PAGE_TABLE + 0x10(WORK)
	jr	STORE_DONE
	
10:
	
/* $B%l%8%9%?@@_Dj(B Namcot 118 $B$G$9$h!#(B
 * $1: pointer
 * t0: pointer & 7
 * t1: t0 + WORK
 * t2: $BA02s=q$$$?CM(B
 */
	andi	t0, $1, 0x07
	
	addu	t1, t0, WORK
	lbu	t2, OFFSET_MMC3_R0(t1)
	beq	t2, a1, store_done     /* $BA02s$HF1$8CM(B */
/* R0,R1 $B$J$i(B d0 $B$rL5;k$7$F(B chr bank for 0000-, 0800- $B$r!#(B
 * R2-R5 $B$J$i(B chr bank for 1000-,1400-,1800-,1c00- $B$r!#(B
 * R6,R7 $B$J$i(B prg bank.
 */
	lbu	t2, OFFSET_PBANK_MASK(WORK)
	addiu	t3, t0, -6
	bgez	t3, 6f
	lw	t2, OFFSET_CHR_OFFSET_MASK(WORK)
	sb	zero, OFFSET_BG_CHRBANK_TOUCH_FLAG(WORK)
	sb	zero, OFFSET_OBJ_CHRBANK_TOUCH_FLAG(WORK)
	mul	t4, a1, 0x400
#if 0
/* debug */
	ori	a2, t4, 0x3ff
	and	a3, a2, t2
	tne	a2, a3
#endif
	and	t4, t4, t2
	srl	t4, t4, 10  /* / 0x400 */
/* d5 $B$G(B mirror
 */
	andi	t3, a1, 0x20
	sll	t3, t3, 1 + 4  /* 0x20 -> 0x400 */
	sh	t3, OFFSET_VRAM_MIRROR_MASK_AND(WORK)
	
	addiu	t3, t0, -2
	bgez	t3, 2f
/* R0,R1 - d0 $B$OL58z(B */
	andi	t4, t4, 0xfffe
	sb	t4, OFFSET_MMC3_R0(t1)
	sll	t0, t0, 2
	addu	t0, t0, WORK
	sh	t4, OFFSET_CHRBANK_REG0000(t0) /* 0000 or 0800 */
	addiu	t4, t4, 1
	sh	t4, OFFSET_CHRBANK_REG0400(t0) /* 0400 or 0c00 */
	jr	STORE_DONE
2:
/* R2-R5
 * chr bank for 1000-, 1400-, 1800-, 1c00- $B$r!#(B
 * t3: t0 - 2
 */
	sb	t4, OFFSET_MMC3_R0(t1)
	sll	t3, t3, 1
	addu	t3, t3, WORK
	sh	t4, OFFSET_CHRBANK_REG1000(t3)
	jr	STORE_DONE
6:
/* R6-R7 pbank.
 * R6 $B$J$i(B mapmode $B$K$h$C$F(B window $B$,0c$&!#(B
 * $1: pointer
 * t0: pointer & 7
 * t1: t0 + WORK
 * t2: pbank mask
 * t3: t0 - 6
 */
	lw	t0, OFFSET_PRGROM(WORK)
	and	t2, t2, a1
	sb	t2, OFFSET_MMC3_R0(t1)
	bne	t3, zero, 7f
/* R6 */
	andi	$1, $1, 0x40
	beq	$1, zero, 40f
/* map mode 1 - R6 $B$O(B c000-dfff */
	addiu	t2, t2, -6  /* $B8e$G(B -0xc000 $BAjEv$K$J$k(B */
	mul	t2, t2, 0x2000
	addu	t2, t2, t0
	sw	t2, OFFSET_PAGE_TABLE + 0x18(WORK)
	jr	STORE_DONE
40:
/* map mode 0 - R6 $B$O(B 8000-9fff */
	addiu	t2, t2, -4  /* $B8e$G(B -0x8000 $BAjEv$K$J$k(B */
	mul	t2, t2, 0x2000
	addu	t2, t2, t0
	sw	t2, OFFSET_PAGE_TABLE + 0x10(WORK)
	jr	STORE_DONE
7:
/* R7 - mapmode $B$K$+$+$o$i$:(B a000-bfff */
	addiu	t2, t2, -5  /* $B8e$G(B -0xa000 $BAjEv$K$J$k(B */
	mul	t2, t2, 0x2000
	addu	t2, t2, t0
	sw	t2, OFFSET_PAGE_TABLE + 0x14(WORK)
	jr	STORE_DONE
	
	GLOBAL(store5a_8000)
store5a_8000:
/* PC-JY-? mapper for o/cracked/tekken2.nes, o/cracked/samuspi2.nes
 * 8000: pbank for 8000-9fff ?
 * 8001: pbank for a000-bfff ?
 * 8002: pbank for c000-dfff ?
 * 8003: pbank for e000-ffff ?
 * 0x2000 bytes/bank $B$G$7$g$&!#(B
 * 9000-9007: chrbank low for 0000-,0400-,...,1c00- ?
 */
	andi	t0, a0, 0x0003
	andi	t3, a0, 0x1000
	bne	t3, zero, 10f
	sll	t1, t0, 2
	addu	t1, t1, WORK
	lw	t2, OFFSET_PRGROM(WORK)
	lbu	t3, OFFSET_PBANK_MASK(WORK)
	and	t3, t3, a1
	addiu	t0, t0, 4  /* $B8e$N(B -0x8000 $B$KAjEv(B */
	subu	t3, t3, t0
	mul	t3, t3, 0x2000
	addu	t3, t3, t2
	sw	t3, OFFSET_PAGE_TABLE + 0x10(t1)
	jr	STORE_DONE
10:
#if 0
/* debug */
	move	a2, a0
	PRINTF("5a(%x->%x)\n");
#endif
	andi	t0, a0, 0x0007
	sll	t0, t0, 1
	addu	t0, t0, WORK
	sb	a1, OFFSET_CHRBANK_REG0000 + 1(t0)
	sb	zero, OFFSET_BG_CHRBANK_TOUCH_FLAG(WORK)
	sb	zero, OFFSET_OBJ_CHRBANK_TOUCH_FLAG(WORK)
	jr	STORE_DONE

	GLOBAL(store5a_a000)
store5a_a000:
/* 
 * a000-a007: chrbank high ?
 */
	andi	t0, a0, 0x0007
	andi	t3, a0, 0x1000
	bne	t3, zero, 10f
	sll	t0, t0, 1
	addu	t0, t0, WORK
	sb	a1, OFFSET_CHRBANK_REG0000 + 0(t0)
	sb	zero, OFFSET_BG_CHRBANK_TOUCH_FLAG(WORK)
	sb	zero, OFFSET_OBJ_CHRBANK_TOUCH_FLAG(WORK)
	jr	STORE_DONE
10:
#if 0
/* debug */
	move	a2, a0
	PRINTF("5a(%x->%x)\n");
#endif
	jr	STORE_DONE

	GLOBAL(store5a_c000)
store5a_c000:
/* c002/c005, c004/c003 $B$KF1$8CM(B ?
 * c005: irq lines, c003: enable $B$K$7$F$_$h$&!#(B
 */
#if 0
/* debug */
	move	a2, a0
	lhu	a3, OFFSET_LINECNT(WORK)
	PRINTF("5a_irq(%x->%x)line=%x\n");
#endif
	xori	t0, a0, 0xc005
	xori	t1, a0, 0xc003
	beq	t0, zero, 5f
	xori	t0, a0, 0xc002
	beq	t1, zero, 3f
	beq	t0, zero, 5f

	jr	STORE_DONE
5:
	lh	t2, OFFSET_LINECNT(WORK)
	move	t3, a1
	bltz	t2, 1f
	addu	t3, t2, a1
1:
	sh	t3, OFFSET_LINECNT_IRQ(WORK)
	sb	a1, OFFSET_LINECNT_IRQ_ENABLED(WORK)
	jr	STORE_DONE

3:
	sb	a1, OFFSET_LINECNT_IRQ_ENABLED(WORK)
	jr	STORE_DONE
	
	GLOBAL(store5c_8000)
store5c_8000:
/* Jaleco Moepro88
 *
 * $B=q$-9~$`(B rom address $B$K$O!"=q$-9~$`CM$HF1$8$b$N$,3JG<$5$l$F$$$k(B
 * $B>l9g$,$[$H$s$I!#(B
 * $B%W%m%F%/%H$+$b!#(B
 * 80b0-80bf: pbank @@ c000-ffff, 0x4000 bytes/bank
 */
#if 0
/* debug */
	move	a2, a0
	PRINTF("5c(%x->%x)\n");
#endif

	.set	noreorder
	andi	t0, a0, 0x00f0
	xori	t1, t0, 0xb0
	beq	t1, zero, 11f
	nop
	.set	reorder

	
11:
/* pbank @@ c000-ffff */
	
		
	jr	STORE_DONE

		
	
		
	GLOBAL(store63_4020)
store63_4020:
#if 0
/* debug */
	PRINTF("63_4020=%x\n");
#endif
	jr	STORE_DONE

	GLOBAL(storee6_8000)
storee6_8000:
/* 22 in 1
 * $B<jH4$-$@@$1$I!"$3$l$G(B $B$I$&(B ?
 */
	andi	a0, a0, 0xfffe
	andi	a1, a1, 0x7f
/* thru */

	GLOBAL(storee2_8000)
storee2_8000:
/* 76 in 1
 * 8000,8002,..., fffe: | p4 | M | Z | p3-p0 | q |
 * 8001,8003,..., ffff:     - - - - - - | w | p5 |
 * M: mirror 0 $B$G=D;}$A(B ?
 */
#if 0
/* debug */
	move	a2, a0
	PRINTF("e2(%x->%x)\n");
#endif
	andi	t0, a0, 0x0001
	addu	t1, t0, WORK
	sb	a1, OFFSET_SS_PBANK0(t1)
	bne	t0, zero, 10f
/* 8000,8002,...
 * M $B$N$_=hM}(B
 */
	andi	t0, a1, 0x40
	sll	t0, t0, 4     /* 0x40 -> 0x400 */
	li	t1, 0x800
	subu	t0, t1, t0
	sh	t0, OFFSET_VRAM_MIRROR_MASK_AND(WORK)
10:
	lhu	t0, OFFSET_SS_PBANK0(WORK)
/* chrram protect ? */
	la	t2, store_2007_chrram
	andi	t1, t0, 0x0002
	beq	t1, zero, 2f
	la	t2, store_2007_chrrom
2:
	sw	t2, OFFSET_STORE_PPU_FUNCTBL + 7 * 4(WORK)

	andi	t1, t0, 0x8000
	andi	t2, t0, 0x1e00
	andi	t3, t0, 0x0001
	sll	t3, t3, 5        /* p5 */
	srl	t2, t2, 1 + 8    /* p3-p0 */
	srl	t1, t1, 3 + 8    /* p4 */
	or	t1, t1, t2
	or	t1, t1, t3
	sll	t1, t1, 15  /* * 0x8000 */
	addiu	t1, t1, -0x8000
	lw	t2, OFFSET_PRGROM(WORK)
	addu	t3, t2, t1
	move	t4, t3
/* t0: register data
 * t1: bank no
 * t2: prgrom
 * t3: page table 8000-,a000-
 * t4:            c000-,e000-
 */
/* 0x8000 bytes/bank? 0x4000 bytes/bank ? */
	andi	$1, t0, 0x2000
	beq	$1, zero, 1f
/* 0x4000 bytes/bank
 * 8000-bfff, c000-ffff $B$N$I$C$A$,M-8z(B ?
 */
	andi	$1, t0, 0x0100
	addiu	t3, t3, 0x4000
	bne	$1, zero, 1f
/* 8000-bfff $B$,M-8z(B */
	addiu	t3, t3, -0x4000
	addiu	t4, t4, -0x4000
1:
	sw	t3, OFFSET_PAGE_TABLE + 0x10(WORK)
	sw	t3, OFFSET_PAGE_TABLE + 0x14(WORK)
	sw	t4, OFFSET_PAGE_TABLE + 0x18(WORK)
	sw	t4, OFFSET_PAGE_TABLE + 0x1c(WORK)
	jr	STORE_DONE
	
	GLOBAL(storee3_8000)
storee3_8000:
/* 1200in1
 * a9|            |a0
 * HL|p|f|pppp|h|m|s
 * $B=q$-9~$`CM$G$O$J$/!"$=$N%"%I%l%9$K0UL#$,$"$k!#(B
 *
 */
#if 0
/* debug */
	move	a2, a0
	PRINTF("e3(%x->%x)\n");
#endif

/* a1: mirror 0=$B2#;}$A(B */
	li	t0, 0x400
	andi	t2, a0, 0x0002
	beq	t2, zero, 1f
	li	t0, 0x800
1:
	sh	t0, OFFSET_VRAM_MIRROR_MASK_AND(WORK)

/* a8,a6-a3: 0x8000 bytes $BC10L$N(B select
 * $B$3$N(B top $B$r(B t4 $B$K!#(Boffset $B$r(B t3 $B$K!#(B
 */
	lw	t4, OFFSET_PRGROM(WORK)
	andi	t0, a0, 0x0100
	andi	t1, a0, 0x0078
	srl	t0, t0, 1
	or	t0, t0, t1
	sll	t3, t0, 12  /* 0x08 -> 0x8000 */
	addu	t1, t4, t3

/* a0: page size
 * 1 $B$J$i(B 32KB prg rom
 * 0 $B$J$i(B 16KB prg rom. a2 $B$,(B 1 $B$J$i(B top += 0x4000
 */
	li	t0, -0x8000
	addu	t2, t0, t1
	sw	t2, OFFSET_PAGE_TABLE + 0x10(WORK)
	sw	t2, OFFSET_PAGE_TABLE + 0x14(WORK)
	sw	t2, OFFSET_PAGE_TABLE + 0x18(WORK)
	sw	t2, OFFSET_PAGE_TABLE + 0x1c(WORK)

	andi	t0, a0, 0x01
	andi	t1, a0, 0x04
	bne	t0, zero, 4f
	bne	t1, zero, 1f
/* 8000-bfff $B$r(B c000-ffff $B$K$b!#(B*/
	addiu	t2, t2, -0x4000
	sw	t2, OFFSET_PAGE_TABLE + 0x18(WORK)
	sw	t2, OFFSET_PAGE_TABLE + 0x1c(WORK)
	j	4f
1:
/* c000-ffff $B$r(B 8000-bfff $B$K$b!#(B*/
	addiu	t2, t2, 0x4000
	sw	t2, OFFSET_PAGE_TABLE + 0x10(WORK)
	sw	t2, OFFSET_PAGE_TABLE + 0x14(WORK)
4:
/* page fixing ?
 */
	la	t0, store_2007_chrrom
	sw	t0, OFFSET_STORE_PPU_FUNCTBL + 7 * 4(WORK)
	
	andi	t0, a0, 0x0080
	andi	t1, a0, 0x0200
	bne	t0, zero, 8f
/* page fix $B$N$H$-$O(B chrram write enable */
	la	t0, store_2007_chrram
	sw	t0, OFFSET_STORE_PPU_FUNCTBL + 7 * 4(WORK)
	
	li	t2, 0x1c000
	or	t3, t3, t2
	bne	t1, zero, 2f
	xor	t3, t3, t2
2:
	addu	t3, t3, t4
	li	t2, -0xc000
	addu	t2, t2, t3
	sw	t2, OFFSET_PAGE_TABLE + 0x18(WORK)
	sw	t2, OFFSET_PAGE_TABLE + 0x1c(WORK)

8:
	jr	STORE_DONE

	GLOBAL(storee0_8000)
storee0_8000:
/* 72 in 1
 * A14 $B$r(B 0 $B$K$7$F(B 110 in 1 $B$HF1MM$K!#(B
 */
	andi	a0, a0, 0xbfff
/* thru */
	GLOBAL(storee1_8000)
storee1_8000:
/* 110 in 1
 * $B=q$-9~$`(B address $B$K0UL#$,$"$k!#(B
 * a14: prg rom, chr rom $B$N(B lower half, upper half $B$N(B selector.
 *      $B$&!<$s!"$H$j$"$($:(B 110 in 1 only $B$H$7$F(B
 *      1 $B$J$i(B prgrom offset + 0x100000, chrrom offset +0x80000 $B$K!#(B
 * a13: $B2#;}$A(B or $B=D;}$A(B
 * a12: 0=0x8000 bytes/bank, 1=0x4000 bytes/bank
 *  -> 0x4000 bytes/bank $B$N$H$-(B a6 $B$K$h$C$F(B $BA0H>(B, $B8eH>(B $B$I$C$A$r(B mirror $B$9$k$+!#(B
 * a11-a7: pbank 0x8000 bytes $BC10L(B
 * a5-a0: chrbank 0x2000 bytes $BC10L(B
 */
#if 0
/* debug */
	move	a1, a0
	move	a2, PC
	PRINTF("e1(%x)PC=%x\n");
#endif

	andi	t0, a0, 0x2000
	srl	t0, t0, 4 - 1   /* 0x2000 -> 0x400 */
	addiu	t0, t0, 0x400
	sh	t0, OFFSET_VRAM_MIRROR_MASK_AND(WORK)

/* t0: temp
 * t1: prgrom -> temp
 * t2: 0 or 0x100000, select lower/upper rom
 * t3: page table 8000-,a000-
 * t4:            c000-,e000-
 */
	andi	t2, a0, 0x4000
	sll	t2, t2, 2 + 4   /* 0 or 0x100000 */
	lw	t1, OFFSET_PRGROM(WORK)
	andi	t0, a0, 0x0f80
	sll	t0, t0, 15 - 7  /* 0x80 -> 0x8000 */
	addu	t0, t0, t2
#if 0
/* debug */
	move	a1, t0
	PRINTF("e1_prg_offset=%x\n");
#endif
	
	addiu	t0, t0, -0x8000
	addu	t3, t0, t1
	move	t4, t3
	
/* 0x8000 bytes/bank? 0x4000 bytes/bank ? */
	andi	t1, a0, 0x1000
	beq	t1, zero, 1f
/* 0x4000 bytes/bank
 * 8000-bfff, c000-ffff $B$N$I$C$A$,M-8z(B ?
 */
	andi	t0, a0, 0x0040
	addiu	t3, t3, 0x4000
	bne	t0, zero, 1f
/* 8000-bfff $B$,M-8z(B */
	addiu	t3, t3, -0x4000
	addiu	t4, t4, -0x4000
1:
	sw	t3, OFFSET_PAGE_TABLE + 0x10(WORK)
	sw	t3, OFFSET_PAGE_TABLE + 0x14(WORK)
	sw	t4, OFFSET_PAGE_TABLE + 0x18(WORK)
	sw	t4, OFFSET_PAGE_TABLE + 0x1c(WORK)

/* chrbank
 * t2: 0 or 0x100000, lower/upper -> 0 or 0x200 $B$K!#(B
 */
	srl	t2, t2, 8 + 3
	andi	t0, a0, 0x3f
	sll	t0, t0, 3    /* 0x400 bytes/bank -> 0x2000 bytes/bank */
	or	t0, t0, t2

	move	t1, WORK
	addiu	t2, t1, 0x10
1:
	sh	t0, OFFSET_CHRBANK_REG0000(t1)
	addiu	t0, t0, 1
	addiu	t1, t1, 2
	bne	t1, t2, 1b
	
	sb	zero, OFFSET_BG_CHRBANK_TOUCH_FLAG(WORK)
	sb	zero, OFFSET_OBJ_CHRBANK_TOUCH_FLAG(WORK)
	jr	STORE_DONE

	GLOBAL(storee5_8000)
storee5_8000:
/* 31 in 1
 * $B=q$-9~$`%"%I%l%9$K0UL#$,$"$k!#(B
 * 8000-ffff $B$N!"(BA5: mirror
 * A4-A0: chrbank/pbank
 * $B$?$@@$7!"(Bpbank entry #0 $B$O(B smario.nes $B$G!"(B#0,#1 $B$O(B #0 $B$HF1$807$$!#(B
 */
#if 0
/* debug */
	move	a2, a0
	PRINTF("e5(%x->%x)\n");
#endif

/* mirror */
	andi	t0, a0, 0x20
	sll	t0, t0, 1 + 4  /* 0x20 -> 0x400 */
	addiu	t0, t0, 0x400
	sh	t0, OFFSET_VRAM_MIRROR_MASK_AND(WORK)

/* chrbank */
	andi	t0, a0, 0x1f
	sll	t0, t0, 3
	move	t1, WORK
	addiu	t2, t1, 0x10
1:
	sh	t0, OFFSET_CHRBANK_REG0000(t1)
	addiu	t0, t0, 1
	addiu	t1, t1, 2
	bne	t1, t2, 1b

	sb	zero, OFFSET_BG_CHRBANK_TOUCH_FLAG(WORK)
	sb	zero, OFFSET_OBJ_CHRBANK_TOUCH_FLAG(WORK)

/* pbank */
	andi	t0, a0, 0x1e
	li	t2, 0x4000
	bne	t0, zero, 1f  /* 16KB mode */
	li	t2, 0
	andi	a0, a0, 0xfffe
1:
	lw	t1, OFFSET_PRGROM(WORK)
	andi	t0, a0, 0x1f
	mul	t0, t0, 0x4000
	addiu	t0, t0, -0x8000
	addu	t0, t0, t1
	sw	t0, OFFSET_PAGE_TABLE + 0x10(WORK)
	sw	t0, OFFSET_PAGE_TABLE + 0x14(WORK)
	subu	t0, t0, t2
	sw	t0, OFFSET_PAGE_TABLE + 0x18(WORK)
	sw	t0, OFFSET_PAGE_TABLE + 0x1c(WORK)
#if 0
/* debug */
	lw	a1, OFFSET_CHRBANK_REG0000(WORK)
	lw	a2, OFFSET_CHRBANK_REG1000(WORK)
	PRINTF("%08x %08x\n");
#endif
	jr	STORE_DONE

	GLOBAL(storeqd_4020)
storeqd_4020:
	GLOBAL(storeqd_4021)
storeqd_4021:
/* timer l,h -> $B5U$K!#(B
 * endianness $B0MB8(B !!
 */
	xori	t0, a0, 0x01
	addu	t0, t0, WORK
	sb	a1, OFFSET_QD4020H - 0x4020(t0)
	jr	STORE_DONE
	
	GLOBAL(storeqd_4022)
storeqd_4022:
/* timer IRQ -> line $BC10L$G07$&!#(B
 * d1: IRQ enable
 * d0: 0 = 1 $B2s!"(B1 = $BO"B3(B ($B$G$b!"%U%l!<%`$r$^$?$0$H!"$&$^$/$+$+$i$J$$(B)
 * see also: store45_a000
 */
	lhu	t0, OFFSET_QD4020H(WORK)
	sb	a1, OFFSET_QD4020H + 2(WORK)
	andi	t1, a1, 0x02
	sb	t1, OFFSET_LINECNT_IRQ_ENABLED(WORK)
	lh	t3, OFFSET_LINECNT(WORK)

	li	t2, (-(LINECYCLE_CONST0 + LINECYCLE_CONST1) / 0x100)
	divu	zero, t0, t2
	mflo	t0

	addu	t3, t3, t0
	sh	t3, OFFSET_LINECNT_IRQ(WORK)
/* linecnt_irq $B$O(B QD IRQ $B$r;H$&$HGK2u$5$l$k(B */
	sh	t3, OFFSET_VRC4_LINECNT_SAVE(WORK)
/* $B0l1~(B $BO"B3(B $BBP:v(B */
	sh	t0, OFFSET_LINECNT_IRQ_PRESET(WORK)
	jr	STORE_DONE

	GLOBAL(storeqd_4023)
storeqd_4023:
/* 4023H $B$O(B Sound_Write $B$b9T$&(B */
	sb	a1, OFFSET_QD4020H + 3(WORK)
	j	store_sound_4023

	GLOBAL(storeqd_4025)
storeqd_4025:
/* 4025: d7=1: IRQ enable
 *       d6: 0= header 1=data
 *       d5: 1
 *       d4: 1=check CRC --> 2 bytes skip
 *       d3: 0 = $B2#;}$A(B 1 = $B=D;}$A(B
 *       d2: /WRGATE 0 $B$G(B WR
 *       d1: /MOTORON
 *       d0: /QDRES
 */
	sb	a1, OFFSET_QD4020H + 5(WORK)
/* VRAM mirror */
	andi	$1, a1, 0x08
	sll	$1, $1, 7    /* 0x08 -> 0x400 */
	addiu	$1, $1, 0x400
	sh	$1, OFFSET_VRAM_MIRROR_MASK_AND(WORK)

/* IRQ on ?
 *
 * on $B$J$i(B line $B=*N;;~(B $B$9$0$K(B IRQ $B$,$+$+$k$h$&$K!#(B
 * ($B$?$@@$7(B linecnt > 238 $B$J$i(B -20 $B$K$9$k(B)
 * off $B$J$i(B linecnt_save $B$+$iLa$7$F$*$/(B
 */
	andi	t0, a1, 0x80
	lh	t1, OFFSET_VRC4_LINECNT_SAVE(WORK)
	beq	t0, zero, 1f
	lh	t1, OFFSET_LINECNT(WORK)
	addiu	t1, t1, 1
	slti	t0, t1, 238
	bne	t0, zero, 1f
	li	t1, -20
1:
	sh	t1, OFFSET_LINECNT_IRQ(WORK)
	andi	t0, a1, 0x03
#if 0
/* debug */
	move a1,t1
	PRINTF("4025 IRQ=%x\n");
#endif
	
/* QD reset ? */
	lhu	t2, OFFSET_QDOFFSET + 2(WORK)
	xori	t0, t0, 0x02
	bne	t0, zero, store_done
	lbu	t1, OFFSET_QD4030H + 2(WORK)
	sh	zero, OFFSET_QDOFFSET + 2(WORK)
	andi	t1, t1, 0xfd
	sb	t1, OFFSET_QD4030H + 2(WORK)
	jr	STORE_DONE

	GLOBAL(storeqd_4026)
storeqd_4026:
	sb	a1, OFFSET_QD4030H + 3(WORK)
	jr	STORE_DONE

	GLOBAL(storeqd_8000)
storeqd_8000:
/* emu-cpu address $B$,(B 0x8000-0xdfff $B$N$H$-$N$_Mh$k!#(B
 * prgrom + 0 .. prgrom + 0x5fff $B$K=q$-9~$_!#(B
 */
#if 0
/* debug */
	move a2,a0
	PRINTF("qd(%x->%x)\n");
#endif
	lw	t1, OFFSET_PRGROM(WORK)
	addu	t0, a0, t1
	sb	a1, -0x8000(t0)
	jr	STORE_DONE
	
	GLOBAL(storeqd_4024)
storeqd_4024:
	lbu	t0, OFFSET_QD4020H + 5(WORK)
	lw	t1, OFFSET_QDIMAGE(WORK)
	lw	t2, OFFSET_QDOFFSET(WORK)
	andi	t0, t0, 0x87
	xori	t0, t0, 0x81
	bne	t0, zero, store_done
	addu	t1, t1, t2
	sb	a1, -2(t1)
	sb	zero, OFFSET_QD_DIRTY(WORK)
	jr	STORE_DONE
	
	GLOBAL(wdm_42)
wdm_42:
/* disksys $B$N(B $B%7%9%F%`(B ROM $B6u4V(B $B$G<B9T$5$l$?$J$i!"(B
 * $BFCJL$J0UL#$r;}$D!#(B
 * ($BFCJL$J>l=j$K(B $BKd$a9~$s$G$"$k(B)
 * $B$=$l0J30$O(B undef_op
 */
	lw	t0, OFFSET_QDIMAGE(WORK)
	li	t1, 0xe000
	sltu	t1, PC, t1
	beq	t0, zero, undef_op
	bne	t1, zero, undef_op  /* disksys $B$@@$1$I(B PC < 0xe000 */
/* $B<B:]$K$O!"!VFCJL$J>l=j!W$H$O(B
 * diskedit.bin
 * 0xe406: 85 01  sta 01  ->  42 01  wdm 01
 * $B$N>l=j$G$"$k!#(B
 * $B$3$3$G$O!"(BQD $B%$%s%U%)%a!<%7%g%s%V%m%C%/$X$N%]%$%s%?$,3NDj$7$?$H$-(B
 * $B$KMh$k!#(B
 * $BK\Mh(B sta 01 $B$J$N$G$^$:!"$=$N=hM}$r9T$&!#(B
 */
	lbu	t0, OFFSET_WRAM + 0(WORK)
	sb	A, OFFSET_WRAM + 1(WORK)

/* emu-cpu address (0x00,0x01) $B$r(B L,H $B$N%]%$%s%?$H$7$F(B
 * $B%$%s%U%)%a!<%7%g%s%V%m%C%/$N%G!<%?$rD:$/!#(B
 * I/O port $B$8$c$J$/!"$I$&$;(B RAM or ROM $B>e$K$7$+$J$$$s$@@$+$i(B
 * page table $B7PM3$G;2>H!#(B
 */
	sll	t1, A, 8
	or	t0, t0, t1
/* maker code $B$O(B $B<+L@@$J$N$G(B $BD:$+$J$$!#(B*/
	addiu	t0, t0, 1
/* t0 = emu-cpu address
 * t1 = loop address
 * t2 = loop address end
 */
	move	t1, WORK
	addiu	t2, t1, 8
1:
/* 
 * page table $B;2>H$N$?$a!"(B0x2000 -> 0x04 (d1,d0 $B$O(B 00 $B$K(B)
 */
	srl	t3, t0, 13
	sll	t3, t3, 2
	addu	PAGE_PTR, t3, WORK
	lw	t3, OFFSET_PAGE_TABLE(PAGE_PTR)
	addu	t3, t3, t0
	lbu	t3, 0(t3)
	sb	t3, OFFSET_QD_INFO_BLOCK(t1)
	addiu	t0, t0, 1
	addiu	t1, t1, 1
	bne	t1, t2, 1b

	lw	t0, OFFSET_QD_INFO_BLOCK(WORK)
	lw	t1, OFFSET_QD_INFO_BLOCK + 4(WORK)

/* t0 $B$,(B 0xffffffff $B$J$i!"(Bdisk, side $B$H$b$KJQ99$7$J$$!#(B*/
	addiu	t2, t0, 1
	beq	t2, zero, next

/* $B$8$c$"!"(Bqdimage + 0x10 $B$N$H$3$m$K(B game code, ver, side, vol $B$,$"$k$N$G(B
 * 4 $B2s$^$G(B compare $B$7$F$$$3$&!#(B
 * t0,t1 = compare source data
 * $1 = temp
 * t2 = qdimage
 * t3 = loop qdimage
 * t4 = loop qdimage end
 */
	lw	t2, OFFSET_QDIMAGE(WORK)
	lw	t3, OFFSET_QDIMAGE(WORK)
	li	t4, 0x40000
	addu	t4, t4, t2
1:
	lw	$1, 0x10(t3)
	bne	$1, t0, 2f
	lw	$1, 0x14(t3)
	beq	$1, t1, 3f
2:
	li	$1, 0x10000
	addu	t3, t3, $1
	bne	t3, t4, 1b
/* $B$"$l(B!? $B$J$$(B ... */
	move	t3, t2
3:
/* $BH/8+!*$3$N(B qd offset $B$G!#(B*/
	subu	t3, t3, t2
	sw	t3, OFFSET_QDOFFSET(WORK)
	j	next

undef_op:
/* debug */
	TRAP("UNDEFINED OP(v0)");
1:
	j	1b

	GLOBAL(linecnt_over00)
linecnt_over00: /* $B5/$3$C$F$O$$$1$J$$$N$K(B $B5/$3$C$F$7$^$C$?$iL58B%k!<%W!#(B*/
	TRAP("UNEXPECTED LINECNT OVER");
	j	linecnt_over00
	
	
		
	GLOBAL(convert_chrdata)
convert_chrdata:
/* a0: chrrom top (keep!)
 * a1: chrrom offset (keep!)
 * a2: dst top (keep!)
 * a3: keep!
 * chr data $B%3%s%P!<%H$N%"%k%4%j%:%`$O(B
 * offset $B$O(B 0x10 bytes $BC10L!#(B
 * (offset & 0x000e) $B$,(B chrline $B$G(B 8 $BDL$j$"$k$,!"$3$l$K$h$C$F(B
 * $B7k2L$N(B offset $B$,(B +0,+0x80,+0x100,...,+0x380 $B$H$J$k!#(B
 * 0x40 chars/bank $B$@@$+$i!#(B
 * (offset & 0x03f0) $B$,(B chr.no $B$G(B 0x40 $BDL$j$"$j!"$3$l$O(B
 * $B7k2L$N(B offset +0,+2,+4,...,+0x7e $B$H$J$k!#(B
 * $B$=$l$h$j>e0L(B bit $B$O(B $B$=$N$^$^;H$&!#(B
 *
 */
	andi	t0, a1, 0x0e
	sll	t0, t0, 7    /* 0x0e -> 0x380 */
	andi	t1, a1, 0x3f0
	srl	t1, t1, 3    /* 0x3f0 -> 0x7e */
	or	t0, t0, t1
	li	t1, 0xfffc00
	and	t1, t1, a1
	or	t0, t0, t1
	addu	t1, t0, a2
	addu	t0, a0, a1
/*
 * t0: src addr top
 * t1: dst addr top
 */
	addiu	t4, t0, 8
1:
	lbu	t2, 0(t0)
	lbu	t3, 8(t0)
	sll	t3, t3, 8
	or	t3, t3, t2
	sh	t3, 0(t1)
	addiu	t0, t0, 1
	addiu	t1, t1, 0x80
	bne	t0, t4, 1b
	jr	ra

	GLOBAL(emuframe_done)
emuframe_done:
#if 0
/* debug */
	PRINTF("emuframe_done\n");
#endif

	
/* a2 $B$,:F3+$9$k$Y$-(B PC
 * store $B4X?t$J$I$+$i$N(B suspend $B$G(B ra $B$rGK2u$7$J$$$h$&$K!#(B
 */
	sw	ra, OFFSET_THREAD_RA(WORK)
	sw	a2, OFFSET_THREAD_PC(WORK)
	sw	STORE_DONE, OFFSET_THREAD_STORE_DONE(WORK)
	sw	JUMPTBLP, OFFSET_THREAD_JUMPTBLP(WORK)
	sw	PAGE_PTR, OFFSET_THREAD_PAGE_PTR(WORK)
	sw	LINECYCLE, OFFSET_THREAD_LINECYCLE(WORK)
	
	sh	PC, OFFSET_PC(WORK)
	sb	A, OFFSET_A(WORK)
	sb	X, OFFSET_X(WORK)
	sb	Y, OFFSET_Y(WORK)
	sb	SP, OFFSET_SP(WORK)
	sb	Z, OFFSET_WORK_Z(WORK)
	sb	C, OFFSET_WORK_C(WORK)
	sb	V, OFFSET_WORK_V(WORK)
	sb	N, OFFSET_WORK_N(WORK)

	lw	s0, OFFSET_STACK_S0(sp)
	lw	s1, OFFSET_STACK_S1(sp)
	lw	s2, OFFSET_STACK_S2(sp)
	lw	s3, OFFSET_STACK_S3(sp)
	lw	s4, OFFSET_STACK_S4(sp)
	lw	s5, OFFSET_STACK_S5(sp)
	lw	s6, OFFSET_STACK_S6(sp)
	lw	s7, OFFSET_STACK_S7(sp)
	lw	gp, OFFSET_STACK_GP(sp)
	lw	fp, OFFSET_STACK_FP(sp)
	lw	ra, OFFSET_STACK_RA(sp)
	
	addiu	sp, sp, EMU_RFC_ASM_STACKSIZE
	jr	ra

	.end	ks_emu_rfc_asm
	
/* extern void ks_clear_r4300_watch(void); */
	.globl	ks_clear_r4300_watch
	.ent	ks_clear_r4300_watch	
ks_clear_r4300_watch:
	.set	noreorder
	mtc0	zero, C0_WATCHLO
	jr	ra
	nop
	.set	reorder
	.end	ks_clear_r4300_watch
@
