1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Orginal from Vision-8 Emulator / Copyright (C) 1997-1999 Marcel de Kogel
11 * Modified for Archos by Blueloop (a.wenger@gmx.de)
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ****************************************************************************/
28 #define memset rb->memset
29 #define memcpy rb->memcpy
32 /* #define CHIP8_DEBUG */
34 #if (LCD_WIDTH >= 112) && (LCD_HEIGHT >= 64)
35 #define CHIP8_SUPER /* SCHIP even on the archos recorder (112x64) */
38 /****************************************************************************/
39 /** (S)CHIP-8 core emulation, from Vision-8 + mods by Fdy **/
40 /** The core is completely generic and can be used outside of Rockbox, **/
41 /** thus the STATIC, EXTERN etc. Please do not modify. **/
42 /****************************************************************************/
43 /** Vision8: CHIP8 emulator *************************************************/
47 /** This file contains the portable CHIP8 emulation engine definitions **/
49 /** Copyright (C) Marcel de Kogel 1997 **/
50 /** You are not allowed to distribute this software commercially **/
51 /** Please, notify me, if you make any changes to this file **/
52 /****************************************************************************/
61 typedef unsigned char byte
; /* sizeof(byte)==1 */
62 typedef unsigned short word
; /* sizeof(word)>=2 */
64 struct chip8_regs_struct
66 byte alg
[16]; /* 16 general registers */
67 byte delay
,sound
; /* delay and sound timer */
68 word i
; /* index register */
69 word pc
; /* program counter */
70 word sp
; /* stack pointer */
73 EXTERN
struct chip8_regs_struct chip8_regs
;
76 #define CHIP8_WIDTH 128
77 #define CHIP8_HEIGHT 64
78 EXTERN byte chip8_super
; /* != 0 if in SCHIP display mode */
80 #define CHIP8_WIDTH 64
81 #define CHIP8_HEIGHT 32
84 EXTERN byte chip8_iperiod
; /* number of opcodes per */
85 /* timeslice (1/50sec.) */
86 EXTERN byte chip8_keys
[16]; /* if 1, key is held down */
87 EXTERN byte chip8_display
[CHIP8_WIDTH
*CHIP8_HEIGHT
];/* 0xff if pixel is set, */
89 EXTERN byte chip8_mem
[4096]; /* machine memory. program */
90 /* is loaded at 0x200 */
91 EXTERN byte chip8_running
; /* if 0, emulation stops */
93 EXTERN
void chip8_execute (void); /* execute chip8_iperiod */
95 EXTERN
void chip8_reset (void); /* reset virtual machine */
96 EXTERN
void chip8 (void); /* start chip8 emulation */
98 EXTERN
void chip8_sound_on (void); /* turn sound on */
99 EXTERN
void chip8_sound_off (void); /* turn sound off */
100 EXTERN
void chip8_interrupt (void); /* update keyboard, */
104 EXTERN byte chip8_trace
; /* if 1, call debugger */
106 EXTERN word chip8_trap
; /* if pc==trap, set trace */
108 EXTERN
void chip8_debug (word opcode
,struct chip8_regs_struct
*regs
);
111 #endif /* __CHIP8_H */
113 /** Vision8: CHIP8 emulator *************************************************/
117 /** This file contains the portable CHIP8 emulation engine **/
118 /** SCHIP emulation (C) Frederic Devernay 2005 **/
120 /** Copyright (C) Marcel de Kogel 1997 **/
121 /** You are not allowed to distribute this software commercially **/
122 /** Please, notify me, if you make any changes to this file **/
123 /****************************************************************************/
126 #define STATIC static
127 #define EXTERN static
128 and include this file for single-object generation
132 #include <stdlib.h> /* for memset, etc. */
139 #define DBG_(_x) ((void)(_x))
141 #define DBG_(_x) ((void)0)
144 STATIC
struct chip8_regs_struct chip8_regs
;
146 static byte chip8_key_pressed
;
147 STATIC byte chip8_keys
[16]; /* if 1, key is held down */
148 STATIC byte chip8_display
[CHIP8_WIDTH
*CHIP8_HEIGHT
]; /* 0xff if pixel is set, */
151 STATIC byte chip8_super
; /* != 0 if in SCHIP display mode */
153 STATIC byte chip8_mem
[4096]; /* machine memory. program */
154 /* is loaded at 0x200 */
156 #define read_mem(a) (chip8_mem[(a)&4095])
157 #define write_mem(a,v) (chip8_mem[(a)&4095]=(v))
159 STATIC byte chip8_iperiod
;
161 STATIC byte chip8_running
; /* Flag for End-of-Emulation */
163 #define get_reg_offset(opcode) (chip8_regs.alg+(opcode>>8))
164 #define get_reg_value(opcode) (*get_reg_offset(opcode))
165 #define get_reg_offset_2(opcode) (chip8_regs.alg+((opcode>>4)&0x0f))
166 #define get_reg_value_2(opcode) (*get_reg_offset_2(opcode))
168 typedef void (*opcode_fn
) (word opcode
);
169 typedef void (*math_fn
) (byte
*reg1
,byte reg2
);
173 static void op_call (word opcode
)
176 write_mem (chip8_regs
.sp
,chip8_regs
.pc
&0xff);
178 write_mem (chip8_regs
.sp
,chip8_regs
.pc
>>8);
179 chip8_regs
.pc
=opcode
;
181 if(chip8_regs
.sp
< 0x1c0)
182 printf("warning: more than 16 subroutine calls, sp=%x\n", chip8_regs
.sp
);
186 static void op_jmp (word opcode
)
188 chip8_regs
.pc
=opcode
;
191 static void op_key (word opcode
)
194 static byte tested
[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
196 byte key
, key_value
,cp_value
;
197 if ((opcode
&0xff)==0x9e) /* skp */
199 else if ((opcode
&0xff)==0xa1) /* sknp */
202 DBG_(printf("unhandled key opcode 0x%x\n", opcode
));
205 key
= get_reg_value(opcode
)&0x0f;
209 DBG_(printf("testing key %d\n", key
));
212 key_value
=chip8_keys
[key
];
213 if (cp_value
==key_value
)
217 static void op_skeq_const (word opcode
)
219 if (get_reg_value(opcode
)==(opcode
&0xff))
223 static void op_skne_const (word opcode
)
225 if (get_reg_value(opcode
)!=(opcode
&0xff))
229 static void op_skeq_reg (word opcode
)
231 if (get_reg_value(opcode
)==get_reg_value_2(opcode
))
235 static void op_skne_reg (word opcode
)
237 if (get_reg_value(opcode
)!=get_reg_value_2(opcode
))
241 static void op_mov_const (word opcode
)
243 *get_reg_offset(opcode
)=opcode
&0xff;
246 static void op_add_const (word opcode
)
248 *get_reg_offset(opcode
)+=opcode
&0xff;
251 static void op_mvi (word opcode
)
256 static void op_jmi (word opcode
)
258 chip8_regs
.pc
=opcode
+chip8_regs
.alg
[0];
261 static void op_rand (word opcode
)
263 *get_reg_offset(opcode
)=rand()&(opcode
&0xff);
266 static void math_or (byte
*reg1
,byte reg2
)
271 static void math_mov (byte
*reg1
,byte reg2
)
276 static void math_nop (byte
*reg1
,byte reg2
)
280 DBG_(printf("Warning: math nop!\n"));
283 static void math_and (byte
*reg1
,byte reg2
)
288 static void math_xor (byte
*reg1
,byte reg2
)
293 static void math_add (byte
*reg1
,byte reg2
)
298 chip8_regs
.alg
[15]=tmp
>>8;
301 static void math_sub (byte
*reg1
,byte reg2
)
306 chip8_regs
.alg
[15]=((byte
)(tmp
>>8))+1;
309 static void math_shr (byte
*reg1
,byte reg2
)
312 chip8_regs
.alg
[15]=*reg1
&1;
316 static void math_shl (byte
*reg1
,byte reg2
)
319 chip8_regs
.alg
[15]=*reg1
>>7;
323 static void math_rsb (byte
*reg1
,byte reg2
)
328 chip8_regs
.alg
[15]=((byte
)(tmp
>>8))+1;
332 /* SUPER: scroll down n lines (or half in CHIP8 mode) */
333 static void scroll_down(word opcode
)
335 int n
= opcode
& 0xf;
336 byte
*dst
= chip8_display
+ CHIP8_WIDTH
*CHIP8_HEIGHT
-1;
337 byte
*src
= dst
- n
*CHIP8_WIDTH
;
338 while(src
>= chip8_display
) {
341 while(dst
>= chip8_display
) {
345 /* SUPER: scroll 4 pixels left! */
346 static void scroll_left(void)
348 byte
*dst
= chip8_display
;
350 byte
*eol
= chip8_display
+ CHIP8_WIDTH
;
351 byte
*eoi
= chip8_display
+ CHIP8_WIDTH
*CHIP8_HEIGHT
;
364 static void scroll_right(void)
366 byte
*dst
= chip8_display
+ CHIP8_WIDTH
*CHIP8_HEIGHT
-1;
368 byte
*bol
= chip8_display
+ CHIP8_WIDTH
*(CHIP8_HEIGHT
-1);
369 while(bol
>= chip8_display
) {
383 static void op_system (word opcode
)
385 switch ((byte
)opcode
)
395 DBG_(printf("SUPER: quit the emulator\n"));
399 DBG_(printf("SUPER: set CHIP-8 graphic mode\n"));
400 memset (chip8_display
,0,sizeof(chip8_display
));
404 DBG_(printf("SUPER: set SCHIP graphic mode\n"));
405 memset (chip8_display
,0,sizeof(chip8_display
));
410 memset (chip8_display
,0,sizeof(chip8_display
));
413 chip8_regs
.pc
=read_mem(chip8_regs
.sp
)<<8;
415 chip8_regs
.pc
+=read_mem(chip8_regs
.sp
);
420 if ((opcode
& 0xF0) == 0xC0)
425 DBG_(printf("unhandled system opcode 0x%x\n", opcode
));
432 static void op_misc (word opcode
)
436 static byte firstwait
= 1;
438 reg
=get_reg_offset(opcode
);
439 switch ((byte
)opcode
)
441 case 0x07: /* gdelay */
442 *reg
=chip8_regs
.delay
;
447 printf("waiting for key press\n");
451 if (chip8_key_pressed
)
452 *reg
=chip8_key_pressed
-1;
456 case 0x15: /* sdelay */
457 chip8_regs
.delay
=*reg
;
459 case 0x18: /* ssound */
460 chip8_regs
.sound
=*reg
;
461 if (chip8_regs
.sound
)
465 chip8_regs
.i
+=(*reg
);
467 case 0x29: /* font */
468 chip8_regs
.i
=((word
)(*reg
&0x0f))*5;
471 case 0x30: /* xfont */
472 chip8_regs
.i
=((word
)(*reg
&0x0f))*10+0x50;
477 for (j
=0;i
>=100;i
-=100)
479 write_mem (chip8_regs
.i
,j
);
480 for (j
=0;i
>=10;i
-=10)
482 write_mem (chip8_regs
.i
+1,j
);
483 write_mem (chip8_regs
.i
+2,i
);
486 for (i
=0,j
=(opcode
>>8)&0x0f; i
<=j
; ++i
)
487 write_mem(chip8_regs
.i
+i
,chip8_regs
.alg
[i
]);
490 for (i
=0,j
=(opcode
>>8)&0x0f; i
<=j
; ++i
)
491 chip8_regs
.alg
[i
]=read_mem(chip8_regs
.i
+i
);
495 DBG_(printf("SUPER: save V0..V%x (X<8) in the HP48 flags\n", (opcode
>>8)&0x0f));
498 DBG_(printf("SUPER: load V0..V%x (X<8) from the HP48 flags\n", (opcode
>>8)&0x0f));
502 DBG_(printf("unhandled misc opcode 0x%x\n", opcode
));
507 static void op_sprite (word opcode
)
510 byte n
,x
,x2
,y
,collision
;
512 x
=get_reg_value(opcode
);
513 y
=get_reg_value_2(opcode
);
518 /*printf("SUPER: sprite(%x)\n", opcode);*/
521 q
=chip8_display
+y
*CHIP8_WIDTH
;
527 for (collision
=1;n
;--n
,q
+=CHIP8_WIDTH
)
530 for (y
=read_mem(p
++),x2
=x
;y
;y
<<=1,x2
=(x2
+1)&(CHIP8_WIDTH
-1))
532 collision
&=(q
[x2
]^=0xff);
533 x2
=(x
+8)&(CHIP8_WIDTH
-1);
535 for (y
=read_mem(p
++);y
;y
<<=1,x2
=(x2
+1)&(CHIP8_WIDTH
-1))
537 collision
&=(q
[x2
]^=0xff);
544 for (collision
=1;n
;--n
,q
+=CHIP8_WIDTH
)
546 for (y
=read_mem(p
++),x2
=x
;y
;y
<<=1,x2
=(x2
+1)&(CHIP8_WIDTH
-1))
548 collision
&=(q
[x2
]^=0xff);
555 q
=chip8_display
+y
*CHIP8_WIDTH
*2;
560 for (collision
=1;n
;--n
,q
+=CHIP8_WIDTH
*2)
562 for (y
=read_mem(p
++),x2
=x
*2;y
;y
<<=1,x2
=(x2
+2)&(CHIP8_WIDTH
-1))
566 q
[x2
+CHIP8_WIDTH
]^=0xff;
567 q
[x2
+CHIP8_WIDTH
+1]^=0xff;
568 collision
&= q
[x2
]|q
[x2
+1]|q
[x2
+CHIP8_WIDTH
]|q
[x2
+CHIP8_WIDTH
+1];
575 q
=chip8_display
+y
*CHIP8_WIDTH
;
578 for (collision
=1;n
;--n
,q
+=CHIP8_WIDTH
)
580 for (y
=read_mem(p
++),x2
=x
;y
;y
<<=1,x2
=(x2
+1)&(CHIP8_WIDTH
-1))
582 collision
&=(q
[x2
]^=0xff);
585 chip8_regs
.alg
[15]=collision
^1;
588 static const math_fn math_opcodes
[16]=
608 static void op_math (word opcode
)
610 (*(math_opcodes
[opcode
&0x0f]))
611 (get_reg_offset(opcode
),get_reg_value_2(opcode
));
614 static const opcode_fn main_opcodes
[16]=
635 STATIC byte chip8_trace
;
636 STATIC word chip8_trap
;
638 /****************************************************************************/
639 /* This routine is called every opcode when chip8_trace==1. It prints the */
640 /* current register contents and the opcode being executed */
641 /****************************************************************************/
642 STATIC
void chip8_debug (word opcode
,struct chip8_regs_struct
*regs
)
645 static const byte hextable
[16] = "0123456789ABCDEF";
648 v1
[1] = hextable
[(opcode
>>8)&0x0f];
649 v2
[1] = hextable
[(opcode
>>8)&0x0f];
650 printf ("PC=%04X: %04X - ",regs
->pc
,opcode
);
651 switch (opcode
>>12) {
653 if ((opcode
&0xff0) == 0xc0) {
654 printf ("SCD %01X ; Scroll down n lines",opcode
&0xf);
656 else switch (opcode
&0xfff) {
658 printf ("CLS ; Clear screen");
661 printf ("RET ; Return from subroutine call");
664 printf("SCR ; Scroll right");
667 printf("SCL ; Scroll left");
670 printf("EXIT ; Terminate the interpreter");
673 printf("LOW ; Disable extended screen mode");
676 printf("HIGH ; Enable extended screen mode");
679 printf ("SYS %03X ; Unknown system call",opcode
&0xff);
683 printf ("JP %03X ; Jump to address",opcode
&0xfff);
686 printf ("CALL %03X ; Call subroutine",opcode
&0xfff);
689 printf ("SE %s,%02X ; Skip if register == constant",v1
,opcode
&0xff);
692 printf ("SNE %s,%02X ; Skip if register <> constant",v1
,opcode
&0xff);
695 printf ("SE %s,%s ; Skip if register == register",v1
,v2
);
698 printf ("LD %s,%02X ; Set VX = Byte",v1
,opcode
&0xff);
701 printf ("ADD %s,%02X ; Set VX = VX + Byte",v1
,opcode
&0xff);
704 switch (opcode
&0x0f) {
706 printf ("LD %s,%s ; Set VX = VY, VF updates",v1
,v2
);
709 printf ("OR %s,%s ; Set VX = VX | VY, VF updates",v1
,v2
);
712 printf ("AND %s,%s ; Set VX = VX & VY, VF updates",v1
,v2
);
715 printf ("XOR %s,%s ; Set VX = VX ^ VY, VF updates",v1
,v2
);
718 printf ("ADD %s,%s ; Set VX = VX + VY, VF = carry",v1
,v2
);
721 printf ("SUB %s,%s ; Set VX = VX - VY, VF = !borrow",v1
,v2
);
724 printf ("SHR %s,%s ; Set VX = VX >> 1, VF = carry",v1
,v2
);
727 printf ("SUBN %s,%s ; Set VX = VY - VX, VF = !borrow",v1
,v2
);
730 printf ("SHL %s,%s ; Set VX = VX << 1, VF = carry",v1
,v2
);
733 printf ("Illegal opcode");
737 printf ("SNE %s,%s ; Skip next instruction iv VX!=VY",v1
,v2
);
740 printf ("LD I,%03X ; Set I = Addr",opcode
&0xfff);
743 printf ("JP V0,%03X ; Jump to Addr + V0",opcode
&0xfff);
746 printf ("RND %s,%02X ; Set VX = random & Byte",v1
,opcode
&0xff);
749 printf ("DRW %s,%s,%X ; Draw n byte sprite stored at [i] at VX,VY. Set VF = collision",v1
,v2
,opcode
&0x0f);
752 switch (opcode
&0xff) {
754 printf ("SKP %s ; Skip next instruction if key VX down",v1
);
757 printf ("SKNP %s ; Skip next instruction if key VX up",v1
);
760 printf ("%04X ; Illegal opcode", opcode
);
764 switch (opcode
&0xff) {
766 printf ("LD %s,DT ; Set VX = delaytimer",v1
);
769 printf ("LD %s,K ; Set VX = key, wait for keypress",v1
);
772 printf ("LD DT,%s ; Set delaytimer = VX",v1
);
775 printf ("LD ST,%s ; Set soundtimer = VX",v1
);
778 printf ("ADD I,%s ; Set I = I + VX",v1
);
781 printf ("LD LF,%s ; Point I to 5 byte numeric sprite for value in VX",v1
);
784 printf ("LD HF,%s ; Point I to 10 byte numeric sprite for value in VX",v1
);
787 printf ("LD B,%s ; Store BCD of VX in [I], [I+1], [I+2]",v1
);
790 printf ("LD [I],%s ; Store V0..VX in [I]..[I+X]",v1
);
793 printf ("LD %s,[I] ; Read V0..VX from [I]..[I+X]",v1
);
796 printf ("LD R,%s ; Store V0..VX in RPL user flags (X<=7)",v1
);
799 printf ("LD %s,R ; Read V0..VX from RPL user flags (X<=7)",v1
);
802 printf ("%04X ; Illegal opcode", opcode
);
806 printf ("\n; Registers: ");
807 for (i
=0;i
<16;++i
) printf ("%02x ",(regs
->alg
[i
])&0xff);
808 printf ("\n; Index: %03x Stack:%03x Delay:%02x Sound:%02x\n",
809 regs
->i
&0xfff,regs
->sp
&0xfff,regs
->delay
&0xff,regs
->sound
&0xff);
813 /****************************************************************************/
814 /* Execute chip8_iperiod opcodes */
815 /****************************************************************************/
816 STATIC
void chip8_execute(void)
821 for (i
= chip8_iperiod
; i
;--i
)
823 /* Fetch the opcode */
824 opcode
=(read_mem(chip8_regs
.pc
)<<8)+read_mem(chip8_regs
.pc
+1);
826 /* Check if trap address has been reached */
827 if ((chip8_regs
.pc
&4095)==chip8_trap
)
829 /* Call the debugger if chip8_trace!=0 */
831 chip8_debug (opcode
,&chip8_regs
);
834 (*(main_opcodes
[opcode
>>12]))(opcode
&0x0fff); /* Emulate this opcode */
837 if (chip8_regs
.delay
)
839 if (chip8_regs
.sound
)
840 if (--chip8_regs
.sound
== 0)
843 /* Update the machine status */
846 for (i
=key_pressed
=0;i
<16;++i
) /* check if a key was first */
847 if (chip8_keys
[i
]) /* pressed */
849 if (key_pressed
&& key_pressed
!=chip8_key_pressed
)
850 chip8_key_pressed
=key_pressed
;
855 /****************************************************************************/
856 /* Reset the virtual chip8 machine */
857 /****************************************************************************/
858 STATIC
void chip8_reset(void)
860 static const byte chip8_sprites
[0x50]=
862 0xf9,0x99,0xf2,0x62,0x27,
863 0xf1,0xf8,0xff,0x1f,0x1f,
864 0x99,0xf1,0x1f,0x8f,0x1f,
865 0xf8,0xf9,0xff,0x12,0x44,
866 0xf9,0xf9,0xff,0x9f,0x1f,
867 0xf9,0xf9,0x9e,0x9e,0x9e,
868 0xf8,0x88,0xfe,0x99,0x9e,
869 0xf8,0xf8,0xff,0x8f,0x88,
870 }; /* 4x5 pixel hexadecimal character font patterns */
872 static const byte schip_sprites
[10*10]=
874 0x3C, 0x7E, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x7E, 0x3C, /* 0 */
875 0x18, 0x38, 0x58, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, /* 1 */
876 0x3E, 0x7F, 0xC3, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xFF, 0xFF, /* 2 */
877 0x3C, 0x7E, 0xC3, 0x03, 0x0E, 0x0E, 0x03, 0xC3, 0x7E, 0x3C, /* 3 */
878 0x06, 0x0E, 0x1E, 0x36, 0x66, 0xC6, 0xFF, 0xFF, 0x06, 0x06, /* 4 */
879 0xFF, 0xFF, 0xC0, 0xC0, 0xFC, 0xFE, 0x03, 0xC3, 0x7E, 0x3C, /* 5 */
880 0x3E, 0x7C, 0xC0, 0xC0, 0xFC, 0xFE, 0xC3, 0xC3, 0x7E, 0x3C, /* 6 */
881 0xFF, 0xFF, 0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x60, 0x60, /* 7 */
882 0x3C, 0x7E, 0xC3, 0xC3, 0x7E, 0x7E, 0xC3, 0xC3, 0x7E, 0x3C, /* 8 */
883 0x3C, 0x7E, 0xC3, 0xC3, 0x7F, 0x3F, 0x03, 0x03, 0x3E, 0x7C, /* 9 */
884 }; /* 8x10 pixel font patterns (only 10) */
889 write_mem (i
<<1,chip8_sprites
[i
]&0xf0);
890 write_mem ((i
<<1)+1,chip8_sprites
[i
]<<4);
894 for (i=0; i<100; i++)
895 write_mem (i+0x50,schip_sprites[i]);
897 memcpy(chip8_mem
+0x50, schip_sprites
, 100);
900 memset (chip8_regs
.alg
,0,sizeof(chip8_regs
.alg
));
901 memset (chip8_keys
,0,sizeof(chip8_keys
));
903 memset (chip8_display
,0,sizeof(chip8_display
));
904 chip8_regs
.delay
=chip8_regs
.sound
=chip8_regs
.i
=0;
915 /****************************************************************************/
916 /* Start CHIP8 emulation */
917 /****************************************************************************/
918 STATIC
void chip8 (void)
921 while (chip8_running
==1) chip8_execute ();
924 /****************************************************************************/
925 /** END OF (S)CHIP-8 core emulation, from Vision-8 + mods by Fdy **/
926 /****************************************************************************/
928 /* size of the displayed area */
929 #if (CHIP8_WIDTH == 128) && (LCD_WIDTH < 128)
930 #define CHIP8_LCDWIDTH 112
932 #define CHIP8_LCDWIDTH CHIP8_WIDTH
935 #if (LCD_WIDTH > CHIP8_LCDWIDTH)
936 #define CHIP8_X ((LCD_WIDTH - CHIP8_LCDWIDTH)/2)
940 #if (LCD_HEIGHT > CHIP8_HEIGHT)
941 #define CHIP8_Y (((LCD_HEIGHT - CHIP8_HEIGHT)>>4)<<3)
946 /* variable button definitions */
947 #if CONFIG_KEYPAD == RECORDER_PAD /* only 9 out of 16 chip8 buttons */
948 #define CHIP8_OFF BUTTON_OFF
949 #define CHIP8_KEY1 BUTTON_F1
950 #define CHIP8_KEY2 BUTTON_UP
951 #define CHIP8_KEY3 BUTTON_F3
952 #define CHIP8_KEY4 BUTTON_LEFT
953 #define CHIP8_KEY5 BUTTON_PLAY
954 #define CHIP8_KEY6 BUTTON_RIGHT
955 #define CHIP8_KEY7 BUTTON_F2
956 #define CHIP8_KEY8 BUTTON_DOWN
957 #define CHIP8_KEY9 BUTTON_ON
959 #elif CONFIG_KEYPAD == ARCHOS_AV300_PAD /* only 9 out of 16 chip8 buttons */
960 #define CHIP8_OFF BUTTON_OFF
961 #define CHIP8_KEY1 BUTTON_F1
962 #define CHIP8_KEY2 BUTTON_UP
963 #define CHIP8_KEY3 BUTTON_F3
964 #define CHIP8_KEY4 BUTTON_LEFT
965 #define CHIP8_KEY5 BUTTON_SELECT
966 #define CHIP8_KEY6 BUTTON_RIGHT
967 #define CHIP8_KEY7 BUTTON_F2
968 #define CHIP8_KEY8 BUTTON_DOWN
969 #define CHIP8_KEY9 BUTTON_ON
971 #elif CONFIG_KEYPAD == ONDIO_PAD /* even more limited */
972 #define CHIP8_OFF BUTTON_OFF
973 #define CHIP8_KEY2 BUTTON_UP
974 #define CHIP8_KEY4 BUTTON_LEFT
975 #define CHIP8_KEY5 BUTTON_MENU
976 #define CHIP8_KEY6 BUTTON_RIGHT
977 #define CHIP8_KEY8 BUTTON_DOWN
979 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
980 (CONFIG_KEYPAD == IRIVER_H300_PAD)
981 #define CHIP8_OFF BUTTON_OFF
982 #define CHIP8_KEY2 BUTTON_UP
983 #define CHIP8_KEY4 BUTTON_LEFT
984 #define CHIP8_KEY5 BUTTON_SELECT
985 #define CHIP8_KEY6 BUTTON_RIGHT
986 #define CHIP8_KEY8 BUTTON_DOWN
988 #define CHIP8_RC_OFF BUTTON_RC_STOP
990 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
991 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
992 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
993 #define CHIP8_OFF BUTTON_MENU
994 #define CHIP8_KEY2 BUTTON_SCROLL_BACK
995 #define CHIP8_KEY4 BUTTON_LEFT
996 #define CHIP8_KEY5 BUTTON_PLAY
997 #define CHIP8_KEY6 BUTTON_RIGHT
998 #define CHIP8_KEY8 BUTTON_SCROLL_FWD
1000 #elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD)
1001 #define CHIP8_OFF BUTTON_POWER
1002 #define CHIP8_KEY2 BUTTON_UP
1003 #define CHIP8_KEY4 BUTTON_LEFT
1004 #define CHIP8_KEY5 BUTTON_SELECT
1005 #define CHIP8_KEY6 BUTTON_RIGHT
1006 #define CHIP8_KEY8 BUTTON_DOWN
1008 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
1009 #define CHIP8_OFF BUTTON_POWER
1010 #define CHIP8_KEY1 BUTTON_MENU
1011 #define CHIP8_KEY2 BUTTON_UP
1012 #define CHIP8_KEY3 BUTTON_VOL_DOWN
1013 #define CHIP8_KEY4 BUTTON_LEFT
1014 #define CHIP8_KEY5 BUTTON_SELECT
1015 #define CHIP8_KEY6 BUTTON_RIGHT
1016 #define CHIP8_KEY7 BUTTON_VOL_UP
1017 #define CHIP8_KEY8 BUTTON_DOWN
1018 #define CHIP8_KEY9 BUTTON_A
1020 #elif CONFIG_KEYPAD == SANSA_E200_PAD || \
1021 CONFIG_KEYPAD == SANSA_FUZE_PAD
1022 #define CHIP8_OFF BUTTON_POWER
1023 #define CHIP8_KEY2 BUTTON_SCROLL_BACK
1024 #define CHIP8_KEY4 BUTTON_LEFT
1025 #define CHIP8_KEY5 BUTTON_SELECT
1026 #define CHIP8_KEY6 BUTTON_RIGHT
1027 #define CHIP8_KEY8 BUTTON_SCROLL_FWD
1029 #elif CONFIG_KEYPAD == SANSA_C200_PAD || \
1030 CONFIG_KEYPAD == SANSA_CLIP_PAD || \
1031 CONFIG_KEYPAD == SANSA_M200_PAD
1032 #define CHIP8_OFF BUTTON_POWER
1033 #define CHIP8_KEY2 BUTTON_UP
1034 #define CHIP8_KEY4 BUTTON_LEFT
1035 #define CHIP8_KEY5 BUTTON_SELECT
1036 #define CHIP8_KEY6 BUTTON_RIGHT
1037 #define CHIP8_KEY8 BUTTON_DOWN
1039 #elif (CONFIG_KEYPAD == IRIVER_H10_PAD)
1040 #define CHIP8_OFF BUTTON_POWER
1041 #define CHIP8_KEY2 BUTTON_SCROLL_UP
1042 #define CHIP8_KEY4 BUTTON_LEFT
1043 #define CHIP8_KEY5 BUTTON_PLAY
1044 #define CHIP8_KEY6 BUTTON_RIGHT
1045 #define CHIP8_KEY8 BUTTON_SCROLL_DOWN
1047 #elif (CONFIG_KEYPAD == GIGABEAT_S_PAD)
1048 #define CHIP8_OFF BUTTON_BACK
1049 #define CHIP8_KEY1 BUTTON_MENU
1050 #define CHIP8_KEY2 BUTTON_UP
1051 #define CHIP8_KEY3 BUTTON_VOL_DOWN
1052 #define CHIP8_KEY4 BUTTON_LEFT
1053 #define CHIP8_KEY5 BUTTON_SELECT
1054 #define CHIP8_KEY6 BUTTON_RIGHT
1055 #define CHIP8_KEY7 BUTTON_VOL_UP
1056 #define CHIP8_KEY8 BUTTON_DOWN
1057 #define CHIP8_KEY9 BUTTON_PLAY
1059 #elif (CONFIG_KEYPAD == MROBE100_PAD)
1060 #define CHIP8_OFF BUTTON_POWER
1061 #define CHIP8_KEY1 BUTTON_MENU
1062 #define CHIP8_KEY2 BUTTON_UP
1063 #define CHIP8_KEY3 BUTTON_PLAY
1064 #define CHIP8_KEY4 BUTTON_LEFT
1065 #define CHIP8_KEY5 BUTTON_SELECT
1066 #define CHIP8_KEY6 BUTTON_RIGHT
1067 #define CHIP8_KEY7 BUTTON_DISPLAY
1068 #define CHIP8_KEY8 BUTTON_DOWN
1070 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
1071 #define CHIP8_OFF BUTTON_RC_REC
1072 #define CHIP8_KEY1 BUTTON_RC_MENU
1073 #define CHIP8_KEY2 BUTTON_RC_VOL_UP
1074 #define CHIP8_KEY3 BUTTON_RC_MODE
1075 #define CHIP8_KEY4 BUTTON_RC_REW
1076 #define CHIP8_KEY5 BUTTON_RC_PLAY
1077 #define CHIP8_KEY6 BUTTON_RC_FF
1078 #define CHIP8_KEY8 BUTTON_RC_VOL_DOWN
1080 #elif (CONFIG_KEYPAD == COWON_D2_PAD)
1081 #define CHIP8_OFF BUTTON_POWER
1083 #elif CONFIG_KEYPAD == CREATIVEZVM_PAD
1084 #define CHIP8_OFF BUTTON_BACK
1085 #define CHIP8_KEY1 BUTTON_MENU
1086 #define CHIP8_KEY2 BUTTON_UP
1087 #define CHIP8_KEY3 BUTTON_CUSTOM
1088 #define CHIP8_KEY4 BUTTON_LEFT
1089 #define CHIP8_KEY5 BUTTON_PLAY
1090 #define CHIP8_KEY6 BUTTON_RIGHT
1091 #define CHIP8_KEY8 BUTTON_DOWN
1093 #elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
1094 #define CHIP8_OFF BUTTON_POWER
1095 #define CHIP8_KEY1 BUTTON_MENU
1096 #define CHIP8_KEY2 BUTTON_UP
1097 #define CHIP8_KEY3 BUTTON_VOL_DOWN
1098 #define CHIP8_KEY4 BUTTON_LEFT
1099 #define CHIP8_KEY5 BUTTON_SELECT
1100 #define CHIP8_KEY6 BUTTON_RIGHT
1101 #define CHIP8_KEY7 BUTTON_VOL_UP
1102 #define CHIP8_KEY8 BUTTON_DOWN
1103 #define CHIP8_KEY9 BUTTON_VIEW
1105 #elif CONFIG_KEYPAD == PHILIPS_HDD6330_PAD
1106 #define CHIP8_OFF BUTTON_POWER
1107 #define CHIP8_KEY1 BUTTON_PREV
1108 #define CHIP8_KEY2 BUTTON_PLAY
1109 #define CHIP8_KEY3 BUTTON_NEXT
1110 #define CHIP8_KEY4 BUTTON_LEFT
1111 #define CHIP8_KEY5 BUTTON_UP
1112 #define CHIP8_KEY6 BUTTON_RIGHT
1113 #define CHIP8_KEY7 BUTTON_MENU
1114 #define CHIP8_KEY8 BUTTON_DOWN
1115 #define CHIP8_KEY9 BUTTON_VIEW
1116 #define CHIP8_KEY0 BUTTON_VOL_DOWN
1118 #elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD
1119 #define CHIP8_OFF BUTTON_POWER
1120 #define CHIP8_KEY1 BUTTON_LEFT
1121 #define CHIP8_KEY2 BUTTON_UP
1122 #define CHIP8_KEY3 BUTTON_RIGHT
1123 #define CHIP8_KEY4 BUTTON_PREV
1124 #define CHIP8_KEY5 BUTTON_PLAY
1125 #define CHIP8_KEY6 BUTTON_NEXT
1126 #define CHIP8_KEY7 BUTTON_MENU
1127 #define CHIP8_KEY8 BUTTON_DOWN
1128 #define CHIP8_KEY9 BUTTON_VOL_UP
1129 #define CHIP8_KEY0 BUTTON_VOL_DOWN
1131 #elif (CONFIG_KEYPAD == ONDAVX747_PAD) || \
1132 CONFIG_KEYPAD == ONDAVX777_PAD || \
1133 CONFIG_KEYPAD == MROBE500_PAD
1134 #define CHIP8_OFF BUTTON_POWER
1136 #elif CONFIG_KEYPAD == SAMSUNG_YH_PAD
1137 #define CHIP8_OFF BUTTON_REC
1138 #define CHIP8_KEY2 BUTTON_UP
1139 #define CHIP8_KEY4 BUTTON_LEFT
1140 #define CHIP8_KEY5 BUTTON_PLAY
1141 #define CHIP8_KEY6 BUTTON_RIGHT
1142 #define CHIP8_KEY8 BUTTON_DOWN
1144 #elif CONFIG_KEYPAD == PBELL_VIBE500_PAD
1145 #define CHIP8_OFF BUTTON_REC
1146 #define CHIP8_KEY2 BUTTON_UP
1147 #define CHIP8_KEY4 BUTTON_PREV
1148 #define CHIP8_KEY5 BUTTON_OK
1149 #define CHIP8_KEY6 BUTTON_NEXT
1150 #define CHIP8_KEY8 BUTTON_DOWN
1152 #elif CONFIG_KEYPAD == MPIO_HD200_PAD
1154 #define CHIP8_OFF (BUTTON_REC|BUTTON_PLAY)
1155 #define CHIP8_KEY2 BUTTON_REW
1156 #define CHIP8_KEY4 BUTTON_FF
1157 #define CHIP8_KEY5 BUTTON_PLAY
1158 #define CHIP8_KEY6 BUTTON_VOL_DOWN
1159 #define CHIP8_KEY8 BUTTON_VOL_UP
1161 #elif CONFIG_KEYPAD == MPIO_HD300_PAD
1163 #define CHIP8_OFF (BUTTON_REC|BUTTON_REPEAT)
1164 #define CHIP8_KEY2 BUTTON_REW
1165 #define CHIP8_KEY4 BUTTON_FF
1166 #define CHIP8_KEY5 BUTTON_PLAY
1167 #define CHIP8_KEY6 BUTTON_DOWN
1168 #define CHIP8_KEY8 BUTTON_UP
1171 #error No keymap defined!
1174 #ifdef HAVE_TOUCHSCREEN
1176 #define CHIP8_OFF BUTTON_TOPLEFT
1179 #define CHIP8_KEY1 BUTTON_TOPRIGHT
1182 #define CHIP8_KEY2 BUTTON_TOPMIDDLE
1185 #define CHIP8_KEY3 BUTTON_BOTTOMLEFT
1188 #define CHIP8_KEY4 BUTTON_MIDLEFT
1191 #define CHIP8_KEY5 BUTTON_CENTER
1194 #define CHIP8_KEY6 BUTTON_MIDRIGHT
1197 #define CHIP8_KEY7 BUTTON_BOTTOMRIGHT
1200 #define CHIP8_KEY8 BUTTON_BOTTOMMIDDLE
1204 static byte chip8_virtual_keys
[16];
1205 static byte chip8_keymap
[16];
1207 static unsigned long starttimer
; /* Timer value at the beginning */
1208 static unsigned long cycles
; /* Number of update cycles (50Hz) */
1210 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
1211 static bool is_playing
;
1213 /* one frame of bitswapped mp3 data */
1214 static unsigned char beep
[]={255,
1215 223, 28, 35, 0,192,210, 35,226, 72,188,242, 1,128,166, 16, 68,146,252,151, 19,
1216 10,180,245,127, 96,184, 3,184, 30, 0,118, 59,128,121,102, 6,212, 0, 97, 6,
1217 42, 65, 28,134,192,145, 57, 38,136, 73, 29, 38,132, 15, 21, 70, 91,185, 99,198,
1218 15,192, 83, 6, 33,129, 20, 6, 97, 33, 4, 6,245,128, 92, 6, 24, 0, 86, 6,
1219 56,129, 44, 24,224, 25, 13, 48, 50, 82,180, 11,251,106,249, 59, 24, 82,175,223,
1220 252,119, 76,134,120,236,149,250,247,115,254,145,173,174,168,180,255,107,195, 89,
1221 24, 25, 48,131,192, 61, 48, 64, 10,176, 49, 64, 1,152, 50, 32, 8,140, 48, 16,
1222 5,129, 51,196,187, 41,177, 23,138, 70, 50, 8, 10,242, 48,192, 3,248,226, 0,
1223 20,100, 18, 96, 41, 96, 78,102, 7,201,122, 76,119, 20,137, 37,177, 15,132,224,
1224 20, 17,191, 67,147,187,116,211, 41,169, 63,172,182,186,217,155,111,140,104,254,
1225 111,181,184,144, 17,148, 21,101,166,227,100, 86, 85, 85, 85};
1227 /* callback to request more mp3 data */
1228 static void callback(unsigned char** start
, size_t* size
)
1230 *start
= beep
; /* give it the same frame again */
1231 *size
= sizeof(beep
);
1233 #endif /* PLATFORM_NATIVE */
1235 /****************************************************************************/
1237 /****************************************************************************/
1238 static void chip8_sound_on (void)
1240 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
1242 rb
->mp3_play_pause(true); /* kickoff audio */
1246 /****************************************************************************/
1247 /* Turn sound off */
1248 /****************************************************************************/
1249 static void chip8_sound_off (void)
1251 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
1253 rb
->mp3_play_pause(false); /* pause audio */
1257 /****************************************************************************/
1258 /* Update the display */
1259 /****************************************************************************/
1260 static void chip8_update_display(void)
1265 /* frame buffer in hardware fomat */
1266 unsigned char lcd_framebuf
[CHIP8_HEIGHT
/8][CHIP8_LCDWIDTH
];
1268 for (y
=0;y
<CHIP8_HEIGHT
/8;++y
)
1270 row
= lcd_framebuf
[y
];
1271 for (x
=0, lcd_x
=0;x
<CHIP8_WIDTH
;++x
,++lcd_x
)
1277 if (chip8_display
[x
+(y
*8+i
)*CHIP8_WIDTH
] != 0)
1282 #if (CHIP8_LCDWIDTH < 128) /* LCD_WIDTH between 112 and 127 */
1284 row
[-1] |= w
; /* overlay on */
1291 #if (CONFIG_PLATFORM & PLATFORM_HOSTED) || (LCD_DEPTH >= 4)
1292 rb
->lcd_set_drawmode(DRMODE_SOLID
);
1293 rb
->lcd_mono_bitmap(lcd_framebuf
[0], CHIP8_X
, CHIP8_Y
, CHIP8_LCDWIDTH
,
1297 rb
->lcd_blit_mono(lcd_framebuf
[0], CHIP8_X
, CHIP8_Y
>>3, CHIP8_LCDWIDTH
,
1298 CHIP8_HEIGHT
>>3, CHIP8_LCDWIDTH
);
1302 static void chip8_keyboard(void)
1305 int button
= rb
->button_get(false);
1311 case CHIP8_OFF
: /* Abort Emulator */
1315 case CHIP8_KEY2
: chip8_virtual_keys
[2] = 1; break;
1316 case CHIP8_KEY2
| BUTTON_REL
: chip8_virtual_keys
[2] = 0; break;
1317 case CHIP8_KEY4
: chip8_virtual_keys
[4] = 1; break;
1318 case CHIP8_KEY4
| BUTTON_REL
: chip8_virtual_keys
[4] = 0; break;
1319 case CHIP8_KEY6
: chip8_virtual_keys
[6] = 1; break;
1320 case CHIP8_KEY6
| BUTTON_REL
: chip8_virtual_keys
[6] = 0; break;
1321 case CHIP8_KEY8
: chip8_virtual_keys
[8] = 1; break;
1322 case CHIP8_KEY8
| BUTTON_REL
: chip8_virtual_keys
[8] = 0; break;
1323 case CHIP8_KEY5
: chip8_virtual_keys
[5] = 1; break;
1324 case CHIP8_KEY5
| BUTTON_REL
: chip8_virtual_keys
[5] = 0; break;
1326 case CHIP8_KEY1
: chip8_virtual_keys
[1] = 1; break;
1327 case CHIP8_KEY1
| BUTTON_REL
: chip8_virtual_keys
[1] = 0; break;
1330 case CHIP8_KEY3
: chip8_virtual_keys
[3] = 1; break;
1331 case CHIP8_KEY3
| BUTTON_REL
: chip8_virtual_keys
[3] = 0; break;
1334 case CHIP8_KEY7
: chip8_virtual_keys
[7] = 1; break;
1335 case CHIP8_KEY7
| BUTTON_REL
: chip8_virtual_keys
[7] = 0; break;
1338 case CHIP8_KEY9
: chip8_virtual_keys
[9] = 1; break;
1339 case CHIP8_KEY9
| BUTTON_REL
: chip8_virtual_keys
[9] = 0; break;
1343 if (rb
->default_event_handler(button
) == SYS_USB_CONNECTED
)
1344 chip8_running
= 2; /* indicates stopped because of USB */
1347 for(i
=0; i
<16; i
++) {
1348 chip8_keys
[i
] = chip8_virtual_keys
[chip8_keymap
[i
]];
1352 /****************************************************************************/
1353 /* Update keyboard and display, sync emulation with VDP clock */
1354 /****************************************************************************/
1355 static void chip8_interrupt (void)
1357 unsigned long current_tick
;
1358 unsigned long timer
, runtime
;
1360 chip8_update_display();
1363 runtime
= cycles
* HZ
/ 50;
1364 timer
= starttimer
+ runtime
;
1365 current_tick
= *rb
->current_tick
;
1366 if (TIME_AFTER(timer
, current_tick
))
1368 rb
->sleep(timer
- current_tick
);
1376 static bool chip8_init(const char* file
)
1383 fd
= rb
->open(file
, O_RDONLY
);
1385 rb
->lcd_puts(0, 6, "File Error.");
1388 numread
= rb
->read(fd
, chip8_mem
+0x200, 4096-0x200);
1391 rb
->lcd_puts(0, 6, "I/O Error.");
1395 /* is there a c8k file (chip8 keys) ? */
1396 char c8kname
[MAX_PATH
];
1397 rb
->strcpy(c8kname
, file
);
1398 for(i
=0; i
<16; i
++) {
1399 chip8_virtual_keys
[i
] = 0;
1400 chip8_keymap
[i
] = i
;
1402 len
= rb
->strlen(c8kname
);
1403 c8kname
[len
-2] = '8';
1404 c8kname
[len
-1] = 'k';
1405 fd
= rb
->open(c8kname
, O_RDONLY
);
1407 rb
->lcd_puts(0, 6, "File&Keymap OK.");
1408 numread
= rb
->read(fd
, chip8_keymap
, 16);
1413 rb
->lcd_puts(0, 6, "File OK.");
1415 for(i
=0; i
<16; i
++) {
1416 if (chip8_keymap
[i
] >= '0'
1417 && chip8_keymap
[i
] <= '9')
1418 chip8_keymap
[i
] -= '0';
1419 else if (chip8_keymap
[i
] >= 'A'
1420 && chip8_keymap
[i
] <= 'F')
1421 chip8_keymap
[i
] -= 'A' - 10;
1422 else if (chip8_keymap
[i
] >= 'a'
1423 && chip8_keymap
[i
] <= 'f')
1424 chip8_keymap
[i
] -= 'a' - 10;
1426 chip8_keymap
[i
] %= 16;
1431 static bool chip8_run(const char* file
)
1435 rb
->lcd_clear_display();
1436 rb
->lcd_puts(0, 0, "SChip8 Emulator");
1437 rb
->lcd_puts(0, 1, " (c) by ");
1438 rb
->lcd_puts(0, 2, "Marcel de Kogel");
1439 rb
->lcd_puts(0, 3, " Rockbox: ");
1440 rb
->lcd_puts(0, 4, " Blueloop/Fdy ");
1441 rb
->lcd_puts(0, 5, "---------------");
1442 ok
= chip8_init(file
);
1447 rb
->lcd_clear_display();
1448 #if (CHIP8_X > 0) && (CHIP8_Y > 0)
1449 rb
->lcd_drawrect(CHIP8_X
-1,CHIP8_Y
-1,CHIP8_LCDWIDTH
+2,CHIP8_HEIGHT
+2);
1453 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
1455 is_playing
= rb
->mp3_is_playing(); /* would we disturb playback? */
1456 if (!is_playing
) /* no? then we can make sound */
1458 rb
->mp3_play_data(beep
, sizeof(beep
), callback
);
1461 starttimer
= *rb
->current_tick
;
1467 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
1469 { /* stop it if we used audio */
1470 rb
->mp3_play_stop(); /* Stop audio playback */
1474 if (chip8_running
== 3) {
1475 /* unsupported instruction */
1476 rb
->splash(HZ
, "Error: Unsupported"
1478 " CHIP-8 instruction. (maybe S-CHIP)"
1480 " (S)CHIP-8 instruction."
1490 /***************** Plugin Entry Point *****************/
1492 enum plugin_status
plugin_start(const void* parameter
)
1494 const char* filename
;
1496 if (parameter
== NULL
)
1498 rb
->splash(HZ
, "Play a .ch8 file!");
1499 return PLUGIN_ERROR
;
1503 filename
= (char*) parameter
;
1506 /* now go ahead and have fun! */
1507 if (chip8_run(filename
))
1508 if (chip8_running
== 0)
1511 return PLUGIN_USB_CONNECTED
;
1513 return PLUGIN_ERROR
;