Compare commits

...

97 commits
v0.3 ... master

Author SHA1 Message Date
tpunix
65d8764c24
Merge pull request #271 from bucanero/master
Saroo single save improvements
2025-02-14 11:06:20 +08:00
Damian Parrino
ab39208147 add crc32
- add crc32 checksum at offset 0x0C
- use ".SRO" file extension for Saroo single saves
2025-01-27 11:27:29 -03:00
tpunix
4d1928b285
Merge pull request #269 from bucanero/master
Add support for .BUP save format (import/export) to savetool
2025-01-27 11:23:17 +08:00
Damian Parrino
4a3cb6d640 update 2025-01-24 19:37:11 -03:00
Damián Parrino
058f1f1e77
Update bup_format.h 2025-01-24 19:14:15 -03:00
Damian Parrino
44730ba369 add .BUP format support
Vmem format
2025-01-22 11:51:07 -03:00
tpu
6d213af4a4 检测LOADDISC的返回值 2024-12-23 23:33:32 +08:00
tpu
a17c95943f 封面显示bugfix 2024-12-23 23:32:35 +08:00
tpu
b57308e76d 增加非游戏文件的处理 2024-12-22 22:52:53 +08:00
tpu
125911fb40 调整封面数据的校验和 2024-12-22 21:27:26 +08:00
tpu
329ca231c5 自动建立obj目录 2024-12-21 22:46:42 +08:00
tpu
8cca7ed9a5 增加区域文件 2024-12-21 22:33:50 +08:00
tpu
589832f159 更新sysid,支持全区域运行 2024-12-21 22:31:53 +08:00
tpu
319d454f31 按Z以系统光驱模式加载二进制文件 2024-12-21 22:30:31 +08:00
tpu
dc4b03008c 更新game_patch 2024-12-21 22:23:37 +08:00
tpu
295dc605cd BIOS兼容性增强 2024-12-21 22:22:36 +08:00
tpu
a7f540030a 增加刻录盘的支持 2024-12-21 22:19:51 +08:00
tpu
5033fd1107 修复背景与封面偶尔冲突的bug 2024-12-21 21:49:14 +08:00
tpu
1805e1e7a2 load_disc bugfix 2024-12-21 21:48:52 +08:00
tpu
0cd298759e 忽略cue中不支持的tag 2024-12-21 21:38:58 +08:00
tpu
b0569a920d typo fixup 2024-12-21 21:37:26 +08:00
tpu
5fa7c1618e 增加显示游戏封面功能 2024-10-13 19:56:04 +08:00
tpu
1dcffe12f0 支持V-Saturn 1.00的BIOS 2024-10-13 18:42:13 +08:00
tpu
eb48c664d6 支持系统存档与外置存储卡共存 2024-10-13 18:41:24 +08:00
tpu
b5fd8ac829 优化菜单显示 2024-10-13 18:35:21 +08:00
tpu
23264ff52a 使用dma优化memcpy 2024-10-13 18:28:00 +08:00
tpu
2b0a33e2e3 启动时显示SAROO的logo 2024-10-13 18:24:27 +08:00
tpu
8687c46d6b 优化按键轮询的间隔时间 2024-10-13 18:23:22 +08:00
tpu
6f6e18289b 增加常用日文汉字编码
增加希腊语字库
2024-10-12 20:17:57 +08:00
tpunix
459f05ffab
Merge pull request #203 from notcbw/newglyphs
添加一些缺失字形
2024-10-09 22:27:45 +08:00
tpunix
02a50799fc
Merge pull request #197 from aravikusu/master
Add Swedish language
2024-10-09 22:23:25 +08:00
tpunix
0dc8087d59
Merge branch 'master' into master 2024-10-09 22:23:12 +08:00
tpunix
20dd55f93a
Merge pull request #159 from PoliPyc/Polish_translation
Add Polish language
2024-10-09 22:17:19 +08:00
Bowen Cui
f9cde76cb2 add additional kanji/hanzi glyphs 2024-10-05 20:54:17 +08:00
Aravix
4f20b3f270 Add Swedish language 2024-09-13 02:06:39 +02:00
poliakustyczny
791f28ff3c Added polish translation for SAROO menu 2024-07-06 23:02:49 +02:00
tpu
d335365d27 修复read_file的bug 2024-06-28 23:22:07 +08:00
tpu
c8e9ea024f 更新game_patch 2024-06-28 23:21:42 +08:00
tpu
2ce57fbe30 更新saroocfg.txt 2024-06-27 22:52:40 +08:00
tpu
e3428a7d9f 更新language.c 2024-06-27 22:52:28 +08:00
tpunix
cd3f44d183
Merge pull request #152 from D-Meister2/master
Add Greek language
2024-06-27 22:27:29 +08:00
tpunix
a8d42b4a07
Merge branch 'master' into master 2024-06-27 22:27:03 +08:00
tpunix
e229cce1a1
Merge pull request #150 from buhman/romanian
Firm_Saturn/language.c: add Romanian translation
2024-06-27 22:22:04 +08:00
tpu
c354286a68 忽略POSTGAP
增加cat_dir大小
2024-06-27 22:19:43 +08:00
DasMeister22
39acd5c702
Update saroocfg.txt to add Greek 2024-06-26 02:15:17 +03:00
DasMeister22
cb6c964acf
Update language.c to add Greek 2024-06-26 02:14:47 +03:00
DasMeister22
1b004f3d94
Add Greek 2024-06-26 02:09:51 +03:00
Zack Buhman
0e53e8ab48 Firm_Saturn/language.c: add Romanian translation 2024-06-23 14:32:24 -05:00
tpu
c8608f8c05 优化read_file/write_file,去掉无用的数据搬运 2024-06-22 20:10:46 +08:00
tpu
0b01032b6b 修复cdb.options的处理机制。 2024-06-22 19:56:49 +08:00
tpu
7b79e6dc10 更加灵活的gameid匹配方式 2024-06-22 19:55:13 +08:00
tpu
d0c763b165 读写文件时加锁,以避免同时访问导致SD卡损坏。 2024-06-22 19:53:47 +08:00
tpu
08729370a1 支持多个INDEX的镜像。 2024-06-22 19:47:58 +08:00
tpunix
aec33ad54f
Merge pull request #130 from st4rl3ss/master
Italian translation for SAROO menu
2024-06-21 22:53:15 +08:00
tpunix
572b051acc
Merge pull request #110 from pplatoon/patch-1
Update language.c
2024-06-21 22:52:24 +08:00
Antonio Bellotta
402b52fe2d Italian translation 2024-06-03 11:45:44 +02:00
pplatoon
844cf1de64
Update language.c
Correct translation in spanish
2024-05-16 14:03:06 +02:00
tpu
3398b8451e hook_getkey兼容更多的BIOS版本 2024-05-15 19:51:59 +08:00
tpu
e6854bf651 更新game_patch 2024-05-15 19:51:24 +08:00
tpu
3e2bbcee0e qsort4修正 2024-05-08 22:54:33 +08:00
tpu
8e0bfd0976 更新配置文件 2024-05-07 23:35:16 +08:00
tpu
70c2ce94bd cdp_boot bugfix 2024-05-07 23:35:07 +08:00
tpu
00bb864541 更新语言文件 2024-05-07 23:34:41 +08:00
tpu
a185ddfe15 cdc bugfix 2024-05-05 00:49:43 +08:00
tpu
eb27380af1 实现特殊的SEEK到PLAY的状态转换 2024-05-05 00:48:15 +08:00
tpu
34911aaed0 增加pend_delay参数(Play end delay) 2024-05-05 00:42:41 +08:00
tpu
59ba25b9aa 9球界面,按Start返回SAROO菜单。
按C使用系统存档
2024-05-05 00:40:55 +08:00
tpu
680c482ad2 增加游戏分类显示功能 2024-05-05 00:27:24 +08:00
tpu
8bb9dece68 增加游戏排序功能 2024-05-05 00:22:42 +08:00
tpu
c56b9052e2 调整内存布局 2024-05-05 00:20:46 +08:00
tpu
578c7cbff0 增加背景图片功能(gif)
增加背景音乐功能
2024-05-05 00:14:30 +08:00
tpu
864509a620 disk_io增加锁保护。 2024-05-05 00:12:17 +08:00
tpu
2f8c7c8eb8 优化菜单滚动显示 2024-05-05 00:00:03 +08:00
tpu
39106d6538 切换240p显示模式 2024-05-04 23:55:34 +08:00
tpu
f1760a958e 增加copy/move sector功能 2024-05-04 23:42:50 +08:00
tpunix
ef0dd50d00
Merge pull request #97 from williamdsw/master
Daytona USA - All regions sector_delay fix
2024-05-04 23:02:00 +08:00
tpunix
70604b503a
Merge pull request #92 from sl1pkn07/master
Spanish Translation
2024-05-04 23:01:45 +08:00
William Santos
9bdba0cb60 :fix: LAST GLADIATORS sector_delay 2024-04-20 18:31:18 -03:00
William Santos
04766d6597 DAYTONA USA sector_delay fix 2024-04-20 17:43:16 -03:00
sL1pKn07
8dfa75ecda Spanish Translation 2024-03-30 18:02:36 +01:00
tpu
a08d61e9ce 修正德语翻译 2024-03-18 16:00:06 +08:00
tpu
a8dd955aed 调整版本号的间距 2024-03-15 17:18:36 +08:00
tpu
5a6bcc41a7 更新saroocfg.txt 2024-03-13 15:16:08 +08:00
tpu
5cb823e4e2 添加字体生成工具 2024-03-11 17:12:40 +08:00
tpu
b403a6804a init_cdblock增加HIRQ_EHST返回值。
移除为InTheHunt做的hack代码。
2024-03-11 17:02:28 +08:00
tpu
b50e7088ba 忽略cue文件中的FLAGS标记。 2024-03-11 17:01:36 +08:00
tpu
f34591d550 更新配置文件 2024-03-11 16:22:24 +08:00
tpu
56b5e0bc88 增加德语支持。 2024-03-11 16:22:02 +08:00
tpu
ca1d4caebd 更新game_patch 2024-03-11 15:55:10 +08:00
tpu
65984a50c8 1. 字体系统更新,使用变宽字体。CJK部分使用文泉驿点阵字体。
2. 增加菜单内容超长滚动显示功能。
3. 增加俄语与繁体中文翻译。
4. 主菜单中LT键切换语言。
5. 改进Makefile
2024-03-11 15:53:46 +08:00
tpu
db5f86a3ea 调整延时参数的范围: 65535->655350 2024-03-11 15:43:30 +08:00
tpu
2b202568b8 增加游戏中换盘功能 2024-03-11 15:41:22 +08:00
tpunix
9cdad31f6d
Merge pull request #67 from odiaboeeu/master
The game Bug has a problem that freezes in the first stage and with t…
2024-01-30 08:31:27 +08:00
Nelson Melo
83e21fc99a The game Bug has a problem that freezes in the first stage and with this delay it fixes this problem 2024-01-29 20:10:47 -03:00
tpunix
d1eed8bb80
Merge pull request #43 from mime29/master
[NOT TESTED] Added French language support
2024-01-26 15:04:24 +08:00
tpu
ac9ae584fa exFat support 2024-01-18 23:15:02 +08:00
Mikael
ec6cbaf24f Added French language support 2024-01-05 15:52:22 +09:00
92 changed files with 670090 additions and 5202 deletions

View file

@ -20,6 +20,7 @@
int sd_read_sector(u32 block, int count, u8 *buf);
int sd_write_sector(u32 block, int count, u8 *buf);
static osSemaphoreId_t sem_diskio;
/*-----------------------------------------------------------------------*/
/* Get Drive Status */
@ -38,6 +39,7 @@ DSTATUS disk_status (BYTE pdrv)
DSTATUS disk_initialize (BYTE pdrv)
{
sem_diskio = osSemaphoreNew(1, 1, NULL);
return RES_OK;
}
@ -51,6 +53,10 @@ DRESULT disk_read (BYTE pdrv, BYTE *buff, LBA_t sector, UINT count)
{
int result, retry;
result = osSemaphoreAcquire(sem_diskio, 100);
if(result==osErrorTimeout)
return RES_ERROR;
//printk("disk_read: pdrv=%d sector=%08x count=%d buf=%08x\n", pdrv, sector, count, buff);
retry = 4;
while(retry){
@ -67,6 +73,8 @@ DRESULT disk_read (BYTE pdrv, BYTE *buff, LBA_t sector, UINT count)
}
}
osSemaphoreRelease(sem_diskio);
if(result)
return RES_ERROR;
return RES_OK;
@ -84,6 +92,10 @@ DRESULT disk_write (BYTE pdrv, const BYTE *buff, LBA_t sector, UINT count)
{
int result, retry;
result = osSemaphoreAcquire(sem_diskio, 100);
if(result==osErrorTimeout)
return RES_ERROR;
retry = 4;
while(retry){
result = sd_write_sector(sector, count, (BYTE *)buff);
@ -99,6 +111,8 @@ DRESULT disk_write (BYTE pdrv, const BYTE *buff, LBA_t sector, UINT count)
}
}
osSemaphoreRelease(sem_diskio);
if(result)
return RES_ERROR;
return RES_OK;

View file

@ -231,7 +231,7 @@
/ buffer in the filesystem object (FATFS) is used for the file data transfer. */
#define FF_FS_EXFAT 0
#define FF_FS_EXFAT 1
/* This option switches support for exFAT filesystem. (0:Disable or 1:Enable)
/ To enable exFAT, also LFN needs to be enabled. (FF_USE_LFN >= 1)
/ Note that enabling exFAT discards ANSI C (C89) compatibility. */

View file

@ -266,7 +266,7 @@ int printk(char *fmt, ...)
printed_len = vsnprintk(printk_buf, sizeof(printk_buf), fmt, args);
va_end(args);
#ifdef BOOT
#if defined(BOOT) || (0)
_puts(printk_buf);
#else
uart4_puts(printk_buf);

View file

@ -114,7 +114,7 @@ static void sd_power_on(int on)
SDIO->POWER = 0x00000000;
}
static int sd_card_insert(void)
int sd_card_insert(void)
{
// PA15
return (GPIOA->IDR&0x8000)? 0: 1;
@ -303,7 +303,7 @@ int sd_read_sector(u32 start, int size, u8 *buf)
if(sd_rca==0)
return -1;
if(type==0x24){
if(type==0x24 || type==0x61){
return sd_read_blocks(start, size, buf);
}
@ -330,7 +330,7 @@ int sd_write_sector(u32 start, int size, u8 *buf)
if(sd_rca==0)
return -1;
if(type==0x24){
if(type==0x24 || type==0x61){
return sd_write_blocks(start, size, buf);
}

View file

@ -334,13 +334,13 @@ void simple_shell(void)
}
#ifndef BOOT
CMD(spt){
void play_i2s(void);
play_i2s();
CMD(aplay){
void play_i2s(char *audio_file);
play_i2s(sp);
}
CMD(lscue){
int list_disc(int show);
list_disc(1);
int list_disc(int cid, int show);
list_disc(arg[0], 1);
}
CMD(load){
int load_disc(int index);
@ -389,6 +389,20 @@ void simple_shell(void)
}
printk("play_delay: %d\n", play_delay);
}
CMD(fedly){
extern int pend_delay_force;
if(argc){
pend_delay_force = arg[0];
}
printk("pend_delay_force: %d\n", pend_delay_force);
}
CMD(edly){
extern int pend_delay;
if(argc){
pend_delay = arg[0];
}
printk("pend_delay: %d\n", pend_delay);
}
CMD(seram){
FIL fp;
int retv = f_open(&fp, "/exram.bin", FA_CREATE_ALWAYS|FA_WRITE);

View file

@ -409,7 +409,7 @@ void fpga_config(void)
break;
osDelay(1);
}
if(i==10){
if(i==100){
printk("FPGA config timeout!\n");
led_event(LEDEV_FPGA_ERROR);
}else{

View file

@ -190,8 +190,8 @@ void uart4_puts(char *str)
if(in_isr())
break;
if(retv){
while(get_free()<(BUF_SIZE/2)){
osDelay(10);
while(get_free()<(len)){
osDelay(1);
};
}
}while(retv);

View file

@ -16,7 +16,7 @@
*/
#define CMSIS_device_header "stm32h7xx.h"
/* ARM::CMSIS:RTOS2:Keil RTX5:Library:5.5.1 */
/* ARM::CMSIS:RTOS2:Keil RTX5:Library:5.5.2 */
#define RTE_CMSIS_RTOS2 /* CMSIS-RTOS2 */
#define RTE_CMSIS_RTOS2_RTX5 /* CMSIS-RTOS2 Keil RTX5 */

View file

@ -11,8 +11,9 @@
#define FIRM_ADDR 0x61000000
#define IMGINFO_ADDR 0x61080000
#define SYSINFO_ADDR 0x610a0000
#define TMPBUFF_ADDR 0x610c0000
#define SYSINFO_ADDR 0x610a3000
#define SAVINFO_ADDR 0x610a4000
#define TMPBUFF_ADDR 0x610c7000
#define STIRQ_CDC 0x0001
@ -112,6 +113,8 @@
#define SSCMD_LSAVE 0x000a
#define SSCMD_LMEMS 0x000b
#define SSCMD_SMEMS 0x000c
#define SSCMD_STARTUP 0x000d
#define SSCMD_SELECT 0x000e
#define MSF_TO_FAD(m,s,f) ((m * 4500) + (s * 75) + f)
@ -157,6 +160,8 @@ typedef struct
FIL *fp;
u32 fad_0;
u32 fad_start;
int *index;
int max_index;
u32 fad_end;
u32 file_offset;
u16 sector_size;
@ -291,6 +296,14 @@ extern int sector_delay;
extern int sector_delay_force;
extern int play_delay;
extern int play_delay_force;
extern int pend_delay;
extern int pend_delay_force;
extern char mdisc_str[];
extern int next_disc;
extern int sort_mode;
extern int category_num;
extern int category_current;
extern int total_disc;
/******************************************************************************/
@ -309,7 +322,7 @@ extern int play_delay_force;
extern int log_mask;
#define SSLOG(mask, fmt, ...) {if(log_mask&mask) { printk(fmt, ##__VA_ARGS__);}}
#define SSLOG(mask, fmt, ...) {if(log_mask&mask) {printk(fmt, ##__VA_ARGS__);}}
/******************************************************************************/
@ -338,6 +351,10 @@ void free_block(BLOCK *block);
int filter_sector(TRACK_INFO *track, BLOCK *wblk);
void fs_lock(void);
void fs_unlock(void);
/******************************************************************************/
@ -353,10 +370,14 @@ int fad_to_track(u32 fad);
u32 bswap32(u32 d);
void init_toc(void);
char *get_category(int id);
int list_bins(int show);
int list_disc(int show);
int list_disc(int cid, int show);
int load_disc(int index);
int load_pcm(char *fname);
int unload_disc(void);
int get_disc_ip(int index, u8 *ipbuf);
int open_savefile(void);
int load_savefile(char *gameid);
@ -365,6 +386,17 @@ int flush_savefile(void);
int load_smems(int id);
int flush_smems(int flag);
void qsort4(void *data, int num, int (*cmp_func)(const void*, const void*));
void gif_decode_init(void);
void gif_decode_timer(void);
void gif_decode_exit(void);
void cover_init(void);
void load_cover(int index);
/******************************************************************************/

View file

@ -148,10 +148,8 @@ int fill_audio_buffer(u8 *data)
// test
void play_i2s(void)
void play_i2s(char *audio_file)
{
char *audio_file = "/srmp7.bin";
FIL fp;
int retv, size;
u32 rv;

View file

@ -8,6 +8,10 @@
/******************************************************************************/
FIL track_fp[100];
int index_table[2048];
int current_index;
int sort_mode = 0;
/******************************************************************************/
@ -31,14 +35,6 @@ int get_gameid(char *gameid)
memcpy(gameid, fbuf+i, 16);
gameid[16] = 0;
for(i=15; i>=0; i--){
if(gameid[i]==0x20){
gameid[i] = 0;
}else{
break;
}
}
return 0;
}
@ -46,6 +42,34 @@ int get_gameid(char *gameid)
/******************************************************************************/
int load_pcm(char *fname)
{
FIL *fp = &track_fp[0];
TRACK_INFO *tk;
int retv;
retv = f_open(fp, fname, FA_READ);
if(retv){
return -2;
}
tk = &cdb.tracks[0];
tk->fp = fp;
tk->file_offset = 0;
tk->sector_size = 2352;
tk->fad_0 = 150;
tk->fad_start = 150;
tk->fad_end = 150 + (f_size(fp))/2352 - 1;
tk->mode = 3;
tk->ctrl_addr = 0x01;
cdb.track_num = 1;
init_toc();
return 0;
}
int parse_iso(char *fname)
{
FIL *fp = &track_fp[0];
@ -74,10 +98,10 @@ int parse_iso(char *fname)
}
int parse_cue(char *fname)
int parse_cue(char *fname, u8 *ipbuf)
{
FIL fp;
u8 *fbuf = (u8*)0x24002000;
u8 *fbuf = (u8*)0x2400b000;
char *dir_name = (char*)0x2400a000;
char *full_path = (char*)0x2400a200;
int i, retv;
@ -120,6 +144,19 @@ int parse_cue(char *fname)
return -5;
sprintk(full_path, "%s/%s", dir_name, tfile);
if(ipbuf){
// 如果ipbuf存在则意味着只需读IP信息。在第一个FILE里面。
tk_fp = &track_fp[99];
retv = f_open(tk_fp, full_path, FA_READ);
if(retv){
return -6;
}
retv = f_read(tk_fp, ipbuf, 256, &nread);
f_close(tk_fp);
return retv;
}
if(tno!=-1){
// close last track
tk = &cdb.tracks[tno];
@ -183,19 +220,26 @@ int parse_cue(char *fname)
tk = &cdb.tracks[tno];
if(idx==0){
tk->fad_0 = fad_offset + fad;
}
if(idx==1){
}else if(idx==1){
tk->fad_start = fad_offset + fad;
if(tk->fad_0==0)
tk->fad_0 = tk->fad_start;
tk->file_offset = fad*tk->sector_size;
tk->ctrl_addr = (tk->mode==3)? 0x01 : 0x41;
tk->index = &index_table[current_index];
tk->max_index = 1;
}else{
index_table[current_index] = fad_offset + fad;
current_index += 1;
tk->max_index += 1;
}
}else if(strcmp(token, "PREGAP")==0){
}else if(strcmp(token, "POSTGAP")==0){
}else if(strcmp(token, "CATALOG")==0){
}else if(strcmp(token, "REM")==0){
}else if(strcmp(token, "FLAGS")==0){
}else{
return -10;
//return -10;
}
}
@ -215,6 +259,7 @@ int parse_cue(char *fname)
/******************************************************************************/
int category_current = 0;
int total_disc;
static int *disc_path = (int *)(IMGINFO_ADDR+4);
static char *path_str = (char*)(IMGINFO_ADDR);
@ -228,8 +273,8 @@ int list_bins(int show)
FILINFO *info;
total_disc = 0;
pbptr = 0x1000;
memset(disc_path, 0x00, 0x20000-4);
pbptr = 0x2800;
memset(disc_path, 0x00, 0x23000-4);
*(int*)(IMGINFO_ADDR) = 0;
memset(&dir, 0, sizeof(dir));
@ -250,8 +295,8 @@ int list_bins(int show)
if(!(info->fattrib & AM_DIR)){
disc_path[total_disc] = pbptr;
sprintk(path_str+pbptr, "/SAROO/BIN/%s", info->fname);
pbptr += strlen(info->fname)+1+11;
strcpy(path_str+pbptr, info->fname);
pbptr += strlen(info->fname)+1;
total_disc += 1;
*(int*)(IMGINFO_ADDR) = total_disc;
@ -274,20 +319,39 @@ int list_bins(int show)
}
int list_disc(int show)
int path_cmp(const void *a, const void *b)
{
char *s1 = path_str + *(u32*)(a);
char *s2 = path_str + *(u32*)(b);
if(sort_mode == 1){
return strcmp(s1, s2);
}else{
return strcmp(s2, s1);
}
}
int list_disc(int cid, int show)
{
FRESULT retv;
DIR dir;
FILINFO *info;
char cat_dir[48] = "/SAROO/ISO/";
total_disc = 0;
pbptr = 0x1000;
memset(disc_path, 0x00, 0x20000-4);
pbptr = 0x2800;
memset(disc_path, 0x00, 0x23000-4);
*(int*)(IMGINFO_ADDR) = 0;
memset(&dir, 0, sizeof(dir));
retv = f_opendir(&dir, "/SAROO/ISO");
if(category_num>0){
strcat(cat_dir, get_category(cid));
category_current = cid;
}else{
category_current = 0;
}
retv = f_opendir(&dir, cat_dir);
if(retv)
return -1;
@ -303,8 +367,8 @@ int list_disc(int show)
if(info->fattrib & AM_DIR){
disc_path[total_disc] = pbptr;
sprintk(path_str+pbptr, "/SAROO/ISO/%s", info->fname);
pbptr += strlen(info->fname)+1+11;
strcpy(path_str+pbptr, info->fname);
pbptr += strlen(info->fname)+1;
total_disc += 1;
*(int*)(IMGINFO_ADDR) = total_disc;
@ -314,6 +378,10 @@ int list_disc(int show)
f_closedir(&dir);
free(info);
if(sort_mode){
qsort4(disc_path, total_disc, path_cmp);
}
printk("Total discs: %d\n", total_disc);
if(show){
int i;
@ -327,6 +395,20 @@ int list_disc(int show)
}
int find_disc(char *name)
{
int i;
for(i=0; i<total_disc; i++){
if(strcmp(name, path_str+disc_path[i])==0){
return i;
}
}
return -1;
}
int unload_disc(void)
{
int i;
@ -374,7 +456,7 @@ int find_cue_iso(char *dirname, char *outname)
if(info->fattrib & AM_DIR){
}else{
char *p = strrchr(info->fname, '.');
if(strcmp(p, ".cue")==0){
if(strcasecmp(p, ".cue")==0){
// ¶Áµ½cue, Ö±½Ó·µ»Ø.
sprintk(outname, "%s/%s", dirname, info->fname);
type = 1;
@ -398,22 +480,37 @@ int load_disc(int index)
{
int retv;
char *fname;
char cat_dir[256];
unload_disc();
if((index&0xffff)==0xffff){
return -1;
}
if(disc_path[index]==0){
printk("Invalid disc index %d\n", index);
return -1;
}
if(category_num){
sprintk(cat_dir, "/SAROO/ISO/%s/%s", get_category(category_current), path_str+disc_path[index]);
}else{
sprintk(cat_dir, "/SAROO/ISO/%s", path_str+disc_path[index]);
}
fname = malloc(256);
retv = find_cue_iso(path_str+disc_path[index], fname);
if(retv<0)
retv = find_cue_iso(cat_dir, fname);
if(retv<=0){
if(retv==0)
retv = -2;
goto _exit;
}
unload_disc();
current_index = 0;
printk("Load disc: {%s}\n", fname);
if(retv==1){
retv = parse_cue(fname);
retv = parse_cue(fname, NULL);
}else{
retv = parse_iso(fname);
}
@ -425,7 +522,26 @@ int load_disc(int index)
if(retv){
goto _exit;
}
mdisc_str[0] = 0;
next_disc = -1;
parse_config("/SAROO/saroocfg.txt", gameid);
if(mdisc_str[0]){
int mlen = strlen(mdisc_str);
strcpy(fname, path_str+disc_path[index]);
char *p = strstr(fname, mdisc_str);
if(p){
p[mlen] += 1;
next_disc = find_disc(fname);
if(next_disc<0){
p[mlen] = '1';
next_disc = find_disc(fname);
}
printk("next disc: [%d] %s\n", next_disc, fname);
}
}
if(sector_delay_force>=0){
sector_delay = sector_delay_force;
@ -435,6 +551,10 @@ int load_disc(int index)
play_delay = play_delay_force;
printk(" force play_delay = %d\n", play_delay);
}
if(pend_delay_force>=0){
pend_delay = pend_delay_force;
printk(" force pend_delay = %d\n", pend_delay);
}
load_savefile(gameid);
}
@ -444,3 +564,44 @@ _exit:
return retv;
}
int get_disc_ip(int index, u8 *ipbuf)
{
int retv;
char *fname;
char cat_dir[256];
if(disc_path[index]==0){
printk("Invalid disc index %d\n", index);
return -1;
}
if(category_num){
sprintk(cat_dir, "/SAROO/ISO/%s/%s", get_category(category_current), path_str+disc_path[index]);
}else{
sprintk(cat_dir, "/SAROO/ISO/%s", path_str+disc_path[index]);
}
fname = malloc(256);
retv = find_cue_iso(cat_dir, fname);
if(retv<=0){
if(retv==0)
retv = -2;
goto _exit;
}else if(retv==1){
retv = parse_cue(fname, ipbuf);
}else{
FIL *fp = &track_fp[99];
retv = f_open(fp, fname, FA_READ);
if(retv)
goto _exit;
u32 nread;
retv = f_read(fp, ipbuf, 256, &nread);
f_close(fp);
}
_exit:
free(fname);
return retv;
}

View file

@ -53,6 +53,28 @@ void free_block(BLOCK *block)
}
BLOCK *dup_block(BLOCK *block)
{
if(block==NULL)
return NULL;
BLOCK *new = alloc_block();
if(new==NULL)
return NULL;
new->size = block->size;
new->fad = block->fad;
new->cn = block->cn;
new->fn = block->fn;
new->sm = block->sm;
new->ci = block->ci;
memcpy(new->data, block->data, 2352);
new->next = NULL;
return new;
}
BLOCK *find_block(PARTITION *part, int index)
{
BLOCK *p;
@ -79,6 +101,28 @@ BLOCK *find_block(PARTITION *part, int index)
return NULL;
}
void append_block(PARTITION *part, BLOCK *block)
{
BLOCK *p, *prev;
int i, irqs;
irqs = disable_irq();
if(part->tail==NULL){
part->head = block;
}else{
part->tail->next = block;
}
part->tail = block;
block->next = NULL;
part->numblocks += 1;
restore_irq(irqs);
}
void remove_block(PARTITION *part, int index)
{
BLOCK *p, *prev;
@ -451,16 +495,10 @@ int filter_sector(TRACK_INFO *track, BLOCK *wblk)
// 普通命令
static int old_status;
// 0x00 [SR]
int get_cd_status(void)
{
set_report(cdb.status);
if(old_status!=cdb.status){
SSLOG(_DEBUG, " %02x\n", cdb.status);
old_status = cdb.status;
}
return 0;
}
@ -530,8 +568,13 @@ int init_cdblock(void)
SSLOG(_INFO, "init_cdblock\n");
// Wait change_dir finished
while(cdb.play_type==PLAYTYPE_DIR){
osDelay(1);
}
// Stop Play task
if(cdb.play_type!=0){
if(cdb.play_type){
cdb.pause_request = 1;
cdb.play_wait = 0;
disk_task_wakeup();
@ -584,9 +627,24 @@ int init_cdblock(void)
HIRQ_CLR = HIRQ_PEND | HIRQ_DRDY | HIRQ_BFUL;
set_report(cdb.status);
return HIRQ_ESEL;
return HIRQ_ESEL|HIRQ_EHST;
}
// 0x05 [S-]
int open_tray(void)
{
SSLOG(_INFO, "open_tray\n");
SSCR1 = (cdb.status<<8);
SSCR2 = 0x0000;
SSCR3 = 0x0000;
SSCR4 = 0x0000;
return 0;
}
// 0x06 [S-]
int end_trans(void)
{
@ -690,6 +748,8 @@ int play_cd(void)
cdb.index = start_pos&0xff;
play_tno = 1;
}
cdb.play_track = &cdb.tracks[cdb.track-1];
if(end_pos==0xffffff){
// PTYPE_NOCHG
@ -698,10 +758,13 @@ int play_cd(void)
cdb.play_fad_end = cdb.play_fad_start+end_pos&0x0fffff;
}else if(end_pos){
// PTYPE_TNO
if((end_pos&0xff)>1)
cdb.play_fad_end = track_to_fad(end_pos);
else
int index = end_pos&0xff;
if(start_pos==end_pos && index>0){
cdb.play_fad_end = track_to_fad((end_pos&0xff00)|(index+1)) - 1;
}else{
cdb.play_fad_end = track_to_fad((end_pos&0xff00)|0x63);
}
if(play_tno){
// STEAM-HEART'S fixup
// 明确指定start与stop的情况下,强制更新fad.
@ -720,6 +783,7 @@ int play_cd(void)
if((mode&0x7f)!=0x7f)
cdb.max_repeat = mode&0x0f;
cdb.options = 0x08;
cdb.repcnt = 0;
cdb.pause_request = 0;
cdb.play_type = PLAYTYPE_SECTOR;
@ -1089,8 +1153,6 @@ void free_partition(PARTITION *pt)
}
// 有些游戏(InTheHunt)利用reset_filter来删除扇区。这里需要hack一下。
static int gs_spos, gs_snum=0;
// 0x48 [SR]
int reset_filter(void)
@ -1112,13 +1174,7 @@ int reset_filter(void)
}
if(mode==0){
if(gs_snum){
// 只删除get_sector_data用到的block。
while(gs_snum){
remove_block(&cdb.part[fid], gs_spos);
gs_snum -= 1;
}
}else if(fid<MAX_SELECTORS){
if(fid<MAX_SELECTORS){
free_partition(&cdb.part[fid]);
}
}else{
@ -1151,7 +1207,6 @@ int reset_filter(void)
}
}
}
gs_snum = 0;
return HIRQ_ESEL;
}
@ -1314,8 +1369,6 @@ int get_sector_data(void)
set_status(STAT_WAIT | cdb.status);
return 0;
}
gs_spos = spos;
gs_snum = snum;
cdb.trans_type = TRANS_DATA;
cdb.trans_part_index = pt;
@ -1334,8 +1387,6 @@ int del_sector_data(void)
int pt, spos, snum;
PARTITION *pp;
gs_snum = 0;
pt = cdb.cr3>>8;
spos = cdb.cr2;
snum = cdb.cr4;
@ -1369,8 +1420,6 @@ int get_del_sector_data(void)
int pt, spos, snum;
PARTITION *pp;
gs_snum = 0;
if(cdb.trans_type){
set_status(STAT_WAIT | cdb.status);
return 0;
@ -1437,6 +1486,90 @@ int put_sector_data(void)
}
static int copy_move_error;
// 0x65 [SR]
int copy_sector_data(void)
{
int src, dst, spos, snum;
PARTITION *ps, *pd;
dst = cdb.cr1&0xff;
src = cdb.cr3>>8;
spos = cdb.cr2;
snum = cdb.cr4;
ps = &cdb.part[src];
pd = &cdb.part[dst];
SSLOG(_BUFIO, "copy_sector_data: src=%d(%d) spos=%d snum=%d dst=%d\n", src, ps->numblocks, spos, snum, dst);
if(spos==0xffff){
spos = ps->numblocks-1;
}
if(snum==0xffff){
snum = ps->numblocks-spos;
}
SSLOG(_BUFIO, " : src=%d(%d) spos=%d snum=%d\n", src, ps->numblocks, spos, snum);
copy_move_error = 0;
BLOCK *bs = find_block(ps, spos);
while(snum){
BLOCK *new = dup_block(bs);
if(new==NULL){
copy_move_error = 1;
break;
}
append_block(pd, new);
bs = bs->next;
snum -= 1;
}
set_status(cdb.status);
return HIRQ_ECPY;
}
// 0x66 [SR]
int move_sector_data(void)
{
int src, dst, spos, snum, i;
PARTITION *ps, *pd;
dst = cdb.cr1&0xff;
src = cdb.cr3>>8;
spos = cdb.cr2;
snum = cdb.cr4;
ps = &cdb.part[src];
pd = &cdb.part[dst];
SSLOG(_BUFIO, "move_sector_data: src=%d(%d) spos=%d snum=%d dst=%d\n", src, ps->numblocks, spos, snum, dst);
if(spos==0xffff){
spos = ps->numblocks-1;
}
if(snum==0xffff){
snum = ps->numblocks-spos;
}
SSLOG(_BUFIO, " : src=%d(%d) spos=%d snum=%d\n", src, ps->numblocks, spos, snum);
copy_move_error = 0;
for(i=0; i<snum; i++){
BLOCK *bs = find_block(ps, spos);
BLOCK *new = dup_block(bs);
if(new==NULL){
copy_move_error = 1;
break;
}
append_block(pd, new);
remove_block(ps, spos);
}
set_status(cdb.status);
return HIRQ_ECPY;
}
// 0x67 [S-]
int get_copy_error(void)
{
@ -1913,6 +2046,8 @@ char *cmd_str(int cmd)
case 0x62: return "del_sector_data";
case 0x63: return "get_del_sector_data";
case 0x64: return "put_sector_data";
case 0x65: return "copy_sector_data";
case 0x66: return "move_sector_data";
case 0x67: return "get_copy_error";
// file io
@ -1940,7 +2075,7 @@ void cdc_cmd_process(void)
cmd = (cdb.cr1>>8)&0xff;
//if(cmd!=0)
SSLOG(_DEBUG, "\nSS CDC: %s\n", cmd_str(cmd));
SSLOG(_DEBUG, "\nSS CDC: HIRQ=%04x STAT=%02x %s\n", HIRQ, cdb.status, cmd_str(cmd));
cmd = (cdb.cr1>>8)&0xff;
switch(cmd){
@ -1955,6 +2090,8 @@ void cdc_cmd_process(void)
break;
case 0x04: hirq = init_cdblock();
break;
case 0x05: hirq = open_tray();
break;
case 0x06: hirq = end_trans();
break;
@ -2019,6 +2156,10 @@ void cdc_cmd_process(void)
break;
case 0x64: hirq = put_sector_data();
break;
case 0x65: hirq = copy_sector_data();
break;
case 0x66: hirq = move_sector_data();
break;
case 0x67: hirq = get_copy_error();
break;

View file

@ -8,6 +8,7 @@
osSemaphoreId_t sem_wait_irq;
osSemaphoreId_t sem_wait_disc;
osSemaphoreId_t sem_wait_pause;
osMutexId_t mutex_fs;
int lang_id = 0;
int debug_flags = 0;
@ -15,7 +16,11 @@ int sector_delay = 0;
int sector_delay_force = -1;
int play_delay = 0;
int play_delay_force = -1;
int pend_delay = 0;
int pend_delay_force = -1;
int auto_update = 0;
char mdisc_str[16];
int next_disc = -1;
int log_mask = LOG_MASK_DEFAULT;
@ -75,15 +80,15 @@ u32 track_to_fad(u16 track_index)
t = (track_index>>8)-1;
index = track_index&0xff;
TRACK_INFO *tk = &cdb.tracks[t];
if(index==0x01){
return cdb.tracks[t].fad_start;
//} else if(index==0x63){
} else if(index>1){
return cdb.tracks[t].fad_end;
if(index<=0x01){
return tk->fad_start;
} else if(index > tk->max_index){
return tk->fad_end;
} else{
return tk->index[index-2];
}
return cdb.tracks[t].fad_start;
}
int fad_to_track(u32 fad)
@ -157,12 +162,12 @@ int get_sector(int fad, BLOCK *wblk)
if(fad>=buf_fad_start && fad<buf_fad_end){
// 在内部缓存中找到了要play的扇区
//printk(" fad_%08x found at buffer!\n", fad);
//SSLOG(_DTASK, " fad_%08x found at buffer!\n", fad);
dp = buf_fad_offset+(fad-buf_fad_start)*buf_fad_size;
wblk->data = sector_buffer+dp;
}else{
// 内部缓存中没有要play的扇区. 从文件重新读取.
//printk(" fad_%08x not found. need read from file.\n", fad);
//SSLOG(_DTASK, " fad_%08x not found. need read from file.\n", fad);
cdb.ctrladdr = cdb.play_track->ctrl_addr;
cdb.index = 1;
@ -174,9 +179,11 @@ int get_sector(int fad, BLOCK *wblk)
buf_fad_offset = dp&0x1ff;
dp &= ~0x1ff;
fs_lock();
//printk(" seek at %08x\n", dp);
retv = f_lseek(cdb.play_track->fp, dp);
f_lseek(cdb.play_track->fp, dp);
retv = f_read(cdb.play_track->fp, sector_buffer, 0x8000, (u32*)&nread);
fs_unlock();
if(retv==0){
int num_fad = (nread-buf_fad_offset)/buf_fad_size;
buf_fad_end = buf_fad_start+num_fad;
@ -244,13 +251,13 @@ void disk_task(void *arg)
cdb.status = STAT_NODISC;
set_status(cdb.status);
list_disc(0);
int wait_ticks = 10;
int play_wait_count = 0;
int lazy_play_state = 0;
while(1){
_restart_wait:
wait_ticks = (cdb.play_wait || cdb.block_free!=MAX_BLOCKS)? 1: 10;
wait_ticks = (cdb.play_wait || cdb.block_free!=MAX_BLOCKS)? 1: 2;
retv = osSemaphoreAcquire(sem_wait_disc, wait_ticks);
if(retv==osErrorTimeout){
if(cdb.pause_request){
@ -266,8 +273,25 @@ _restart_wait:
}
}
}
if(next_disc>=0){
int sd_card_insert(void);
int sdio_reset(void);
if(cdb.status==STAT_OPEN){
if(sd_card_insert()){
sdio_reset();
load_disc(next_disc);
HIRQ = HIRQ_DCHG;
}
}else{
if(sd_card_insert()==0){
cdb.status = STAT_OPEN;
}
}
}
HIRQ = HIRQ_SCDQ;
set_peri_report();
gif_decode_timer();
goto _restart_wait;
}
@ -310,14 +334,32 @@ _restart_nowait:
if(calc_delay>1000)
#endif
{
cdb.status = STAT_BUSY;
hw_delay(10000);
cdb.status = STAT_SEEK;
hw_delay(calc_delay);
}
lazy_play_state = 1;
}
}
cdb.status = STAT_PLAY;
int old_status = cdb.status;
if(play_delay){
// SEEK向PLAY状态转换有一定的延迟。
if(lazy_play_state==1){
lazy_play_state = 2;
}else if(lazy_play_state==2){
cdb.status = STAT_PLAY;
lazy_play_state = 0;
}
}else{
cdb.status = STAT_PLAY;
}
if(old_status!=cdb.status){
if(cdb.play_track->mode==3){
cdb.options = 0x00;
}
}
while(cdb.fad<cdb.play_fad_end){
if(cdb.pause_request){
@ -390,12 +432,18 @@ _restart_nowait:
}
}else{
if(cdb.repcnt>=cdb.max_repeat){
if(pend_delay){
hw_delay(pend_delay);
cdb.status = STAT_BUSY;
hw_delay(pend_delay);
}
cdb.status = STAT_PAUSE;
if(cdb.play_type==PLAYTYPE_FILE){
HIRQ = HIRQ_EFLS;
}
HIRQ = HIRQ_PEND;
cdb.play_type = 0;
cdb.index = 0;
}else{
if(cdb.repcnt<14)
cdb.repcnt += 1;
@ -477,7 +525,7 @@ void ss_cmd_handle(void)
break;
case SSCMD_LISTDISC:
// 列出镜像信息
retv = list_disc(0);
retv = list_disc(SS_ARG, 0);
SS_ARG = retv;
SS_CMD = 0;
break;
@ -486,6 +534,8 @@ void ss_cmd_handle(void)
retv = load_disc(SS_ARG);
SS_ARG = retv;
SS_CMD = 0;
gif_decode_exit();
break;
case SSCMD_CHECK:
{
@ -509,7 +559,8 @@ void ss_cmd_handle(void)
{
FIL fp;
int offset = *(u32*)(TMPBUFF_ADDR+0x00);
int size = *(u32*)(TMPBUFF_ADDR+0x04);
int size = *(u32*)(TMPBUFF_ADDR+0x04);
int baddr = *(u32*)(TMPBUFF_ADDR+0x08);
char *name = (char*)(TMPBUFF_ADDR+0x10);
int retv = f_open(&fp, name, FA_READ);
if(retv==FR_OK){
@ -517,7 +568,8 @@ void ss_cmd_handle(void)
f_lseek(&fp, offset);
if(size==0)
size = f_size(&fp);
retv = f_read(&fp, (void*)(TMPBUFF_ADDR+0x0100), size, &rsize);
u8 *rbuf = (u8*)((baddr&0x00ffffff)|0x61000000);
retv = f_read(&fp, rbuf, size, &rsize);
*(u32*)(TMPBUFF_ADDR+0x04) = rsize;
f_close(&fp);
SSLOG(_INFO, "\nSSCMD_FILERD: retv=%d rsize=%08x %s\n", retv, rsize, name);
@ -531,13 +583,17 @@ void ss_cmd_handle(void)
FIL fp;
int offset = *(u32*)(TMPBUFF_ADDR);
int size = *(u32*)(TMPBUFF_ADDR+0x04);
int baddr = *(u32*)(TMPBUFF_ADDR+0x08);
char *name = (char*)(TMPBUFF_ADDR+0x10);
int flags = (offset==-1)? FA_CREATE_ALWAYS : FA_OPEN_ALWAYS;
int retv = f_open(&fp, name, flags|FA_WRITE);
if(retv==FR_OK){
u32 wsize = 0;
u8 *wbuf = (u8*)((baddr&0x00ffffff)|0x61000000);
if(offset<0)
offset = 0;
f_lseek(&fp, offset);
retv = f_write(&fp, (void*)(TMPBUFF_ADDR+0x0100), size, &wsize);
retv = f_write(&fp, wbuf, size, &wsize);
*(u32*)(TMPBUFF_ADDR+0x04) = wsize;
f_close(&fp);
SSLOG(_INFO, "\nSSCMD_FILEWR: retv=%d wsize=%08x %s\n", retv, wsize, name);
@ -570,6 +626,63 @@ void ss_cmd_handle(void)
SS_ARG = retv;
SS_CMD = 0;
break;
case SSCMD_STARTUP: {
// 土星端启动!
// 复位buffer
buf_fad_start = 0;
buf_fad_end = 0;
buf_fad_size = 0;
// 镜像列表
list_disc(0, 0);
// 封面数据
cover_init();
// 背景音乐
int audio_repeat = 0;
retv = load_pcm("/SAROO/bgsound.pcm");
if(retv){
retv = load_pcm("/SAROO/bgsound_r.pcm");
if(retv==0){
audio_repeat = 1;
}
}
SS_ARG = retv;
//SS_CMD = 0;
if(retv==0){
cdb.play_fad_start = track_to_fad(0x0100);
cdb.play_fad_end = track_to_fad(0x0163);
cdb.track = 0x01;
cdb.index = 0x00;
cdb.fad = cdb.play_fad_start;
cdb.max_repeat = (audio_repeat)? 0x0f : 0x00;
cdb.repcnt = 0;
cdb.options = 0x00;
cdb.pause_request = 0;
cdb.play_type = PLAYTYPE_SECTOR;
disk_task_wakeup();
}
TIM6->CR1 = 0x0005;
gif_decode_init();
break;
}
case SSCMD_SELECT: {
int index = SS_ARG;
printk("\nSelect %04x\n", index);
if(index&0x8000){
gif_decode_exit();
}
if(index&0x4000){
gif_decode_init();
}else{
load_cover(index);
}
break;
}
default:
SSLOG(_INFO, "[SS] unkonw cmd: %04x\n", cmd);
break;
@ -638,6 +751,9 @@ void TIM6_DAC_IRQHandler(void)
void hw_delay(int us)
{
us = (us+9)/10;
if(us==0)
us = 2;
TIM6->CR1 = 0;
TIM6->ARR = us;
TIM6->CNT = 0;
@ -651,13 +767,14 @@ void tim6_init(void)
sem_tim6 = osSemaphoreNew(1, 0, NULL);
TIM6->CR1 = 0;
TIM6->PSC = (200-1); // 200M/100 = 1M
TIM6->PSC = (2000-1); // 200M/2000 = 100k
TIM6->SR = 0;
TIM6->DIER = 1;
NVIC_EnableIRQ(TIM6_DAC_IRQn);
}
void ss_hw_init(void)
{
// Release FPGA_NRESET
@ -729,14 +846,28 @@ void ss_sw_init(void)
cdb.cddev_filter = 0xff;
}
void fs_lock(void)
{
osMutexAcquire(mutex_fs, osWaitForever);
}
void fs_unlock(void)
{
osMutexRelease(mutex_fs);
}
void saturn_config(void)
{
FIL fp;
int retv;
u32 rv;
memset((u8*)SYSINFO_ADDR, 0, 0x1000);
parse_config("/SAROO/saroocfg.txt", NULL);
if(auto_update){
int fp, fl;
@ -787,11 +918,12 @@ void saturn_config(void)
led_event(LEDEV_NOFIRM);
return;
}
int fsize = f_size(&fp);
printk("Found Saturn bootrom file.\n");
printk(" Size %08x\n", f_size(&fp));
printk(" Size %08x\n", fsize);
rv = 0;
retv = f_read(&fp, (void*)FIRM_ADDR, f_size(&fp), &rv);
retv = f_read(&fp, (void*)FIRM_ADDR, fsize, &rv);
printk(" f_read: retv=%d rv=%08x\n", retv, rv);
f_close(&fp);
@ -815,6 +947,7 @@ void saturn_config(void)
sem_wait_irq = osSemaphoreNew(1, 0, NULL);
sem_wait_disc = osSemaphoreNew(1, 0, NULL);
sem_wait_pause = osSemaphoreNew(1, 0, NULL);
mutex_fs = osMutexNew(NULL);
osThreadAttr_t attr;
memset(&attr, 0, sizeof(attr));

View file

@ -8,6 +8,131 @@
/******************************************************************************/
u32 adler32(u8 *data, int len)
{
u32 a = 1, b = 0;
int i;
for(i=0; i<len; i++) {
a = (a + data[i]) % 65521;
b = (b + a) % 65521;
}
return (b<<16) | a;
}
/******************************************************************************/
// 将gameid分解为id与ver
static char *gameid_split(char *gid)
{
int len1, len2;
char *ver, *p;
len2 = 0;
ver = strchr(gid, ' ');
if(ver){
*ver++ = 0;
while(*ver==' ') ver++;
p = strchr(ver, ' ');
if(p) *p = 0;
len2 = strlen(ver);
}
len1 = strlen(gid);
if(len1+len2==16 && ver){
strcpy(gid+len1, ver);
ver = NULL;
}
return ver;
}
int gameid_match(char *gid1, char *gid2)
{
char id1[24], id2[24];
char *ver1, *ver2;
strcpy(id1, gid1);
strcpy(id2, gid2);
ver1 = gameid_split(id1);
ver2 = gameid_split(id2);
if(strcmp(id1, id2)){
return 0;
}
if(ver1 && ver1){
if(strcmp(ver1, ver2)){
return 0;
}
}else if(ver1==NULL && ver2==NULL){
}else{
return 0;
}
return 1;
}
/******************************************************************************/
static int max_depth;
static int *qstack = (int*)0x2400a000;
static int qtop;
#define qs_push(lp, rp) ( qstack[qtop++] = ((lp)<<16) | (rp))
void qsort4(void *idata, int num, int (*cmp_func)(const void*, const void*))
{
int *data = (int*)idata;
int ilp, irp, lp, rp, flag;
if(num<2)
return;
max_depth = 0;
qtop = 0;
qs_push(0, num-1);
while(qtop){
qtop -= 1;
ilp = qstack[qtop]>>16;
irp = qstack[qtop]&0xffff;
lp = ilp;
rp = irp;
flag = -1;
while(rp > lp){
if(cmp_func(data+lp, data+rp)>0){
int temp = data[rp];
data[rp] = data[lp];
data[lp] = temp;
flag = -flag;
}
if(flag<0){
rp -= 1;
}else{
lp += 1;
}
}
if(ilp<lp-1) qs_push(ilp, lp-1);
if(lp+1<irp) qs_push(lp+1, irp);
if(max_depth<qtop){
max_depth = qtop;
}
}
//printk("qsort4: max_depth=%d\n", max_depth);
}
/******************************************************************************/
char *get_token(char **str_in)
{
char *str, *start, match;
@ -118,6 +243,26 @@ int config_wrmem(char *lbuf)
return 0;
}
static char catbuf[32];
int category_num = 0;
int config_category(char *lbuf)
{
char *category = (char*)(SYSINFO_ADDR+0x0e80); // 610a3e80
if(category_num<12){
memcpy(category+category_num*32, catbuf, 31);
category_num += 1;
*(u8*)(SYSINFO_ADDR+0x0c) = category_num;
}
return 0;
}
char *get_category(int id)
{
return (char*)(SYSINFO_ADDR + 0x0e80 + id*32); // 610a3e80
}
/******************************************************************************/
@ -125,24 +270,33 @@ int config_wrmem(char *lbuf)
#define ARG_NON 0
#define ARG_HEX 1
#define ARG_DEC 2
#define ARG_STR 3
#define GA 0x0100
typedef struct {
char *name;
int type;
void *action;
void *action_ex;
}CFGARG;
CFGARG arg_list [] = {
{"sector_delay", ARG_DEC, &sector_delay},
{"play_delay", ARG_DEC, &play_delay},
{"auto_update", ARG_DEC, &auto_update},
{"exmem_", ARG_NON, config_exmem},
{"M_", ARG_NON, config_wrmem},
{"lang_id", ARG_DEC, &lang_id},
{"debug", ARG_HEX, &debug_flags},
{"log_mask", ARG_HEX, &log_mask},
{"lang_id", GA|ARG_DEC, &lang_id,},
{"debug", GA|ARG_HEX, &debug_flags,},
{"log_mask", GA|ARG_HEX, &log_mask,},
{"auto_update", GA|ARG_DEC, &auto_update,},
{"category", GA|ARG_STR, &catbuf, config_category},
{"sector_delay", ARG_DEC, &sector_delay,},
{"play_delay", ARG_DEC, &play_delay,},
{"pend_delay", ARG_DEC, &pend_delay,},
{"exmem_", ARG_NON, config_exmem,},
{"M_", ARG_NON, config_wrmem,},
{"multi_disc", ARG_STR, &mdisc_str,},
{"sort_mode", GA|ARG_DEC, &sort_mode,},
{NULL},
};
@ -192,7 +346,7 @@ _next_section:
g_sec = 1;
in_sec = 1;
printk("Global config:\n");
}else if(gameid && strcmp(lbuf+1, gameid)==0){
}else if(gameid && gameid_match(lbuf+1, gameid)){
// ÕÒµ½ÁËÓëgame_idÆ¥ÅäµÄsection
in_sec = 1;
printk("Game config:\n");
@ -214,12 +368,35 @@ _next_section:
CFGARG *arg = arg_list;
while(arg->name){
int nlen = strlen(arg->name);
int type = arg->type;
int global = (type&GA);
type &= 0xff;
if(global && (gameid || g_sec!=1) ){
arg += 1;
continue;
}
if(strncmp(lbuf, arg->name, nlen)==0){
if(arg->type==ARG_NON){
if(type==ARG_NON){
int (*action)(char*) = arg->action;
retv = action(lbuf+nlen);
}else if(type==ARG_STR){
p = strchr(lbuf+nlen, '"');
if(p){
char *st = p+1;
p = strchr(st, '"');
if(p){
*p = 0;
printk(" %s = \"%s\"\n", arg->name, st);
strcpy((char*)(arg->action), st);
retv = 0;
}else{
retv = -1;
}
}else{
retv = -1;
}
}else{
int base = (arg->type==ARG_DEC)? 10 : 16;
int base = (type==ARG_DEC)? 10 : 16;
p = strchr(lbuf+nlen, '=');
if(p){
int value = strtoul(p+1, NULL, base);
@ -237,6 +414,11 @@ _next_section:
if(retv){
printk("Invalid config line: {%s}\n", lbuf);
led_event(LEDEV_SCFG_ERROR);
}else{
if(arg->action_ex){
void (*action_ex)(void) = arg->action_ex;
action_ex();
}
}
}
arg += 1;
@ -252,15 +434,15 @@ _next_section:
/******************************************************************************/
#define SSAVE_FILE "/SAROO/SS_SAVE.BIN"
#define SSAVE_ADDR (SYSINFO_ADDR+0x10000)
#define SSAVE_ADDR (SAVINFO_ADDR+0x00000)
static FIL ss_fp;
static int ss_index;
#define SMEMS_FILE "/SAROO/SS_MEMS.BIN"
#define SMEMS_HDR (TMPBUFF_ADDR+0x1000)
#define SMEMS_BUF (TMPBUFF_ADDR+0x4000)
#define SMEMS_HDR (SAVINFO_ADDR+0x10000)
#define SMEMS_BUF (SAVINFO_ADDR+0x13000)
static FIL sm_fp;
static int sm_index0;
@ -362,7 +544,9 @@ int load_savefile(char *gameid)
f_lseek(&ss_fp, i*0x10000);
f_write(&ss_fp, (u8*)SSAVE_ADDR, 0x10000, &rv);
fs_lock();
f_sync(&ss_fp);
fs_unlock();
return 0;
}
@ -375,11 +559,16 @@ int flush_savefile(void)
if(ss_index==0)
return -1;
fs_lock();
printk("Flush savefile at %08x\n", ss_index*0x10000);
f_lseek(&ss_fp, ss_index*0x10000);
f_write(&ss_fp, (u8*)SSAVE_ADDR, 0x10000, &rv);
f_sync(&ss_fp);
printk("Flush done.\n\n");
fs_unlock();
return 0;
}
@ -419,6 +608,7 @@ int flush_smems(int flag)
memcpy32((u8*)SMEMS_BUF+d*1024, (u8*)SMEMS_HDR+8192, 1024);
}
printk("\nflush_smems: flag=%02x s0=%04x s1=%04x d=%d\n", flag, sm_index0, sm_index1, d);
fs_lock();
if(flag&1){
printk("Flush SMEMS header.\n");
@ -437,8 +627,12 @@ int flush_smems(int flag)
f_lseek(&sm_fp, sm_index1*1024);
f_write(&sm_fp, (u8*)SMEMS_BUF, 64*1024, &rv);
}
f_sync(&sm_fp);
printk("Flush done.\n\n");
fs_unlock();
return 0;
}
@ -446,3 +640,169 @@ int flush_smems(int flag)
/******************************************************************************/
static FIL cover_fp;
static int cover_inited = 0;
static int *ip_cache_table[12];
static int *ip_cache_ptr;
static int find_cover(char *gid, int fsum)
{
u8 *cover_buf = (u8*)0x614f0000;
int i;
for(i=0; i<2048; i++){
u8 *hdr = cover_buf+i*32;
if(hdr[0]==0)
break;
if(strcmp((char*)hdr, gid))
continue;
if(*(u32*)(hdr+12)!=fsum)
continue;
return (int)hdr;
}
return -1;
}
static int last_chdr;
// 初始化COVER数据
void cover_init(void)
{
int i, retv;
u32 nread;
retv = f_open(&cover_fp, "/SAROO/cover.bin", FA_READ);
if(retv!=FR_OK){
// 打开cover.bin失败.
cover_inited = -1;
return;
}
// 读cover.bin的头部到0x6140f000处。
f_read(&cover_fp, (u8*)0x614f0000, 0x10000, &nread);
// ip_cache存放游戏index到cover的映射.
ip_cache_ptr = (int*)(0x614e0000);
memset((u8*)0x614e0000, 0, 2560*4);
// 每个类别有一个指向ip_cache的指针.
for(i=0; i<12; i++){
ip_cache_table[i] = NULL;
}
memset((u8*)0x61400100, 0, 324*240);
cover_inited = 1;
last_chdr = -1;
}
void load_cover(int index)
{
int i, retv;
u32 nread;
if(index&0x8000){
last_chdr = -1;
}
index &= 0x7fff;
if(cover_inited<0){
// 无cover.bin
return;
}
// 取得当前类别的ip_cache指针.
int *ip_cache = ip_cache_table[category_current];
if(ip_cache==NULL){
// 初始化当前类别的指针
ip_cache_table[category_current] = ip_cache_ptr;
ip_cache = ip_cache_ptr;
ip_cache_ptr += total_disc;
}
// 获得cover头部指针
int chdr = ip_cache[index];
if(chdr==-1){
// 该游戏没有cover.
printk(" No Cover!\n");
goto _no_cover;
}else if(chdr==0){
// 第一次选择该游戏建立cache
u8 ipbuf[256];
char gid[16];
retv = get_disc_ip(index, ipbuf);
if(retv<0){
printk(" get_disc_ip failed!\n");
ip_cache[index] = -1;
goto _no_cover;
}
u8 *ip = ipbuf;
if(strncmp((char*)ipbuf, "SEGA SEGASATURN ", 16)){
ip = ipbuf+0x10;
}
memcpy(gid, ip+0x20, 16);
char *p = strrchr(gid, 'V');
if(p)
*p = 0;
p = strchr(gid, ' ');
if(p)
*p = 0;
int fsum = adler32(ip+0x30, 64);
chdr = (int)find_cover(gid, fsum);
if(chdr<0){
printk(" No Cover Found! {%12s} {%08x}\n", gid, fsum);
ip_cache[index] = -1;
goto _no_cover;
}
ip_cache[index] = chdr;
}
if(chdr==last_chdr)
return;
last_chdr = chdr;
int w = *(u16*)(chdr+0x14);
int h = *(u16*)(chdr+0x16);
int offset = *(int*)(chdr+0x10);
f_lseek(&cover_fp, offset);
f_read(&cover_fp, (u8*)0x61400c00, w*h+0x0400, &nread);
memcpy((u8*)0x61400100, (u8*)0x61400c00, 0x0400);
*(u16*)(0x61400004) = w;
*(u16*)(0x61400006) = h;
*(u16*)(0x61400008) = 0;
*(u16*)(0x6140000a) = 0;
*(u16*)(0x6140000c) = 176;
*(u16*)(0x6140000e) = (h>128)? 24 : 88;
*(u8*)0x61400000 = 3;
*(u8*)0x61400002 = 1;
return;
_no_cover:
last_chdr = -1;
*(u16*)(0x61400004) = 128;
*(u16*)(0x61400006) = 128;
*(u16*)(0x61400008) = 0;
*(u16*)(0x6140000a) = 0;
*(u16*)(0x6140000c) = 176;
*(u16*)(0x6140000e) = 88;
memset((u8*)0x61401000, 0, 128*192);
*(u8*)0x61400000 = 4;
return;
}
/******************************************************************************/

420
Firm_MCU/Saturn/tinygif.c Normal file
View file

@ -0,0 +1,420 @@
#include "main.h"
#include "ff.h"
#include <stdlib.h>
#include "cdc.h"
/******************************************************************************/
typedef struct {
u16 prefix;
u8 last;
u8 current;
u16 length;
}DICT;
typedef struct GIF_DECODER{
// 指向文件头后面的数据块
u8 *ibuf;
int iptr;
// 解码状态
int frames;
int gtimer;
// 全局信息
int gflag;
int width;
int height;
// 调色板
void (*set_palete)(struct GIF_DECODER *gd, int pal_num, u8 *pal, int global);
// 像素输出
void (*out_pixel)(struct GIF_DECODER *gd, int x, int y, int val);
// 控制块信息
int cflag;
int delay;
int trans_color;
// 指向局部图像
u8 *lbuf;
int lpos;
int lflag;
int l_x;
int l_y;
int l_width;
int l_height;
// 块缓存
u8 *bbuf;
int buf_size;
int buf_bits;
int buf_pos;
DICT *dict;
}GIF_DECODER;
static GIF_DECODER g_gd;
int gd_state = -1;
/******************************************************************************/
static int get_code(GIF_DECODER *gd, int code_len)
{
int code;
u8 *p = gd->bbuf;
if(code_len > gd->buf_bits){
p[1] = p[gd->buf_size+2-1];
p[0] = p[gd->buf_size+2-2];
gd->buf_pos = 16 - gd->buf_bits;
gd->buf_size = gd->lbuf[gd->lpos];
memcpy(p+2, gd->lbuf+gd->lpos+1, gd->buf_size);
gd->lpos += gd->buf_size+1;
gd->buf_bits += gd->buf_size*8;
}
int byte = gd->buf_pos>>3;
int bit = gd->buf_pos&7;
code = (p[byte+2]<<16) | (p[byte+1]<<8) | p[byte+0];
code >>= bit;
code &= (1<<code_len)-1;
gd->buf_pos += code_len;
gd->buf_bits -= code_len;
return code;
}
static u8 *gif_decode_clip(GIF_DECODER *gd)
{
int code_size, clear_code, eoi_code, code_len, code_level;
int last_code, code, top, i;
int x, y;
u8 *p = gd->lbuf;
gd->l_x = (p[2]<<8) | p[1];
gd->l_y = (p[4]<<8) | p[3];
gd->l_width = (p[6]<<8) | p[5];
gd->l_height = (p[8]<<8) | p[7];
gd->lflag = p[9];
//printk("lflag: %02x\n", gd->lflag);
//printk("lres: (%d,%d) %dx%d\n", gd->l_x, gd->l_y, gd->l_width, gd->l_height);
*(u16*)(0x61400004) = gd->l_width;
*(u16*)(0x61400006) = gd->l_height;
*(u16*)(0x61400008) = gd->l_x;
*(u16*)(0x6140000a) = gd->l_y;
if(gd->lflag&0x80){
// local palete
int pal_num = 1<<((gd->lflag&7)+1);
gd->set_palete(gd, pal_num, p+10, 0);
p += pal_num*3;
}
p += 10;
code_size = *p++;
gd->lpos = p - gd->lbuf;
clear_code = 1<<code_size;
eoi_code = clear_code+1;
// 初始化字典
for(i=0; i<clear_code; i++){
gd->dict[i].prefix = 0;
gd->dict[i].last = i;
gd->dict[i].current = i;
gd->dict[i].length = 1;
}
gd->buf_bits = 0;
code = clear_code;
last_code = clear_code;
x = 0;
y = 0;
while(1){
if(code==clear_code){
// clear
top = eoi_code;
code_len = code_size+1;
code_level = clear_code<<1;
}
code = get_code(gd, code_len);
//printf("C:%04x T:%04x\n", code, top);
if(code==clear_code)
continue;
if(code==eoi_code)
break;
// 在字典中加一项。注意:第一次加入的是无效项(top=eoi)。
gd->dict[top].prefix = last_code;
gd->dict[top].length = gd->dict[last_code].length+1;
gd->dict[top].last = gd->dict[last_code].last;
if(code>=top){
gd->dict[top].current = gd->dict[last_code].last;
}else{
gd->dict[top].current = gd->dict[code].last;
}
top += 1;
if(top==code_level && code_len<12){
code_len += 1;
code_level <<= 1;
}
last_code = code;
// output code
int len = gd->dict[code].length;
for(i=0; i<len; i++){
gd->out_pixel(gd, x+len-1-i, y, gd->dict[code].current);
code = gd->dict[code].prefix;
}
x += len;
while(x > gd->l_width){
x -= gd->l_width;
y += 1;
}
}
return p;
}
int gif_decode_info(GIF_DECODER *gd, u8 *fbuf, int fsize)
{
u8 *p = fbuf;
if(strncmp((char*)p, "GIF8", 4)){
return -1;
}
p += 6;
gd->gflag = p[4];
gd->width = (p[1]<<8) | p[0];
gd->height = (p[3]<<8) | p[2];
printk("gif_decode_info: %02x\n", gd->gflag);
printk(" res: %dx%d\n", gd->width, gd->height);
if(gd->gflag&0x80){
// global palete
int pal_num = 1<<((gd->gflag&7)+1);
gd->set_palete(gd, pal_num, p+7, 1);
p += pal_num*3;
}
p += 7;
gd->ibuf = p;
gd->iptr = 0;
return 0;
}
int gif_decode_frame(GIF_DECODER *gd)
{
u8 *p = gd->ibuf + gd->iptr;
while(1){
if(p[0]==0x3b){
return 1;
}else if(p[0]==0x21){
if(p[1]==0xf9){
gd->cflag = p[3];
gd->delay = (p[5]<<8) | p[4];
gd->trans_color = p[6];
//printk("\nCTRL: %02x %d\n", gd->cflag, gd->delay);
}
p += 2;
while(p[0]){ p += p[0]+1; }
p += 1;
}else if(p[0]==0x2c){
gd->lbuf = p;
p = gif_decode_clip(gd);
while(p[0]){ p += p[0]+1; }
p += 1;
gd->iptr = p - gd->ibuf;
break;
}else{
printk("Wrong data!\n");
return 1;
}
}
return 0;
}
/******************************************************************************/
static int *gif_pal = (int*)0x61400100;
static u8 *gifbuf = (u8*)0x61401000;
static void gifb_set_palete(GIF_DECODER *gd, int pal_num, u8 *pal, int global)
{
int i;
for(i=0; i<pal_num; i++){
gif_pal[i] = (pal[0]<<16) | (pal[1]<<8) | pal[2];
pal += 3;
}
*(u8*)0x61400002 = 1;
}
static void gifb_put_pixel(GIF_DECODER *gd, int x, int y, int val)
{
if(val==gd->trans_color){
return;
}
while(x >= gd->l_width){
x -= gd->l_width;
y += 1;
}
x += gd->l_x;
y += gd->l_y;
*(u8*)(gifbuf + y*512 + x) = val;
}
#define SCR_W 320
#define SCR_H 240
static int in_decoding;
void gif_decode_init(void)
{
FIL fp;
int retv;
u8 *fbuf = (u8*)0x24020000;
GIF_DECODER *gd = &g_gd;
*(u32*)(0x61400000) = 0;
memset(gd, 0, sizeof(GIF_DECODER));
in_decoding = 0;
retv = f_open(&fp, "/SAROO/mainmenu_bg.gif", FA_READ);
if(retv!=FR_OK){
gd_state = -1;
// 无背景时做一次清屏
*(u16*)(0x61400004) = 128;
*(u16*)(0x61400006) = 128;
*(u16*)(0x61400008) = 0;
*(u16*)(0x6140000a) = 0;
*(u16*)(0x6140000c) = 176;
*(u16*)(0x6140000e) = 88;
memset((u8*)0x61401000, 0, 128*192);
*(u8*)0x61400000 = 4;
return;
}
int fsize = f_size(&fp);
u32 rsize = 0;
f_read(&fp, fbuf, fsize, &rsize);
f_close(&fp);
gd->bbuf = (u8*)0x24010000;
gd->dict = (DICT*)(gd->bbuf+0x1000);
gd->out_pixel = gifb_put_pixel;
gd->set_palete = gifb_set_palete;
gif_decode_info(gd, fbuf, fsize);
*(u16*)(0x61400004) = gd->width;
*(u16*)(0x61400006) = gd->height;
*(u16*)(0x61400008) = 0;
*(u16*)(0x6140000a) = 0;
// gif图片居中放置
*(u16*)(0x6140000c) = (SCR_W - gd->width)/2;
*(u16*)(0x6140000e) = (SCR_H - gd->height)/2;
gd_state = 0;
}
static void change_gd_state(int oldval, int newval)
{
__sync_val_compare_and_swap(&gd_state, oldval, newval);
}
void gif_decode_timer(void)
{
GIF_DECODER *gd = &g_gd;
if(gd_state==0){
// 解码一帧图像
in_decoding = 1;
//TIM6->CR1 = 0x0005;
//int start = TIM6->CNT;
int eof = gif_decode_frame(gd);
in_decoding = 0;
//start = TIM6->CNT-start;
//printk("gif_decode_frame: %d us\n", start*10);
if(gd_state<0)
return;
if(eof){
if(gd->frames>1){
gd->iptr = 0;
gd->frames = 0;
}else{
change_gd_state(0, -2);
}
}else{
gd->frames += 1;
change_gd_state(0, 1);
// 通知SS来取
*(u8*)0x61400000 = 1;
}
}else if(gd_state==1){
if(*(u8*)0x61400000==0){
// SS显示完毕会清标志位
if(gd->delay){
gd->gtimer = osKernelGetTickCount() + gd->delay;
change_gd_state(1, 2);
}else{
change_gd_state(1, 0);
}
}
}else if(gd_state==2){
if(osKernelGetTickCount() >= gd->gtimer){
change_gd_state(2, 0);
}
}
}
void gif_decode_exit(void)
{
__sync_lock_test_and_set(&gd_state, -1);
while(in_decoding){
osDelay(1);
}
}
/******************************************************************************/

View file

@ -73,9 +73,9 @@
<LExpSel>0</LExpSel>
</OPTXL>
<OPTFL>
<tvExp>0</tvExp>
<tvExp>1</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<IsCurrentTarget>0</IsCurrentTarget>
<IsCurrentTarget>1</IsCurrentTarget>
</OPTFL>
<CpuCode>18</CpuCode>
<DebugOpt>
@ -282,7 +282,7 @@
<OPTFL>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<IsCurrentTarget>1</IsCurrentTarget>
<IsCurrentTarget>0</IsCurrentTarget>
</OPTFL>
<CpuCode>18</CpuCode>
<DebugOpt>
@ -364,11 +364,6 @@
<AccSizeX>1</AccSizeX>
</Mm>
</MemoryWindow1>
<ScvdPack>
<Filename>D:\Keil_v5\Packs\ARM\CMSIS\5.6.0\CMSIS\RTOS2\RTX\RTX5.scvd</Filename>
<Type>ARM.CMSIS.5.6.0</Type>
<SubType>1</SubType>
</ScvdPack>
<Tracepoint>
<THDelay>0</THDelay>
</Tracepoint>
@ -761,7 +756,7 @@
<Group>
<GroupName>FatFS</GroupName>
<tvExp>0</tvExp>
<tvExp>1</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<cbSel>0</cbSel>
<RteFlg>0</RteFlg>
@ -905,6 +900,18 @@
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>5</GroupNumber>
<FileNumber>37</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>.\Saturn\tinygif.c</PathWithFileName>
<FilenameWithoutPath>tinygif.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
</Group>
<Group>

View file

@ -634,6 +634,11 @@
<FileType>1</FileType>
<FilePath>.\Saturn\saturn_utils.c</FilePath>
</File>
<File>
<FileName>tinygif.c</FileName>
<FileType>1</FileType>
<FilePath>.\Saturn\tinygif.c</FilePath>
</File>
</Files>
</Group>
<Group>
@ -1338,6 +1343,11 @@
<FileType>1</FileType>
<FilePath>.\Saturn\saturn_utils.c</FilePath>
</File>
<File>
<FileName>tinygif.c</FileName>
<FileType>1</FileType>
<FilePath>.\Saturn\tinygif.c</FilePath>
</File>
</Files>
</Group>
<Group>

View file

@ -8,7 +8,8 @@ CC = sh-elf-gcc
AS = sh-elf-as
OBJDUMP = sh-elf-objdump
OBJCOPY = sh-elf-objcopy
LDFLAGS = -nostartfiles -nostdlib -T ldscript
#LDFLAGS = -nostartfiles -nostdlib -T ldscript
LDFLAGS = -nostartfiles -T ldscript
FLAGS = -Wall -m2 -Os -fomit-frame-pointer -std=c99
LIBS = -lgcc
@ -32,7 +33,10 @@ OBJ = obj/crt0.o \
obj/tiny_xm.o \
obj/version.o
all : BUILD_VER $(EXE)
all : obj BUILD_VER $(EXE)
obj:
mkdir obj
BUILD_VER:
touch version.c
@ -41,11 +45,12 @@ $(EXE) : $(OBJ)
$(CC) $(LDFLAGS) $(OBJ) $(LIBS) -o $(EXE)
$(OBJDUMP) -xd $(EXE) > dump.txt
$(OBJCOPY) -O binary $(EXE) tmp.bin
dd if=/dev/zero of=ssfirm.bin bs=1k count=384
dd if=tmp.bin of=ssfirm.bin conv=notrunc
dd if=hzk14u.bin of=ssfirm.bin bs=1k seek=128 conv=notrunc
cat tmp.bin font_cjk.bin >ssfirm.bin
rm -f tmp.bin
$(OBJ): main.h smpc.h vdp2.h font_latin.h
obj/%.o : %.c
$(CC) -c $< -o $@ $(FLAGS)

View file

@ -84,17 +84,17 @@ int cdc_cmd(int wait, CDCMD *cmd, CDCMD *resp, char *cmdname)
resp->cr4 = CR4;
if((resp->cr1>>8)==0xff){
printk("CMD REJECT!\n");
//printk("CMD REJECT!\n");
return -5;
}
if((resp->cr1>>8)&0x80){
printk("CMD WAIT!\n");
printk("CMD WAIT! HIRQ=%04x CR1=%04x %s\n", HIRQ, resp->cr1, cmdname);
return -6;
}
if(wait){
if(wait_hirq(wait)){
printk("HIRQ TIMEOUT! HIRQ=%04x wait=%04x\n", HIRQ, wait);
printk("HIRQ TIMEOUT! HIRQ=%04x wait=%04x %s\n", HIRQ, wait, cmdname);
}
}
//clear_hirq(wait|HIRQ_CMOK);
@ -484,6 +484,22 @@ int cdc_get_del_data(int bufnum, int spos, int snum)
return cdc_cmd(HIRQ_DRDY, &cmd, &resp, "cdc_get_del_data");
}
int cdc_put_data(int bufnum, int snum)
{
CDCMD cmd, resp;
cmd.cr1 = 0x6400;
cmd.cr2 = 0x0000;
cmd.cr3 = bufnum<<8;
cmd.cr4 = snum;
return cdc_cmd(0, &cmd, &resp, "cdc_put_data");
}
void cdc_trans_data(u8 *buf, int length)
{
int i;
@ -521,7 +537,7 @@ int cdc_auth_device(void)
CDCMD cmd, resp;
int status;
printk("\n\nCD_AUTH ... HIRQ=%04x\n", HIRQ);
//printk("\n\nCD_AUTH ... HIRQ=%04x\n", HIRQ);
cmd.cr1 = 0xe000;
cmd.cr2 = 0x0000;
@ -617,7 +633,8 @@ int cdc_read_file(int selnum, int fid, int offset)
cmd.cr3 = (selnum<<8) | ((fid>>16)&0xff);
cmd.cr4 = fid&0xffff;
return cdc_cmd(HIRQ_EFLS, &cmd, &resp, "cdc_read_file");
return cdc_cmd(0, &cmd, &resp, "cdc_read_file");
// return cdc_cmd(HIRQ_EFLS, &cmd, &resp, "cdc_read_file");
}
@ -637,6 +654,140 @@ int cdc_abort_file(void)
/**********************************************************/
void cdc_auth_hram(CDCMD *resp, int delay)
{
int status;
// cdc_put_data(0, 150);
HIRQ = ~(HIRQ_CMOK|HIRQ_EHST);
CR1 = 0x6400;
CR2 = 0x0000;
CR3 = 0x0000;
CR4 = 150;
while(HIRQ&HIRQ_CMOK);
resp->cr1 = CR1;
resp->cr2 = CR2;
resp->cr3 = CR3;
resp->cr4 = CR4;
status = resp->cr1>>8;
if(status&0x80){
printk("CMD WAIT! HIRQ=%04x status=%02x cdc_put_data\n", HIRQ, status);
}
for(int i=0; i<2352*150; i+=4){
REG(0x25818000) = 0x00020002;
}
// cdc_end_trans
HIRQ = ~(HIRQ_CMOK|HIRQ_EHST);
CR1 = 0x0600;
CR2 = 0x0000;
CR3 = 0x0000;
CR4 = 0x0000;
while(HIRQ&HIRQ_CMOK);
resp->cr1 = CR1;
resp->cr2 = CR2;
resp->cr3 = CR3;
resp->cr4 = CR4;
status = resp->cr1>>8;
if(status&0x80){
printk("CMD WAIT! HIRQ=%04x status=%02x cdc_end_trans\n", HIRQ, status);
}
while(HIRQ&HIRQ_EHST);
HIRQ = ~(HIRQ_DRDY);
for(int i=0; i<delay; i++){
__asm volatile("":::"memory"); // 防止被gcc优化掉
}
// cdc_move_data(0,0,0,50);
HIRQ = ~(HIRQ_CMOK);
CR1 = 0x6600;
CR2 = 0x0000;
CR3 = 0x0000;
CR4 = 50;
while(HIRQ&HIRQ_CMOK);
resp->cr1 = CR1;
resp->cr2 = CR2;
resp->cr3 = CR3;
resp->cr4 = CR4;
status = resp->cr1>>8;
if(status&0x80){
printk("CMD WAIT! HIRQ=%04x status=%02x cdc_put_data\n", HIRQ, status);
}
// cdc_auth
HIRQ = ~(HIRQ_CMOK|HIRQ_DCHG|HIRQ_EFLS);
CR1 = 0xe000;
CR2 = 0x0000;
CR3 = 0x0000;
CR4 = 0x0000;
while(HIRQ&HIRQ_CMOK);
resp->cr1 = CR1;
resp->cr2 = CR2;
resp->cr3 = CR3;
resp->cr4 = CR4;
status = resp->cr1>>8;
if(status&0x80){
printk("CMD WAIT! HIRQ=%04x status=%02x cdc_auth\n", HIRQ, status);
}
while(HIRQ&HIRQ_EFLS);
}
int jhl_auth_hack(int delay)
{
int status;
CDCMD resp;
memcpy((u8*)0x06080000, cdc_auth_hram, 0x400);
void (*go)(CDCMD*, int) = (void*)0x06080000;
#if 1
while(1){
status = (CR1>>8)&0x0f;
if(status>=STATUS_OPEN){
printk("State error! %04x\n", status);
return status;
}
if(status==STATUS_PAUSE)
break;
}
#endif
cdc_set_size(3);
go(&resp, delay);
int old = 0xffffffff;
while(1){
for(int i=0; i<100000; i++){ }
cdc_get_status(&status);
if(status!=old){
printk("stat: %04x\n", status);
}
old = status;
status &= 0x0f;
if(status==STATUS_FATAL)
break;
if(status==STATUS_PAUSE)
break;
if(status==STATUS_OPEN || status==STATUS_NODISC){
return -1;
}
}
cdc_auth_status(&status);
printk("AUTH: %02x\n\n", status);
cdc_set_size(0);
return status;
}
/**********************************************************/
void cdc_init(void)
{
cdc_abort_file();
@ -644,7 +795,20 @@ void cdc_init(void)
cdc_end_trans(NULL);
cdc_reset_selector(0xfc, 0);
#if 0
cdc_auth_device();
int status;
cdc_auth_status(&status);
if(status==3){
for(int i=0; i<8; i++){
status = jhl_auth_hack(10000);
if(status==2)
break;;
}
}
#endif
}
@ -777,6 +941,9 @@ void cdc_file_test(void)
cdc_get_file_scope(&fid, &fnum, &drend);
printk("file scope: fid=%d fnum=%d drend=%d\n", fid, fnum, drend);
cdc_get_file_info(0xffffff, finfo);
if(fnum>254){
fnum = 254;
}
for(i=0; i<fnum; i++){
printk("file %4d: fad=%08x size=%08x %02x %02x %02x %02x\n", i,
finfo[i].fad, finfo[i].size,
@ -789,15 +956,13 @@ void cdc_file_test(void)
do{
cdc_get_numsector(1, &free);
printk("cdc_get_numsector 1: %d HIRQ=%04x\n", free, HIRQ);
}while(free<200);
}while(free==0);
cdc_get_buffer_size(&total, &npart, &free);
printk("cdc_get_buffer_size: free=%d\n", free);
cdc_get_del_data(1, 0, 128);
cdc_get_numsector(1, &free);
printk("cdc_get_numsector 1: %d\n", free);
cdc_trans_data(sbuf, 2048*100);
cdc_get_del_data(1, 0, free);
cdc_trans_data(sbuf, 2048*free);
cdc_end_trans(NULL);
while(1){
@ -806,7 +971,6 @@ void cdc_file_test(void)
break;
}
cdc_get_numsector(1, &free);
printk("cdc_get_numsector 1: %d HIRQ=%04x\n", free, HIRQ);
cdc_get_buffer_size(&total, &npart, &free);

View file

@ -13,103 +13,192 @@
/******************************************************************************/
static const unsigned short vga_pal[256] = {
0x0000, 0x5400, 0x02A0, 0x56A0, 0x0015, 0x5415, 0x0155, 0x56B5, 0x294A, 0x7D4A, 0x2BEA, 0x7FEA, 0x295F, 0x7D5F, 0x2BFF, 0x7FFF,
0x0000, 0x0842, 0x1084, 0x14A5, 0x1CE7, 0x2108, 0x294A, 0x318C, 0x39CE, 0x4210, 0x4A52, 0x5294, 0x5AD6, 0x6739, 0x739C, 0x7FFF,
0x7C00, 0x7C08, 0x7C0F, 0x7C17, 0x7C1F, 0x5C1F, 0x3C1F, 0x201F, 0x001F, 0x011F, 0x01FF, 0x02FF, 0x03FF, 0x03F7, 0x03EF, 0x03E8,
0x03E0, 0x23E0, 0x3FE0, 0x5FE0, 0x7FE0, 0x7EE0, 0x7DE0, 0x7D00, 0x7DEF, 0x7DF3, 0x7DF7, 0x7DFB, 0x7DFF, 0x6DFF, 0x5DFF, 0x4DFF,
0x3DFF, 0x3E7F, 0x3EFF, 0x3F7F, 0x3FFF, 0x3FFB, 0x3FF7, 0x3FF3, 0x3FEF, 0x4FEF, 0x5FEF, 0x6FEF, 0x7FEF, 0x7F6F, 0x7EEF, 0x7E6F,
0x7ED6, 0x7ED8, 0x7EDB, 0x7EDD, 0x7EDF, 0x76DF, 0x6EDF, 0x62DF, 0x5ADF, 0x5B1F, 0x5B7F, 0x5BBF, 0x5BFF, 0x5BFD, 0x5BFB, 0x5BF8,
0x5BF6, 0x63F6, 0x6FF6, 0x77F6, 0x7FF6, 0x7FB6, 0x7F76, 0x7F16, 0x3800, 0x3803, 0x3807, 0x380A, 0x380E, 0x280E, 0x1C0E, 0x0C0E,
0x000E, 0x006E, 0x00EE, 0x014E, 0x01CE, 0x01CA, 0x01C7, 0x01C3, 0x01C0, 0x0DC0, 0x1DC0, 0x29C0, 0x39C0, 0x3940, 0x38E0, 0x3860,
0x38E7, 0x38E8, 0x38EA, 0x38EC, 0x38EE, 0x30EE, 0x28EE, 0x20EE, 0x1CEE, 0x1D0E, 0x1D4E, 0x1D8E, 0x1DCE, 0x1DCC, 0x1DCA, 0x1DC8,
0x1DC7, 0x21C7, 0x29C7, 0x31C7, 0x39C7, 0x3987, 0x3947, 0x3907, 0x394A, 0x394B, 0x394C, 0x394D, 0x394E, 0x354E, 0x314E, 0x2D4E,
0x294E, 0x296E, 0x298E, 0x29AE, 0x29CE, 0x29CD, 0x29CC, 0x29CB, 0x29CA, 0x2DCA, 0x31CA, 0x35CA, 0x39CA, 0x39AA, 0x398A, 0x396A,
0x2000, 0x2002, 0x2004, 0x2006, 0x2008, 0x1808, 0x1008, 0x0808, 0x0008, 0x0048, 0x0088, 0x00C8, 0x0108, 0x0106, 0x0104, 0x0102,
0x0100, 0x0900, 0x1100, 0x1900, 0x2100, 0x20C0, 0x2080, 0x2040, 0x2084, 0x2085, 0x2086, 0x2087, 0x2088, 0x1C88, 0x1888, 0x1488,
0x1088, 0x10A8, 0x10C8, 0x10E8, 0x1108, 0x1107, 0x1106, 0x1105, 0x1104, 0x1504, 0x1904, 0x1D04, 0x2104, 0x20E4, 0x20C4, 0x20A4,
0x20A5, 0x20A6, 0x20A6, 0x20A7, 0x20A8, 0x1CA8, 0x18A8, 0x18A8, 0x14A8, 0x14C8, 0x14C8, 0x14E8, 0x1508, 0x1507, 0x1506, 0x1506,
0x1505, 0x1905, 0x1905, 0x1D05, 0x2105, 0x20E5, 0x20C5, 0x20C5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
// _BGR
static const unsigned int vga_pal[16] = {
0x00000000, 0x00aa0000, 0x0000aa00, 0x00aaaa00,
0x000000aa, 0x00aa00aa, 0x000055aa, 0x00aaaaaa,
0x00555555, 0x00ff5555, 0x0055ff55, 0x00ffff55,
0x005555ff, 0x00ff55ff, 0x0055ffff, 0x00ffffff,
};
#include "font_8x16.h"
#include "font_latin.h"
static const u8 *font_cjk = (u8*)0x02020000;
static int pos_x, pos_y;
static int text_color;
static int llen;
int fbw = 320;
int fbh = 224;
int fbh = 240;
u8 *fbptr = (u8*)VDP2_VRAM;
#include "slogo.h"
void logo_trans(void)
{
#if 1
int i, j;
if(*(u16*)(VDP2_VRAM+0x0848)!=0x000d || *(u16*)(VDP2_VRAM+0x084c)!=0x000d)
return;
for(i=0; i<16; i++){
MZCTL = (i<<12) | (i<<8) | 0x0001;
for(j=0; j<300000; j++){};
}
memcpy((void*)VDP2_VRAM+0x4000, logo_dat+32, size_logo_dat-32);
memcpy((void*)VDP2_CRAM, logo_dat, 32);
memset((void*)VDP2_VRAM+0x6000, 0, 64*64*2);
j = 9;
i = 11;
int cid = 0x0200;
u16 *pt = (u16*)(VDP2_VRAM+0x6000+(j*64+i)*2);
for(j=0; j<6; j++){
for(i=0; i<20; i++){
pt[i] = cid;
cid += 1;
}
pt += 64;
}
for(i=14; i>=0; i--){
MZCTL = (i<<12) | (i<<8) | 0x0001;
for(j=0; j<300000; j++){};
}
MZCTL = 0;
for(j=0; j<5000000; j++){};
CCCTL = 0x0001;
for(i=0; i<32; i++){
CCRNA = i;
for(j=0; j<300000; j++){};
}
CCCTL = 0x0000;
#endif
}
void vdp_init(void)
{
int ii;
volatile unsigned short *vdp2_vram = (volatile unsigned short *)VDP2_VRAM;
volatile unsigned short *vdp2_cram = (volatile unsigned short *)VDP2_CRAM;
TVMD = 0x0000;
int i;
volatile unsigned int *vdp2_cram = (volatile unsigned int*)VDP2_CRAM;
RAMCTL = RAMCTL & (~0x3000);
logo_trans();
// Map Offset Register: Bitmap screen will be located at VRAM offset 0
MPOFN = 0;
// Disable VDP1
VDP1_REG_PTMR = 0;
*((volatile u16 *)(VDP1_RAM)) = 0x8000;
VDP1_REG_FBCR = 0x0000;
VDP1_REG_TVMR = 0x0000;
VDP1_REG_EWDR = 0x0000;
VDP1_REG_EWLR = (0 << 9) | 0;
// Character Control Register: 256 colors, enable NBG0 as a bitmap. |8 for 1024x256 bitmap
CHCTLA = 0x0012|8;
TVMD = 0x0000;
// Screen Scroll Value Registers: No scroll
SCXIN0 = 0;
SCXDN0 = 0;
SCYIN0 = 0;
RAMCTL = 0x2300;
CYCA0L = 0x0e44;
CYCA0U = 0xeeee;
CYCA1L = 0x1e55;
CYCA1U = 0xeeee;
// Map Offset: NBG0 at 0(0x00000), NBG1 at 1(0x20000)
MPOFN = 0x0010;
// ColorRAM: NBG0 at 0, NBG1 at 1
CRAOFA = 0x0010;
// Character Control: NBG0/1: 512x256, 256 colors, bitmap
CHCTLA = 0x1212;
// Priority: 7
PRINA = 0x0707;
// Screen Scroll Value Registers: No scroll
SCXIN0 = 0;
SCXDN0 = 0;
SCYIN0 = 0;
SCYDN0 = 0;
// BackScreen mode
LCTA = 0x7fffe>>1;
BKTA = 0x7fffe>>1;
// Screen Display Enable Register: Invalidate the transparency code for
// NBG0 and display NBG0
BGON = 0x0001;
/* Clear VRAM */
memset((void*)VDP2_VRAM, 0, 0x80000);
/* Clear VRAM */
for (ii = 0; ii < 0x40000; ii++)
vdp2_vram[ii] = 0x0000;
/* Set CRAM */
for (i = 0; i < 256; i++)
vdp2_cram[i] = vga_pal[i];
/* Clear CRAM */
for (ii = 0; ii < 0x0800; ii++)
vdp2_cram[ii] = 0x0000;
// Enable NBG0
BGON = 0x0001;
TVMD = 0x8010;
}
void conio_init(void)
{
int ii;
volatile unsigned short *vdp2_cram = (volatile unsigned short*)VDP2_CRAM;
vdp_init();
for (ii = 0; ii < 256; ii++)
vdp2_cram[ii] = vga_pal[ii];
//vdp2_cram[0] = vdp2_cram[1];
//vdp2_cram[1] = 0x10 << 10;
llen = 1024;
llen = 512;
pos_x = 0;
pos_y = 0;
text_color = 0xf0;
printk_putc = conio_putc;
TVMD = 0x8000;
void fbtest();
fbtest();
}
void nbg1_on(void)
{
CCRNA = 0x0700; // 24:8
CCCTL = 0x0002;
BGON = 0x0003;
}
void nbg1_set_cram(int index, int r, int g, int b)
{
*(u32*)(VDP2_CRAM + 0x0400 + index*4) = (b<<16) | (g<<8) | (r);
}
void nbg1_put_pixel(int x, int y, int color)
{
*(u8*)(VDP2_VRAM + 0x20000 + y*512 + x) = color;
}
void vdp2_win0(int scr, int outside, int sx, int sy, int ex, int ey)
{
if(scr==-1){
WCTLA = 0;
return;
}
WPSX0 = sx<<1;
WPSY0 = sy;
WPEX0 = ex<<1;
WPEY0 = ey;
if(scr==0){
WCTLA = 0x0002 | (outside);
}else{
WCTLA = 0x0200 | (outside<<8);
}
}
/******************************************************************************/
void fbtest(void)
{
int i;
@ -121,32 +210,16 @@ void fbtest(void)
int y = 32;
put_box(x, y, x+10, y+10, i);
}
}
/******************************************************************************/
// CP437中没有ã(e3)的编码这里暂用a(61)代替
static u8 ucs_to_cp437[128] = {
// 0 1 2 3 4 5 6 7 8 9 a b c d e f
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, // 8
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, // 9
0xff, 0xad, 0x9b, 0x9c, 0xa4, 0x9d, 0xa6, 0xa7, 0xa8, 0xa9, 0xa6, 0xae, 0xaa, 0xad, 0xae, 0xaf, // a
0xf8, 0xf1, 0xfd, 0xb3, 0xb4, 0xb5, 0xb6, 0xfa, 0xb8, 0xb9, 0xa7, 0xaf, 0xac, 0xab, 0xbe, 0xa8, // b
0xc0, 0xc1, 0xc2, 0xc3, 0x8e, 0x8f, 0x92, 0x80, 0xc8, 0x90, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, // c
0xd0, 0xa5, 0xd2, 0xd3, 0xd4, 0xd5, 0x99, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0x9a, 0xdd, 0xde, 0xe1, // d
0x85, 0xa0, 0x83, 0x61, 0x84, 0x86, 0x91, 0x87, 0x8a, 0x82, 0x88, 0x89, 0x8d, 0xa1, 0x8c, 0x8b, // e
0xf0, 0xa4, 0x95, 0xa2, 0x93, 0xf5, 0x94, 0xf6, 0xf8, 0x97, 0xa3, 0x96, 0x81, 0xfd, 0xfe, 0x98, // f
};
static u8 *find_ucs(int ucs)
static u8 *find_ucs(u8 *fdat, int ucs)
{
u8 *hzk14u = (u8*)0x02020000;
u16 total = *(u16*)(hzk14u);
u16 *ucslist = (u16*)0x02020002;
u8 *font_data = hzk14u+2+total*2;
int total = *(u16*)(fdat);
u8 *fi;
int low, high, mp;
@ -154,9 +227,12 @@ static u8 *find_ucs(int ucs)
high = total-1;
while(low<=high){
mp = (low+high)/2;
if(ucs==ucslist[mp]){
return font_data+mp*28;
}else if(ucs>ucslist[mp]){
fi = fdat+2+mp*5;
int code = (fi[0]<<8) | fi[1];
if(ucs==code){
int offset = (fi[2]<<16) | (fi[3]<<8) | fi[4];
return fdat+offset;
}else if(ucs>code){
low = mp+1;
}else{
high = mp-1;
@ -167,46 +243,68 @@ static u8 *find_ucs(int ucs)
}
void conio_put_char(int x, int y, int color, int v)
static u8 *find_font(int ucs)
{
int r, c;
u8 *bmp, *font_data;
unsigned char fg = (color >> 4) & 0x0F;
unsigned char bg = (color >> 0) & 0x0F;
u8 *fdat;
bmp = fbptr+y*llen+x;
if(v>=0x0100){
if(v==0x30fc)
v = 0x2014; // gb2312没有'ー'这个符号用A1AA(U2014)代替。
bmp += llen+1;
font_data = find_ucs(v);
if(font_data==NULL){
font_data = find_ucs(0x25a1);
}
for (r=0; r<14; r++) {
u16 b = *(u16*)(font_data+r*2);
for (c=0; c<14; c++) {
u8 d = (b&(1<<(15-c))) ? fg : bg;
bmp[c] = d;
}
bmp += llen;
}
}else{
if(v>=0x80){
v = ucs_to_cp437[v-0x80];
}
font_data = font_8x16+v*16;
for (r=0; r<16; r++) {
u8 b = font_data[r];
for (c=0; c<8; c++) {
u8 d = (b & (0x80 >> c)) ? fg : bg;
bmp[c] = d;
}
bmp += llen;
fdat = find_ucs(font_latin, ucs);
if(fdat==NULL){
fdat = find_ucs((u8*)font_cjk, ucs);
if(fdat==NULL){
fdat = find_ucs((u8*)font_cjk, 0x25a1);
}
}
return fdat;
}
int fb_draw_font_buf(u8 *bmp, int x, int color, u8 *font_data, int lb, int rb)
{
int r, c, bx;
u8 fg = (color >> 4) & 0x0F;
u8 bg = (color >> 0) & 0x0F;
int ft_adv = font_data[0];
int ft_bw = font_data[1]>>4;
int ft_bh = font_data[1]&0x0f;
int ft_bx = font_data[2]>>4;
int ft_by = font_data[2]&0x0f;
int ft_lsize = (ft_bw>8)? 2: 1;
//printk("%02x: w=%d h=%d x=%d y=%d, adv=%d\n", v, ft_bw, ft_bh, ft_bx, ft_by, ft_adv);
if(x+ft_adv<lb)
return ft_adv;
bx = x + ft_bx;
bmp += ft_by*llen + bx;
for (r=0; r<ft_bh; r++) {
int b, mask;
if(ft_lsize==1){
b = font_data[3+r];
mask = 0x80;
}else{
b = (font_data[3+r*2+0]<<8) | (font_data[3+r*2+1]);
mask = 0x8000;
}
for (c=0; c<ft_bw; c++) {
if((bx+c)>=lb && (bx+c)<=rb){
bmp[c] = (b&mask) ? fg : bg;
}
mask >>= 1;
}
bmp += llen;
}
return ft_adv;
}
int fb_draw_font(int x, int y, int color, u8 *font_data, int lb, int rb)
{
u8 *bmp = fbptr + y*llen;
return fb_draw_font_buf(bmp, x, color, font_data, lb, rb);
}
@ -221,29 +319,31 @@ static int utf8_to_ucs(char **ustr)
*ustr = str+1;
return *str;
}else if(*str<0xe0){
ucs = ((str[0]&0x1f)<<6) | (str[1]&0x3f);
*ustr = str+2;
if(str[1]<0x80){
ucs = '?';
*ustr = str+1;
}else{
ucs = ((str[0]&0x1f)<<6) | (str[1]&0x3f);
*ustr = str+2;
}
return ucs;
}else{
ucs = ((str[0]&0x0f)<<12) | ((str[1]&0x3f)<<6) | (str[2]&0x3f);
*ustr = str+3;
if(str[1]<0x80){
ucs = '?';
*ustr = str+1;
}else if(str[2]<0x80){
ucs = '?';
*ustr = str+2;
}else{
ucs = ((str[0]&0x0f)<<12) | ((str[1]&0x3f)<<6) | (str[2]&0x3f);
*ustr = str+3;
}
return ucs;
}
}
void conio_put_string(int x, int y, int color, char *str)
{
int ch;
while( (ch=utf8_to_ucs(&str)) ){
conio_put_char(x, y, color, ch);
x += (ch>=0x100)? 16 : 8;
}
}
void conio_putc(int ch)
{
if(ch=='\r'){
@ -255,9 +355,9 @@ void conio_putc(int ch)
pos_y = 0;
}
}else{
conio_put_char(pos_x, pos_y, text_color, ch);
pos_x += (ch>=0x100)? 16 : 8;;
u8 *font_data = find_font(ch);
int adv = fb_draw_font(pos_x, pos_y, text_color, font_data, 0, fbw-1);
pos_x += adv;
if(pos_x>=fbw){
pos_x = 0;
pos_y += 16;
@ -334,9 +434,7 @@ void put_hline(int y, int x1, int x2, int c)
}
bmp += y*llen+x1;
for(x=0; x<x2; x++){
bmp[x] = c;
}
memset((u8*)bmp, c, x2);
}
void put_vline(int x, int y1, int y2, int c)
@ -378,6 +476,10 @@ void put_box(int x1, int y1, int x2, int y2, int c)
/******************************************************************************/
#define PAD_REPEAT_TIME 500
#define PAD_REPEAT_RATE 100
static u32 last_pdat = 0;
static u32 last_value;
static u32 curr_pdat = 0;
@ -387,7 +489,9 @@ static int pdat_wait;
u32 conio_getc(void)
{
u32 pdat = pad_read();
int pdat = pad_read();
if(pdat==-1)
return 0;
switch(pdat_state){
case 0:
@ -416,24 +520,19 @@ u32 conio_getc(void)
if(curr_pdat){
// 转入重复状态
pdat_state = 3;
pdat_count = 0;
pdat_wait = 500;
pdat_wait = get_timer() + MS2TICK(PAD_REPEAT_TIME);
}else{
pdat_state = 0;
}
last_value = (pdat<<16) | curr_pdat;
//printk("key0: %08x\n", last_value);
return last_value;
case 3:
// 重复状态
if(pdat != curr_pdat){
pdat_state = 0;
}else{
pdat_count += 1;
if(pdat_count==pdat_wait){
pdat_wait = 30;
pdat_count = 0;
//printk("keyr: %08x\n", last_value);
if(get_timer()>=pdat_wait){
pdat_wait = PAD_REPEAT_RATE;
return last_value;
}
}
@ -448,44 +547,204 @@ u32 conio_getc(void)
/******************************************************************************/
#define MENU_LB 8
#define MENU_RB 311
static void draw_menu_item(int index, char *item, int select)
static int sel_oob;
static int sel_state;
static int sel_cnt;
static int sel_offset;
static u8 *sel_fdat[96];
static u8 *sel_pbuf = (u8*)0x060f8000;
int menu_draw_string(int x, int y, int color, char *str, int lb, int rb)
{
int mx = 16;
int my = 24+index*16;
int color = text_color;
int ch, adv;
if(select){
color = 0x0f;
while( (ch=utf8_to_ucs(&str)) ){
u8 *font_data = find_font(ch);
adv = fb_draw_font(x, y, color, font_data, lb, rb);
x += adv;
if(x>rb)
return 1;
}
put_box(mx, my, mx+36*8-1, my+16-1, (color&0x0f));
conio_put_string(mx, my, color, item);
return 0;
}
void menu_update(MENU_DESC *menu)
static void draw_menu_item(int index, char *item, int select)
{
int y = 24+index*16;
int color = text_color;
if(select){
color = 0x8f;
}
put_box(MENU_LB, y, MENU_RB, y+16-1, (color&0x0f));
menu_draw_string(MENU_LB, y, color, item, MENU_LB, MENU_RB);
}
static int draw_menu_item_select(int index, char *item)
{
int x;
int color = 0x8f;
int i, adv;
//int y = 24+index*16;
//put_box(MENU_LB, y, MENU_RB, y+16-1, (color&0x0f));
memset(sel_pbuf, (color&0x0f), llen*16);
x = MENU_LB-sel_offset;
i = 0;
while(sel_fdat[i]){
adv = (sel_fdat[i])[0];
if(x+adv>=MENU_LB){
fb_draw_font_buf(sel_pbuf, x, color, sel_fdat[i], MENU_LB, MENU_RB);
}
i += 1;
x += adv;
if(x>MENU_RB){
return 1;
}
}
return 0;
}
static void put_select_item(int index)
{
int i, y = 24+index*16;
u8 *dst = fbptr + y*llen + MENU_LB;
u8 *src = sel_pbuf+MENU_LB;
for(i=0; i<16; i++){
#if 0
memcpy(dst, src, (MENU_RB-MENU_LB+1));
#else
//cpu_dmemcpy(dst, src, (MENU_RB-MENU_LB+1), 0);
scu_dmemcpy(dst, src, (MENU_RB-MENU_LB+1), 0);
#endif
dst += llen;
src += llen;
}
}
#define SEL_IDLE_TIME 1000
static int scroll_oob;
static int stimer_end;
void menu_timer(MENU_DESC *menu)
{
if(sel_state==0){
if(sel_oob==0)
return;
int now = get_timer();
stimer_end = now + MS2TICK(SEL_IDLE_TIME);
sel_state = 1;
}else if(sel_state==1){
int now = get_timer();
if(now>=stimer_end){
sel_state = 2;
sel_offset = 0;
}
}else if(sel_state==2){
sel_offset += 1;
int i = menu->current;
scroll_oob = draw_menu_item_select(i, menu->items[i]);
sel_state = 3;
}else if(sel_state==3){
if((TVSTAT&0x0008)==0)
return;
put_select_item(menu->current);
if(scroll_oob==0){
sel_state = 4;
int now = get_timer();
stimer_end = now + MS2TICK(SEL_IDLE_TIME);
}else{
sel_state = 2;
}
}else if(sel_state==4){
int now = get_timer();
if(now>=stimer_end){
sel_state = 5;
}
}else if(sel_state==5){
sel_offset -= 1;
int i = menu->current;
draw_menu_item_select(i, menu->items[i]);
sel_state = 6;
}else if(sel_state==6){
if((TVSTAT&0x0008)==0)
return;
put_select_item(menu->current);
if(sel_offset==0){
sel_state = 0;
}else{
sel_state = 5;
}
}
}
static void sel_init(MENU_DESC *menu)
{
int ch, n, w;
char *str = menu->items[menu->current];
n = 0;
w = 0;
while( (ch=utf8_to_ucs(&str)) ){
sel_fdat[n] = find_font(ch);
w += (sel_fdat[n])[0];
n += 1;
}
sel_fdat[n] = NULL;
sel_oob = (w>(MENU_RB+1-MENU_LB))? 1: 0;
sel_state = 0;
sel_cnt = 0;
sel_offset = 0;
}
void menu_update(MENU_DESC *menu, int new)
{
int i, select;
for(i=0; i<menu->num; i++){
select = (i==menu->current)? 1: 0;
draw_menu_item(i, menu->items[i], select);
if(new>=0){
int old = menu->current;
menu->current = new;
draw_menu_item(old, menu->items[old], 0);
draw_menu_item(new, menu->items[new], 1);
}else{
for(i=0; i<menu->num; i++){
select = (i==menu->current)? 1: 0;
draw_menu_item(i, menu->items[i], select);
}
}
menu_status(menu, NULL);
sel_init(menu);
}
void draw_menu_frame(MENU_DESC *menu)
{
memset(fbptr, 0, fbh*llen);
conio_put_string(32, 4, text_color, menu->title);
menu_draw_string(16, 6, text_color, menu->title, 0, fbw-1);
put_rect(10, 19, 309, 205, 0x0f);
put_rect(13, 22, 306, 202, 0x0f);
put_hline( 22, 0, fbw-1, 0x0f);
put_hline(217, 0, fbw-1, 0x0f);
menu_update(menu);
menu_update(menu, -1);
if(menu->version){
menu_status(menu, menu->version);
}
@ -495,19 +754,19 @@ void draw_menu_frame(MENU_DESC *menu)
void menu_status(MENU_DESC *menu, char *string)
{
int mx = 16;
int my = 224-16;
int my = 240-16-5;
put_box(mx, my, mx+36*8-1, my+16-1, 0);
if(string){
conio_put_string(mx, my, text_color, string);
menu_draw_string(mx, my, text_color, string, 0, fbw-1);
}
}
void add_menu_item(MENU_DESC *menu, char *item)
{
strncpy(menu->items[menu->num], item, 64);
menu->items[menu->num][36] = 0;
strncpy(menu->items[menu->num], item, 96);
menu->items[menu->num][95] = 0;
menu->num += 1;
}
@ -516,14 +775,12 @@ int menu_default(MENU_DESC *menu, int ctrl)
{
if(BUTTON_DOWN(ctrl, PAD_UP)){
if(menu->current>0){
menu->current -= 1;
menu_update(menu);
menu_update(menu, menu->current-1);
}
return 1;
}else if(BUTTON_DOWN(ctrl, PAD_DOWN)){
if(menu->current<(menu->num-1)){
menu->current += 1;
menu_update(menu);
menu_update(menu, menu->current+1);
}
return 1;
}else{
@ -543,8 +800,11 @@ _restart:
#if 1
while(1){
ctrl = conio_getc();
if(ctrl==0)
if(ctrl==0){
menu_timer(menu);
gif_timer();
continue;
}
retv = menu->handle(ctrl);
if(retv==MENU_EXIT)
break;

View file

@ -24,21 +24,21 @@ start:
_func_table:
.long 0x00000000
.long 0x00000004
.long 0x00000008
.long 0x0000000c
.long 0x00000010
.long 0x00000014
.long 0x00000018
.long 0x0000001c
.long 0x00000020
.long 0x00000024
.long 0x00000028
.long 0x0000002c
.long 0x00000030
.long 0x00000034
.long 0x00000038
.long 0x0000003c
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
_next_start:
! Disable interrupts

File diff suppressed because it is too large Load diff

BIN
Firm_Saturn/font_cjk.bin Normal file

Binary file not shown.

876
Firm_Saturn/font_latin.h Normal file
View file

@ -0,0 +1,876 @@
#ifndef __font_latin__
#define __font_latin__
#define font_latin_size 13885
static unsigned char font_latin[] = {
0x02, 0x7d, 0x00, 0x20, 0x00, 0x0c, 0x73, 0x00, 0x21, 0x00, 0x0c, 0x76, 0x00, 0x22, 0x00, 0x0c,
0x84, 0x00, 0x23, 0x00, 0x0c, 0x8a, 0x00, 0x24, 0x00, 0x0c, 0x97, 0x00, 0x25, 0x00, 0x0c, 0xa8,
0x00, 0x26, 0x00, 0x0c, 0xbf, 0x00, 0x27, 0x00, 0x0c, 0xcc, 0x00, 0x28, 0x00, 0x0c, 0xd2, 0x00,
0x29, 0x00, 0x0c, 0xe3, 0x00, 0x2a, 0x00, 0x0c, 0xf4, 0x00, 0x2b, 0x00, 0x0c, 0xfb, 0x00, 0x2c,
0x00, 0x0d, 0x05, 0x00, 0x2d, 0x00, 0x0d, 0x0c, 0x00, 0x2e, 0x00, 0x0d, 0x10, 0x00, 0x2f, 0x00,
0x0d, 0x15, 0x00, 0x30, 0x00, 0x0d, 0x23, 0x00, 0x31, 0x00, 0x0d, 0x30, 0x00, 0x32, 0x00, 0x0d,
0x3d, 0x00, 0x33, 0x00, 0x0d, 0x4a, 0x00, 0x34, 0x00, 0x0d, 0x57, 0x00, 0x35, 0x00, 0x0d, 0x64,
0x00, 0x36, 0x00, 0x0d, 0x71, 0x00, 0x37, 0x00, 0x0d, 0x7e, 0x00, 0x38, 0x00, 0x0d, 0x8b, 0x00,
0x39, 0x00, 0x0d, 0x98, 0x00, 0x3a, 0x00, 0x0d, 0xa5, 0x00, 0x3b, 0x00, 0x0d, 0xb0, 0x00, 0x3c,
0x00, 0x0d, 0xbd, 0x00, 0x3d, 0x00, 0x0d, 0xc5, 0x00, 0x3e, 0x00, 0x0d, 0xcb, 0x00, 0x3f, 0x00,
0x0d, 0xd3, 0x00, 0x40, 0x00, 0x0d, 0xe1, 0x00, 0x41, 0x00, 0x0d, 0xfc, 0x00, 0x42, 0x00, 0x0e,
0x15, 0x00, 0x43, 0x00, 0x0e, 0x23, 0x00, 0x44, 0x00, 0x0e, 0x31, 0x00, 0x45, 0x00, 0x0e, 0x3f,
0x00, 0x46, 0x00, 0x0e, 0x4d, 0x00, 0x47, 0x00, 0x0e, 0x5b, 0x00, 0x48, 0x00, 0x0e, 0x74, 0x00,
0x49, 0x00, 0x0e, 0x82, 0x00, 0x4a, 0x00, 0x0e, 0x90, 0x00, 0x4b, 0x00, 0x0e, 0x9e, 0x00, 0x4c,
0x00, 0x0e, 0xac, 0x00, 0x4d, 0x00, 0x0e, 0xba, 0x00, 0x4e, 0x00, 0x0e, 0xd3, 0x00, 0x4f, 0x00,
0x0e, 0xe1, 0x00, 0x50, 0x00, 0x0e, 0xfa, 0x00, 0x51, 0x00, 0x0f, 0x08, 0x00, 0x52, 0x00, 0x0f,
0x21, 0x00, 0x53, 0x00, 0x0f, 0x2f, 0x00, 0x54, 0x00, 0x0f, 0x3d, 0x00, 0x55, 0x00, 0x0f, 0x56,
0x00, 0x56, 0x00, 0x0f, 0x64, 0x00, 0x57, 0x00, 0x0f, 0x7d, 0x00, 0x58, 0x00, 0x0f, 0x96, 0x00,
0x59, 0x00, 0x0f, 0xa4, 0x00, 0x5a, 0x00, 0x0f, 0xbd, 0x00, 0x5b, 0x00, 0x0f, 0xcb, 0x00, 0x5c,
0x00, 0x0f, 0xdc, 0x00, 0x5d, 0x00, 0x0f, 0xea, 0x00, 0x5e, 0x00, 0x0f, 0xfb, 0x00, 0x5f, 0x00,
0x10, 0x02, 0x00, 0x60, 0x00, 0x10, 0x06, 0x00, 0x61, 0x00, 0x10, 0x0b, 0x00, 0x62, 0x00, 0x10,
0x16, 0x00, 0x63, 0x00, 0x10, 0x24, 0x00, 0x64, 0x00, 0x10, 0x2f, 0x00, 0x65, 0x00, 0x10, 0x3d,
0x00, 0x66, 0x00, 0x10, 0x48, 0x00, 0x67, 0x00, 0x10, 0x56, 0x00, 0x68, 0x00, 0x10, 0x64, 0x00,
0x69, 0x00, 0x10, 0x72, 0x00, 0x6a, 0x00, 0x10, 0x80, 0x00, 0x6b, 0x00, 0x10, 0x91, 0x00, 0x6c,
0x00, 0x10, 0x9f, 0x00, 0x6d, 0x00, 0x10, 0xad, 0x00, 0x6e, 0x00, 0x10, 0xc0, 0x00, 0x6f, 0x00,
0x10, 0xcb, 0x00, 0x70, 0x00, 0x10, 0xd6, 0x00, 0x71, 0x00, 0x10, 0xe4, 0x00, 0x72, 0x00, 0x10,
0xf2, 0x00, 0x73, 0x00, 0x10, 0xfd, 0x00, 0x74, 0x00, 0x11, 0x08, 0x00, 0x75, 0x00, 0x11, 0x15,
0x00, 0x76, 0x00, 0x11, 0x20, 0x00, 0x77, 0x00, 0x11, 0x2b, 0x00, 0x78, 0x00, 0x11, 0x3e, 0x00,
0x79, 0x00, 0x11, 0x49, 0x00, 0x7a, 0x00, 0x11, 0x57, 0x00, 0x7b, 0x00, 0x11, 0x62, 0x00, 0x7c,
0x00, 0x11, 0x73, 0x00, 0x7d, 0x00, 0x11, 0x84, 0x00, 0x7e, 0x00, 0x11, 0x95, 0x00, 0xa0, 0x00,
0x11, 0x9b, 0x00, 0xa1, 0x00, 0x11, 0x9e, 0x00, 0xa2, 0x00, 0x11, 0xac, 0x00, 0xa3, 0x00, 0x11,
0xb9, 0x00, 0xa4, 0x00, 0x11, 0xc6, 0x00, 0xa5, 0x00, 0x11, 0xcf, 0x00, 0xa6, 0x00, 0x11, 0xdc,
0x00, 0xa7, 0x00, 0x11, 0xec, 0x00, 0xa8, 0x00, 0x11, 0xfd, 0x00, 0xa9, 0x00, 0x12, 0x01, 0x00,
0xaa, 0x00, 0x12, 0x18, 0x00, 0xab, 0x00, 0x12, 0x22, 0x00, 0xac, 0x00, 0x12, 0x2a, 0x00, 0xad,
0x00, 0x12, 0x31, 0x00, 0xae, 0x00, 0x12, 0x35, 0x00, 0xaf, 0x00, 0x12, 0x4c, 0x00, 0xb0, 0x00,
0x12, 0x50, 0x00, 0xb1, 0x00, 0x12, 0x57, 0x00, 0xb2, 0x00, 0x12, 0x63, 0x00, 0xb3, 0x00, 0x12,
0x6c, 0x00, 0xb4, 0x00, 0x12, 0x75, 0x00, 0xb5, 0x00, 0x12, 0x7a, 0x00, 0xb6, 0x00, 0x12, 0x88,
0x00, 0xb7, 0x00, 0x12, 0x99, 0x00, 0xb8, 0x00, 0x12, 0x9d, 0x00, 0xb9, 0x00, 0x12, 0xa3, 0x00,
0xba, 0x00, 0x12, 0xac, 0x00, 0xbb, 0x00, 0x12, 0xb6, 0x00, 0xbc, 0x00, 0x12, 0xbe, 0x00, 0xbd,
0x00, 0x12, 0xd7, 0x00, 0xbe, 0x00, 0x12, 0xf0, 0x00, 0xbf, 0x00, 0x13, 0x09, 0x00, 0xc0, 0x00,
0x13, 0x17, 0x00, 0xc1, 0x00, 0x13, 0x36, 0x00, 0xc2, 0x00, 0x13, 0x55, 0x00, 0xc3, 0x00, 0x13,
0x74, 0x00, 0xc4, 0x00, 0x13, 0x93, 0x00, 0xc5, 0x00, 0x13, 0xb0, 0x00, 0xc6, 0x00, 0x13, 0xcf,
0x00, 0xc7, 0x00, 0x13, 0xe8, 0x00, 0xc8, 0x00, 0x13, 0xf9, 0x00, 0xc9, 0x00, 0x14, 0x0a, 0x00,
0xca, 0x00, 0x14, 0x1b, 0x00, 0xcb, 0x00, 0x14, 0x2c, 0x00, 0xcc, 0x00, 0x14, 0x3c, 0x00, 0xcd,
0x00, 0x14, 0x4d, 0x00, 0xce, 0x00, 0x14, 0x5e, 0x00, 0xcf, 0x00, 0x14, 0x6f, 0x00, 0xd0, 0x00,
0x14, 0x7f, 0x00, 0xd1, 0x00, 0x14, 0x98, 0x00, 0xd2, 0x00, 0x14, 0xa9, 0x00, 0xd3, 0x00, 0x14,
0xc8, 0x00, 0xd4, 0x00, 0x14, 0xe7, 0x00, 0xd5, 0x00, 0x15, 0x06, 0x00, 0xd6, 0x00, 0x15, 0x25,
0x00, 0xd7, 0x00, 0x15, 0x42, 0x00, 0xd8, 0x00, 0x15, 0x4c, 0x00, 0xd9, 0x00, 0x15, 0x65, 0x00,
0xda, 0x00, 0x15, 0x76, 0x00, 0xdb, 0x00, 0x15, 0x87, 0x00, 0xdc, 0x00, 0x15, 0x98, 0x00, 0xdd,
0x00, 0x15, 0xa8, 0x00, 0xde, 0x00, 0x15, 0xc7, 0x00, 0xdf, 0x00, 0x15, 0xd5, 0x00, 0xe0, 0x00,
0x15, 0xe3, 0x00, 0xe1, 0x00, 0x15, 0xf1, 0x00, 0xe2, 0x00, 0x15, 0xff, 0x00, 0xe3, 0x00, 0x16,
0x0d, 0x00, 0xe4, 0x00, 0x16, 0x1b, 0x00, 0xe5, 0x00, 0x16, 0x28, 0x00, 0xe6, 0x00, 0x16, 0x37,
0x00, 0xe7, 0x00, 0x16, 0x4a, 0x00, 0xe8, 0x00, 0x16, 0x58, 0x00, 0xe9, 0x00, 0x16, 0x66, 0x00,
0xea, 0x00, 0x16, 0x74, 0x00, 0xeb, 0x00, 0x16, 0x82, 0x00, 0xec, 0x00, 0x16, 0x8f, 0x00, 0xed,
0x00, 0x16, 0x9d, 0x00, 0xee, 0x00, 0x16, 0xab, 0x00, 0xef, 0x00, 0x16, 0xb9, 0x00, 0xf0, 0x00,
0x16, 0xc6, 0x00, 0xf1, 0x00, 0x16, 0xd4, 0x00, 0xf2, 0x00, 0x16, 0xe2, 0x00, 0xf3, 0x00, 0x16,
0xf0, 0x00, 0xf4, 0x00, 0x16, 0xfe, 0x00, 0xf5, 0x00, 0x17, 0x0c, 0x00, 0xf6, 0x00, 0x17, 0x1a,
0x00, 0xf7, 0x00, 0x17, 0x27, 0x00, 0xf8, 0x00, 0x17, 0x31, 0x00, 0xf9, 0x00, 0x17, 0x3c, 0x00,
0xfa, 0x00, 0x17, 0x4a, 0x00, 0xfb, 0x00, 0x17, 0x58, 0x00, 0xfc, 0x00, 0x17, 0x66, 0x00, 0xfd,
0x00, 0x17, 0x73, 0x00, 0xfe, 0x00, 0x17, 0x84, 0x00, 0xff, 0x00, 0x17, 0x95, 0x01, 0x00, 0x00,
0x17, 0xa5, 0x01, 0x01, 0x00, 0x17, 0xc0, 0x01, 0x02, 0x00, 0x17, 0xcc, 0x01, 0x03, 0x00, 0x17,
0xeb, 0x01, 0x04, 0x00, 0x17, 0xf9, 0x01, 0x05, 0x00, 0x18, 0x16, 0x01, 0x06, 0x00, 0x18, 0x23,
0x01, 0x07, 0x00, 0x18, 0x34, 0x01, 0x08, 0x00, 0x18, 0x42, 0x01, 0x09, 0x00, 0x18, 0x53, 0x01,
0x0a, 0x00, 0x18, 0x61, 0x01, 0x0b, 0x00, 0x18, 0x71, 0x01, 0x0c, 0x00, 0x18, 0x7e, 0x01, 0x0d,
0x00, 0x18, 0x8f, 0x01, 0x0e, 0x00, 0x18, 0x9d, 0x01, 0x0f, 0x00, 0x18, 0xbc, 0x01, 0x10, 0x00,
0x18, 0xd3, 0x01, 0x11, 0x00, 0x18, 0xea, 0x01, 0x12, 0x00, 0x18, 0xf7, 0x01, 0x13, 0x00, 0x19,
0x06, 0x01, 0x14, 0x00, 0x19, 0x12, 0x01, 0x15, 0x00, 0x19, 0x23, 0x01, 0x16, 0x00, 0x19, 0x31,
0x01, 0x17, 0x00, 0x19, 0x41, 0x01, 0x18, 0x00, 0x19, 0x4e, 0x01, 0x19, 0x00, 0x19, 0x5e, 0x01,
0x1a, 0x00, 0x19, 0x6b, 0x01, 0x1b, 0x00, 0x19, 0x7c, 0x01, 0x1c, 0x00, 0x19, 0x8a, 0x01, 0x1d,
0x00, 0x19, 0xa9, 0x01, 0x1e, 0x00, 0x19, 0xba, 0x01, 0x1f, 0x00, 0x19, 0xd9, 0x01, 0x20, 0x00,
0x19, 0xea, 0x01, 0x21, 0x00, 0x1a, 0x07, 0x01, 0x22, 0x00, 0x1a, 0x17, 0x01, 0x23, 0x00, 0x1a,
0x38, 0x01, 0x24, 0x00, 0x1a, 0x49, 0x01, 0x25, 0x00, 0x1a, 0x5a, 0x01, 0x26, 0x00, 0x1a, 0x6b,
0x01, 0x27, 0x00, 0x1a, 0x78, 0x01, 0x28, 0x00, 0x1a, 0x85, 0x01, 0x29, 0x00, 0x1a, 0x95, 0x01,
0x2a, 0x00, 0x1a, 0xa2, 0x01, 0x2b, 0x00, 0x1a, 0xb1, 0x01, 0x2c, 0x00, 0x1a, 0xbd, 0x01, 0x2d,
0x00, 0x1a, 0xce, 0x01, 0x2e, 0x00, 0x1a, 0xdc, 0x01, 0x2f, 0x00, 0x1a, 0xec, 0x01, 0x30, 0x00,
0x1a, 0xfc, 0x01, 0x31, 0x00, 0x1b, 0x0c, 0x01, 0x32, 0x00, 0x1b, 0x16, 0x01, 0x33, 0x00, 0x1b,
0x2d, 0x01, 0x34, 0x00, 0x1b, 0x3d, 0x01, 0x35, 0x00, 0x1b, 0x4e, 0x01, 0x36, 0x00, 0x1b, 0x5f,
0x01, 0x37, 0x00, 0x1b, 0x71, 0x01, 0x38, 0x00, 0x1b, 0x83, 0x01, 0x39, 0x00, 0x1b, 0x8d, 0x01,
0x3a, 0x00, 0x1b, 0x9e, 0x01, 0x3b, 0x00, 0x1b, 0xaf, 0x01, 0x3c, 0x00, 0x1b, 0xc1, 0x01, 0x3d,
0x00, 0x1b, 0xd3, 0x01, 0x3e, 0x00, 0x1b, 0xea, 0x01, 0x3f, 0x00, 0x1b, 0xf7, 0x01, 0x40, 0x00,
0x1c, 0x0e, 0x01, 0x41, 0x00, 0x1c, 0x1b, 0x01, 0x42, 0x00, 0x1c, 0x28, 0x01, 0x43, 0x00, 0x1c,
0x35, 0x01, 0x44, 0x00, 0x1c, 0x54, 0x01, 0x45, 0x00, 0x1c, 0x62, 0x01, 0x46, 0x00, 0x1c, 0x83,
0x01, 0x47, 0x00, 0x1c, 0x92, 0x01, 0x48, 0x00, 0x1c, 0xb1, 0x01, 0x49, 0x00, 0x1c, 0xbf, 0x01,
0x4a, 0x00, 0x1c, 0xd6, 0x01, 0x4b, 0x00, 0x1c, 0xf3, 0x01, 0x4c, 0x00, 0x1d, 0x00, 0x01, 0x4d,
0x00, 0x1d, 0x0f, 0x01, 0x4e, 0x00, 0x1d, 0x1b, 0x01, 0x4f, 0x00, 0x1d, 0x2c, 0x01, 0x50, 0x00,
0x1d, 0x3a, 0x01, 0x51, 0x00, 0x1d, 0x4b, 0x01, 0x52, 0x00, 0x1d, 0x59, 0x01, 0x53, 0x00, 0x1d,
0x70, 0x01, 0x54, 0x00, 0x1d, 0x81, 0x01, 0x55, 0x00, 0x1d, 0xa0, 0x01, 0x56, 0x00, 0x1d, 0xae,
0x01, 0x57, 0x00, 0x1d, 0xcf, 0x01, 0x58, 0x00, 0x1d, 0xde, 0x01, 0x59, 0x00, 0x1d, 0xfd, 0x01,
0x5a, 0x00, 0x1e, 0x0b, 0x01, 0x5b, 0x00, 0x1e, 0x1c, 0x01, 0x5c, 0x00, 0x1e, 0x2a, 0x01, 0x5d,
0x00, 0x1e, 0x3b, 0x01, 0x5e, 0x00, 0x1e, 0x49, 0x01, 0x5f, 0x00, 0x1e, 0x59, 0x01, 0x60, 0x00,
0x1e, 0x66, 0x01, 0x61, 0x00, 0x1e, 0x77, 0x01, 0x62, 0x00, 0x1e, 0x85, 0x01, 0x63, 0x00, 0x1e,
0x95, 0x01, 0x64, 0x00, 0x1e, 0xa4, 0x01, 0x65, 0x00, 0x1e, 0xb5, 0x01, 0x66, 0x00, 0x1e, 0xc2,
0x01, 0x67, 0x00, 0x1e, 0xcf, 0x01, 0x68, 0x00, 0x1e, 0xdb, 0x01, 0x69, 0x00, 0x1e, 0xeb, 0x01,
0x6a, 0x00, 0x1e, 0xf8, 0x01, 0x6b, 0x00, 0x1f, 0x07, 0x01, 0x6c, 0x00, 0x1f, 0x13, 0x01, 0x6d,
0x00, 0x1f, 0x24, 0x01, 0x6e, 0x00, 0x1f, 0x32, 0x01, 0x6f, 0x00, 0x1f, 0x43, 0x01, 0x70, 0x00,
0x1f, 0x51, 0x01, 0x71, 0x00, 0x1f, 0x62, 0x01, 0x72, 0x00, 0x1f, 0x70, 0x01, 0x73, 0x00, 0x1f,
0x80, 0x01, 0x74, 0x00, 0x1f, 0x8d, 0x01, 0x75, 0x00, 0x1f, 0xac, 0x01, 0x76, 0x00, 0x1f, 0xc5,
0x01, 0x77, 0x00, 0x1f, 0xe4, 0x01, 0x78, 0x00, 0x1f, 0xf5, 0x01, 0x79, 0x00, 0x20, 0x12, 0x01,
0x7a, 0x00, 0x20, 0x23, 0x01, 0x7b, 0x00, 0x20, 0x31, 0x01, 0x7c, 0x00, 0x20, 0x41, 0x01, 0x7d,
0x00, 0x20, 0x4e, 0x01, 0x7e, 0x00, 0x20, 0x5f, 0x02, 0x1a, 0x00, 0x20, 0x6d, 0x02, 0x1b, 0x00,
0x20, 0x7f, 0x03, 0x74, 0x00, 0x20, 0x90, 0x03, 0x75, 0x00, 0x20, 0x96, 0x03, 0x7e, 0x00, 0x20,
0x9c, 0x03, 0x84, 0x00, 0x20, 0xa8, 0x03, 0x85, 0x00, 0x20, 0xae, 0x03, 0x86, 0x00, 0x20, 0xb7,
0x03, 0x87, 0x00, 0x20, 0xce, 0x03, 0x88, 0x00, 0x20, 0xd3, 0x03, 0x89, 0x00, 0x20, 0xea, 0x03,
0x8a, 0x00, 0x21, 0x01, 0x03, 0x8c, 0x00, 0x21, 0x0e, 0x03, 0x8e, 0x00, 0x21, 0x25, 0x03, 0x8f,
0x00, 0x21, 0x3c, 0x03, 0x90, 0x00, 0x21, 0x53, 0x03, 0x91, 0x00, 0x21, 0x64, 0x03, 0x92, 0x00,
0x21, 0x7b, 0x03, 0x93, 0x00, 0x21, 0x88, 0x03, 0x94, 0x00, 0x21, 0x95, 0x03, 0x95, 0x00, 0x21,
0xa2, 0x03, 0x96, 0x00, 0x21, 0xaf, 0x03, 0x97, 0x00, 0x21, 0xbc, 0x03, 0x98, 0x00, 0x21, 0xd3,
0x03, 0x99, 0x00, 0x21, 0xe0, 0x03, 0x9a, 0x00, 0x21, 0xed, 0x03, 0x9b, 0x00, 0x21, 0xfa, 0x03,
0x9c, 0x00, 0x22, 0x11, 0x03, 0x9d, 0x00, 0x22, 0x28, 0x03, 0x9e, 0x00, 0x22, 0x3f, 0x03, 0x9f,
0x00, 0x22, 0x56, 0x03, 0xa0, 0x00, 0x22, 0x63, 0x03, 0xa1, 0x00, 0x22, 0x7a, 0x03, 0xa3, 0x00,
0x22, 0x87, 0x03, 0xa4, 0x00, 0x22, 0x94, 0x03, 0xa5, 0x00, 0x22, 0xa1, 0x03, 0xa6, 0x00, 0x22,
0xb8, 0x03, 0xa7, 0x00, 0x22, 0xcf, 0x03, 0xa8, 0x00, 0x22, 0xe6, 0x03, 0xa9, 0x00, 0x22, 0xfd,
0x03, 0xaa, 0x00, 0x23, 0x14, 0x03, 0xab, 0x00, 0x23, 0x24, 0x03, 0xac, 0x00, 0x23, 0x41, 0x03,
0xad, 0x00, 0x23, 0x4f, 0x03, 0xae, 0x00, 0x23, 0x5d, 0x03, 0xaf, 0x00, 0x23, 0x6e, 0x03, 0xb0,
0x00, 0x23, 0x7c, 0x03, 0xb1, 0x00, 0x23, 0x8d, 0x03, 0xb2, 0x00, 0x23, 0x97, 0x03, 0xb3, 0x00,
0x23, 0xa8, 0x03, 0xb4, 0x00, 0x23, 0xb5, 0x03, 0xb5, 0x00, 0x23, 0xc3, 0x03, 0xb6, 0x00, 0x23,
0xcd, 0x03, 0xb7, 0x00, 0x23, 0xde, 0x03, 0xb8, 0x00, 0x23, 0xeb, 0x03, 0xb9, 0x00, 0x23, 0xf8,
0x03, 0xba, 0x00, 0x24, 0x02, 0x03, 0xbb, 0x00, 0x24, 0x0c, 0x03, 0xbc, 0x00, 0x24, 0x19, 0x03,
0xbd, 0x00, 0x24, 0x26, 0x03, 0xbe, 0x00, 0x24, 0x30, 0x03, 0xbf, 0x00, 0x24, 0x42, 0x03, 0xc0,
0x00, 0x24, 0x4c, 0x03, 0xc1, 0x00, 0x24, 0x56, 0x03, 0xc2, 0x00, 0x24, 0x63, 0x03, 0xc3, 0x00,
0x24, 0x70, 0x03, 0xc4, 0x00, 0x24, 0x7a, 0x03, 0xc5, 0x00, 0x24, 0x84, 0x03, 0xc6, 0x00, 0x24,
0x8e, 0x03, 0xc7, 0x00, 0x24, 0x9b, 0x03, 0xc8, 0x00, 0x24, 0xa8, 0x03, 0xc9, 0x00, 0x24, 0xbf,
0x03, 0xca, 0x00, 0x24, 0xd0, 0x03, 0xcb, 0x00, 0x24, 0xdd, 0x03, 0xcc, 0x00, 0x24, 0xea, 0x03,
0xcd, 0x00, 0x24, 0xf8, 0x03, 0xce, 0x00, 0x25, 0x06, 0x03, 0xd1, 0x00, 0x25, 0x1f, 0x03, 0xd2,
0x00, 0x25, 0x2c, 0x03, 0xd3, 0x00, 0x25, 0x39, 0x03, 0xd4, 0x00, 0x25, 0x4a, 0x03, 0xd5, 0x00,
0x25, 0x5a, 0x03, 0xd6, 0x00, 0x25, 0x6a, 0x04, 0x00, 0x00, 0x25, 0x7d, 0x04, 0x01, 0x00, 0x25,
0x8e, 0x04, 0x02, 0x00, 0x25, 0x9e, 0x04, 0x03, 0x00, 0x25, 0xb7, 0x04, 0x04, 0x00, 0x25, 0xc8,
0x04, 0x05, 0x00, 0x25, 0xd6, 0x04, 0x06, 0x00, 0x25, 0xe4, 0x04, 0x07, 0x00, 0x25, 0xf2, 0x04,
0x08, 0x00, 0x26, 0x02, 0x04, 0x09, 0x00, 0x26, 0x10, 0x04, 0x0a, 0x00, 0x26, 0x29, 0x04, 0x0b,
0x00, 0x26, 0x42, 0x04, 0x0c, 0x00, 0x26, 0x5b, 0x04, 0x0d, 0x00, 0x26, 0x6c, 0x04, 0x0e, 0x00,
0x26, 0x7d, 0x04, 0x0f, 0x00, 0x26, 0x9c, 0x04, 0x10, 0x00, 0x26, 0xac, 0x04, 0x11, 0x00, 0x26,
0xc5, 0x04, 0x12, 0x00, 0x26, 0xd3, 0x04, 0x13, 0x00, 0x26, 0xe1, 0x04, 0x14, 0x00, 0x26, 0xef,
0x04, 0x15, 0x00, 0x27, 0x0c, 0x04, 0x16, 0x00, 0x27, 0x1a, 0x04, 0x17, 0x00, 0x27, 0x33, 0x04,
0x18, 0x00, 0x27, 0x41, 0x04, 0x19, 0x00, 0x27, 0x4f, 0x04, 0x1a, 0x00, 0x27, 0x60, 0x04, 0x1b,
0x00, 0x27, 0x6e, 0x04, 0x1c, 0x00, 0x27, 0x87, 0x04, 0x1d, 0x00, 0x27, 0xa0, 0x04, 0x1e, 0x00,
0x27, 0xae, 0x04, 0x1f, 0x00, 0x27, 0xc7, 0x04, 0x20, 0x00, 0x27, 0xd5, 0x04, 0x21, 0x00, 0x27,
0xe3, 0x04, 0x22, 0x00, 0x27, 0xf1, 0x04, 0x23, 0x00, 0x28, 0x0a, 0x04, 0x24, 0x00, 0x28, 0x23,
0x04, 0x25, 0x00, 0x28, 0x3c, 0x04, 0x26, 0x00, 0x28, 0x4a, 0x04, 0x27, 0x00, 0x28, 0x67, 0x04,
0x28, 0x00, 0x28, 0x75, 0x04, 0x29, 0x00, 0x28, 0x8e, 0x04, 0x2a, 0x00, 0x28, 0xab, 0x04, 0x2b,
0x00, 0x28, 0xc4, 0x04, 0x2c, 0x00, 0x28, 0xdd, 0x04, 0x2d, 0x00, 0x28, 0xeb, 0x04, 0x2e, 0x00,
0x28, 0xf9, 0x04, 0x2f, 0x00, 0x29, 0x12, 0x04, 0x30, 0x00, 0x29, 0x20, 0x04, 0x31, 0x00, 0x29,
0x2b, 0x04, 0x32, 0x00, 0x29, 0x3a, 0x04, 0x33, 0x00, 0x29, 0x45, 0x04, 0x34, 0x00, 0x29, 0x50,
0x04, 0x35, 0x00, 0x29, 0x5d, 0x04, 0x36, 0x00, 0x29, 0x68, 0x04, 0x37, 0x00, 0x29, 0x7b, 0x04,
0x38, 0x00, 0x29, 0x86, 0x04, 0x39, 0x00, 0x29, 0x91, 0x04, 0x3a, 0x00, 0x29, 0x9f, 0x04, 0x3b,
0x00, 0x29, 0xaa, 0x04, 0x3c, 0x00, 0x29, 0xb5, 0x04, 0x3d, 0x00, 0x29, 0xc8, 0x04, 0x3e, 0x00,
0x29, 0xd3, 0x04, 0x3f, 0x00, 0x29, 0xde, 0x04, 0x40, 0x00, 0x29, 0xe9, 0x04, 0x41, 0x00, 0x29,
0xf7, 0x04, 0x42, 0x00, 0x2a, 0x02, 0x04, 0x43, 0x00, 0x2a, 0x0d, 0x04, 0x44, 0x00, 0x2a, 0x1b,
0x04, 0x45, 0x00, 0x2a, 0x3a, 0x04, 0x46, 0x00, 0x2a, 0x45, 0x04, 0x47, 0x00, 0x2a, 0x52, 0x04,
0x48, 0x00, 0x2a, 0x5d, 0x04, 0x49, 0x00, 0x2a, 0x70, 0x04, 0x4a, 0x00, 0x2a, 0x87, 0x04, 0x4b,
0x00, 0x2a, 0x92, 0x04, 0x4c, 0x00, 0x2a, 0xa5, 0x04, 0x4d, 0x00, 0x2a, 0xb0, 0x04, 0x4e, 0x00,
0x2a, 0xbb, 0x04, 0x4f, 0x00, 0x2a, 0xce, 0x04, 0x50, 0x00, 0x2a, 0xd9, 0x04, 0x51, 0x00, 0x2a,
0xe7, 0x04, 0x52, 0x00, 0x2a, 0xf4, 0x04, 0x53, 0x00, 0x2b, 0x05, 0x04, 0x54, 0x00, 0x2b, 0x13,
0x04, 0x55, 0x00, 0x2b, 0x1e, 0x04, 0x56, 0x00, 0x2b, 0x29, 0x04, 0x57, 0x00, 0x2b, 0x37, 0x04,
0x58, 0x00, 0x2b, 0x44, 0x04, 0x59, 0x00, 0x2b, 0x55, 0x04, 0x5a, 0x00, 0x2b, 0x68, 0x04, 0x5b,
0x00, 0x2b, 0x7b, 0x04, 0x5c, 0x00, 0x2b, 0x89, 0x04, 0x5d, 0x00, 0x2b, 0x97, 0x04, 0x5e, 0x00,
0x2b, 0xa5, 0x04, 0x5f, 0x00, 0x2b, 0xb6, 0x04, 0x60, 0x00, 0x2b, 0xc3, 0x04, 0x61, 0x00, 0x2b,
0xdc, 0x04, 0x62, 0x00, 0x2b, 0xef, 0x04, 0x63, 0x00, 0x2c, 0x08, 0x04, 0x64, 0x00, 0x2c, 0x16,
0x04, 0x65, 0x00, 0x2c, 0x2f, 0x04, 0x66, 0x00, 0x2c, 0x42, 0x04, 0x67, 0x00, 0x2c, 0x5b, 0x04,
0x68, 0x00, 0x2c, 0x6e, 0x04, 0x69, 0x00, 0x2c, 0x87, 0x04, 0x6a, 0x00, 0x2c, 0x9a, 0x04, 0x6b,
0x00, 0x2c, 0xb3, 0x04, 0x6c, 0x00, 0x2c, 0xc6, 0x04, 0x6d, 0x00, 0x2c, 0xdf, 0x04, 0x6e, 0x00,
0x2c, 0xf2, 0x04, 0x6f, 0x00, 0x2d, 0x06, 0x04, 0x70, 0x00, 0x2d, 0x17, 0x04, 0x71, 0x00, 0x2d,
0x30, 0x04, 0x72, 0x00, 0x2d, 0x49, 0x04, 0x73, 0x00, 0x2d, 0x62, 0x04, 0x74, 0x00, 0x2d, 0x6d,
0x04, 0x75, 0x00, 0x2d, 0x86, 0x04, 0x76, 0x00, 0x2d, 0x91, 0x04, 0x77, 0x00, 0x2d, 0xb0, 0x04,
0x78, 0x00, 0x2d, 0xbe, 0x04, 0x79, 0x00, 0x2d, 0xdd, 0x04, 0x7a, 0x00, 0x2d, 0xf6, 0x04, 0x7b,
0x00, 0x2e, 0x13, 0x04, 0x7c, 0x00, 0x2e, 0x20, 0x04, 0x7d, 0x00, 0x2e, 0x3f, 0x04, 0x7e, 0x00,
0x2e, 0x5a, 0x04, 0x7f, 0x00, 0x2e, 0x79, 0x04, 0x80, 0x00, 0x2e, 0x92, 0x04, 0x81, 0x00, 0x2e,
0xa2, 0x04, 0x82, 0x00, 0x2e, 0xaf, 0x04, 0x83, 0x00, 0x2e, 0xbc, 0x04, 0x84, 0x00, 0x2e, 0xc2,
0x04, 0x85, 0x00, 0x2e, 0xc8, 0x04, 0x86, 0x00, 0x2e, 0xce, 0x04, 0x8c, 0x00, 0x2e, 0xd4, 0x04,
0x8d, 0x00, 0x2e, 0xe3, 0x04, 0x8e, 0x00, 0x2e, 0xef, 0x04, 0x8f, 0x00, 0x2e, 0xfd, 0x04, 0x90,
0x00, 0x2f, 0x0b, 0x04, 0x91, 0x00, 0x2f, 0x1b, 0x04, 0x92, 0x00, 0x2f, 0x28, 0x04, 0x93, 0x00,
0x2f, 0x36, 0x04, 0x94, 0x00, 0x2f, 0x41, 0x04, 0x95, 0x00, 0x2f, 0x52, 0x04, 0x96, 0x00, 0x2f,
0x60, 0x04, 0x97, 0x00, 0x2f, 0x7d, 0x04, 0x98, 0x00, 0x2f, 0x94, 0x04, 0x99, 0x00, 0x2f, 0xa5,
0x04, 0x9a, 0x00, 0x2f, 0xb3, 0x04, 0x9b, 0x00, 0x2f, 0xd0, 0x04, 0x9c, 0x00, 0x2f, 0xdd, 0x04,
0x9d, 0x00, 0x2f, 0xeb, 0x04, 0x9e, 0x00, 0x2f, 0xf6, 0x04, 0x9f, 0x00, 0x30, 0x0f, 0x04, 0xa0,
0x00, 0x30, 0x1d, 0x04, 0xa1, 0x00, 0x30, 0x36, 0x04, 0xa2, 0x00, 0x30, 0x41, 0x04, 0xa3, 0x00,
0x30, 0x5e, 0x04, 0xa4, 0x00, 0x30, 0x6b, 0x04, 0xa5, 0x00, 0x30, 0x84, 0x04, 0xa6, 0x00, 0x30,
0x97, 0x04, 0xa7, 0x00, 0x30, 0xb6, 0x04, 0xa8, 0x00, 0x30, 0xcf, 0x04, 0xa9, 0x00, 0x30, 0xe8,
0x04, 0xaa, 0x00, 0x30, 0xf3, 0x04, 0xab, 0x00, 0x31, 0x04, 0x04, 0xac, 0x00, 0x31, 0x12, 0x04,
0xad, 0x00, 0x31, 0x2f, 0x04, 0xae, 0x00, 0x31, 0x3c, 0x04, 0xaf, 0x00, 0x31, 0x55, 0x04, 0xb0,
0x00, 0x31, 0x63, 0x04, 0xb1, 0x00, 0x31, 0x7c, 0x04, 0xb2, 0x00, 0x31, 0x8a, 0x04, 0xb3, 0x00,
0x31, 0xa7, 0x04, 0xb4, 0x00, 0x31, 0xb4, 0x04, 0xb5, 0x00, 0x31, 0xd1, 0x04, 0xb6, 0x00, 0x31,
0xe8, 0x04, 0xb7, 0x00, 0x32, 0x05, 0x04, 0xb8, 0x00, 0x32, 0x12, 0x04, 0xb9, 0x00, 0x32, 0x20,
0x04, 0xba, 0x00, 0x32, 0x2b, 0x04, 0xbb, 0x00, 0x32, 0x39, 0x04, 0xbc, 0x00, 0x32, 0x44, 0x04,
0xbd, 0x00, 0x32, 0x5d, 0x04, 0xbe, 0x00, 0x32, 0x68, 0x04, 0xbf, 0x00, 0x32, 0x87, 0x04, 0xc0,
0x00, 0x32, 0x95, 0x04, 0xc1, 0x00, 0x32, 0xa3, 0x04, 0xc2, 0x00, 0x32, 0xc2, 0x04, 0xc3, 0x00,
0x32, 0xdb, 0x04, 0xc4, 0x00, 0x32, 0xec, 0x04, 0xc7, 0x00, 0x32, 0xfa, 0x04, 0xc8, 0x00, 0x33,
0x0b, 0x04, 0xcb, 0x00, 0x33, 0x19, 0x04, 0xcc, 0x00, 0x33, 0x29, 0x04, 0xd0, 0x00, 0x33, 0x36,
0x04, 0xd1, 0x00, 0x33, 0x55, 0x04, 0xd2, 0x00, 0x33, 0x63, 0x04, 0xd3, 0x00, 0x33, 0x80, 0x04,
0xd4, 0x00, 0x33, 0x8d, 0x04, 0xd5, 0x00, 0x33, 0xa6, 0x04, 0xd6, 0x00, 0x33, 0xb9, 0x04, 0xd7,
0x00, 0x33, 0xca, 0x04, 0xd8, 0x00, 0x33, 0xd8, 0x04, 0xd9, 0x00, 0x33, 0xf1, 0x04, 0xda, 0x00,
0x33, 0xfc, 0x04, 0xdb, 0x00, 0x34, 0x19, 0x04, 0xdc, 0x00, 0x34, 0x26, 0x04, 0xdd, 0x00, 0x34,
0x43, 0x04, 0xde, 0x00, 0x34, 0x5a, 0x04, 0xdf, 0x00, 0x34, 0x6a, 0x04, 0xe0, 0x00, 0x34, 0x77,
0x04, 0xe1, 0x00, 0x34, 0x85, 0x04, 0xe2, 0x00, 0x34, 0x93, 0x04, 0xe3, 0x00, 0x34, 0xa3, 0x04,
0xe4, 0x00, 0x34, 0xb0, 0x04, 0xe5, 0x00, 0x34, 0xc0, 0x04, 0xe6, 0x00, 0x34, 0xcd, 0x04, 0xe7,
0x00, 0x34, 0xea, 0x04, 0xe8, 0x00, 0x34, 0xf7, 0x04, 0xe9, 0x00, 0x35, 0x10, 0x04, 0xea, 0x00,
0x35, 0x1b, 0x04, 0xeb, 0x00, 0x35, 0x38, 0x04, 0xec, 0x00, 0x35, 0x45, 0x04, 0xed, 0x00, 0x35,
0x55, 0x04, 0xee, 0x00, 0x35, 0x62, 0x04, 0xef, 0x00, 0x35, 0x7f, 0x04, 0xf0, 0x00, 0x35, 0x8f,
0x04, 0xf1, 0x00, 0x35, 0xac, 0x04, 0xf2, 0x00, 0x35, 0xbc, 0x04, 0xf3, 0x00, 0x35, 0xdb, 0x04,
0xf4, 0x00, 0x35, 0xec, 0x04, 0xf5, 0x00, 0x35, 0xfc, 0x04, 0xf8, 0x00, 0x36, 0x09, 0x04, 0xf9,
0x00, 0x36, 0x26, 0x04, 0x00, 0x0d, 0x04, 0x1b, 0x22, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x00, 0x80, 0x80, 0x05, 0x33, 0x12, 0xa0, 0xa0, 0xa0, 0x08, 0x7a, 0x03, 0x14, 0x14, 0x14,
0x7e, 0x28, 0x28, 0xfc, 0x50, 0x50, 0x50, 0x08, 0x7e, 0x01, 0x10, 0x10, 0x7c, 0x92, 0x92, 0x50,
0x38, 0x14, 0x12, 0x92, 0x92, 0x7c, 0x10, 0x10, 0x0c, 0xba, 0x03, 0x70, 0x80, 0x89, 0x00, 0x89,
0x00, 0x72, 0x00, 0x02, 0x00, 0x04, 0x00, 0x09, 0xc0, 0x12, 0x20, 0x12, 0x20, 0x21, 0xc0, 0x0a,
0x8a, 0x13, 0x30, 0x48, 0x48, 0x30, 0x20, 0x52, 0x8a, 0x84, 0x8a, 0x71, 0x03, 0x13, 0x12, 0x80,
0x80, 0x80, 0x05, 0x3e, 0x12, 0x20, 0x40, 0x40, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x40, 0x40, 0x20, 0x05, 0x3e, 0x12, 0x80, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x40, 0x40, 0x80, 0x07, 0x54, 0x13, 0x20, 0xf8, 0x20, 0x50, 0x09, 0x77, 0x15, 0x10, 0x10,
0x10, 0xfe, 0x10, 0x10, 0x10, 0x03, 0x24, 0x0b, 0x40, 0x40, 0x40, 0x80, 0x09, 0x71, 0x18, 0xfe,
0x03, 0x12, 0x1b, 0x80, 0x80, 0x04, 0x4b, 0x02, 0x10, 0x10, 0x20, 0x20, 0x20, 0x40, 0x40, 0x40,
0x80, 0x80, 0x80, 0x08, 0x6a, 0x13, 0x78, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x78,
0x08, 0x3a, 0x23, 0x20, 0xe0, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x08, 0x6a, 0x13,
0x78, 0x84, 0x84, 0x08, 0x10, 0x20, 0x40, 0x80, 0x80, 0xfc, 0x08, 0x6a, 0x13, 0x78, 0x84, 0x84,
0x04, 0x38, 0x04, 0x04, 0x84, 0x84, 0x78, 0x08, 0x7a, 0x13, 0x0c, 0x14, 0x24, 0x24, 0x44, 0x84,
0xfe, 0x04, 0x04, 0x04, 0x08, 0x6a, 0x13, 0xfc, 0x80, 0x80, 0x80, 0xf8, 0x04, 0x04, 0x84, 0x84,
0x78, 0x08, 0x6a, 0x13, 0x78, 0x84, 0x80, 0x80, 0xb8, 0xc4, 0x84, 0x84, 0x84, 0x78, 0x08, 0x6a,
0x13, 0xfc, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, 0x40, 0x08, 0x6a, 0x13, 0x78, 0x84,
0x84, 0x84, 0x78, 0x84, 0x84, 0x84, 0x84, 0x78, 0x08, 0x6a, 0x13, 0x78, 0x84, 0x84, 0x84, 0x84,
0x7c, 0x04, 0x84, 0x84, 0x78, 0x03, 0x18, 0x15, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80,
0x04, 0x2a, 0x05, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x80, 0x08, 0x65, 0x16,
0x0c, 0x30, 0xc0, 0x30, 0x0c, 0x09, 0x63, 0x17, 0xfc, 0x00, 0xfc, 0x08, 0x65, 0x16, 0xc0, 0x30,
0x0c, 0x30, 0xc0, 0x08, 0x6b, 0x12, 0x30, 0xcc, 0x84, 0x84, 0x04, 0x08, 0x10, 0x20, 0x00, 0x20,
0x20, 0x0d, 0xbc, 0x12, 0x0f, 0x00, 0x30, 0xc0, 0x40, 0x20, 0x46, 0xa0, 0x89, 0x20, 0x91, 0x20,
0x91, 0x20, 0x93, 0x40, 0x8d, 0x80, 0x40, 0x00, 0x60, 0x80, 0x1f, 0x00, 0x0b, 0x9b, 0x12, 0x08,
0x00, 0x08, 0x00, 0x14, 0x00, 0x14, 0x00, 0x22, 0x00, 0x22, 0x00, 0x41, 0x00, 0x7f, 0x00, 0x41,
0x00, 0x80, 0x80, 0x80, 0x80, 0x09, 0x7b, 0x12, 0xfc, 0x86, 0x82, 0x82, 0x82, 0xfc, 0x82, 0x82,
0x82, 0x82, 0xfc, 0x0a, 0x8b, 0x12, 0x1c, 0x63, 0x41, 0x80, 0x80, 0x80, 0x80, 0x80, 0x41, 0x63,
0x1c, 0x0a, 0x8b, 0x12, 0xf8, 0x86, 0x82, 0x81, 0x81, 0x81, 0x81, 0x81, 0x82, 0x86, 0xf8, 0x09,
0x7b, 0x12, 0xfe, 0x80, 0x80, 0x80, 0x80, 0xfc, 0x80, 0x80, 0x80, 0x80, 0xfe, 0x09, 0x7b, 0x12,
0xfe, 0x80, 0x80, 0x80, 0x80, 0xfc, 0x80, 0x80, 0x80, 0x80, 0x80, 0x0b, 0x9b, 0x12, 0x1e, 0x00,
0x61, 0x80, 0x40, 0x80, 0x80, 0x00, 0x80, 0x00, 0x87, 0x80, 0x80, 0x80, 0x80, 0x80, 0x40, 0x80,
0x63, 0x80, 0x1c, 0x80, 0x0a, 0x8b, 0x12, 0x81, 0x81, 0x81, 0x81, 0x81, 0xff, 0x81, 0x81, 0x81,
0x81, 0x81, 0x05, 0x1b, 0x22, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x08, 0x6b, 0x12, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x84, 0x84, 0x78, 0x0a, 0x8b,
0x12, 0x82, 0x84, 0x88, 0x90, 0xa0, 0xe0, 0x90, 0x88, 0x84, 0x82, 0x81, 0x08, 0x6b, 0x12, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xfc, 0x0d, 0xbb, 0x12, 0x80, 0x20, 0x80,
0x20, 0xc0, 0x60, 0xa0, 0xa0, 0xa0, 0xa0, 0x91, 0x20, 0x91, 0x20, 0x8a, 0x20, 0x8a, 0x20, 0x84,
0x20, 0x84, 0x20, 0x0a, 0x8b, 0x12, 0xc1, 0xc1, 0xa1, 0x91, 0x91, 0x89, 0x89, 0x85, 0x85, 0x83,
0x83, 0x0b, 0x9b, 0x12, 0x1c, 0x00, 0x63, 0x00, 0x41, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x41, 0x00, 0x63, 0x00, 0x1c, 0x00, 0x09, 0x7b, 0x12, 0xfc, 0x86, 0x82,
0x82, 0x86, 0xfc, 0x80, 0x80, 0x80, 0x80, 0x80, 0x0b, 0x9b, 0x12, 0x1c, 0x00, 0x63, 0x00, 0x41,
0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x88, 0x80, 0x84, 0x80, 0x43, 0x00, 0x63, 0x00, 0x1c,
0x80, 0x09, 0x7b, 0x12, 0xfc, 0x86, 0x82, 0x82, 0x84, 0xf8, 0x84, 0x82, 0x82, 0x82, 0x82, 0x09,
0x7b, 0x12, 0x38, 0xc6, 0x82, 0x80, 0x60, 0x18, 0x06, 0x02, 0x82, 0xc6, 0x38, 0x09, 0x9b, 0x02,
0xff, 0x80, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00,
0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x0a, 0x8b, 0x12, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
0x81, 0x81, 0x42, 0x3c, 0x0b, 0x9b, 0x12, 0x80, 0x80, 0x80, 0x80, 0x41, 0x00, 0x41, 0x00, 0x22,
0x00, 0x22, 0x00, 0x22, 0x00, 0x14, 0x00, 0x14, 0x00, 0x08, 0x00, 0x08, 0x00, 0x0f, 0xdb, 0x12,
0x82, 0x08, 0x82, 0x08, 0x85, 0x08, 0x45, 0x10, 0x45, 0x10, 0x45, 0x10, 0x28, 0xa0, 0x28, 0xa0,
0x28, 0xa0, 0x10, 0x40, 0x10, 0x40, 0x0a, 0x8b, 0x12, 0x81, 0x81, 0x42, 0x24, 0x18, 0x18, 0x24,
0x42, 0x42, 0x81, 0x81, 0x09, 0x9b, 0x02, 0x80, 0x80, 0x41, 0x00, 0x41, 0x00, 0x22, 0x00, 0x22,
0x00, 0x14, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x09, 0x7b, 0x12,
0xfe, 0x02, 0x04, 0x08, 0x18, 0x10, 0x20, 0x60, 0x40, 0x80, 0xfe, 0x04, 0x3e, 0x12, 0xe0, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xe0, 0x04, 0x4b, 0x02, 0x80,
0x80, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x04, 0x3e, 0x02, 0xe0, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xe0, 0x07, 0x74, 0x03, 0x10, 0x28,
0x44, 0x82, 0x08, 0x81, 0x0f, 0xff, 0x05, 0x22, 0x12, 0x80, 0x40, 0x08, 0x78, 0x15, 0x78, 0xcc,
0x04, 0x7c, 0xc4, 0x84, 0xcc, 0x76, 0x08, 0x6b, 0x12, 0x80, 0x80, 0x80, 0xb8, 0xcc, 0x84, 0x84,
0x84, 0x84, 0xcc, 0xb8, 0x08, 0x68, 0x15, 0x78, 0xcc, 0x80, 0x80, 0x80, 0x84, 0xcc, 0x78, 0x08,
0x6b, 0x12, 0x04, 0x04, 0x04, 0x74, 0xcc, 0x84, 0x84, 0x84, 0x84, 0xcc, 0x74, 0x08, 0x68, 0x15,
0x78, 0xcc, 0x84, 0xfc, 0x80, 0x80, 0xcc, 0x78, 0x03, 0x4b, 0x02, 0x30, 0x40, 0x40, 0xe0, 0x40,
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x08, 0x6b, 0x15, 0x74, 0xcc, 0x84, 0x84, 0x84, 0x84, 0xcc,
0x74, 0x04, 0xcc, 0x78, 0x08, 0x6b, 0x12, 0x80, 0x80, 0x80, 0xb8, 0xcc, 0x84, 0x84, 0x84, 0x84,
0x84, 0x84, 0x03, 0x1b, 0x12, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x04, 0x3e, 0x02, 0x20, 0x20, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0xc0, 0x07, 0x6b, 0x12, 0x80, 0x80, 0x80, 0x88, 0x90, 0xa0, 0xc0, 0xa0, 0x90, 0x88, 0x84, 0x03,
0x1b, 0x12, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x0b, 0x98, 0x15,
0xb3, 0x00, 0xcc, 0x80, 0x88, 0x80, 0x88, 0x80, 0x88, 0x80, 0x88, 0x80, 0x88, 0x80, 0x88, 0x80,
0x08, 0x68, 0x15, 0xb8, 0xcc, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x08, 0x68, 0x15, 0x78, 0xcc,
0x84, 0x84, 0x84, 0x84, 0xcc, 0x78, 0x08, 0x6b, 0x15, 0xb8, 0xcc, 0x84, 0x84, 0x84, 0x84, 0xcc,
0xb8, 0x80, 0x80, 0x80, 0x08, 0x6b, 0x15, 0x74, 0xcc, 0x84, 0x84, 0x84, 0x84, 0xcc, 0x74, 0x04,
0x04, 0x04, 0x05, 0x48, 0x15, 0xb0, 0xc0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x08, 0x68, 0x15,
0x78, 0x84, 0x80, 0x78, 0x0c, 0x04, 0x84, 0x78, 0x04, 0x4a, 0x03, 0x40, 0x40, 0xf0, 0x40, 0x40,
0x40, 0x40, 0x40, 0x40, 0x30, 0x08, 0x68, 0x15, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0xcc, 0x74,
0x08, 0x68, 0x15, 0x84, 0x84, 0x84, 0x48, 0x48, 0x48, 0x30, 0x30, 0x0a, 0x98, 0x05, 0x88, 0x80,
0x88, 0x80, 0x88, 0x80, 0x49, 0x00, 0x49, 0x00, 0x55, 0x00, 0x22, 0x00, 0x22, 0x00, 0x07, 0x78,
0x05, 0xc6, 0x44, 0x28, 0x10, 0x10, 0x28, 0x44, 0xc6, 0x07, 0x7b, 0x05, 0x82, 0x82, 0x44, 0x44,
0x24, 0x28, 0x18, 0x10, 0x10, 0x30, 0x60, 0x07, 0x68, 0x05, 0xfc, 0x04, 0x08, 0x10, 0x20, 0x40,
0x80, 0xfc, 0x05, 0x5e, 0x02, 0x18, 0x20, 0x20, 0x20, 0x20, 0x40, 0x80, 0x40, 0x20, 0x20, 0x20,
0x20, 0x20, 0x18, 0x03, 0x1e, 0x12, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x05, 0x5e, 0x02, 0xc0, 0x20, 0x20, 0x20, 0x20, 0x10, 0x08, 0x10, 0x20,
0x20, 0x20, 0x20, 0x20, 0xc0, 0x08, 0x63, 0x17, 0x64, 0xb4, 0x98, 0x04, 0x00, 0x0d, 0x04, 0x1b,
0x15, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x08, 0x6a, 0x14, 0x04,
0x78, 0xcc, 0x90, 0x90, 0xa0, 0xa4, 0xcc, 0x78, 0x80, 0x08, 0x7a, 0x03, 0x3c, 0x42, 0x40, 0x20,
0x20, 0xf8, 0x20, 0x40, 0x62, 0xdc, 0x08, 0x66, 0x15, 0x84, 0x78, 0x48, 0x48, 0x78, 0x84, 0x07,
0x7a, 0x03, 0x82, 0x82, 0x44, 0x44, 0x28, 0xfe, 0x10, 0xfe, 0x10, 0x10, 0x03, 0x1d, 0x12, 0x80,
0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x08, 0x5e, 0x22, 0x70,
0xd8, 0x88, 0xc0, 0x70, 0x98, 0x88, 0x88, 0xc8, 0x70, 0x18, 0x88, 0xd8, 0x70, 0x05, 0x51, 0x03,
0xd8, 0x0c, 0xaa, 0x13, 0x1e, 0x00, 0x61, 0x80, 0x4c, 0x80, 0x92, 0x40, 0x90, 0x40, 0x90, 0x40,
0x92, 0x40, 0x4c, 0x80, 0x61, 0x80, 0x1e, 0x00, 0x06, 0x47, 0x12, 0xe0, 0x10, 0x70, 0x90, 0xd0,
0x00, 0xf0, 0x08, 0x65, 0x16, 0x24, 0x48, 0x90, 0x48, 0x24, 0x09, 0x74, 0x16, 0xfe, 0x02, 0x02,
0x02, 0x05, 0x41, 0x08, 0xf0, 0x0c, 0xaa, 0x13, 0x1e, 0x00, 0x61, 0x80, 0x5c, 0x80, 0x92, 0x40,
0x92, 0x40, 0x9c, 0x40, 0x92, 0x40, 0x52, 0x80, 0x61, 0x80, 0x1e, 0x00, 0x04, 0x41, 0x03, 0xf0,
0x06, 0x44, 0x13, 0x60, 0x90, 0x90, 0x60, 0x09, 0x79, 0x14, 0x10, 0x10, 0x10, 0xfe, 0x10, 0x10,
0x10, 0x00, 0xfe, 0x05, 0x46, 0x03, 0x60, 0x90, 0x10, 0x20, 0x40, 0xf0, 0x05, 0x46, 0x03, 0x60,
0x90, 0x20, 0x10, 0x90, 0x60, 0x05, 0x22, 0x22, 0x40, 0x80, 0x08, 0x6b, 0x15, 0x84, 0x84, 0x84,
0x84, 0x84, 0x84, 0xcc, 0xb4, 0x80, 0x80, 0x80, 0x08, 0x7e, 0x02, 0x3e, 0x74, 0xf4, 0xf4, 0xf4,
0x74, 0x34, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x04, 0x21, 0x18, 0xc0, 0x05, 0x43, 0x0d,
0x20, 0x90, 0x60, 0x05, 0x26, 0x13, 0x40, 0xc0, 0x40, 0x40, 0x40, 0x40, 0x06, 0x47, 0x12, 0x60,
0x90, 0x90, 0x90, 0x60, 0x00, 0xf0, 0x08, 0x65, 0x16, 0x90, 0x48, 0x24, 0x48, 0x90, 0x0c, 0xab,
0x12, 0x41, 0x00, 0xc2, 0x00, 0x42, 0x00, 0x44, 0x00, 0x44, 0x00, 0x48, 0x80, 0x09, 0x80, 0x12,
0x80, 0x14, 0x80, 0x27, 0xc0, 0x20, 0x80, 0x0c, 0x9b, 0x12, 0x42, 0x00, 0xc4, 0x00, 0x44, 0x00,
0x48, 0x00, 0x48, 0x00, 0x53, 0x00, 0x14, 0x80, 0x20, 0x80, 0x21, 0x00, 0x42, 0x00, 0x47, 0x80,
0x0c, 0xbb, 0x02, 0x60, 0x80, 0x91, 0x00, 0x21, 0x00, 0x12, 0x00, 0x92, 0x00, 0x64, 0x40, 0x04,
0xc0, 0x09, 0x40, 0x0a, 0x40, 0x13, 0xe0, 0x10, 0x40, 0x08, 0x6b, 0x15, 0x10, 0x10, 0x00, 0x10,
0x20, 0x40, 0x80, 0x84, 0x84, 0xcc, 0x30, 0x0b, 0x9e, 0x10, 0x10, 0x00, 0x08, 0x00, 0x00, 0x00,
0x08, 0x00, 0x08, 0x00, 0x14, 0x00, 0x14, 0x00, 0x22, 0x00, 0x22, 0x00, 0x41, 0x00, 0x7f, 0x00,
0x41, 0x00, 0x80, 0x80, 0x80, 0x80, 0x0b, 0x9e, 0x10, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08,
0x00, 0x08, 0x00, 0x14, 0x00, 0x14, 0x00, 0x22, 0x00, 0x22, 0x00, 0x41, 0x00, 0x7f, 0x00, 0x41,
0x00, 0x80, 0x80, 0x80, 0x80, 0x0b, 0x9e, 0x10, 0x08, 0x00, 0x14, 0x00, 0x00, 0x00, 0x08, 0x00,
0x08, 0x00, 0x14, 0x00, 0x14, 0x00, 0x22, 0x00, 0x22, 0x00, 0x41, 0x00, 0x7f, 0x00, 0x41, 0x00,
0x80, 0x80, 0x80, 0x80, 0x0b, 0x9e, 0x10, 0x1a, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08,
0x00, 0x14, 0x00, 0x14, 0x00, 0x22, 0x00, 0x22, 0x00, 0x41, 0x00, 0x7f, 0x00, 0x41, 0x00, 0x80,
0x80, 0x80, 0x80, 0x0b, 0x9d, 0x10, 0x36, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x14, 0x00,
0x14, 0x00, 0x22, 0x00, 0x22, 0x00, 0x41, 0x00, 0x7f, 0x00, 0x41, 0x00, 0x80, 0x80, 0x80, 0x80,
0x0b, 0x9e, 0x10, 0x1c, 0x00, 0x22, 0x00, 0x1c, 0x00, 0x08, 0x00, 0x08, 0x00, 0x14, 0x00, 0x14,
0x00, 0x22, 0x00, 0x22, 0x00, 0x41, 0x00, 0x7f, 0x00, 0x41, 0x00, 0x80, 0x80, 0x80, 0x80, 0x0e,
0xcb, 0x12, 0x0f, 0xf0, 0x1c, 0x00, 0x14, 0x00, 0x14, 0x00, 0x24, 0x00, 0x27, 0xe0, 0x44, 0x00,
0x7c, 0x00, 0x44, 0x00, 0x84, 0x00, 0x87, 0xf0, 0x0a, 0x8e, 0x12, 0x1c, 0x63, 0x41, 0x80, 0x80,
0x80, 0x80, 0x80, 0x41, 0x63, 0x1c, 0x08, 0x24, 0x18, 0x09, 0x7e, 0x10, 0x20, 0x10, 0x00, 0xfe,
0x80, 0x80, 0x80, 0x80, 0xfc, 0x80, 0x80, 0x80, 0x80, 0xfe, 0x09, 0x7e, 0x10, 0x08, 0x10, 0x00,
0xfe, 0x80, 0x80, 0x80, 0x80, 0xfc, 0x80, 0x80, 0x80, 0x80, 0xfe, 0x09, 0x7e, 0x10, 0x10, 0x28,
0x00, 0xfe, 0x80, 0x80, 0x80, 0x80, 0xfc, 0x80, 0x80, 0x80, 0x80, 0xfe, 0x09, 0x7d, 0x10, 0x6c,
0x00, 0xfe, 0x80, 0x80, 0x80, 0x80, 0xfc, 0x80, 0x80, 0x80, 0x80, 0xfe, 0x05, 0x2e, 0x10, 0x80,
0x40, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x05, 0x2e, 0x20,
0x40, 0x80, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x05, 0x3e,
0x10, 0x40, 0xa0, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x05,
0x5d, 0x00, 0xd8, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0a,
0x9b, 0x02, 0x7c, 0x00, 0x43, 0x00, 0x41, 0x00, 0x40, 0x80, 0x40, 0x80, 0xf0, 0x80, 0x40, 0x80,
0x40, 0x80, 0x41, 0x00, 0x43, 0x00, 0x7c, 0x00, 0x0a, 0x8e, 0x10, 0x1a, 0x2c, 0x00, 0xc1, 0xc1,
0xa1, 0x91, 0x91, 0x89, 0x89, 0x85, 0x85, 0x83, 0x83, 0x0b, 0x9e, 0x10, 0x10, 0x00, 0x08, 0x00,
0x00, 0x00, 0x1c, 0x00, 0x63, 0x00, 0x41, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x41, 0x00, 0x63, 0x00, 0x1c, 0x00, 0x0b, 0x9e, 0x10, 0x04, 0x00, 0x08, 0x00, 0x00,
0x00, 0x1c, 0x00, 0x63, 0x00, 0x41, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x41, 0x00, 0x63, 0x00, 0x1c, 0x00, 0x0b, 0x9e, 0x10, 0x08, 0x00, 0x14, 0x00, 0x00, 0x00,
0x1c, 0x00, 0x63, 0x00, 0x41, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x41, 0x00, 0x63, 0x00, 0x1c, 0x00, 0x0b, 0x9e, 0x10, 0x1a, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x1c,
0x00, 0x63, 0x00, 0x41, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x41,
0x00, 0x63, 0x00, 0x1c, 0x00, 0x0b, 0x9d, 0x10, 0x36, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x63, 0x00,
0x41, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x41, 0x00, 0x63, 0x00,
0x1c, 0x00, 0x09, 0x77, 0x15, 0x82, 0x44, 0x28, 0x10, 0x28, 0x44, 0x82, 0x0b, 0xbb, 0x02, 0x0e,
0x20, 0x31, 0xc0, 0x20, 0x80, 0x41, 0x40, 0x42, 0x40, 0x44, 0x40, 0x48, 0x40, 0x50, 0x40, 0x20,
0x80, 0x71, 0x80, 0x8e, 0x00, 0x0a, 0x8e, 0x10, 0x10, 0x08, 0x00, 0x81, 0x81, 0x81, 0x81, 0x81,
0x81, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x0a, 0x8e, 0x10, 0x04, 0x08, 0x00, 0x81, 0x81, 0x81, 0x81,
0x81, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x0a, 0x8e, 0x10, 0x08, 0x14, 0x00, 0x81, 0x81, 0x81,
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x0a, 0x8d, 0x10, 0x66, 0x00, 0x81, 0x81, 0x81,
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x09, 0x9e, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00,
0x00, 0x80, 0x80, 0x41, 0x00, 0x41, 0x00, 0x22, 0x00, 0x22, 0x00, 0x14, 0x00, 0x08, 0x00, 0x08,
0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x09, 0x7b, 0x12, 0x80, 0x80, 0xfc, 0x86, 0x82, 0x82,
0x86, 0xfc, 0x80, 0x80, 0x80, 0x07, 0x5b, 0x12, 0x70, 0x88, 0x88, 0x88, 0xb0, 0x90, 0x88, 0x88,
0x88, 0x88, 0xb0, 0x08, 0x7b, 0x12, 0x20, 0x10, 0x00, 0x78, 0xcc, 0x04, 0x7c, 0xc4, 0x84, 0xcc,
0x76, 0x08, 0x7b, 0x12, 0x08, 0x10, 0x00, 0x78, 0xcc, 0x04, 0x7c, 0xc4, 0x84, 0xcc, 0x76, 0x08,
0x7b, 0x12, 0x10, 0x28, 0x00, 0x78, 0xcc, 0x04, 0x7c, 0xc4, 0x84, 0xcc, 0x76, 0x08, 0x7b, 0x12,
0x34, 0x58, 0x00, 0x78, 0xcc, 0x04, 0x7c, 0xc4, 0x84, 0xcc, 0x76, 0x08, 0x7a, 0x13, 0x6c, 0x00,
0x78, 0xcc, 0x04, 0x7c, 0xc4, 0x84, 0xcc, 0x76, 0x08, 0x7c, 0x11, 0x30, 0x48, 0x30, 0x00, 0x78,
0xcc, 0x04, 0x7c, 0xc4, 0x84, 0xcc, 0x76, 0x0d, 0xb8, 0x15, 0x7b, 0xc0, 0xc6, 0x60, 0x04, 0x20,
0x7f, 0xe0, 0xc4, 0x00, 0x84, 0x00, 0xce, 0x60, 0x7b, 0xc0, 0x08, 0x6b, 0x15, 0x78, 0xcc, 0x80,
0x80, 0x80, 0x84, 0xcc, 0x78, 0x10, 0x48, 0x30, 0x08, 0x6b, 0x12, 0x20, 0x10, 0x00, 0x78, 0xcc,
0x84, 0xfc, 0x80, 0x80, 0xcc, 0x78, 0x08, 0x6b, 0x12, 0x10, 0x20, 0x00, 0x78, 0xcc, 0x84, 0xfc,
0x80, 0x80, 0xcc, 0x78, 0x08, 0x6b, 0x12, 0x10, 0x28, 0x00, 0x78, 0xcc, 0x84, 0xfc, 0x80, 0x80,
0xcc, 0x78, 0x08, 0x6a, 0x13, 0xcc, 0x00, 0x78, 0xcc, 0x84, 0xfc, 0x80, 0x80, 0xcc, 0x78, 0x03,
0x2b, 0x02, 0x80, 0x40, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x03, 0x2b, 0x12,
0x40, 0x80, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x03, 0x3b, 0x02, 0x40, 0xa0,
0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x03, 0x3a, 0x03, 0xa0, 0x00, 0x40, 0x40,
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x08, 0x6b, 0x12, 0xd8, 0x70, 0x90, 0x08, 0x7c, 0x84, 0x84,
0x84, 0x84, 0xcc, 0x78, 0x08, 0x6b, 0x12, 0x34, 0x58, 0x00, 0xb8, 0xcc, 0x84, 0x84, 0x84, 0x84,
0x84, 0x84, 0x08, 0x6b, 0x12, 0x20, 0x10, 0x00, 0x78, 0xcc, 0x84, 0x84, 0x84, 0x84, 0xcc, 0x78,
0x08, 0x6b, 0x12, 0x08, 0x10, 0x00, 0x78, 0xcc, 0x84, 0x84, 0x84, 0x84, 0xcc, 0x78, 0x08, 0x6b,
0x12, 0x30, 0x48, 0x00, 0x78, 0xcc, 0x84, 0x84, 0x84, 0x84, 0xcc, 0x78, 0x08, 0x6b, 0x12, 0x34,
0x58, 0x00, 0x78, 0xcc, 0x84, 0x84, 0x84, 0x84, 0xcc, 0x78, 0x08, 0x6a, 0x13, 0xcc, 0x00, 0x78,
0xcc, 0x84, 0x84, 0x84, 0x84, 0xcc, 0x78, 0x09, 0x77, 0x15, 0x10, 0x10, 0x00, 0xfe, 0x00, 0x10,
0x10, 0x08, 0x88, 0x05, 0x3d, 0x62, 0x46, 0x4a, 0x52, 0x62, 0x46, 0xbc, 0x08, 0x6b, 0x12, 0x20,
0x10, 0x00, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0xcc, 0x74, 0x08, 0x6b, 0x12, 0x08, 0x10, 0x00,
0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0xcc, 0x74, 0x08, 0x6b, 0x12, 0x30, 0x48, 0x00, 0x84, 0x84,
0x84, 0x84, 0x84, 0x84, 0xcc, 0x74, 0x08, 0x6a, 0x13, 0xcc, 0x00, 0x84, 0x84, 0x84, 0x84, 0x84,
0x84, 0xcc, 0x74, 0x07, 0x7e, 0x02, 0x08, 0x10, 0x00, 0x82, 0xc2, 0x44, 0x44, 0x24, 0x28, 0x18,
0x10, 0x10, 0x30, 0x60, 0x08, 0x6e, 0x12, 0x80, 0x80, 0x80, 0xb8, 0xcc, 0x84, 0x84, 0x84, 0x84,
0xcc, 0xb8, 0x80, 0x80, 0x80, 0x07, 0x7d, 0x03, 0x6c, 0x00, 0x82, 0xc2, 0x44, 0x44, 0x24, 0x28,
0x18, 0x10, 0x10, 0x30, 0x60, 0x0b, 0x9c, 0x11, 0x1e, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00,
0x14, 0x00, 0x14, 0x00, 0x22, 0x00, 0x22, 0x00, 0x3e, 0x00, 0x41, 0x00, 0x41, 0x00, 0xe3, 0x80,
0x07, 0x69, 0x14, 0x78, 0x00, 0x70, 0xc8, 0x18, 0x68, 0x88, 0xc8, 0x74, 0x0b, 0x9e, 0x10, 0x12,
0x00, 0x12, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x14, 0x00, 0x14, 0x00, 0x22,
0x00, 0x22, 0x00, 0x3e, 0x00, 0x41, 0x00, 0x41, 0x00, 0xe3, 0x80, 0x07, 0x6b, 0x12, 0x48, 0x48,
0x30, 0x00, 0x70, 0xc8, 0x18, 0x68, 0x88, 0xc8, 0x74, 0x0b, 0x9d, 0x13, 0x08, 0x00, 0x08, 0x00,
0x14, 0x00, 0x14, 0x00, 0x22, 0x00, 0x22, 0x00, 0x3e, 0x00, 0x41, 0x00, 0x41, 0x00, 0xe3, 0x80,
0x08, 0x00, 0x12, 0x00, 0x0c, 0x00, 0x07, 0x6a, 0x16, 0x70, 0xc8, 0x18, 0x68, 0x88, 0xc8, 0x74,
0x20, 0x48, 0x30, 0x0a, 0x8e, 0x10, 0x04, 0x0c, 0x10, 0x00, 0x3d, 0x63, 0xc1, 0x81, 0x80, 0x80,
0x80, 0xc1, 0x62, 0x3c, 0x07, 0x6b, 0x12, 0x08, 0x18, 0x20, 0x00, 0x78, 0xc8, 0x80, 0x80, 0x80,
0xc4, 0x78, 0x0a, 0x8e, 0x10, 0x08, 0x1c, 0x22, 0x00, 0x3d, 0x63, 0xc1, 0x81, 0x80, 0x80, 0x80,
0xc1, 0x62, 0x3c, 0x07, 0x6b, 0x12, 0x20, 0x70, 0x88, 0x00, 0x78, 0xc8, 0x80, 0x80, 0x80, 0xc4,
0x78, 0x0a, 0x8d, 0x10, 0x08, 0x08, 0x00, 0x3d, 0x63, 0xc1, 0x81, 0x80, 0x80, 0x80, 0xc1, 0x62,
0x3c, 0x07, 0x6a, 0x13, 0x20, 0x20, 0x00, 0x78, 0xc8, 0x80, 0x80, 0x80, 0xc4, 0x78, 0x0a, 0x8e,
0x10, 0x22, 0x1c, 0x08, 0x00, 0x3d, 0x63, 0xc1, 0x81, 0x80, 0x80, 0x80, 0xc1, 0x62, 0x3c, 0x07,
0x6b, 0x12, 0x88, 0x70, 0x20, 0x00, 0x78, 0xc8, 0x80, 0x80, 0x80, 0xc4, 0x78, 0x0a, 0x9e, 0x00,
0x22, 0x00, 0x1c, 0x00, 0x08, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x23, 0x00, 0x21, 0x00, 0x20, 0x80,
0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x21, 0x00, 0x23, 0x00, 0xfe, 0x00, 0x0b, 0x9a, 0x13, 0x19,
0x80, 0x08, 0x80, 0x09, 0x00, 0x78, 0x00, 0xc8, 0x00, 0x88, 0x00, 0x88, 0x00, 0x88, 0x00, 0xd8,
0x00, 0x74, 0x00, 0x0a, 0x9a, 0x03, 0xfe, 0x00, 0x23, 0x00, 0x21, 0x00, 0x20, 0x80, 0xf8, 0x80,
0x20, 0x80, 0x20, 0x80, 0x21, 0x00, 0x23, 0x00, 0xfe, 0x00, 0x07, 0x6a, 0x13, 0x18, 0x1c, 0x08,
0x78, 0xc8, 0x88, 0x88, 0x88, 0xd8, 0x74, 0x09, 0x7c, 0x11, 0x78, 0x00, 0xfe, 0x42, 0x40, 0x44,
0x7c, 0x44, 0x40, 0x40, 0x42, 0xfe, 0x07, 0x69, 0x14, 0x78, 0x00, 0x70, 0x88, 0xf8, 0x80, 0x80,
0xc4, 0x78, 0x09, 0x7e, 0x10, 0x48, 0x48, 0x30, 0x00, 0xfe, 0x42, 0x40, 0x44, 0x7c, 0x44, 0x40,
0x40, 0x42, 0xfe, 0x07, 0x6b, 0x12, 0x48, 0x48, 0x30, 0x00, 0x70, 0x88, 0xf8, 0x80, 0x80, 0xc4,
0x78, 0x09, 0x7d, 0x10, 0x10, 0x10, 0x00, 0xfe, 0x42, 0x40, 0x44, 0x7c, 0x44, 0x40, 0x40, 0x42,
0xfe, 0x07, 0x6a, 0x13, 0x20, 0x20, 0x00, 0x70, 0x88, 0xf8, 0x80, 0x80, 0xc4, 0x78, 0x09, 0x7d,
0x13, 0xfe, 0x42, 0x40, 0x44, 0x7c, 0x44, 0x40, 0x40, 0x42, 0xfe, 0x10, 0x24, 0x18, 0x07, 0x6a,
0x16, 0x70, 0x88, 0xf8, 0x80, 0x80, 0xc4, 0x78, 0x20, 0x48, 0x30, 0x09, 0x7e, 0x10, 0x44, 0x38,
0x10, 0x00, 0xfe, 0x42, 0x40, 0x44, 0x7c, 0x44, 0x40, 0x40, 0x42, 0xfe, 0x07, 0x6b, 0x12, 0x88,
0x70, 0x20, 0x00, 0x70, 0x88, 0xf8, 0x80, 0x80, 0xc4, 0x78, 0x0b, 0x9e, 0x10, 0x08, 0x00, 0x1c,
0x00, 0x22, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x63, 0x00, 0x41, 0x00, 0x81, 0x00, 0x80, 0x00, 0x87,
0x80, 0x81, 0x00, 0xc1, 0x00, 0x63, 0x00, 0x3e, 0x00, 0x07, 0x6e, 0x12, 0x20, 0x70, 0x88, 0x00,
0x78, 0xd0, 0x88, 0xc8, 0x70, 0x40, 0x78, 0x84, 0xcc, 0x70, 0x0b, 0x9e, 0x10, 0x12, 0x00, 0x12,
0x00, 0x0c, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x63, 0x00, 0x41, 0x00, 0x81, 0x00, 0x80, 0x00, 0x87,
0x80, 0x81, 0x00, 0xc1, 0x00, 0x63, 0x00, 0x3e, 0x00, 0x07, 0x6e, 0x12, 0x48, 0x48, 0x30, 0x00,
0x78, 0xd0, 0x88, 0xc8, 0x70, 0x40, 0x78, 0x84, 0xcc, 0x70, 0x0b, 0x9d, 0x10, 0x08, 0x00, 0x08,
0x00, 0x00, 0x00, 0x3d, 0x00, 0x63, 0x00, 0x41, 0x00, 0x81, 0x00, 0x80, 0x00, 0x87, 0x80, 0x81,
0x00, 0xc1, 0x00, 0x63, 0x00, 0x3e, 0x00, 0x07, 0x6d, 0x13, 0x20, 0x20, 0x00, 0x78, 0xd0, 0x88,
0xc8, 0x70, 0x40, 0x78, 0x84, 0xcc, 0x70, 0x0b, 0x9f, 0x13, 0x3d, 0x00, 0x63, 0x00, 0x41, 0x00,
0x81, 0x00, 0x80, 0x00, 0x87, 0x80, 0x81, 0x00, 0xc1, 0x00, 0x63, 0x00, 0x3e, 0x00, 0x00, 0x00,
0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x10, 0x00, 0x07, 0x6e, 0x12, 0x10, 0x20, 0x30, 0x00, 0x78,
0xd0, 0x88, 0xc8, 0x70, 0x40, 0x78, 0x84, 0xcc, 0x70, 0x0a, 0x8e, 0x10, 0x08, 0x1c, 0x22, 0x00,
0xe7, 0x42, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x42, 0xe7, 0x07, 0x7e, 0x00, 0x20, 0x70, 0x88,
0x00, 0xc0, 0x40, 0x40, 0x58, 0x6c, 0x44, 0x44, 0x44, 0x44, 0xee, 0x0a, 0x8a, 0x13, 0xe7, 0x42,
0xff, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x42, 0xe7, 0x07, 0x7a, 0x03, 0xc0, 0x70, 0x40, 0x58, 0x6c,
0x44, 0x44, 0x44, 0x44, 0xee, 0x05, 0x5d, 0x00, 0x68, 0xb0, 0x00, 0x70, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x70, 0x04, 0x5a, 0x03, 0x68, 0xb0, 0x00, 0x60, 0x20, 0x20, 0x20, 0x20,
0x20, 0x70, 0x05, 0x4c, 0x11, 0xf0, 0x00, 0xe0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
0xe0, 0x04, 0x49, 0x04, 0xf0, 0x00, 0x60, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x05, 0x4e, 0x10,
0x90, 0x90, 0x60, 0x00, 0xe0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0xe0, 0x04, 0x4b,
0x02, 0x90, 0x90, 0x60, 0x00, 0x60, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x05, 0x4d, 0x13, 0xe0,
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0xe0, 0x40, 0x90, 0x60, 0x03, 0x4d, 0x03, 0x40,
0x40, 0x00, 0xc0, 0x40, 0x40, 0x40, 0x40, 0x40, 0xe0, 0x40, 0x90, 0x60, 0x05, 0x3d, 0x10, 0x40,
0x40, 0x00, 0xe0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0xe0, 0x03, 0x37, 0x06, 0xc0,
0x40, 0x40, 0x40, 0x40, 0x40, 0xe0, 0x0b, 0x9a, 0x13, 0xe3, 0x80, 0x41, 0x00, 0x41, 0x00, 0x41,
0x00, 0x41, 0x00, 0x41, 0x00, 0x41, 0x00, 0x41, 0x00, 0x45, 0x00, 0xe6, 0x00, 0x07, 0x6d, 0x03,
0x44, 0x44, 0x00, 0xcc, 0x44, 0x44, 0x44, 0x44, 0x44, 0xe4, 0x04, 0x14, 0x18, 0x06, 0x5e, 0x10,
0x20, 0x70, 0x88, 0x00, 0x70, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xa0, 0xc0, 0x04, 0x5e,
0x02, 0x20, 0x70, 0x88, 0x00, 0x60, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xa0, 0xc0, 0x0a,
0x8f, 0x23, 0xee, 0x44, 0x48, 0x50, 0x60, 0x50, 0x48, 0x44, 0x42, 0xe7, 0x00, 0x08, 0x08, 0x08,
0x10, 0x07, 0x7f, 0x03, 0xc0, 0x40, 0x40, 0x4c, 0x48, 0x70, 0x50, 0x48, 0x4c, 0xe6, 0x00, 0x10,
0x10, 0x10, 0x20, 0x07, 0x77, 0x06, 0x4c, 0x48, 0x70, 0x50, 0x48, 0x4c, 0xe6, 0x09, 0x7e, 0x10,
0x10, 0x30, 0x40, 0x00, 0xe0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x42, 0xfe, 0x03, 0x4e,
0x00, 0x10, 0x30, 0x40, 0x00, 0xc0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0xe0, 0x09,
0x7f, 0x13, 0xe0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x42, 0xfe, 0x00, 0x10, 0x10, 0x10,
0x20, 0x03, 0x3f, 0x03, 0xc0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0xe0, 0x00, 0x40,
0x40, 0x40, 0x80, 0x0d, 0xba, 0x13, 0xe0, 0x60, 0x40, 0x20, 0x40, 0x40, 0x40, 0x00, 0x40, 0x00,
0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x42, 0x00, 0xfe, 0x00, 0x07, 0x6a, 0x03, 0xcc, 0x44, 0x48,
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0xe0, 0x0d, 0xaa, 0x13, 0xe0, 0x00, 0x40, 0x00, 0x40, 0x00,
0x40, 0x00, 0x40, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x42, 0x00, 0xfe, 0x00, 0x07, 0x5a,
0x03, 0xc0, 0x40, 0x40, 0x40, 0x40, 0x48, 0x48, 0x40, 0x40, 0xe0, 0x09, 0x7a, 0x13, 0xe0, 0x40,
0x40, 0x40, 0x60, 0xc0, 0x40, 0x40, 0x42, 0xfe, 0x03, 0x3a, 0x03, 0xc0, 0x40, 0x40, 0x40, 0x60,
0xc0, 0x40, 0x40, 0x40, 0xe0, 0x0b, 0x9e, 0x10, 0x02, 0x00, 0x06, 0x00, 0x08, 0x00, 0x00, 0x00,
0xe3, 0x80, 0x61, 0x00, 0x51, 0x00, 0x59, 0x00, 0x49, 0x00, 0x4d, 0x00, 0x45, 0x00, 0x45, 0x00,
0x43, 0x00, 0xe1, 0x00, 0x07, 0x7b, 0x02, 0x08, 0x18, 0x20, 0x00, 0xd8, 0x6c, 0x44, 0x44, 0x44,
0x44, 0xee, 0x0b, 0x9f, 0x13, 0xe3, 0x80, 0x61, 0x00, 0x51, 0x00, 0x59, 0x00, 0x49, 0x00, 0x4d,
0x00, 0x45, 0x00, 0x45, 0x00, 0x43, 0x00, 0xe1, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08,
0x00, 0x10, 0x00, 0x07, 0x7c, 0x06, 0xd8, 0x6c, 0x44, 0x44, 0x44, 0x44, 0xee, 0x00, 0x10, 0x10,
0x10, 0x20, 0x0b, 0x9e, 0x10, 0x22, 0x00, 0x1c, 0x00, 0x08, 0x00, 0x00, 0x00, 0xe3, 0x80, 0x61,
0x00, 0x51, 0x00, 0x59, 0x00, 0x49, 0x00, 0x4d, 0x00, 0x45, 0x00, 0x45, 0x00, 0x43, 0x00, 0xe1,
0x00, 0x07, 0x7b, 0x02, 0x44, 0x38, 0x10, 0x00, 0xd8, 0x6c, 0x44, 0x44, 0x44, 0x44, 0xee, 0x0b,
0xaa, 0x13, 0xc0, 0x00, 0x40, 0x00, 0x80, 0x00, 0x1b, 0x00, 0x0d, 0x80, 0x08, 0x80, 0x08, 0x80,
0x08, 0x80, 0x08, 0x80, 0x1d, 0xc0, 0x0b, 0x9d, 0x13, 0xe3, 0x80, 0x61, 0x00, 0x51, 0x00, 0x59,
0x00, 0x49, 0x00, 0x4d, 0x00, 0x45, 0x00, 0x45, 0x00, 0x43, 0x00, 0xe1, 0x00, 0x01, 0x00, 0x05,
0x00, 0x06, 0x00, 0x07, 0x6a, 0x06, 0xd8, 0x6c, 0x44, 0x44, 0x44, 0x44, 0xe4, 0x04, 0x14, 0x18,
0x0a, 0x8c, 0x11, 0x3c, 0x00, 0x3c, 0x66, 0x42, 0x81, 0x81, 0x81, 0x81, 0x42, 0x66, 0x3c, 0x07,
0x59, 0x14, 0x78, 0x00, 0x70, 0xd8, 0x88, 0x88, 0x88, 0xd8, 0x70, 0x0a, 0x8e, 0x10, 0x24, 0x24,
0x18, 0x00, 0x3c, 0x66, 0x42, 0x81, 0x81, 0x81, 0x81, 0x42, 0x66, 0x3c, 0x07, 0x5b, 0x12, 0x48,
0x48, 0x30, 0x00, 0x70, 0xd8, 0x88, 0x88, 0x88, 0xd8, 0x70, 0x0a, 0x8e, 0x10, 0x09, 0x1b, 0x24,
0x00, 0x3c, 0x66, 0x42, 0x81, 0x81, 0x81, 0x81, 0x42, 0x66, 0x3c, 0x07, 0x6b, 0x12, 0x24, 0x6c,
0x90, 0x00, 0x70, 0xd8, 0x88, 0x88, 0x88, 0xd8, 0x70, 0x0d, 0xba, 0x13, 0x1f, 0xe0, 0x64, 0x20,
0x44, 0x00, 0x84, 0x40, 0x87, 0xc0, 0x84, 0x40, 0x84, 0x00, 0x44, 0x20, 0x64, 0x20, 0x1f, 0xe0,
0x0b, 0xa7, 0x16, 0x77, 0x00, 0xd9, 0x80, 0x8f, 0x00, 0x88, 0x00, 0x88, 0x00, 0xdc, 0x40, 0x77,
0x80, 0x09, 0x9e, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x26, 0x00,
0x22, 0x00, 0x22, 0x00, 0x26, 0x00, 0x3c, 0x00, 0x24, 0x00, 0x22, 0x00, 0x23, 0x00, 0xf1, 0x80,
0x05, 0x5b, 0x02, 0x08, 0x18, 0x20, 0x00, 0xb8, 0x68, 0x40, 0x40, 0x40, 0x40, 0xe0, 0x09, 0x9f,
0x03, 0xfc, 0x00, 0x26, 0x00, 0x22, 0x00, 0x22, 0x00, 0x26, 0x00, 0x3c, 0x00, 0x24, 0x00, 0x22,
0x00, 0x23, 0x00, 0xf1, 0x80, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x10, 0x00, 0x05,
0x5c, 0x06, 0xb8, 0x68, 0x40, 0x40, 0x40, 0x40, 0xe0, 0x00, 0x20, 0x20, 0x20, 0x40, 0x09, 0x9e,
0x00, 0x22, 0x00, 0x1c, 0x00, 0x08, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x26, 0x00, 0x22, 0x00, 0x22,
0x00, 0x26, 0x00, 0x3c, 0x00, 0x24, 0x00, 0x22, 0x00, 0x23, 0x00, 0xf1, 0x80, 0x05, 0x5b, 0x02,
0x88, 0x70, 0x20, 0x00, 0xb8, 0x68, 0x40, 0x40, 0x40, 0x40, 0xe0, 0x08, 0x6e, 0x10, 0x08, 0x18,
0x20, 0x00, 0x74, 0xcc, 0x84, 0xc0, 0x70, 0x18, 0x04, 0x84, 0xcc, 0xb8, 0x06, 0x4b, 0x12, 0x10,
0x30, 0x40, 0x00, 0x70, 0x90, 0xc0, 0x60, 0x30, 0x90, 0xe0, 0x08, 0x6e, 0x10, 0x10, 0x38, 0x44,
0x00, 0x74, 0xcc, 0x84, 0xc0, 0x70, 0x18, 0x04, 0x84, 0xcc, 0xb8, 0x06, 0x5b, 0x12, 0x20, 0x70,
0x88, 0x00, 0x70, 0x90, 0xc0, 0x60, 0x30, 0x90, 0xe0, 0x08, 0x6d, 0x13, 0x74, 0xcc, 0x84, 0xc0,
0x70, 0x18, 0x04, 0x84, 0xcc, 0xb8, 0x20, 0x10, 0x60, 0x06, 0x4a, 0x16, 0x70, 0x90, 0xc0, 0x60,
0x30, 0x90, 0xe0, 0x40, 0x20, 0xc0, 0x08, 0x6e, 0x10, 0x44, 0x38, 0x10, 0x00, 0x74, 0xcc, 0x84,
0xc0, 0x70, 0x18, 0x04, 0x84, 0xcc, 0xb8, 0x06, 0x5b, 0x12, 0x88, 0x70, 0x20, 0x00, 0x70, 0x90,
0xc0, 0x60, 0x30, 0x90, 0xe0, 0x09, 0x7d, 0x13, 0xfe, 0x92, 0x92, 0x10, 0x10, 0x10, 0x10, 0x10,
0x10, 0x38, 0x10, 0x08, 0x30, 0x04, 0x4c, 0x04, 0x40, 0x40, 0xf0, 0x40, 0x40, 0x40, 0x40, 0x40,
0x30, 0x20, 0x10, 0x60, 0x09, 0x7e, 0x10, 0x44, 0x38, 0x10, 0x00, 0xfe, 0x92, 0x92, 0x10, 0x10,
0x10, 0x10, 0x10, 0x10, 0x38, 0x08, 0x7a, 0x03, 0x06, 0x42, 0x44, 0xf0, 0x40, 0x40, 0x40, 0x40,
0x40, 0x30, 0x09, 0x7a, 0x13, 0xfe, 0x92, 0x92, 0x10, 0x38, 0x10, 0x10, 0x10, 0x10, 0x38, 0x04,
0x49, 0x04, 0x40, 0x40, 0xf0, 0x40, 0x40, 0x70, 0x40, 0x40, 0x30, 0x0a, 0x8d, 0x10, 0x1a, 0x2c,
0x00, 0xe7, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x66, 0x3c, 0x07, 0x7a, 0x03, 0x34, 0x58,
0x00, 0xcc, 0x44, 0x44, 0x44, 0x44, 0x6c, 0x36, 0x0a, 0x8c, 0x11, 0x3c, 0x00, 0xe7, 0x42, 0x42,
0x42, 0x42, 0x42, 0x42, 0x42, 0x66, 0x3c, 0x07, 0x79, 0x04, 0x78, 0x00, 0xcc, 0x44, 0x44, 0x44,
0x44, 0x6c, 0x36, 0x0a, 0x8e, 0x10, 0x24, 0x24, 0x18, 0x00, 0xe7, 0x42, 0x42, 0x42, 0x42, 0x42,
0x42, 0x42, 0x66, 0x3c, 0x07, 0x7b, 0x02, 0x48, 0x48, 0x30, 0x00, 0xcc, 0x44, 0x44, 0x44, 0x44,
0x6c, 0x36, 0x0a, 0x8e, 0x10, 0x08, 0x14, 0x08, 0x00, 0xe7, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
0x42, 0x66, 0x3c, 0x07, 0x7b, 0x02, 0x10, 0x28, 0x10, 0x00, 0xcc, 0x44, 0x44, 0x44, 0x44, 0x6c,
0x36, 0x0a, 0x8e, 0x10, 0x09, 0x1b, 0x24, 0x00, 0xe7, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
0x66, 0x3c, 0x07, 0x7b, 0x02, 0x12, 0x36, 0x48, 0x00, 0xcc, 0x44, 0x44, 0x44, 0x44, 0x6c, 0x36,
0x0a, 0x8d, 0x13, 0xe7, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x66, 0x3c, 0x10, 0x24, 0x18,
0x07, 0x7a, 0x06, 0xcc, 0x44, 0x44, 0x44, 0x44, 0x6c, 0x36, 0x10, 0x24, 0x18, 0x0d, 0xde, 0x00,
0x02, 0x00, 0x07, 0x00, 0x08, 0x80, 0x00, 0x00, 0xe7, 0x38, 0x42, 0x10, 0x62, 0x30, 0x22, 0x20,
0x22, 0x20, 0x35, 0x60, 0x15, 0x40, 0x18, 0xc0, 0x18, 0xc0, 0x08, 0x80, 0x0b, 0xbb, 0x02, 0x04,
0x00, 0x0e, 0x00, 0x11, 0x00, 0x00, 0x00, 0xee, 0xe0, 0x44, 0x40, 0x44, 0x40, 0x24, 0x80, 0x3b,
0x80, 0x11, 0x00, 0x11, 0x00, 0x09, 0x9e, 0x00, 0x08, 0x00, 0x1c, 0x00, 0x22, 0x00, 0x00, 0x00,
0xe3, 0x80, 0x41, 0x00, 0x22, 0x00, 0x32, 0x00, 0x14, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00,
0x08, 0x00, 0x1c, 0x00, 0x07, 0x7e, 0x02, 0x10, 0x38, 0x44, 0x00, 0xee, 0x44, 0x44, 0x28, 0x28,
0x10, 0x30, 0x20, 0xa0, 0xc0, 0x09, 0x9d, 0x00, 0x12, 0x00, 0x12, 0x00, 0x00, 0x00, 0xe3, 0x80,
0x41, 0x00, 0x22, 0x00, 0x32, 0x00, 0x14, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00,
0x1c, 0x00, 0x08, 0x8e, 0x00, 0x02, 0x06, 0x08, 0x00, 0x7f, 0x43, 0x46, 0x04, 0x08, 0x18, 0x30,
0x60, 0xc1, 0xff, 0x06, 0x6b, 0x02, 0x08, 0x18, 0x20, 0x00, 0xfc, 0x88, 0x18, 0x30, 0x60, 0xc4,
0xfc, 0x08, 0x8d, 0x00, 0x08, 0x08, 0x00, 0x7f, 0x43, 0x46, 0x04, 0x08, 0x18, 0x30, 0x60, 0xc1,
0xff, 0x06, 0x6a, 0x03, 0x20, 0x20, 0x00, 0xfc, 0x88, 0x18, 0x30, 0x60, 0xc4, 0xfc, 0x08, 0x8e,
0x00, 0x22, 0x1c, 0x08, 0x00, 0x7f, 0x43, 0x46, 0x04, 0x08, 0x18, 0x30, 0x60, 0xc1, 0xff, 0x06,
0x6b, 0x02, 0x88, 0x70, 0x20, 0x00, 0xfc, 0x88, 0x18, 0x30, 0x60, 0xc4, 0xfc, 0x09, 0x7f, 0x13,
0xfe, 0x92, 0x92, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x38, 0x00, 0x10, 0x10, 0x10, 0x20, 0x04,
0x4e, 0x04, 0x40, 0x40, 0xf0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x30, 0x00, 0x20, 0x20, 0x20, 0x40,
0x04, 0x43, 0x03, 0x30, 0x60, 0x80, 0x04, 0x43, 0x0e, 0x10, 0x60, 0xc0, 0x04, 0x29, 0x06, 0x40,
0x40, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x80, 0x05, 0x33, 0x12, 0x20, 0x60, 0x80, 0x05, 0x46,
0x10, 0x10, 0x30, 0x40, 0x00, 0xa0, 0xa0, 0x0c, 0xba, 0x03, 0x22, 0x00, 0x67, 0x00, 0x85, 0x00,
0x05, 0x00, 0x08, 0x80, 0x08, 0x80, 0x0f, 0x80, 0x18, 0xc0, 0x10, 0x40, 0x38, 0xe0, 0x04, 0x12,
0x18, 0x80, 0x80, 0x0b, 0xaa, 0x03, 0x3f, 0xc0, 0x68, 0x40, 0x88, 0x00, 0x08, 0x80, 0x0f, 0x80,
0x08, 0x80, 0x08, 0x00, 0x08, 0x40, 0x08, 0x40, 0x1f, 0xc0, 0x0c, 0xba, 0x03, 0x38, 0xe0, 0x70,
0x40, 0x90, 0x40, 0x10, 0x40, 0x1f, 0xc0, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x38,
0xe0, 0x07, 0x6a, 0x03, 0x3c, 0x68, 0x88, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x1c, 0x0c, 0xba,
0x03, 0x27, 0x80, 0x6c, 0xc0, 0x88, 0x40, 0x10, 0x20, 0x10, 0x20, 0x10, 0x20, 0x10, 0x20, 0x08,
0x40, 0x0c, 0xc0, 0x07, 0x80, 0x0b, 0xba, 0x03, 0x38, 0xe0, 0x70, 0x40, 0x88, 0x80, 0x08, 0x80,
0x05, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x07, 0x00, 0x0d, 0xca, 0x03, 0x23,
0x00, 0x6c, 0xc0, 0x88, 0x40, 0x10, 0x20, 0x10, 0x20, 0x10, 0x20, 0x10, 0x20, 0x08, 0x40, 0x24,
0x90, 0x3c, 0xf0, 0x05, 0x5e, 0x00, 0x08, 0x18, 0x20, 0x00, 0x50, 0x50, 0x00, 0x60, 0xa0, 0x20,
0x20, 0x20, 0x28, 0x30, 0x0b, 0x9a, 0x13, 0x08, 0x00, 0x1c, 0x00, 0x14, 0x00, 0x14, 0x00, 0x22,
0x00, 0x22, 0x00, 0x3e, 0x00, 0x63, 0x00, 0x41, 0x00, 0xe3, 0x80, 0x09, 0x7a, 0x13, 0xfc, 0x46,
0x42, 0x46, 0x7c, 0x46, 0x42, 0x42, 0x46, 0xfc, 0x09, 0x7a, 0x13, 0xfe, 0x42, 0x40, 0x40, 0x40,
0x40, 0x40, 0x40, 0x40, 0xe0, 0x09, 0x7a, 0x13, 0x10, 0x10, 0x28, 0x28, 0x28, 0x44, 0x44, 0x44,
0x82, 0xfe, 0x09, 0x7a, 0x13, 0xfe, 0x42, 0x40, 0x44, 0x7c, 0x44, 0x40, 0x42, 0x42, 0xfe, 0x09,
0x7a, 0x13, 0xfe, 0x82, 0x04, 0x08, 0x10, 0x10, 0x20, 0x40, 0x82, 0xfe, 0x0b, 0x9a, 0x13, 0xe3,
0x80, 0x41, 0x00, 0x41, 0x00, 0x41, 0x00, 0x7f, 0x00, 0x41, 0x00, 0x41, 0x00, 0x41, 0x00, 0x41,
0x00, 0xe3, 0x80, 0x0a, 0x8a, 0x13, 0x3c, 0x66, 0x42, 0xa5, 0xbd, 0xa5, 0x81, 0x42, 0x66, 0x3c,
0x05, 0x3a, 0x13, 0xe0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0xe0, 0x0a, 0x8a, 0x13,
0xee, 0x44, 0x48, 0x50, 0x70, 0x50, 0x48, 0x44, 0x42, 0xe7, 0x0a, 0x9a, 0x03, 0x08, 0x00, 0x08,
0x00, 0x14, 0x00, 0x36, 0x00, 0x22, 0x00, 0x22, 0x00, 0x63, 0x00, 0x41, 0x00, 0x41, 0x00, 0xe3,
0x80, 0x0d, 0xba, 0x13, 0xe0, 0xe0, 0x60, 0xc0, 0x51, 0x40, 0x51, 0x40, 0x5b, 0x40, 0x4a, 0x40,
0x4a, 0x40, 0x4e, 0x40, 0x44, 0x40, 0xe4, 0xe0, 0x0b, 0x9a, 0x13, 0xe3, 0x80, 0x61, 0x00, 0x51,
0x00, 0x59, 0x00, 0x49, 0x00, 0x4d, 0x00, 0x45, 0x00, 0x47, 0x00, 0x43, 0x00, 0xe1, 0x00, 0x09,
0x9a, 0x03, 0x7f, 0x00, 0x41, 0x00, 0x00, 0x00, 0x22, 0x00, 0x3e, 0x00, 0x22, 0x00, 0x00, 0x00,
0x00, 0x00, 0x80, 0x80, 0xff, 0x80, 0x0a, 0x8a, 0x13, 0x3c, 0x66, 0x42, 0x81, 0x81, 0x81, 0x81,
0x42, 0x66, 0x3c, 0x0b, 0x9a, 0x13, 0xff, 0x80, 0x41, 0x00, 0x41, 0x00, 0x41, 0x00, 0x41, 0x00,
0x41, 0x00, 0x41, 0x00, 0x41, 0x00, 0x41, 0x00, 0xe3, 0x80, 0x08, 0x6a, 0x13, 0xf8, 0x4c, 0x44,
0x44, 0x4c, 0x78, 0x40, 0x40, 0x40, 0xe0, 0x09, 0x8a, 0x13, 0xfe, 0xc2, 0x60, 0x30, 0x18, 0x10,
0x20, 0x40, 0xc1, 0xff, 0x09, 0x7a, 0x13, 0xfe, 0x92, 0x92, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
0x38, 0x09, 0x9a, 0x03, 0xe3, 0x80, 0x41, 0x00, 0x22, 0x00, 0x22, 0x00, 0x14, 0x00, 0x08, 0x00,
0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x1c, 0x00, 0x0b, 0x9a, 0x13, 0x1c, 0x00, 0x08, 0x00, 0x7f,
0x00, 0xc9, 0x80, 0x88, 0x80, 0x88, 0x80, 0xc9, 0x80, 0x7f, 0x00, 0x08, 0x00, 0x1c, 0x00, 0x0b,
0x9a, 0x13, 0xe3, 0x80, 0x41, 0x00, 0x22, 0x00, 0x36, 0x00, 0x1c, 0x00, 0x14, 0x00, 0x22, 0x00,
0x63, 0x00, 0x41, 0x00, 0xe3, 0x80, 0x0b, 0xba, 0x03, 0xce, 0x60, 0x64, 0xc0, 0x24, 0x80, 0x24,
0x80, 0x1f, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x0b, 0xaa, 0x03,
0x0c, 0x00, 0x33, 0x00, 0x21, 0x00, 0x40, 0x80, 0x40, 0x80, 0x40, 0x80, 0x40, 0x80, 0x21, 0x00,
0x92, 0x40, 0xf3, 0xc0, 0x05, 0x3d, 0x10, 0xa0, 0xa0, 0x00, 0xe0, 0x40, 0x40, 0x40, 0x40, 0x40,
0x40, 0x40, 0x40, 0xe0, 0x09, 0x9d, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00, 0xe3, 0x80, 0x41,
0x00, 0x22, 0x00, 0x22, 0x00, 0x14, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x1c,
0x00, 0x09, 0x8b, 0x12, 0x04, 0x0c, 0x10, 0x00, 0x76, 0xd4, 0x88, 0x88, 0x88, 0xd5, 0x66, 0x06,
0x5b, 0x12, 0x08, 0x18, 0x20, 0x00, 0x78, 0xc8, 0x80, 0x60, 0x80, 0xc8, 0x70, 0x08, 0x7e, 0x02,
0x04, 0x0c, 0x10, 0x00, 0x6c, 0xb2, 0x22, 0x22, 0x22, 0x22, 0x22, 0x02, 0x02, 0x02, 0x05, 0x5b,
0x02, 0x10, 0x30, 0x40, 0x00, 0x60, 0xa0, 0x20, 0x20, 0x20, 0x28, 0x30, 0x08, 0x7e, 0x00, 0x04,
0x0c, 0x10, 0x00, 0x28, 0x28, 0x00, 0x64, 0xa2, 0x22, 0x22, 0x22, 0x26, 0x1c, 0x09, 0x87, 0x16,
0x76, 0xd4, 0x88, 0x88, 0x88, 0xd5, 0x66, 0x08, 0x6e, 0x12, 0x78, 0xcc, 0x84, 0x8c, 0x98, 0x8c,
0x84, 0x84, 0x84, 0xcc, 0xb8, 0x80, 0x80, 0x80, 0x06, 0x6a, 0x06, 0xc4, 0xa4, 0x24, 0x28, 0x28,
0x18, 0x18, 0x10, 0x30, 0x30, 0x07, 0x5b, 0x12, 0x70, 0x98, 0x80, 0x40, 0x70, 0x98, 0x88, 0x88,
0x88, 0xd8, 0x70, 0x06, 0x57, 0x16, 0x78, 0xc8, 0x80, 0x60, 0x80, 0xc8, 0x70, 0x07, 0x6e, 0x12,
0x20, 0x44, 0x3c, 0x10, 0x20, 0x40, 0x40, 0x80, 0x80, 0xc0, 0x78, 0x04, 0x24, 0x38, 0x08, 0x7a,
0x06, 0x6c, 0xb2, 0x22, 0x22, 0x22, 0x22, 0x22, 0x02, 0x02, 0x02, 0x07, 0x5a, 0x13, 0x70, 0xd8,
0x88, 0x88, 0xf8, 0x88, 0x88, 0x88, 0xd8, 0x70, 0x05, 0x57, 0x06, 0x60, 0xa0, 0x20, 0x20, 0x20,
0x28, 0x30, 0x08, 0x77, 0x06, 0x46, 0xca, 0x50, 0x70, 0x58, 0x4c, 0x46, 0x08, 0x8a, 0x13, 0x60,
0x50, 0x10, 0x10, 0x28, 0x28, 0x48, 0x44, 0x85, 0x83, 0x07, 0x7a, 0x06, 0xcc, 0x44, 0x44, 0x44,
0x44, 0x6c, 0x76, 0x40, 0x40, 0x60, 0x08, 0x77, 0x06, 0xc6, 0x42, 0x22, 0x22, 0x14, 0x14, 0x08,
0x07, 0x6f, 0x11, 0x20, 0x40, 0x38, 0x20, 0x40, 0x78, 0x20, 0x40, 0x80, 0x80, 0xc0, 0x78, 0x04,
0x24, 0x38, 0x08, 0x67, 0x16, 0x78, 0xcc, 0x84, 0x84, 0x84, 0xcc, 0x78, 0x08, 0x87, 0x06, 0x7e,
0xa4, 0x24, 0x24, 0x24, 0x25, 0x66, 0x08, 0x6a, 0x16, 0x78, 0xcc, 0x84, 0x84, 0x84, 0xcc, 0xb8,
0x80, 0x80, 0x80, 0x07, 0x6a, 0x16, 0x38, 0xc0, 0x80, 0x80, 0x80, 0x60, 0x38, 0x04, 0x24, 0x38,
0x08, 0x77, 0x16, 0x7e, 0xc8, 0x84, 0x84, 0x84, 0xcc, 0x78, 0x06, 0x57, 0x06, 0x78, 0xa0, 0x20,
0x20, 0x20, 0x28, 0x30, 0x08, 0x77, 0x06, 0x64, 0xa2, 0x22, 0x22, 0x22, 0x26, 0x1c, 0x09, 0x7a,
0x16, 0x18, 0x54, 0xd2, 0x92, 0x92, 0x54, 0x38, 0x10, 0x10, 0x10, 0x08, 0x8a, 0x06, 0xc3, 0xa6,
0x24, 0x3c, 0x18, 0x38, 0x28, 0x64, 0x45, 0xc3, 0x09, 0x9a, 0x06, 0x88, 0x80, 0x49, 0x00, 0x49,
0x00, 0x49, 0x00, 0x6b, 0x00, 0x3e, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x0b,
0x97, 0x16, 0x63, 0x00, 0x88, 0x80, 0x88, 0x80, 0x88, 0x80, 0x88, 0x80, 0xc9, 0x80, 0x77, 0x00,
0x05, 0x5a, 0x03, 0x50, 0x50, 0x00, 0x60, 0xa0, 0x20, 0x20, 0x20, 0x28, 0x30, 0x08, 0x7a, 0x03,
0x28, 0x28, 0x00, 0x64, 0xa2, 0x22, 0x22, 0x22, 0x26, 0x1c, 0x08, 0x6b, 0x12, 0x08, 0x18, 0x20,
0x00, 0x78, 0xcc, 0x84, 0x84, 0x84, 0xcc, 0x78, 0x08, 0x7b, 0x02, 0x08, 0x18, 0x20, 0x00, 0x64,
0xa2, 0x22, 0x22, 0x22, 0x26, 0x1c, 0x0b, 0x9b, 0x12, 0x02, 0x00, 0x06, 0x00, 0x08, 0x00, 0x00,
0x00, 0x63, 0x00, 0x88, 0x80, 0x88, 0x80, 0x88, 0x80, 0x88, 0x80, 0xc9, 0x80, 0x77, 0x00, 0x09,
0x8a, 0x03, 0x0c, 0x0a, 0x0a, 0x66, 0xa3, 0x22, 0x22, 0x22, 0x36, 0x1c, 0x09, 0x8a, 0x03, 0xc6,
0x69, 0x2b, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x38, 0x09, 0x8e, 0x00, 0x04, 0x0c, 0x10, 0x00,
0xc6, 0x69, 0x2b, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x38, 0x09, 0x8d, 0x00, 0x14, 0x14, 0x00,
0xc6, 0x69, 0x2b, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x38, 0x09, 0x7d, 0x13, 0x10, 0x10, 0x10,
0x38, 0x54, 0x92, 0x92, 0x92, 0x54, 0x38, 0x10, 0x10, 0x10, 0x0b, 0xa8, 0x05, 0x7f, 0xc0, 0xa0,
0x80, 0x44, 0x40, 0x44, 0x40, 0x44, 0x40, 0x44, 0x40, 0x64, 0xc0, 0x3b, 0x80, 0x09, 0x7e, 0x10,
0x20, 0x10, 0x00, 0xfe, 0x80, 0x80, 0x80, 0x80, 0xfc, 0x80, 0x80, 0x80, 0x80, 0xfe, 0x09, 0x7d,
0x10, 0x6c, 0x00, 0xfe, 0x80, 0x80, 0x80, 0x80, 0xfc, 0x80, 0x80, 0x80, 0x80, 0xfe, 0x0c, 0xbb,
0x02, 0xff, 0x80, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x0f, 0x80, 0x08, 0x40, 0x08, 0x20, 0x08,
0x20, 0x08, 0x20, 0x08, 0x40, 0x09, 0x80, 0x07, 0x6e, 0x10, 0x10, 0x20, 0x00, 0xfc, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x0a, 0x8b, 0x12, 0x1c, 0x63, 0x41, 0x80, 0x80,
0xfc, 0x80, 0x80, 0x41, 0x63, 0x1c, 0x09, 0x7b, 0x12, 0x38, 0xc6, 0x82, 0x80, 0x60, 0x18, 0x06,
0x02, 0x82, 0xc6, 0x38, 0x05, 0x1b, 0x22, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x05, 0x5d, 0x00, 0xd8, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x08, 0x6b, 0x12, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x84, 0x84, 0x78,
0x0e, 0xdb, 0x02, 0x3f, 0x00, 0x21, 0x00, 0x21, 0x00, 0x21, 0x00, 0x21, 0x00, 0x21, 0xf0, 0x21,
0x18, 0x21, 0x08, 0x21, 0x08, 0x21, 0x18, 0xc1, 0xf0, 0x0e, 0xcb, 0x12, 0x82, 0x00, 0x82, 0x00,
0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0xff, 0xe0, 0x82, 0x30, 0x82, 0x10, 0x82, 0x10, 0x82, 0x30,
0x83, 0xe0, 0x0c, 0xbb, 0x02, 0xff, 0x80, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x0f, 0x80, 0x08,
0x40, 0x08, 0x20, 0x08, 0x20, 0x08, 0x20, 0x08, 0x20, 0x08, 0x20, 0x0a, 0x8e, 0x10, 0x08, 0x10,
0x00, 0x82, 0x84, 0x88, 0x90, 0xa0, 0xe0, 0x90, 0x88, 0x84, 0x82, 0x81, 0x0a, 0x8e, 0x10, 0x10,
0x08, 0x00, 0x83, 0x83, 0x85, 0x89, 0x89, 0x91, 0x91, 0xa1, 0xa1, 0xc1, 0xc1, 0x0b, 0x9e, 0x10,
0x22, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x41, 0x00, 0x41, 0x00, 0x22, 0x00,
0x22, 0x00, 0x14, 0x00, 0x14, 0x00, 0x08, 0x00, 0x10, 0x00, 0x60, 0x00, 0x0a, 0x8d, 0x12, 0x81,
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xff, 0x08, 0x08, 0x0b, 0x9b, 0x12, 0x08,
0x00, 0x08, 0x00, 0x14, 0x00, 0x14, 0x00, 0x22, 0x00, 0x22, 0x00, 0x41, 0x00, 0x7f, 0x00, 0x41,
0x00, 0x80, 0x80, 0x80, 0x80, 0x09, 0x7b, 0x12, 0xfe, 0x80, 0x80, 0x80, 0x80, 0xfc, 0x86, 0x82,
0x82, 0x86, 0xfc, 0x09, 0x7b, 0x12, 0xfc, 0x86, 0x82, 0x82, 0x82, 0xfc, 0x82, 0x82, 0x82, 0x82,
0xfc, 0x07, 0x6b, 0x12, 0xfc, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x0a,
0xad, 0x02, 0x3f, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80,
0x20, 0x80, 0x40, 0x80, 0x40, 0x80, 0xff, 0xc0, 0x80, 0x40, 0x80, 0x40, 0x09, 0x7b, 0x12, 0xfe,
0x80, 0x80, 0x80, 0x80, 0xfc, 0x80, 0x80, 0x80, 0x80, 0xfe, 0x0f, 0xdb, 0x12, 0x82, 0x08, 0x42,
0x10, 0x22, 0x20, 0x12, 0x40, 0x0a, 0x80, 0x07, 0x00, 0x0a, 0x80, 0x12, 0x40, 0x22, 0x20, 0x42,
0x10, 0x82, 0x08, 0x09, 0x7b, 0x12, 0x38, 0xc6, 0x82, 0x02, 0x06, 0x18, 0x06, 0x02, 0x82, 0xc6,
0x38, 0x0a, 0x8b, 0x12, 0x83, 0x83, 0x85, 0x89, 0x89, 0x91, 0x91, 0xa1, 0xa1, 0xc1, 0xc1, 0x0a,
0x8e, 0x10, 0x24, 0x3c, 0x00, 0x83, 0x83, 0x85, 0x89, 0x89, 0x91, 0x91, 0xa1, 0xa1, 0xc1, 0xc1,
0x0a, 0x8b, 0x12, 0x82, 0x84, 0x88, 0x90, 0xa0, 0xe0, 0x90, 0x88, 0x84, 0x82, 0x81, 0x0a, 0x9b,
0x02, 0x3f, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20,
0x80, 0x20, 0x80, 0x20, 0x80, 0xc0, 0x80, 0x0d, 0xbb, 0x12, 0x80, 0x20, 0x80, 0x20, 0xc0, 0x60,
0xa0, 0xa0, 0xa0, 0xa0, 0x91, 0x20, 0x91, 0x20, 0x8a, 0x20, 0x8a, 0x20, 0x84, 0x20, 0x84, 0x20,
0x0a, 0x8b, 0x12, 0x81, 0x81, 0x81, 0x81, 0x81, 0xff, 0x81, 0x81, 0x81, 0x81, 0x81, 0x0b, 0x9b,
0x12, 0x1c, 0x00, 0x63, 0x00, 0x41, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x41, 0x00, 0x63, 0x00, 0x1c, 0x00, 0x0a, 0x8b, 0x12, 0xff, 0x81, 0x81, 0x81, 0x81, 0x81,
0x81, 0x81, 0x81, 0x81, 0x81, 0x09, 0x7b, 0x12, 0xfc, 0x86, 0x82, 0x82, 0x86, 0xfc, 0x80, 0x80,
0x80, 0x80, 0x80, 0x0a, 0x8b, 0x12, 0x1c, 0x63, 0x41, 0x80, 0x80, 0x80, 0x80, 0x80, 0x41, 0x63,
0x1c, 0x09, 0x9b, 0x02, 0xff, 0x80, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00,
0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x0b, 0x9b, 0x12, 0x80, 0x80, 0x80,
0x80, 0x41, 0x00, 0x41, 0x00, 0x22, 0x00, 0x22, 0x00, 0x14, 0x00, 0x14, 0x00, 0x08, 0x00, 0x10,
0x00, 0x60, 0x00, 0x0d, 0xbb, 0x12, 0x04, 0x00, 0x1f, 0x00, 0x64, 0xc0, 0x44, 0x40, 0x84, 0x20,
0x84, 0x20, 0x44, 0x40, 0x64, 0xc0, 0x1f, 0x00, 0x04, 0x00, 0x04, 0x00, 0x0a, 0x8b, 0x12, 0x81,
0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x42, 0x81, 0x81, 0x0a, 0x9d, 0x12, 0x81, 0x00, 0x81,
0x00, 0x81, 0x00, 0x81, 0x00, 0x81, 0x00, 0x81, 0x00, 0x81, 0x00, 0x81, 0x00, 0x81, 0x00, 0x81,
0x00, 0xff, 0x80, 0x00, 0x80, 0x00, 0x80, 0x0a, 0x8b, 0x12, 0x81, 0x81, 0x81, 0x81, 0x81, 0x41,
0x3f, 0x01, 0x01, 0x01, 0x01, 0x0d, 0xbb, 0x12, 0x84, 0x20, 0x84, 0x20, 0x84, 0x20, 0x84, 0x20,
0x84, 0x20, 0x84, 0x20, 0x84, 0x20, 0x84, 0x20, 0x84, 0x20, 0x84, 0x20, 0xff, 0xe0, 0x0d, 0xcd,
0x12, 0x84, 0x20, 0x84, 0x20, 0x84, 0x20, 0x84, 0x20, 0x84, 0x20, 0x84, 0x20, 0x84, 0x20, 0x84,
0x20, 0x84, 0x20, 0x84, 0x20, 0xff, 0xf0, 0x00, 0x10, 0x00, 0x10, 0x0a, 0x9b, 0x02, 0xe0, 0x00,
0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x3f, 0x00, 0x21, 0x80, 0x20, 0x80, 0x20, 0x80,
0x21, 0x80, 0x3f, 0x00, 0x0c, 0xab, 0x12, 0x80, 0x40, 0x80, 0x40, 0x80, 0x40, 0x80, 0x40, 0x80,
0x40, 0xfc, 0x40, 0x86, 0x40, 0x82, 0x40, 0x82, 0x40, 0x86, 0x40, 0xfc, 0x40, 0x09, 0x7b, 0x12,
0x80, 0x80, 0x80, 0x80, 0x80, 0xfc, 0x86, 0x82, 0x82, 0x86, 0xfc, 0x0a, 0x8b, 0x12, 0x38, 0xc6,
0x82, 0x01, 0x01, 0x3f, 0x01, 0x01, 0x82, 0xc6, 0x38, 0x0e, 0xcb, 0x12, 0x83, 0x80, 0x8c, 0x60,
0x88, 0x20, 0x90, 0x10, 0x90, 0x10, 0xf0, 0x10, 0x90, 0x10, 0x90, 0x10, 0x88, 0x20, 0x8c, 0x60,
0x83, 0x80, 0x09, 0x7b, 0x12, 0x7e, 0xc2, 0x82, 0x82, 0x42, 0x3e, 0x22, 0x42, 0x42, 0x82, 0x82,
0x08, 0x78, 0x15, 0x78, 0xcc, 0x04, 0x7c, 0xc4, 0x84, 0xcc, 0x76, 0x08, 0x6c, 0x11, 0x04, 0x38,
0x40, 0x80, 0xb8, 0xcc, 0x84, 0x84, 0x84, 0x84, 0xcc, 0x78, 0x08, 0x68, 0x15, 0xf8, 0x84, 0x84,
0xf8, 0x8c, 0x84, 0x84, 0xf8, 0x06, 0x58, 0x15, 0xf8, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x08, 0x8a, 0x05, 0x3e, 0x22, 0x22, 0x22, 0x22, 0x42, 0x42, 0xff, 0x81, 0x81, 0x08, 0x68, 0x15,
0x78, 0xcc, 0x84, 0xfc, 0x80, 0x80, 0xcc, 0x78, 0x0b, 0x98, 0x15, 0x88, 0x80, 0x49, 0x00, 0x2a,
0x00, 0x1c, 0x00, 0x1c, 0x00, 0x2a, 0x00, 0x49, 0x00, 0x88, 0x80, 0x08, 0x68, 0x15, 0x78, 0x84,
0x04, 0x38, 0x0c, 0x04, 0x84, 0x78, 0x08, 0x68, 0x15, 0x84, 0x8c, 0x94, 0x94, 0xa4, 0xa4, 0xc4,
0x84, 0x08, 0x6b, 0x12, 0x48, 0x30, 0x00, 0x84, 0x8c, 0x94, 0x94, 0xa4, 0xa4, 0xc4, 0x84, 0x07,
0x68, 0x15, 0x88, 0x90, 0xa0, 0xc0, 0xa0, 0x90, 0x88, 0x84, 0x08, 0x78, 0x05, 0x3e, 0x22, 0x22,
0x22, 0x22, 0x22, 0x22, 0xc2, 0x0b, 0x98, 0x15, 0xc1, 0x80, 0xc1, 0x80, 0xa2, 0x80, 0xa2, 0x80,
0x94, 0x80, 0x94, 0x80, 0x88, 0x80, 0x88, 0x80, 0x08, 0x68, 0x15, 0x84, 0x84, 0x84, 0xfc, 0x84,
0x84, 0x84, 0x84, 0x08, 0x68, 0x15, 0x78, 0xcc, 0x84, 0x84, 0x84, 0x84, 0xcc, 0x78, 0x08, 0x68,
0x15, 0xfc, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x08, 0x6b, 0x15, 0xb8, 0xcc, 0x84, 0x84,
0x84, 0x84, 0xcc, 0xb8, 0x80, 0x80, 0x80, 0x08, 0x68, 0x15, 0x78, 0xcc, 0x80, 0x80, 0x80, 0x84,
0xcc, 0x78, 0x07, 0x78, 0x05, 0xfe, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x07, 0x7b, 0x05,
0x82, 0x82, 0x44, 0x44, 0x24, 0x28, 0x18, 0x10, 0x10, 0x30, 0x60, 0x0b, 0x9e, 0x12, 0x08, 0x00,
0x08, 0x00, 0x08, 0x00, 0x7f, 0x00, 0xc9, 0x80, 0x88, 0x80, 0x88, 0x80, 0x88, 0x80, 0x88, 0x80,
0xc9, 0x80, 0x7f, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x07, 0x78, 0x05, 0xc6, 0x44, 0x28,
0x10, 0x10, 0x28, 0x44, 0xc6, 0x08, 0x7a, 0x15, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0xfe,
0x02, 0x02, 0x08, 0x68, 0x15, 0x84, 0x84, 0x84, 0xc4, 0x7c, 0x04, 0x04, 0x04, 0x0b, 0x98, 0x15,
0x88, 0x80, 0x88, 0x80, 0x88, 0x80, 0x88, 0x80, 0x88, 0x80, 0x88, 0x80, 0x88, 0x80, 0xff, 0x80,
0x0b, 0xaa, 0x15, 0x88, 0x80, 0x88, 0x80, 0x88, 0x80, 0x88, 0x80, 0x88, 0x80, 0x88, 0x80, 0x88,
0x80, 0xff, 0xc0, 0x00, 0x40, 0x00, 0x40, 0x09, 0x88, 0x05, 0xe0, 0x20, 0x20, 0x3e, 0x23, 0x21,
0x23, 0x3e, 0x0b, 0x98, 0x15, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xf8, 0x80, 0x8c, 0x80, 0x84,
0x80, 0x8c, 0x80, 0xf8, 0x80, 0x08, 0x68, 0x15, 0x80, 0x80, 0x80, 0xf8, 0x8c, 0x84, 0x8c, 0xf8,
0x08, 0x68, 0x15, 0x78, 0xcc, 0x04, 0x3c, 0x04, 0x84, 0xcc, 0x78, 0x0b, 0x98, 0x15, 0x8f, 0x00,
0x99, 0x80, 0x90, 0x80, 0xf0, 0x80, 0x90, 0x80, 0x90, 0x80, 0x99, 0x80, 0x8f, 0x00, 0x08, 0x68,
0x15, 0x7c, 0xc4, 0x84, 0xc4, 0x7c, 0x44, 0x84, 0x84, 0x08, 0x6b, 0x12, 0x20, 0x10, 0x00, 0x78,
0xcc, 0x84, 0xfc, 0x80, 0x80, 0xcc, 0x78, 0x08, 0x6a, 0x13, 0xcc, 0x00, 0x78, 0xcc, 0x84, 0xfc,
0x80, 0x80, 0xcc, 0x78, 0x08, 0x7e, 0x02, 0x40, 0xf8, 0x40, 0x5c, 0x66, 0x42, 0x42, 0x42, 0x42,
0x42, 0x42, 0x02, 0x02, 0x0c, 0x06, 0x5b, 0x12, 0x10, 0x20, 0x00, 0xf8, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x08, 0x68, 0x15, 0x78, 0xcc, 0x80, 0xf0, 0x80, 0x84, 0xcc, 0x78, 0x08, 0x68,
0x15, 0x78, 0x84, 0x80, 0x78, 0x0c, 0x04, 0x84, 0x78, 0x03, 0x1b, 0x12, 0x80, 0x80, 0x00, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x03, 0x3a, 0x03, 0xa0, 0x00, 0x40, 0x40, 0x40, 0x40,
0x40, 0x40, 0x40, 0x40, 0x04, 0x3e, 0x02, 0x20, 0x20, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0xc0, 0x0d, 0xc8, 0x05, 0x3e, 0x00, 0x22, 0x00, 0x22, 0x00, 0x23, 0xe0,
0x22, 0x30, 0x22, 0x10, 0x22, 0x30, 0xc3, 0xe0, 0x0d, 0xb8, 0x15, 0x84, 0x00, 0x84, 0x00, 0x84,
0x00, 0xff, 0xc0, 0x84, 0x60, 0x84, 0x20, 0x84, 0x60, 0x87, 0xc0, 0x08, 0x7b, 0x02, 0x40, 0xf8,
0x40, 0x5c, 0x66, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x07, 0x6b, 0x12, 0x10, 0x20, 0x00, 0x88,
0x90, 0xa0, 0xc0, 0xa0, 0x90, 0x88, 0x84, 0x08, 0x6b, 0x12, 0x20, 0x10, 0x00, 0x84, 0x8c, 0x94,
0x94, 0xa4, 0xa4, 0xc4, 0x84, 0x07, 0x7e, 0x02, 0x44, 0x38, 0x00, 0x82, 0x82, 0x44, 0x44, 0x24,
0x28, 0x18, 0x10, 0x10, 0x30, 0x60, 0x08, 0x6a, 0x15, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84,
0xfc, 0x10, 0x10, 0x0d, 0xbb, 0x12, 0x11, 0x00, 0x60, 0xc0, 0x40, 0x40, 0x80, 0x20, 0x84, 0x20,
0x84, 0x20, 0x84, 0x20, 0x84, 0x20, 0x44, 0x40, 0x4a, 0x40, 0x31, 0x80, 0x0b, 0x98, 0x15, 0x63,
0x00, 0xc1, 0x80, 0x88, 0x80, 0x88, 0x80, 0x88, 0x80, 0x88, 0x80, 0xdd, 0x80, 0x77, 0x00, 0x0a,
0x9b, 0x02, 0x20, 0x00, 0x20, 0x00, 0xf8, 0x00, 0x20, 0x00, 0x20, 0x00, 0x3f, 0x00, 0x21, 0x80,
0x20, 0x80, 0x20, 0x80, 0x21, 0x80, 0x3f, 0x00, 0x09, 0x8b, 0x02, 0x20, 0x20, 0x20, 0xf8, 0x20,
0x20, 0x3e, 0x23, 0x21, 0x23, 0x3e, 0x0d, 0xbb, 0x12, 0x83, 0x80, 0x8c, 0x60, 0x88, 0x20, 0x90,
0x00, 0x90, 0x00, 0xff, 0x80, 0x90, 0x00, 0x90, 0x00, 0x88, 0x20, 0x8c, 0x60, 0x83, 0x80, 0x0b,
0x98, 0x15, 0x8f, 0x00, 0x99, 0x80, 0x90, 0x00, 0xfe, 0x00, 0x90, 0x00, 0x90, 0x80, 0x99, 0x80,
0x8f, 0x00, 0x0d, 0xbb, 0x12, 0x04, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x11, 0x00, 0x11, 0x00, 0x20,
0x80, 0x3b, 0x80, 0x44, 0x40, 0x44, 0x40, 0x84, 0x20, 0x84, 0x20, 0x0b, 0x98, 0x15, 0x08, 0x00,
0x14, 0x00, 0x14, 0x00, 0x22, 0x00, 0x36, 0x00, 0x49, 0x00, 0x49, 0x00, 0x88, 0x80, 0x0f, 0xdb,
0x12, 0x81, 0x00, 0x82, 0x80, 0x82, 0x80, 0x84, 0x40, 0x84, 0x40, 0x88, 0x20, 0xfe, 0xe0, 0x91,
0x10, 0x91, 0x10, 0xa1, 0x08, 0xa1, 0x08, 0x0d, 0xb8, 0x15, 0x82, 0x00, 0x85, 0x00, 0x85, 0x00,
0x88, 0x80, 0xfd, 0x80, 0x92, 0x40, 0x92, 0x40, 0xa2, 0x20, 0x0f, 0xdb, 0x12, 0x7f, 0xf0, 0x40,
0x10, 0x20, 0x20, 0x10, 0x40, 0x08, 0x80, 0x07, 0x00, 0x0a, 0x80, 0x12, 0x40, 0x22, 0x20, 0x42,
0x10, 0x82, 0x08, 0x0b, 0x98, 0x15, 0x7f, 0x00, 0x41, 0x00, 0x22, 0x00, 0x14, 0x00, 0x1c, 0x00,
0x2a, 0x00, 0x49, 0x00, 0x88, 0x80, 0x10, 0xeb, 0x12, 0xbf, 0xf8, 0xa0, 0x08, 0x90, 0x10, 0x88,
0x20, 0x84, 0x40, 0xff, 0x80, 0x85, 0x40, 0x89, 0x20, 0x91, 0x10, 0xa1, 0x08, 0xc1, 0x04, 0x0d,
0xb8, 0x15, 0x9f, 0xc0, 0x90, 0x40, 0x88, 0x80, 0x85, 0x00, 0xff, 0x00, 0x8a, 0x80, 0x92, 0x40,
0xa2, 0x20, 0x09, 0x71, 0x10, 0x28, 0x10, 0x00, 0x78, 0x86, 0x02, 0x02, 0x06, 0x78, 0x06, 0x02,
0x02, 0x06, 0x78, 0x80, 0x78, 0x04, 0x08, 0x6e, 0x12, 0x28, 0x10, 0x00, 0x78, 0x84, 0x04, 0x78,
0x0c, 0x04, 0x04, 0x78, 0x80, 0x78, 0x04, 0x0d, 0xbb, 0x12, 0x84, 0x20, 0x84, 0x20, 0x84, 0x20,
0x84, 0x20, 0x84, 0x20, 0x44, 0x40, 0x64, 0xc0, 0x1f, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00,
0x0b, 0x9b, 0x15, 0x88, 0x80, 0x88, 0x80, 0x88, 0x80, 0x88, 0x80, 0x88, 0x80, 0x88, 0x80, 0xc9,
0x80, 0x7f, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x0b, 0x9b, 0x12, 0x1c, 0x00, 0x63, 0x00,
0x41, 0x00, 0x80, 0x80, 0x80, 0x80, 0xff, 0x80, 0x80, 0x80, 0x80, 0x80, 0x41, 0x00, 0x63, 0x00,
0x1c, 0x00, 0x08, 0x68, 0x15, 0x78, 0xcc, 0x84, 0xfc, 0x84, 0x84, 0xcc, 0x78, 0x0b, 0xab, 0x12,
0x80, 0x40, 0x80, 0x80, 0x41, 0x00, 0x41, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x14, 0x00,
0x14, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x78, 0x15, 0x82, 0x84, 0x84, 0x48, 0x48, 0x48, 0x30,
0x30, 0x0b, 0xae, 0x10, 0x24, 0x00, 0x12, 0x00, 0x00, 0x00, 0x80, 0x40, 0x80, 0x80, 0x41, 0x00,
0x41, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x14, 0x00, 0x14, 0x00, 0x08, 0x00, 0x08, 0x00,
0x08, 0x7b, 0x12, 0x90, 0x48, 0x00, 0x82, 0x84, 0x84, 0x48, 0x48, 0x48, 0x30, 0x30, 0x0f, 0xee,
0x12, 0x1c, 0x00, 0x64, 0x00, 0x42, 0x00, 0x81, 0x04, 0x81, 0x04, 0x81, 0x88, 0x81, 0x88, 0x81,
0x48, 0x42, 0x50, 0x26, 0x30, 0x38, 0x20, 0x00, 0x40, 0x00, 0x40, 0x00, 0x80, 0x0e, 0xdb, 0x15,
0x7a, 0x08, 0xca, 0x08, 0x85, 0x10, 0x85, 0x10, 0x84, 0x90, 0x84, 0xa0, 0x4c, 0x60, 0x78, 0x40,
0x00, 0x80, 0x00, 0x80, 0x01, 0x00, 0x0b, 0x9d, 0x11, 0x08, 0x00, 0x1c, 0x00, 0x6b, 0x00, 0x41,
0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x41, 0x00, 0x6b, 0x00, 0x1c,
0x00, 0x08, 0x00, 0x09, 0x7a, 0x14, 0x10, 0x7c, 0xd6, 0x82, 0x82, 0x82, 0x82, 0xd6, 0x7c, 0x10,
0x0d, 0xbe, 0x10, 0x01, 0x00, 0x1f, 0x00, 0x10, 0x00, 0x11, 0x00, 0x60, 0xc0, 0x40, 0x40, 0x80,
0x20, 0x84, 0x20, 0x84, 0x20, 0x84, 0x20, 0x84, 0x20, 0x44, 0x40, 0x4a, 0x40, 0x31, 0x80, 0x0b,
0x9c, 0x11, 0x02, 0x00, 0x3e, 0x00, 0x20, 0x00, 0x00, 0x00, 0x63, 0x00, 0xc1, 0x80, 0x88, 0x80,
0x88, 0x80, 0x88, 0x80, 0x88, 0x80, 0xdd, 0x80, 0x77, 0x00, 0x0d, 0xbe, 0x10, 0x1f, 0x00, 0x15,
0x00, 0x00, 0x00, 0x11, 0x00, 0x60, 0xc0, 0x40, 0x40, 0x80, 0x20, 0x84, 0x20, 0x84, 0x20, 0x84,
0x20, 0x84, 0x20, 0x44, 0x40, 0x4a, 0x40, 0x31, 0x80, 0x0b, 0x9b, 0x12, 0x3e, 0x00, 0x2a, 0x00,
0x00, 0x00, 0x63, 0x00, 0xc1, 0x80, 0x88, 0x80, 0x88, 0x80, 0x88, 0x80, 0x88, 0x80, 0xdd, 0x80,
0x77, 0x00, 0x0a, 0x8d, 0x12, 0x1c, 0x63, 0x41, 0x80, 0x80, 0x80, 0x80, 0x40, 0x60, 0x18, 0x08,
0x08, 0x08, 0x08, 0x6a, 0x15, 0x78, 0xcc, 0x80, 0x80, 0x80, 0xc0, 0x70, 0x10, 0x10, 0x10, 0x09,
0x7a, 0x13, 0x04, 0x04, 0x38, 0x0e, 0x10, 0x10, 0xe0, 0x38, 0x40, 0x40, 0x05, 0x53, 0x01, 0x08,
0xf8, 0x80, 0x05, 0x53, 0x01, 0x30, 0x48, 0x88, 0x05, 0x53, 0x01, 0x80, 0xf8, 0x80, 0x05, 0x53,
0x01, 0x08, 0xf8, 0x08, 0x09, 0x8c, 0x01, 0x40, 0xe0, 0x40, 0x40, 0x40, 0x40, 0x7e, 0x43, 0x41,
0x41, 0x43, 0x7e, 0x08, 0x79, 0x04, 0x40, 0xe0, 0x40, 0x40, 0x7c, 0x46, 0x42, 0x46, 0x7c, 0x09,
0x7b, 0x12, 0xfc, 0x86, 0x82, 0x8a, 0x86, 0xfc, 0x82, 0x80, 0x80, 0x80, 0x80, 0x08, 0x6b, 0x15,
0xb8, 0xcc, 0x84, 0x84, 0x84, 0x94, 0xcc, 0xb8, 0x84, 0x80, 0x80, 0x07, 0x6d, 0x10, 0x04, 0x04,
0xfc, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x06, 0x5a, 0x13, 0x08, 0x08,
0xf8, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x07, 0x7b, 0x02, 0x7e, 0x40, 0x40, 0x40, 0x40,
0xf0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x06, 0x68, 0x05, 0x7c, 0x40, 0x40, 0xf0, 0x40, 0x40, 0x40,
0x40, 0x08, 0x6e, 0x12, 0xfc, 0x80, 0x80, 0x80, 0x80, 0xf0, 0x88, 0x84, 0x84, 0x84, 0x84, 0x04,
0x08, 0x30, 0x07, 0x5b, 0x15, 0xf8, 0x80, 0x80, 0xe0, 0x90, 0x88, 0x88, 0x88, 0x08, 0x08, 0x30,
0x0f, 0xed, 0x12, 0x82, 0x08, 0x42, 0x10, 0x22, 0x20, 0x12, 0x40, 0x0a, 0x80, 0x07, 0x00, 0x0a,
0x80, 0x12, 0x40, 0x22, 0x20, 0x42, 0x10, 0x82, 0x0c, 0x00, 0x04, 0x00, 0x04, 0x0b, 0xaa, 0x15,
0x88, 0x80, 0x49, 0x00, 0x2a, 0x00, 0x1c, 0x00, 0x1c, 0x00, 0x2a, 0x00, 0x49, 0x00, 0x88, 0xc0,
0x00, 0x40, 0x00, 0x40, 0x09, 0x7e, 0x12, 0x38, 0xc6, 0x82, 0x02, 0x06, 0x18, 0x06, 0x02, 0x82,
0xc6, 0x38, 0x10, 0x24, 0x18, 0x08, 0x6b, 0x15, 0x78, 0x84, 0x04, 0x38, 0x0c, 0x04, 0x84, 0x78,
0x20, 0x48, 0x30, 0x0a, 0x9d, 0x12, 0x82, 0x00, 0x84, 0x00, 0x88, 0x00, 0x90, 0x00, 0xa0, 0x00,
0xe0, 0x00, 0x90, 0x00, 0x88, 0x00, 0x84, 0x00, 0x82, 0x00, 0x81, 0x80, 0x00, 0x80, 0x00, 0x80,
0x07, 0x6a, 0x15, 0x88, 0x90, 0xa0, 0xc0, 0xa0, 0x90, 0x88, 0x8c, 0x04, 0x04, 0x0a, 0x8b, 0x12,
0x82, 0x82, 0x84, 0xa4, 0xa8, 0xf8, 0xa4, 0xa2, 0x82, 0x81, 0x81, 0x07, 0x68, 0x15, 0x84, 0xa4,
0xa8, 0xf0, 0xa8, 0xa8, 0x84, 0x84, 0x0a, 0x9b, 0x02, 0x41, 0x00, 0x42, 0x00, 0xf4, 0x00, 0x48,
0x00, 0x50, 0x00, 0x70, 0x00, 0x48, 0x00, 0x44, 0x00, 0x42, 0x00, 0x41, 0x00, 0x40, 0x80, 0x07,
0x7b, 0x02, 0x40, 0x40, 0xf0, 0x44, 0x48, 0x50, 0x60, 0x50, 0x48, 0x44, 0x42, 0x0b, 0xab, 0x02,
0xe0, 0x80, 0x21, 0x00, 0x22, 0x00, 0x24, 0x00, 0x28, 0x00, 0x38, 0x00, 0x24, 0x00, 0x22, 0x00,
0x21, 0x00, 0x20, 0x80, 0x20, 0x40, 0x08, 0x88, 0x05, 0xe2, 0x24, 0x28, 0x30, 0x28, 0x24, 0x22,
0x21, 0x0a, 0x9d, 0x12, 0x81, 0x00, 0x81, 0x00, 0x81, 0x00, 0x81, 0x00, 0x81, 0x00, 0xff, 0x00,
0x81, 0x00, 0x81, 0x00, 0x81, 0x00, 0x81, 0x00, 0x81, 0x80, 0x00, 0x80, 0x00, 0x80, 0x08, 0x7a,
0x15, 0x84, 0x84, 0x84, 0xfc, 0x84, 0x84, 0x84, 0x86, 0x02, 0x02, 0x0d, 0xcb, 0x12, 0x83, 0xf0,
0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0xfe, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00,
0x82, 0x00, 0x82, 0x00, 0x0b, 0xa8, 0x15, 0x87, 0xc0, 0x84, 0x00, 0x84, 0x00, 0xfc, 0x00, 0x84,
0x00, 0x84, 0x00, 0x84, 0x00, 0x84, 0x00, 0x0f, 0xde, 0x12, 0xff, 0x00, 0x81, 0x00, 0x81, 0x00,
0x81, 0x00, 0x81, 0x00, 0x81, 0xe0, 0x81, 0x10, 0x81, 0x08, 0x81, 0x08, 0x81, 0x08, 0x81, 0x08,
0x00, 0x08, 0x00, 0x10, 0x00, 0x60, 0x0c, 0xab, 0x15, 0xfc, 0x00, 0x84, 0x00, 0x84, 0x00, 0x87,
0x00, 0x84, 0x80, 0x84, 0x40, 0x84, 0x40, 0x84, 0x40, 0x00, 0x40, 0x00, 0x40, 0x01, 0x80, 0x0b,
0x9b, 0x12, 0x1e, 0x00, 0x61, 0x00, 0x40, 0x00, 0x87, 0x00, 0x88, 0x80, 0x88, 0x80, 0x88, 0x80,
0x88, 0x80, 0x45, 0x00, 0x63, 0x00, 0x1c, 0x80, 0x08, 0x78, 0x15, 0x78, 0xc4, 0x88, 0x94, 0x94,
0x94, 0xcc, 0x7a, 0x0a, 0x8e, 0x12, 0x1c, 0x63, 0x41, 0x80, 0x80, 0x80, 0x80, 0x80, 0x41, 0x63,
0x1c, 0x08, 0x24, 0x18, 0x08, 0x6b, 0x15, 0x78, 0xcc, 0x80, 0x80, 0x80, 0x84, 0xcc, 0x78, 0x10,
0x48, 0x30, 0x09, 0x9d, 0x02, 0xff, 0x80, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08,
0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x04, 0x00, 0x04, 0x00, 0x07,
0x7a, 0x05, 0xfe, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x18, 0x08, 0x08, 0x09, 0x9b, 0x02, 0x80,
0x80, 0x41, 0x00, 0x41, 0x00, 0x22, 0x00, 0x22, 0x00, 0x14, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08,
0x00, 0x08, 0x00, 0x08, 0x00, 0x07, 0x7b, 0x05, 0x82, 0x82, 0x44, 0x44, 0x28, 0x28, 0x10, 0x10,
0x10, 0x10, 0x10, 0x09, 0x9b, 0x02, 0x80, 0x80, 0x41, 0x00, 0x41, 0x00, 0x22, 0x00, 0x22, 0x00,
0x14, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x07, 0x7b, 0x05, 0x82,
0x82, 0x44, 0x44, 0x28, 0x28, 0x10, 0x7c, 0x10, 0x10, 0x10, 0x0a, 0x9d, 0x12, 0x81, 0x00, 0x81,
0x00, 0x42, 0x00, 0x24, 0x00, 0x18, 0x00, 0x18, 0x00, 0x24, 0x00, 0x42, 0x00, 0x42, 0x00, 0x81,
0x00, 0x81, 0x80, 0x00, 0x80, 0x00, 0x80, 0x07, 0x7a, 0x05, 0xc6, 0x44, 0x28, 0x10, 0x10, 0x28,
0x44, 0xc6, 0x02, 0x02, 0x0b, 0xbd, 0x02, 0xfe, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10,
0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x1f, 0xe0, 0x00, 0x20, 0x00,
0x20, 0x0a, 0xaa, 0x05, 0xfc, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80,
0x10, 0x80, 0x1f, 0xc0, 0x00, 0x40, 0x00, 0x40, 0x0a, 0x9d, 0x12, 0x81, 0x00, 0x81, 0x00, 0x81,
0x00, 0x81, 0x00, 0x81, 0x00, 0x41, 0x00, 0x3f, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
0x80, 0x00, 0x80, 0x00, 0x80, 0x08, 0x7a, 0x15, 0x84, 0x84, 0x84, 0xc4, 0x7c, 0x04, 0x04, 0x06,
0x02, 0x02, 0x0a, 0x8b, 0x12, 0x81, 0x81, 0x81, 0x81, 0x89, 0x49, 0x3f, 0x09, 0x09, 0x01, 0x01,
0x08, 0x68, 0x15, 0x84, 0x84, 0x94, 0xd4, 0x7c, 0x14, 0x14, 0x04, 0x0a, 0x8b, 0x12, 0x80, 0x80,
0x80, 0x80, 0xfc, 0x82, 0x81, 0x81, 0x81, 0x81, 0x81, 0x08, 0x68, 0x15, 0x80, 0x80, 0x80, 0xf8,
0x8c, 0x84, 0x84, 0x84, 0x0c, 0xbb, 0x02, 0x07, 0x00, 0x18, 0xc0, 0x90, 0x40, 0xa0, 0x20, 0xa0,
0x20, 0x7f, 0xe0, 0x20, 0x00, 0x20, 0x00, 0x10, 0x20, 0x18, 0x60, 0x07, 0x80, 0x09, 0x88, 0x05,
0x1e, 0xb3, 0xa1, 0x7f, 0x20, 0x20, 0x33, 0x1e, 0x0c, 0xbe, 0x02, 0x07, 0x00, 0x18, 0xc0, 0x90,
0x40, 0xa0, 0x20, 0xa0, 0x20, 0x7f, 0xe0, 0x20, 0x00, 0x20, 0x00, 0x10, 0x20, 0x18, 0x60, 0x07,
0x80, 0x02, 0x00, 0x04, 0x80, 0x03, 0x00, 0x09, 0x8b, 0x05, 0x1e, 0xb3, 0xa1, 0x7f, 0x20, 0x20,
0x33, 0x1e, 0x08, 0x12, 0x0c, 0x05, 0x1b, 0x22, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x0f, 0xde, 0x10, 0x08, 0x80, 0x07, 0x00, 0x00, 0x00, 0x82, 0x08, 0x42, 0x10,
0x22, 0x20, 0x12, 0x40, 0x0a, 0x80, 0x07, 0x00, 0x0a, 0x80, 0x12, 0x40, 0x22, 0x20, 0x42, 0x10,
0x82, 0x08, 0x0b, 0x9b, 0x12, 0x22, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x88, 0x80, 0x49, 0x00, 0x2a,
0x00, 0x1c, 0x00, 0x1c, 0x00, 0x2a, 0x00, 0x49, 0x00, 0x88, 0x80, 0x0a, 0x7e, 0x12, 0x82, 0x84,
0x88, 0x90, 0xa0, 0xe0, 0x90, 0x88, 0x84, 0x82, 0x82, 0x02, 0x04, 0x18, 0x07, 0x5b, 0x15, 0x88,
0x90, 0xa0, 0xc0, 0xa0, 0x90, 0x88, 0x88, 0x08, 0x08, 0x30, 0x0a, 0x8e, 0x12, 0x81, 0x81, 0x81,
0x81, 0x81, 0xff, 0x81, 0x81, 0x81, 0x81, 0x81, 0x01, 0x02, 0x0c, 0x08, 0x6b, 0x15, 0x84, 0x84,
0x84, 0xfc, 0x84, 0x84, 0x84, 0x84, 0x04, 0x04, 0x18, 0x0a, 0x8d, 0x12, 0x81, 0x81, 0x81, 0x81,
0x81, 0x41, 0x3f, 0x01, 0x01, 0x01, 0x03, 0x02, 0x02, 0x08, 0x6a, 0x15, 0x84, 0x84, 0x84, 0xc4,
0x7c, 0x04, 0x04, 0x0c, 0x08, 0x08, 0x0b, 0x9e, 0x10, 0x22, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x08,
0x00, 0x08, 0x00, 0x14, 0x00, 0x14, 0x00, 0x22, 0x00, 0x22, 0x00, 0x41, 0x00, 0x7f, 0x00, 0x41,
0x00, 0x80, 0x80, 0x80, 0x80, 0x08, 0x7b, 0x12, 0x48, 0x30, 0x00, 0x78, 0xcc, 0x04, 0x7c, 0xc4,
0x84, 0xcc, 0x76, 0x0b, 0x9d, 0x10, 0x36, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x14, 0x00,
0x14, 0x00, 0x22, 0x00, 0x22, 0x00, 0x41, 0x00, 0x7f, 0x00, 0x41, 0x00, 0x80, 0x80, 0x80, 0x80,
0x08, 0x7a, 0x13, 0x6c, 0x00, 0x78, 0xcc, 0x04, 0x7c, 0xc4, 0x84, 0xcc, 0x76, 0x0e, 0xcb, 0x12,
0x0f, 0xf0, 0x1c, 0x00, 0x14, 0x00, 0x14, 0x00, 0x24, 0x00, 0x27, 0xe0, 0x44, 0x00, 0x7c, 0x00,
0x44, 0x00, 0x84, 0x00, 0x87, 0xf0, 0x0d, 0xb8, 0x15, 0x7b, 0xc0, 0xc6, 0x60, 0x04, 0x20, 0x7f,
0xe0, 0xc4, 0x00, 0x84, 0x00, 0xce, 0x60, 0x7b, 0xc0, 0x09, 0x7e, 0x10, 0x44, 0x38, 0x00, 0xfe,
0x80, 0x80, 0x80, 0x80, 0xfc, 0x80, 0x80, 0x80, 0x80, 0xfe, 0x08, 0x6b, 0x12, 0x48, 0x30, 0x00,
0x78, 0xcc, 0x84, 0xfc, 0x80, 0x80, 0xcc, 0x78, 0x0b, 0x9b, 0x12, 0x3c, 0x00, 0xc3, 0x00, 0x81,
0x00, 0x00, 0x80, 0x00, 0x80, 0xff, 0x80, 0x80, 0x80, 0x80, 0x80, 0x41, 0x00, 0x63, 0x00, 0x1c,
0x00, 0x08, 0x68, 0x15, 0x78, 0xcc, 0x04, 0x04, 0xfc, 0x84, 0xcc, 0x78, 0x0b, 0x9d, 0x10, 0x36,
0x00, 0x00, 0x00, 0x3c, 0x00, 0xc3, 0x00, 0x81, 0x00, 0x00, 0x80, 0x00, 0x80, 0xff, 0x80, 0x80,
0x80, 0x80, 0x80, 0x41, 0x00, 0x63, 0x00, 0x1c, 0x00, 0x08, 0x6a, 0x13, 0xcc, 0x00, 0x78, 0xcc,
0x04, 0x04, 0xfc, 0x84, 0xcc, 0x78, 0x0f, 0xdd, 0x10, 0x18, 0xc0, 0x00, 0x00, 0x82, 0x08, 0x42,
0x10, 0x22, 0x20, 0x12, 0x40, 0x0a, 0x80, 0x07, 0x00, 0x0a, 0x80, 0x12, 0x40, 0x22, 0x20, 0x42,
0x10, 0x82, 0x08, 0x0b, 0x9a, 0x13, 0x63, 0x00, 0x00, 0x00, 0x88, 0x80, 0x49, 0x00, 0x2a, 0x00,
0x1c, 0x00, 0x1c, 0x00, 0x2a, 0x00, 0x49, 0x00, 0x88, 0x80, 0x09, 0x7d, 0x10, 0x6c, 0x00, 0x38,
0xc6, 0x82, 0x02, 0x06, 0x18, 0x06, 0x02, 0x82, 0xc6, 0x38, 0x08, 0x6a, 0x13, 0xcc, 0x00, 0x78,
0x84, 0x04, 0x38, 0x0c, 0x04, 0x84, 0x78, 0x09, 0x7b, 0x12, 0xfe, 0x04, 0x08, 0x10, 0x38, 0x06,
0x02, 0x02, 0x82, 0xc6, 0x38, 0x08, 0x6b, 0x15, 0xfc, 0x08, 0x10, 0x20, 0x78, 0x0c, 0x04, 0x04,
0x84, 0xcc, 0x78, 0x0a, 0x8d, 0x10, 0x3c, 0x00, 0x83, 0x83, 0x85, 0x89, 0x89, 0x91, 0x91, 0xa1,
0xa1, 0xc1, 0xc1, 0x08, 0x6a, 0x13, 0x78, 0x00, 0x84, 0x8c, 0x94, 0x94, 0xa4, 0xa4, 0xc4, 0x84,
0x0a, 0x8d, 0x10, 0x66, 0x00, 0x83, 0x83, 0x85, 0x89, 0x89, 0x91, 0x91, 0xa1, 0xa1, 0xc1, 0xc1,
0x08, 0x6a, 0x13, 0xcc, 0x00, 0x84, 0x8c, 0x94, 0x94, 0xa4, 0xa4, 0xc4, 0x84, 0x0b, 0x9d, 0x10,
0x36, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x63, 0x00, 0x41, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x41, 0x00, 0x63, 0x00, 0x1c, 0x00, 0x08, 0x6a, 0x13, 0xcc, 0x00, 0x78,
0xcc, 0x84, 0x84, 0x84, 0x84, 0xcc, 0x78, 0x0b, 0x9b, 0x12, 0x1c, 0x00, 0x63, 0x00, 0x41, 0x00,
0x80, 0x80, 0x80, 0x80, 0xff, 0x80, 0x80, 0x80, 0x80, 0x80, 0x41, 0x00, 0x63, 0x00, 0x1c, 0x00,
0x08, 0x68, 0x15, 0x78, 0xcc, 0x84, 0xfc, 0x84, 0x84, 0xcc, 0x78, 0x0b, 0x9d, 0x10, 0x36, 0x00,
0x00, 0x00, 0x1c, 0x00, 0x63, 0x00, 0x41, 0x00, 0x80, 0x80, 0x80, 0x80, 0xff, 0x80, 0x80, 0x80,
0x80, 0x80, 0x41, 0x00, 0x63, 0x00, 0x1c, 0x00, 0x08, 0x6a, 0x13, 0xcc, 0x00, 0x78, 0xcc, 0x84,
0xfc, 0x84, 0x84, 0xcc, 0x78, 0x0a, 0x8d, 0x10, 0x6c, 0x00, 0x38, 0xc6, 0x82, 0x01, 0x01, 0x3f,
0x01, 0x01, 0x82, 0xc6, 0x38, 0x08, 0x6a, 0x13, 0xcc, 0x00, 0x78, 0xcc, 0x04, 0x3c, 0x04, 0x84,
0xcc, 0x78, 0x0b, 0x9d, 0x10, 0x3e, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x41, 0x00, 0x41,
0x00, 0x22, 0x00, 0x22, 0x00, 0x14, 0x00, 0x14, 0x00, 0x08, 0x00, 0x10, 0x00, 0x60, 0x00, 0x07,
0x7d, 0x03, 0x38, 0x00, 0x82, 0x82, 0x44, 0x44, 0x24, 0x28, 0x18, 0x10, 0x10, 0x30, 0x60, 0x0b,
0x9d, 0x10, 0x36, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x41, 0x00, 0x41, 0x00, 0x22, 0x00,
0x22, 0x00, 0x14, 0x00, 0x14, 0x00, 0x08, 0x00, 0x10, 0x00, 0x60, 0x00, 0x07, 0x7d, 0x03, 0x6c,
0x00, 0x82, 0x82, 0x44, 0x44, 0x24, 0x28, 0x18, 0x10, 0x10, 0x30, 0x60, 0x0b, 0x9e, 0x10, 0x12,
0x00, 0x24, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x41, 0x00, 0x41, 0x00, 0x22, 0x00, 0x22,
0x00, 0x14, 0x00, 0x14, 0x00, 0x08, 0x00, 0x10, 0x00, 0x60, 0x00, 0x07, 0x7e, 0x02, 0x24, 0x48,
0x00, 0x82, 0x82, 0x44, 0x44, 0x24, 0x28, 0x18, 0x10, 0x10, 0x30, 0x60, 0x0a, 0x8d, 0x10, 0x66,
0x00, 0x81, 0x81, 0x81, 0x81, 0x81, 0x41, 0x3f, 0x01, 0x01, 0x01, 0x01, 0x08, 0x6a, 0x13, 0xcc,
0x00, 0x84, 0x84, 0x84, 0x84, 0x7c, 0x04, 0x04, 0x04, 0x0c, 0xad, 0x10, 0x33, 0x00, 0x00, 0x00,
0x80, 0x40, 0x80, 0x40, 0x80, 0x40, 0x80, 0x40, 0x80, 0x40, 0xfc, 0x40, 0x86, 0x40, 0x82, 0x40,
0x82, 0x40, 0x86, 0x40, 0xfc, 0x40, 0x0b, 0x9a, 0x13, 0x36, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0xf8, 0x80, 0x8c, 0x80, 0x84, 0x80, 0x8c, 0x80, 0xf8, 0x80,
};
#endif

View file

@ -5,6 +5,218 @@
/**********************************************************/
static int (*cdp_boot_game)(void);
static int sk0, sk1;
static int bios_ver;
static int disc_type;
void (*sys_bup_init)(u8*, u8*, void*);
int use_sys_load = 0;
static void (*orig_func)(void);
int my_bios_loadcd_read(void);
int my_bios_loadcd_init(void);
/**********************************************************/
static int ipstat = -1;
static int cdp_auth(void)
{
if(ipstat<0){
ipstat = 0;
}
int cdstat = (CR1>>8)&0x0f;
printk("cdp_auth: ipstat=%d cdstat=%02x\n", ipstat, cdstat);
if(cdstat==STATUS_OPEN || cdstat==STATUS_NODISC){
// 开盖了
return -2;
}
if(cdstat>=STATUS_RETRY){
// 发生错误,复位重试
ipstat = 0;
}
if(ipstat==0){
// 复位cdblock
cdblock_off();
cdblock_on(0);
ipstat = 1;
}else if(ipstat==1){
// 等待cdblock进入工作状态
if(cdstat==STATUS_PAUSE){
my_bios_loadcd_init();
ipstat = 2;
}
}else if(ipstat==2){
// 等待reset_selector完成
if(cdstat==STATUS_PAUSE){
ipstat = 3;
}
}else if(ipstat>=3 && ipstat<11){
// 执行伪认证重试8次
int retv = jhl_auth_hack(100000);
if(retv==2){
ipstat = 12;
}else{
ipstat += 1;
}
}else if(ipstat==11){
// 认证失败
ipstat = 0;
return -1;
}else if(ipstat>=12 && ipstat<16){
// 读IP重试4次
int retv = my_bios_loadcd_read();
if(retv==0){
ipstat = 0;
return 0;
}
ipstat += 1;
}else{
// 读IP失败
ipstat = 0;
return -2;
}
return 1;
}
/**********************************************************/
static void cdp_hook(void)
{
sk0 = *(u16*)0x06020232;
sk1 = *(u16*)0x06020236;
orig_func();
}
static void hook_getkey(void)
{
if(bios_ver==0){
if(*(u32*)(0x0604cd18) == 0x0604406c){
orig_func = (void*)0x0604406c;
*(u32*)(0x0604cd18) = (u32)cdp_hook;
}else if(*(u32*)(0x0604ccf4) == 0x0604406c){
// V-Saturn 1.00
orig_func = (void*)0x0604406c;
*(u32*)(0x0604ccf4) = (u32)cdp_hook;
}
}else if(bios_ver==1){
if(*(u32*)(0x0604d8e0) == 0x06044204){
orig_func = (void*)0x06044204;
*(u32*)(0x0604d8e0) = (u32)cdp_hook;
}else if(*(u32*)(0x0604d8b0) == 0x06044204){
// V-Saturn 1.01
orig_func = (void*)0x06044204;
*(u32*)(0x0604d8b0) = (u32)cdp_hook;
}else if(*(u32*)(0x0604ecec) == 0x06044ae0){
// 1.00a(U)
orig_func = (void*)0x06044ae0;
*(u32*)(0x0604ecec) = (u32)cdp_hook;
}else if(*(u32*)(0x0604ed0c) == 0x06044ae0){
// 1.01a(U)
orig_func = (void*)0x06044ae0;
*(u32*)(0x0604ed0c) = (u32)cdp_hook;
}else if(*(u32*)(0x0604ed28) == 0x06044ae0){
// Samsung-Saturn
orig_func = (void*)0x06044ae0;
*(u32*)(0x0604ed28) = (u32)cdp_hook;
}
}else{
printk("Unkonw BIOS ver!\n");
}
}
static int cdp_boot(void)
{
int pad = (sk0)? sk0 : sk1;
printk("\ncdp_boot! PAD=%04x\n", pad);
hook_getkey();
if(pad & PAD_START){
void (*go)(void) = (void*)(0x02000f00);
go();
}
if(pad & PAD_C){
// SAROO启动但用系统存档
bios_cd_cmd(disc_type|0x80);
}else if(pad & PAD_A){
// SAROO启动
bios_cd_cmd(disc_type);
}
return 0;
}
static int cdp_read_ip(void)
{
if(debug_flag&1)
sci_init();
hook_getkey();
printk("\ncdp_read_ip!\n");
if(disc_type==0){
// SAROO ISO
int (*go)(void) = (void*)0x1874;
int status = go();
if((status==-8)||(status==-4)){
status = 0;
}
return status;
}else{
// 光盘
return cdp_auth();
}
}
static int cdp_init(void)
{
printk("\ncdp_init! HIRQ=%04x STAT=%04x\n", HIRQ, CR1);
if(disc_type==0){
int (*go)() = (void*)0x1904;
return go();
}
if(HIRQ&HIRQ_DCHG){
ipstat = 0;
}else{
ipstat = 12;
}
return 0;
}
/**********************************************************/
static void (*orig_0344)(int, int);
static void my_0344(int and, int or)
{
hook_getkey();
orig_0344(and, or);
}
// 调用04c8的代码必须在内部RAM中运行。
static void _call_04c8(void)
@ -74,6 +286,34 @@ void my_cdplayer(void)
*(u32*)(0x06000358) = (u32)bup_init;
if(use_sys_load==0){
if(*(u32*)(0x06001340)==0x18a8){
// 1.00
bios_ver = 0;
cdp_boot_game = (void*)0x18a8;
*(u32*)(0x06001340) = (u32)cdp_boot;
*(u32*)(0x06001344) = (u32)cdp_read_ip;
*(u32*)(0x06001348) = (u32)cdp_init;
}else if(*(u32*)(0x0600134c)==0x18a8){
// 1.01 1.02
bios_ver = 1;
cdp_boot_game = (void*)0x18a8;
*(u32*)(0x0600134c) = (u32)cdp_boot;
*(u32*)(0x06001350) = (u32)cdp_read_ip;
*(u32*)(0x06001354) = (u32)cdp_init;
}else if(*(u32*)(0x060013d8)==0x19b8){
// 1.03
bios_ver = 2;
cdp_boot_game = (void*)0x19b8;
*(u32*)(0x060013d8) = (u32)cdp_boot;
*(u32*)(0x060013dc) = (u32)cdp_read_ip;
*(u32*)(0x060013e0) = (u32)cdp_init;
}
orig_0344 = (void*)*(u32*)(0x06000344);
*(u32*)(0x06000344) = (u32)my_0344;
}
*(u32*)(0x06000234) = 0x02ac;
*(u32*)(0x06000238) = 0x02bc;
*(u32*)(0x0600023c) = 0x0350;
@ -85,6 +325,9 @@ void my_cdplayer(void)
}
/**********************************************************/
int my_bios_loadcd_init(void)
{
printk("\nmy_bios_loadcd_init!\n");
@ -125,7 +368,8 @@ int my_bios_loadcd_read(void)
tm -= 1;
}
if(tm==0){
printk(" PLAY timeout!\n");
printk(" PLAY timeout! HIRQ=%04x CR1=%04x\n", HIRQ, CR1);
cdc_dump(10000000);
return -1;
}
@ -133,7 +377,17 @@ int my_bios_loadcd_read(void)
cdc_trans_data(sbuf, 2048*16);
cdc_end_trans(&status);
*(u16*)(0x060003a0) = 1;
if(strncmp("SEGA SEGASATURN ", (char*)0x06002000, 16)){
printk("Not a gamedisc!\n");
return -2;
}
if(bios_type<=BIOS_100V){
// 1.00j and V-Saturn 1.00
*(u16*)(0x06000380) = 1;
}else{
*(u16*)(0x060003a0) = 1;
}
memcpy(ipstr, (u8*)0x06002020, 16);
ipstr[16] = 0;
@ -178,9 +432,8 @@ static void my_06b0(void)
static void read_1st(void)
{
printk("Read main ...\n");
int retv;
retv = *(u32*)(0x06000284);
void (*go)(void) = (void(*)(void))retv;
void (*go)(void) = (void*) *(u32*)(0x06000284);
go();
patch_game((char*)0x06002020);
@ -189,6 +442,14 @@ static void read_1st(void)
*(u32*)(0x0600026c) = (u32)my_cdplayer;
}
// 有些游戏没有正确初始化VDP1。这里特殊处理一下。
memset((u8*)0x25c00200, 0x00, 0x80000-0x200);
for(int i=0; i<0x80000; i+=0x20){
*(u16*)(0x25c00000+i) = 0x8000;
}
*(u16*)(0x25c7fffe) = 0xffff;
// 0x06000320: 0x060006b0 bios_set_clock_speed
memcpy((u8*)0x060006b8, code_06b8, sizeof(code_06b8));
*(u32*)(0x060006cc) = (u32)my_06b0;
@ -207,52 +468,55 @@ static void read_1st(void)
}
static int my_bios_loadcd_boot(int r4, int r5)
{
__asm volatile ( "sts.l pr, @-r15" :: );
__asm volatile ( "jmp @%0":: "r" (r5) );
__asm volatile ( "mov r4, r0" :: );
__asm volatile ( "nop" :: );
return 0;
}
int bios_cd_cmd(int type)
{
int retv, ip_size;
my_bios_loadcd_init();
use_sys_bup = (type&0x80)>>7;
use_sys_load = 0;
type &= 0x7f;
disc_type = type;
#if 1
my_bios_loadcd_boot(0, 0x1904);
printk("bios_cd_cmd: type=%02x\n", type);
while(1){
ip_size = bios_loadcd_read();
if(ip_size==0x8000)
break;
#if 0
if(type!=2){
// 0:ISO, 4:光盘
bios_loadcd_init();
while(1){
ip_size = bios_loadcd_read();
if(ip_size==0x8000)
break;
}
char ipstr[64];
memcpy(ipstr, (u8*)0x06002020, 16);
ipstr[16] = 0;
printk("\nLoad game: %s\n", ipstr);
memcpy(ipstr, (u8*)0x06002060, 32);
ipstr[32] = 0;
printk(" %s\n\n", ipstr);
}else
#endif
{
// 2: 刻录游戏盘
my_bios_loadcd_init();
retv = my_bios_loadcd_read();
if(retv<0){
if(retv==-2){
use_sys_load = 1;
my_cdplayer();
}
return retv;
}
// emulate bios_loadcd_boot
*(u32*)(0x06000290) = 3;
ip_size = bios_loadcd_read();//1912读取ip文件
}
char ipstr[64];
memcpy(ipstr, (u8*)0x06002020, 16);
ipstr[16] = 0;
printk("\nLoad game: %s\n", ipstr);
memcpy(ipstr, (u8*)0x06002060, 32);
ipstr[32] = 0;
printk(" %s\n\n", ipstr);
#else
retv = my_bios_loadcd_read();
if(retv)
return retv;
// emulate bios_loadcd_boot
*(u32*)(0x06000290) = 3;
ip_size = bios_loadcd_read();//1912读取ip文件
#endif
if(type>0){
if(type>0 && use_sys_bup==0){
// 光盘游戏。需要通知MCU加载SAVE。
memcpy((void*)(TMPBUFF_ADDR+0x10), (u8*)0x06002020, 16);
*(u8*)(TMPBUFF_ADDR+0x20) = 0;
@ -262,15 +526,23 @@ int bios_cd_cmd(int type)
while(SS_CMD);
}
*(u32*)(0x06002270) = (u32)read_1st;
// 模拟执行1A3c()
// 跳过各种验证
memcpy((u8*)0x060002a0, (u8*)0x060020e0, 32);
memcpy((u8*)0x06000c00, (u8*)0x06002000, 256);
*(u32*)(0x06000254) = 0x6002100;
// 模拟执行18fe()
cdc_change_dir(0, 0xffffff);
cdc_read_file(0, 2, 0);
*(u32*)(0x06002270) = (u32)read_1st;
*(u32*)(0x02000f04) = (u32)cdc_read_sector;
*(u16*)(0x0600220c) = 9;
retv = my_bios_loadcd_boot(ip_size, 0x18be);//跳到18be
if((retv==-8)||(retv==-4)){
*(u32*)(0x06000254) = 0x6002100;
retv = my_bios_loadcd_boot(0, 0x18c6);
}
int (*go)(void) = (void*)0x18d2;
retv = go();
printk("bios_loadcd_boot retv=%d\n", retv);
return retv;

View file

@ -59,6 +59,7 @@ void CHEAT_patch(void)
/**********************************************************/
// KAITEI_DAISENSOU (Japan) 海底大战争日版 第一关后半部分会有音乐丢失情况
void KAITEI_DAISENSOU_handle1(void)
{
cdc_read_sector(2462+150, 0x54f00, (void*)0x22400000);
@ -80,50 +81,64 @@ void KAITEI_DAISENSOU_patch(void)
/**********************************************************/
// Dungeons & Dragons Collection (Japan) (Disc 2) 龙与地下城2
void DND2_patch(void)
{
*(u32*)(0x06015228) = 0x34403440;
//*(u32*)(0x06015228) = 0x34403440;
*(u16*)(0x060151A6) = 0x09;
*(u16*)(0x060151AE) = 0x09;
}
/**********************************************************/
// NOEL3 (Japan)
void NOEL3_patch(void)
{
*(u32*)(0x0603525C) = 0x34403440;
//*(u32*)(0x0603525C) = 0x34403440;
*(u16*)(0x06035104) = 0x09;
}
/**********************************************************/
// FRIENDS (Japan)
void FRIENDS_patch(void)
{
*(u32*)(0x06042928) = 0x34403440;
*(u32*)(0x060429B4) = 0x34403440;
//*(u32*)(0x06042928) = 0x34403440;
//*(u32*)(0x060429B4) = 0x34403440;
*(u16*)(0x060428E8) = 0x09;
*(u16*)(0x0604298A) = 0x09;
}
/**********************************************************/
// Astra Superstars (Japan)
void ASTRA_SUPERSTARS_patch(void)
{
*(u32*)(0x060289E4) = 0x34403440;
//*(u32*)(0x060289E4) = 0x34403440;
*(u16*)(0x06028974) = 0x09;
}
/**********************************************************/
// Magical Night Dreams - Cotton 1 (Japan)棉花小魔女1
void cotton1_patch(void)
{
*(u32*)(0x06018DA8) = 0x34403440;
//*(u32*)(0x06018DA8) = 0x34403440;
*(u16*)(0x06018D80) = 0x09;
}
/**********************************************************/
// Magical Night Dreams - Cotton 2 (Japan)棉花小魔女2
void cotton2_patch(void)
{
*(u32*)(0x060041BC) = 0x34403440;
//*(u32*)(0x060041BC) = 0x34403440;
*(u16*)(0x06004194) = 0x09;
}
@ -131,40 +146,53 @@ void cotton2_patch(void)
// Pocket Fighter (Japan) 口袋战士
void POCKET_FIGHTER_patch(void)
{
*(u32*)(0x06014080) = 0x34403440;
//*(u32*)(0x06014080) = 0x34403440;
*(u32*)(0x06013F48) = 0xd44ae001;
*(u32*)(0x06013F4c) = 0x2400e05c;
*(u32*)(0x06013F50) = 0x000b8041;
//*(u8*)(0x06037C2A) = 0x11;//錦攣역庫稜틉굳댄轎돨꺄렴??
*(u16*)(0x0602DD68) = 0x09;
}
/**********************************************************/
// Street Fighter Zero 3 (Japan) 街霸ZERO3
void SF_ZERO3_patch(void)
{
*(u32*)(0x0602B8AC) = 0x34403440;
//*(u32*)(0x0602B8AC) = 0x34403440;
*(u16*)(0x0602B7FA) = 0x09;
}
/**********************************************************/
// Metal_Slug 合金弹头
void Metal_Slug_patch(void)
{
ssctrl_set(MASK_EXMEM, CS0_RAM1M);
*(u32*)(0x06079E18) = 0x34403440;
//*(u32*)(0x06079E18) = 0x34403440;
*(u16*)(0x06079DEC) = 0x09;
//*(u16*)(0x06079DF2) = 0x09;
}
/*********************************************************/
//Metal_Slug A ºÏ½ðµ¯Í·1.005°æ
// Metal_Slug A 북쏜뎐庫1.005경
void Metal_Slug_A_patch(void)
{
ssctrl_set(MASK_EXMEM, CS0_RAM1M);
*(u32*)(0x06079FBC) = 0x34403440;
//*(u32*)(0x06079FBC) = 0x34403440;
*(u16*)(0x06079F90) = 0x09;
//*(u16*)(0x06079F96) = 0x09;
}
/*********************************************************/
// ULTRAMAN
// 2MB ROM cart
void jump_06b0(void)
{
void (*go)(void) = (void*)(0x04c8);
@ -218,15 +246,16 @@ void ULTRAMAN_patch(void)
/*********************************************************/
// KOF95
// 2MB ROM cart
void kof95_handle(void)
{
if(*(u32*)(0x6002234)== 0x14401FF0) *(u32*)(0x6002234) = 0x34403440;
if(*(u32*)(0x600230c)== 0x14401FF0) *(u32*)(0x600230c) = 0x34403440;
if(*(u32*)(0x6002300)== 0x1FF01FF0) *(u32*)(0x6002300) = 0x34403440;
*(u16*)(0x60020c2) = 0x0009;
*(u16*)(0x600217E) = 0x0009;
*(u16*)(0x6002180) = 0x0009;
read_file("/SAROO/ISO/KOF95.BIN", 0, 0x200000, (void*)0x22400000);
card_init();
void (*go)(int);
go = (void*)0x200000;
go(0x6002048);
@ -237,37 +266,45 @@ void kof95_patch(void)
{
need_bup = 0;
if(*(u32*)(0x6002e28)==0x0607CD80)
*(u32*)(0x607CDC4) = (u32)kof95_handle;
if(*(u32*)(0x6002e28)==0x0607CD80){
if(*(u32*)(0x607CDC4) == 0x6002048)
*(u32*)(0x607CDC4) = (u32)kof95_handle;
else if(*(u32*)(0x607CDC8) == 0x6002048)
*(u32*)(0x607CDC8) = (u32)kof95_handle;
}
}
/**********************************************************/
// KOF96
// 1MB RAM cart only
void kof96_patch(void)
{
ssctrl_set(MASK_EXMEM, CS0_RAM1M);
*(u32*)(0x06058248) = 0x34403440;
//*(u32*)(0x06058248) = 0x34403440;
*(u16*)(0x0605821C) = 0x09;
}
/**********************************************************/
// KOF97
void kof97_patch(void)
{
ssctrl_set(MASK_EXMEM, CS0_RAM1M);
*(u32*)(0x06066FC0) = 0x34403440;
*(u16*)(0x06066F80) = 0x0009;//34403440
}
/**********************************************************/
// Samurai Spirits - Amakusa Kourin 侍魂4
// 1MB RAM cart only
void smrsp4_patch(void)
{
ssctrl_set(MASK_EXMEM, CS0_RAM1M);
*(u32*)(0x6067E60) = 0x34403440;
//*(u32*)(0x6067E60) = 0x34403440;
*(u16*)(0x06067E34) = 0x0009;
}
@ -275,11 +312,14 @@ void smrsp4_patch(void)
// Samurai Spirits - Zankuro Musouken 侍魂3
// 0x0600d1d0: 23301ff0
// 0x0605ad90: 23301ff0
void smrsp3_patch(void)
{
ssctrl_set(MASK_EXMEM, CS0_RAM1M);
*(u32*)0x0600d1d0 = 0x34403440;
*(u32*)0x0605ad90 = 0x34403440;
*(u16*)(0x0600D198) = 0x0009;
*(u16*)(0x0605AD36) = 0x0009;
//*(u32*)0x0600d1d0 = 0x34403440;
//*(u32*)0x0605ad90 = 0x34403440;
}
@ -287,21 +327,26 @@ void smrsp3_patch(void)
// Real Bout Garou Densetsu (Japan) (2M) RB饿狼传说
// 0x0602F6FC: 23301ff0
// 0x0607C36C: 23301ff0
void REAL_BOUT_patch(void)
{
ssctrl_set(MASK_EXMEM, CS0_RAM1M);
*(u32*)0x0602F6FC = 0x34403440;
*(u32*)0x0607C36C = 0x34403440;
*(u16*)(0x0602F5EC) = 0x0009;
*(u16*)(0x0607C340) = 0x0009;
//*(u32*)0x0602F6FC = 0x34403440;
//*(u32*)0x0607C36C = 0x34403440;
}
/**********************************************************/
// Real Bout Garou Densetsu Special (Japan) (Rev A) RB饿狼传说SP V2
// 0x060913C4: 23301ff0
void REAL_BOUT_SP_v2_patch(void)
{
ssctrl_set(MASK_EXMEM, CS0_RAM1M);
*(u32*)0x060913C4 = 0x34403440;
//*(u32*)0x060913C4 = 0x34403440;
*(u16*)(0x06091398) = 0x0009;
}
@ -309,10 +354,12 @@ void REAL_BOUT_SP_v2_patch(void)
// Real Bout Garou Densetsu Special (Japan) v1 RB饿狼传说SP V1
// 0x060913C4: 23301ff0
// 0x06091230: 23301ff0
void REAL_BOUT_SP_v1_patch(void)
{
ssctrl_set(MASK_EXMEM, CS0_RAM1M);
*(u32*)0x06091230 = 0x34403440;
*(u16*)(0x06091204) = 0x0009;
//*(u32*)0x06091230 = 0x34403440;
}
@ -320,18 +367,23 @@ void REAL_BOUT_SP_v1_patch(void)
// SRMP7
// 0x06011204: mov.l #0x23301ff0, r3
// need change to 0x34403440
void srmp7_patch(void)
{
*(u32*)(0x0601121C) = 0x34403440;
//*(u32*)(0x0601121C) = 0x34403440;
*(u16*)(0x06011208) = 0x0009;
}
/**********************************************************/
// Gouketsuji Ichizoku 3 - Groove on Fight (Japan)豪血寺一族3
void GROOVE_ON_FIGHT_handle(void)
{
*(u32*)0x06099ABC=0x34403440;
*(u32*)0x060083B0=0x34403440;
//*(u32*)0x06099ABC=0x34403440;
//*(u32*)0x060083B0=0x34403440;
*(u16*)(0x6008338) = 0x0009;
*(u16*)(0x6099A84) = 0x0009;
*(u32*)0x00280008=0x06004000;
__asm volatile("jmp @%0"::"r"(0x06004000));
__asm volatile( "nop" :: );
@ -339,17 +391,21 @@ void GROOVE_ON_FIGHT_handle(void)
void GROOVE_ON_FIGHT_patch(void)
{
*(u32*)(0x200AA4) = 0x34403440;
*(u32*)(0x202EF0) = 0x34403440;
//*(u32*)(0x200AA4) = 0x34403440;
//*(u32*)(0x202EF0) = 0x34403440;
*(u16*)(0x200A44) = 0x0009;
*(u16*)(0x202EB8) = 0x0009;
*(u32*)(0x200460) = (u32)GROOVE_ON_FIGHT_handle;
}
/**********************************************************/
// Vampire Savior (Japan) 恶魔战士3 救世主
void VAMPIRE_SAVIOR_handle(void)
{
*(u32*)0x06014A64=0x34403440;
//*(u32*)0x06014A64=0x34403440;
*(u16*)(0x6014A52) = 0x0009;
__asm volatile("jmp @%0"::"r"(0x600D000));
__asm volatile ( "nop" :: );
}
@ -365,32 +421,53 @@ void VAMPIRE_SAVIOR_patch(void)
/**********************************************************/
// XMarvel Super Heroes (Japan)
void MARVEL_SUPER_handle(void)
{
void (*go)(void) = (void(*)(void))0x60D0FF4;
go();
*(u32*)0x0600B0FC = 0x34403440;
*(u32*)0x0600B2D8 = 0x34403440;
ssctrl_set(MASK_EXMEM, CS0_RAM1M);
if((REG32(0x600B0FC) == 0x23301FF0) && (REG32(0x600B2D8) == 0x23301FF0)){
//휑경 킹경 쳄경뒈囹宮谿
REG16(0x600B0AC) = 0x0009;
REG16(0x600B1D4) = 0x0009;
}else if((REG32(0x6005F5C) == 0x23301FF0)&&(REG32(0x6005D8C) == 0x23301FF0)){
//휑경DEMO
REG16(0x6005D3C) = 0x0009;
REG16(0x6005E6A) = 0x0009;
}
}
void MARVEL_SUPER_patch(void)
{
*(u32*)(0x060D13F8) = (u32)MARVEL_SUPER_handle;
if(REG32(0x60D13F8) == 0X60D0FF4){
//휑경뵨쳄경
REG32(0x60D13F8)=(u32)MARVEL_SUPER_handle;
}else if(REG32(0x60D1424) == 0X60D0FF4){
//휑경DEMO
REG32(0x60D1424)=(u32)MARVEL_SUPER_handle;
}else if(REG32(0x60D15AC) == 0X60D0FF4){
//킹경
REG32(0x60D15AC)=(u32)MARVEL_SUPER_handle;
}
}
/**********************************************************/
// X-Men vs. Street Fighter (Japan) (3M)
void xmvsf_handle2(void)
{
*(u32*)(0x06014158) = 0x34403440;
//*(u32*)(0x06014158) = 0x34403440;
*(u16*)(0x0601409C) = 0x0009;
__asm volatile("jmp @%0"::"r"(0x6014000));
__asm volatile ( "nop" :: );
}
void xmvsf_handle1(void)
{
*(u16*)(0x60228E0) = 0xe000;
*(u16*)(0x60228f4) = 0xe000;
*(u8*)0x060801FE = 0x5c;
@ -410,6 +487,7 @@ void xmvsf_patch(void)
/**********************************************************/
// Marvel Super Heroes vs. Street Fighter (Japan)
void mshvssf_handle1(void)
{
if(*(u16*)(0x600286e)== 0x2012)
@ -430,10 +508,11 @@ void mshvssf_patch(void)
/**********************************************************/
// WAKUWAKU7 火热火热7
void WAKU7_patch(void)
{
ssctrl_set(MASK_EXMEM, CS0_RAM1M);
*(u32*)(0x0601C19C) = 0x34403440;
*(u16*)(0x0601C164) = 0x9;
*(u16*)(0x0601C16C) = 0x9;
*(u8*) (0x0601244d) = 0xa;
@ -452,13 +531,18 @@ void WAKU7_patch(void)
/**********************************************************/
// FIGHTERS_HISTORY 斗士的历史
void FIGHTERS_HISTORY_patch(void)
{
ssctrl_set(MASK_EXMEM, CS0_RAM1M);
*(u32*)0x060500C8 = 0x34403440;
*(u32*)0x06057000 = 0x34403440;
*(u32*)0x0605707C = 0x34403440;
*(u32*)0x060570E0 = 0x34403440;
*(u16*)(0x0605002E) = 0x9;
*(u16*)(0x06056FEC) = 0x9;
*(u16*)(0x06057028) = 0x9;
*(u16*)(0x060570BA) = 0x9;
//*(u32*)0x060500C8 = 0x34403440;
//*(u32*)0x06057000 = 0x34403440;
//*(u32*)0x0605707C = 0x34403440;
//*(u32*)0x060570E0 = 0x34403440;
}
@ -467,7 +551,367 @@ void FIGHTERS_HISTORY_patch(void)
void FINAL_FIGHT_REVENGE_patch(void)
{
*(u32*)(0x06011A6C) = 0x34403440;
//*(u32*)(0x06011A6C) = 0x34403440;
*(u16*)(0x0601199C) = 0x9;
}
/**********************************************************/
// Amagi_Shien_Japan_patch
// 踏狗삔쇱꿎PAUSE榴檄닒랍돔鈴价琦뻔
void Amagi_Shien_patch(void)
{
*(u16*)(0x06012258) = 0x9;
}
/**********************************************************/
// Sega Saturn de Hakken!! Tamagotchi Park (Japan)
void Tamagotchi_Park_patch(void)
{
*(u16*)(0x06030EDE) = 0xE400;
}
/**********************************************************/
// CYBER_BOTS
void CYBER_BOTS_handle1(void)
{
*(u16*)(0x0601695A) = 0x9;
__asm volatile("jmp @%0"::"r"(0x600D000));
__asm volatile ("nop" :: );
}
void CYBER_BOTS_patch(void)
{
ssctrl_set(MASK_EXMEM, CS0_RAM1M);
*(u32*)(0x060DD058) = (u32)CYBER_BOTS_handle1;
}
/**********************************************************/
// FIGHTERS MEGAMIX_JAP_patch
//jap 1m 2m
void FIGHTERS_MEGAMIX_JAP_patch(void)
{
*(u16*)(0x060203F4) = 0x9;
}
//USA PAL
void FIGHTERS_MEGAMIX_USA_patch(void)
{
if(*(u16*)(0x06020408)==0x400b)
*(u16*)(0x06020408) = 0x9;
else if(*(u16*)(0x0602040C)==0x400b)
*(u16*)(0x0602040C) = 0x9;
}
/**********************************************************/
// Fighting Vipers (Japan) (Rev C) patch
// JAP 1m 2m
void Fighting_Vipers_JAP_patch(void)
{
*(u16*)(0x06022A60) = 0x9;
}
// USA PAL Korea
void Fighting_Vipers_USA_patch(void)
{
if(*(u16*)(0x060229AC)==0x400b)
*(u16*)(0x060229AC) = 0x9; // 킹경
else if(*(u16*)(0x06022990)==0x400b)
*(u16*)(0x06022990) = 0x9; // 쳄경
else if(*(u16*)(0x06022980)==0x400b)
*(u16*)(0x06022980) = 0x9; // 벴경
}
/**********************************************************/
// Gotha
void Gotha_patch(void)
{
*(u16*)(0x0604E3CC) = 0x9;
*(u8*) (0x0604E3D2) = 0x2;
}
/**********************************************************/
// Terra_Cresta_3D (<28>團寧뵀3D) 밑균밟혜
void Terra_Cresta_3D_patch(void)
{
*(u8*) (0x0603AB64) = 0x9;
}
/**********************************************************/
// 빪델질瓜
// 踏狗넋埼逃癎뺄쉥0x25E7FFFF畇냥0x25E7FFF죄닒VRAM돕CS0죄。
void Die_Hard_Trilogy_patch(void)
{
*(u8*)(0x025E7FFF) = 0xff;
}
/**********************************************************/
// <Habitat II> and <Pad Nifty> modem 껸땀
void HABITAT2_handle(void)
{
if(*(u8*)(0x0602A15d)==0x11)
*(u16*)(0x0602A15E) = 0x9;// Pad Nifty (Japan)
else if(*(u8*)(0x0602B52D)==0x11)
*(u16*)(0x0602B52E) = 0x9;// Habitat II (Japan)
__asm volatile("jmp @%0"::"r"(0x6020000));
__asm volatile ("nop" :: );
}
void HABITAT2_patch(void)
{
*(u32*)(0x060105B4) = (u32)HABITAT2_handle;
}
/**********************************************************/
//Dragon's Dream (Japan) modem 껸땀
void Dragons_Dream_patch(void)
{
*(u8*)(0x06040691) = 1;
}
/**********************************************************/
// Hebereke's Popoitto (Japan) (Europe) ???
// 踏狗삔쇱꿎PAUSE榴檄닒랍돔鈴价琦뻔
void Hebereke_Popoitto_patch(void)
{
if(*(u8*)(0x0601D379)==0x01){
*(u8*)(0x0601D379) = 0x56; // (Japan)
*(u8*)(0x0601D2F5) = 0x56;
}else if(*(u8*)(0x0601D399)==0x01){
*(u8*)(0x0601D399) = 0x78; // (Europe)
}
}
/**********************************************************/
//Hissatsu Pachinko Collection (Japan) (Rev A) ???
// 踏狗삔쇱꿎PAUSE榴檄닒랍돔鈴价琦뻔
void Hissatsu_Pachinko_Collection_patch(void)
{
if(*(u8*)(0x0601085D)==0x01)
*(u8*)(0x0601085D) = 0x56; // (Rev A)
else if(*(u8*)(0x0601088D)==0x01)
*(u8*)(0x0601088D) = 0x78; //
}
/**********************************************************/
//Heart of Darkness (Japan) (Proto) 껸땀
void Heart_of_Darkness_patch(void)
{
if(*(u32*)(0x060108c0)==0x04000000){
*(u16*)(0x060108C0) = 0x0240;
*(u16*)(0x060106C4) = 0x0009;
}
}
/**********************************************************/
// VANDAL_HEARTS_CN
void VANDAL_HEARTS_CN_patch(void)
{
int addres=0;
if(REG16(0x06002F70)==0x4C2B) // B2
addres=0x48;
else if(REG16(0x06002F5e)==0x4C2B) // B1
addres=0x51;
if(addres){
REG8(0x06002F5e) =0xaf;
REG8(0x06002F5f) =addres;
REG32(0x06002E04)=0xE00961C3;
REG32(0x06002E08)=0x71547170;
REG32(0x06002E0C)=0x4C2B2101;
}
}
/**********************************************************/
//WHIZZ (Japan) (Europe) 껸땀
// 踏狗菱<E78B97>狂痙청놓迦뺏VDP1
void WHIZZ_patch(void)
{
*(u8*)(0x06003193) = 0x8;
}
/**********************************************************/
// Kidou Senshi Z Gundam - Zenpen Zeta no Kodou (Japan)
// 踏狗菱<E78B97>狂痙청놓迦뺏VDP1
void Gundam_Zenpen_Zeta_no_Kodou_patch(void)
{
*(u8*)(0x060030A1) = 0x8;
}
/**********************************************************/
// RMENU2_patch 꽉데껸땀
void RMENU2_patch(void)
{
*(u32*)(0x06014774) = (u32)bios_cd_cmd;
}
/**********************************************************/
// Fenrir_patch 꽉데껸땀
void Fenrir_patch(void)
{
*(u16*)(0x0600DCCA) = 0x9;
*(u8*) (0x0600DCCC) = 0x41;
*(u32*)(0x0600DD18) = (u32)bios_cd_cmd;
}
/**********************************************************/
void Pia_Carrot_e_Youkoso_2_handle2(void)
{
if((REG32(0x604677C)==0x23301FF0) && (REG16(0x604673C)==0x2122))
REG16(0x604673C) = 0x9;
if((REG32(0x6046808)==0x23301FF0) && (REG16(0x60467DE)==0x2122))
REG16(0x60467DE)=0x9;
if((REG32(0x6046784)==0x60468F8) && (REG16(0x0604674C)==0x490b))
REG16(0x0604674C)=0x9;
void (*go)(void) = (void*)0X6010000;
go();
}
void Pia_Carrot_e_Youkoso_2_handle1(void)
{
if(REG32(0x2100C0)==0x6010000)
REG32(0x2100C0)= (u32)Pia_Carrot_e_Youkoso_2_handle2;
void (*go)(void) = (void*)0x6021FE4;
go();
}
void Pia_Carrot_e_Youkoso_2_patch(void)
{
if((REG32(0x601068C)==0x210000) && (REG32(0x60106B0)==0x6021FE4))
REG32(0x60106B0)= (u32)Pia_Carrot_e_Youkoso_2_handle1;
}
/**********************************************************/
// Ultimate Mortal Kombat 3 쳄경 킹경 킹경錦攣경
void Ultimate_Mortal_Kombat_3_patch(void)
{
int r0 = 0x0601875A;
if(REG16(r0)==0x480b)//쳄경 킹경
REG16(r0)= 0x09;
if(REG16(r0+0x10)==0x480b)//킹경錦攣경
REG16(r0+0x10)= 0x09;
if(REG16(r0+0x54)==0x480b)//쳄경 킹경
REG16(r0+0x54)= 0x09;
if(REG16(r0+0x64)==0x480b)//킹경錦攣경
REG16(r0+0x64)= 0x09;
}
/**********************************************************/
// Batman_Forever_The_Arcade_Game 쳄경 킹경 킹경錦攣경
void Batman_Forever_The_Arcade_Game_handle1(void)
{
int r0=0x06023E44;
if(REG32(r0)==0xD439490B){
//휑경 쳄경 킹경宮谿
REG32(r0) = 0xD23A6122;
REG32(r0+4) = 0x21188BFC;
REG32(r0+8) = 0xD437490B;
REG32(r0+12)= 0x6583EB00;
}
__asm volatile("jmp @%0"::"r"(0x600d000));
__asm volatile ("nop" :: );
}
void Batman_Forever_The_Arcade_Game_patch(void)
{
if(REG32(0x060043C4)==0x600AF9C){
//휑경 쳄경 킹경 寮넋埼宮谿
REG32(0x060043C4) = (u32)Batman_Forever_The_Arcade_Game_handle1;
}
}
/**********************************************************/
//Game no Tatsujin 2 (Japan)껸땀
void Game_no_Tatsujin2_patch(void)
{
if(*(u32*)(0x06011024)==0x880189ED){
*(u16*)(0x06011026) = 0x09;
}
}
/**********************************************************/
void MANX_TT_SUPER_BIKE_patch(void)
{
if(*(u8*)(0x60219B1)==0x01){
//휑경뵨킹경宮谿
*(u8*)(0x60219B3)= 0x03;
*(u8*)(0x60219E7)= 0x03;
*(u8*)(0x602037D)= 0x43;
*(u8*)(0x60203FD)= 0x43;
*(u8*)(0x60204D9)= 0x43;
*(u8*)(0x6020619)= 0x13;
}else if(*(u8*)(0x6021A11)==0x01){
//쳄경
*(u8*)(0x6021A13)= 0x03;
*(u8*)(0x6021A47)= 0x03;
*(u8*)(0x60203DD)= 0x43;
*(u8*)(0x602045D)= 0x43;
*(u8*)(0x6020539)= 0x43;
*(u8*)(0x6020679)= 0x13;
}
}
@ -498,6 +942,7 @@ GAME_DB game_dbs[] = {
{"T-3111G V1.002", "Metal_Slug", Metal_Slug_patch},
{"T-3111G V1.005", "Metal_Slug_A", Metal_Slug_A_patch},
{"MK-81088", "KOF95", kof95_patch},
{"T-3101G", "KOF95", kof95_patch},
{"T-3108G", "KOF96", kof96_patch},
{"T-3121G", "KOF97", kof97_patch},
@ -514,12 +959,62 @@ GAME_DB game_dbs[] = {
{"T-16510G", "SRMP7SP", srmp7_patch},
{"T-1515G", "WAKU7", WAKU7_patch},
{"GS-9107", "FIGHTERS", FIGHTERS_HISTORY_patch},
{"GS-9107", "FIGHTERS_HISTORY", FIGHTERS_HISTORY_patch},
{"T-1248G", "FINAL_FIGHT_REVENGE",FINAL_FIGHT_REVENGE_patch},
{"T-1226G", "XMENVSSF", xmvsf_patch},
{"T-1215G", "MARVEL_SUPER", MARVEL_SUPER_patch},
{"T-1226G", "XMEN_VS_SF", xmvsf_patch},
{"T-1215G", "MARVEL_SUPER", MARVEL_SUPER_patch}, //휑경
{"T-1214H", "MARVEL_SUPER", MARVEL_SUPER_patch}, //쳄경
{"6106664", "MARVEL_SUPER", MARVEL_SUPER_patch}, //휑경demo
{"T-7032H", "MARVEL_SUPER", MARVEL_SUPER_patch}, //킹경
{"T-1238G V1.000", "MSH_VS_SF", mshvssf_patch},
{"T-1513G", "Amagi_Shien", Amagi_Shien_patch},
{"T-13325G", "Tamagotchi_Park", Tamagotchi_Park_patch},
{"T-1217G", "CYBER_BOTS", CYBER_BOTS_patch},
{"GS-9126", "FIGHTERS_MEGAMIX", FIGHTERS_MEGAMIX_JAP_patch},
{"MK-81073", "FIGHTERS_MEGAMIX", FIGHTERS_MEGAMIX_USA_patch},
{"GS-9101", "Fighting_Vipers", Fighting_Vipers_JAP_patch},
{"MK-81041", "Fighting_Vipers", Fighting_Vipers_USA_patch},
{"GS-9009 V1.000", "Gotha", Gotha_patch},
{"T-7102G", "Terra_Cresta_3D", Terra_Cresta_3D_patch},
{"GS-9123", "Die_Hard_Trilogy", Die_Hard_Trilogy_patch},
{"T-16103H", "Die_Hard_Trilogy", Die_Hard_Trilogy_patch},
{"GS-7101", "HABITAT2", HABITAT2_patch},
{"GS-7105", "HABITAT2", HABITAT2_patch},
{"GS-7114", "Dragons_Dream", Dragons_Dream_patch},
{"T-1502H", "Hebereke_Popoitto", Hebereke_Popoitto_patch},
{"T-1503G", "Hissatsu_Pachinko", Hissatsu_Pachinko_Collection_patch},
{"T-1504G", "Hebereke_Popoitto", Hebereke_Popoitto_patch},
{"999999999 V1.000", "Heart_of_Darkness", Heart_of_Darkness_patch},
// {"T-2001G", "Houma_Hunter_Lime_Perfect_Collection",
// Houma_Hunter_Lime_Perfect_Collection_patch},
{"T-1219G", "VANDAL_HEARTS_CN", VANDAL_HEARTS_CN_patch},
{"T-9515H", "WHIZZ", WHIZZ_patch},
{"T-36102G", "WHIZZ", WHIZZ_patch},
{"T-13315G", "Gundam_Zenpen_Zeta", Gundam_Zenpen_Zeta_no_Kodou_patch},
{"T-000001 V0.2.0", "RMENU2", RMENU2_patch},
{"CD0000001 V1.000", "Fenrir", Fenrir_patch},
{"GS-9102 V1.001", "ManX_TT_Super_Bike", MANX_TT_SUPER_BIKE_patch},
{"MK-81210 V1.001", "ManX_TT_Super_Bike", MANX_TT_SUPER_BIKE_patch},
{"MK-81210 V1.000", "ManX_TT_Super_Bike", MANX_TT_SUPER_BIKE_patch},
{"T-20114G", "PIA CARROT 2", Pia_Carrot_e_Youkoso_2_patch},
{"T-25403H", "u_m_k3", Ultimate_Mortal_Kombat_3_patch}, // 廬훙우댔3 킹경/錦攣경
{"T-9701H", "u_m_k3", Ultimate_Mortal_Kombat_3_patch}, // 廬훙우댔3 쳄경
{"T-8140H", "B_F_T", Batman_Forever_The_Arcade_Game_patch}, // 朕疾舅 쳄경 킹경/錦攣경
{"T-8118G", "B_F_T", Batman_Forever_The_Arcade_Game_patch}, // 朕疾舅 휑경
{"T-1509G", "G_N_T2", Game_no_Tatsujin2_patch}, //Game no Tatsujin 2 (Japan)
{NULL,},
};

View file

@ -7,11 +7,11 @@
/******************************************************************************/
#define BUP_WORK_ADDR 0x06000354
#define BUP_MEM_ADDR 0x220b0000
#define BUP_MEM_ADDR (SAVINFO_ADDR)
#define MEMS_HEADER 0x220c1000
#define MEMS_TMP 0x220c3000
#define MEMS_BUFFER 0x220c4000
#define MEMS_HEADER (SAVINFO_ADDR+0x10000)
#define MEMS_TMP (SAVINFO_ADDR+0x12000)
#define MEMS_BUFFER (SAVINFO_ADDR+0x13000)
#define START_BLOCK 0x8000
@ -241,7 +241,7 @@ static void mbuf_mark(int id)
}
}
#ifdef BUP_CHECK
static int chksum(u8 *data, int size)
{
int sum = 0;
@ -254,6 +254,7 @@ static int chksum(u8 *data, int size)
return sum;
}
#endif
static int access_data(int block, u8 *data, int type)
{
@ -290,13 +291,17 @@ static int access_data(int block, u8 *data, int type)
if(type==0){ // read
memcpy(data, bp, asize);
//printk(" sum=%08x\n", chksum(data, asize));
#ifdef BUP_CHECK
printk(" sum=%08x\n", chksum(data, asize));
#endif
}else if(type==1){
if(memcmp(data, bp, asize)){
return BUP_NO_MATCH;
}
}else{ // write
//printk(" sum=%08x\n", chksum(data, asize));
#ifdef BUP_CHECK
printk(" sum=%08x\n", chksum(data, asize));
#endif
memcpy(bp, data, asize);
mbuf_mark(block);
}
@ -369,19 +374,19 @@ static int find_save(char *file_name, int offset, int *last)
/******************************************************************************/
int bup_sel_part(int dev, int num)
// 根据BIOS的BUP代码只有dev为2时才检测num。
int sro_bup_sel_part(int dev, int num)
{
printk("bup_sel_part(%d): %d\n", dev, num);
if(dev>1 || num)
if(dev>=2)
return BUP_NON;
return 0;
}
int bup_format(int dev)
int sro_bup_format(int dev)
{
printk("bup_format(%d)\n", dev);
@ -418,7 +423,7 @@ int bup_format(int dev)
}
int bup_stat(int dev, int dsize, BUPSTAT *stat)
int sro_bup_stat(int dev, int dsize, BUPSTAT *stat)
{
printk("bup_stat(%d): dsize=%d\n", dev, dsize);
@ -451,7 +456,7 @@ int bup_stat(int dev, int dsize, BUPSTAT *stat)
}
int bup_write(int dev, BUPDIR *dir, u8 *data, int mode)
int sro_bup_write(int dev, BUPDIR *dir, u8 *data, int mode)
{
int block_need, block, hdr, last, i;
u8 *bp;
@ -548,7 +553,7 @@ int bup_write(int dev, BUPDIR *dir, u8 *data, int mode)
}
int bup_read(int dev, char *file_name, u8 *data)
int sro_bup_read(int dev, char *file_name, u8 *data)
{
int block;
char nbuf[12];
@ -573,7 +578,7 @@ int bup_read(int dev, char *file_name, u8 *data)
}
int bup_delete(int dev, char *file_name)
int sro_bup_delete(int dev, char *file_name)
{
int block, last, has_data;
u8 *bp;
@ -649,7 +654,7 @@ int bup_delete(int dev, char *file_name)
}
int bup_dir(int dev, char *file_name, int tbsize, BUPDIR *dir)
int sro_bup_dir(int dev, char *file_name, int tbsize, BUPDIR *dir)
{
int block, fnum;
char nbuf[12];
@ -693,7 +698,7 @@ int bup_dir(int dev, char *file_name, int tbsize, BUPDIR *dir)
}
int bup_verify(int dev, char *file_name, u8 *data)
int sro_bup_verify(int dev, char *file_name, u8 *data)
{
int block;
char nbuf[12];
@ -718,7 +723,7 @@ int bup_verify(int dev, char *file_name, u8 *data)
static char mdays[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
void bup_get_date(u32 date, BUPDATE *bdt)
void sro_bup_get_date(u32 date, BUPDATE *bdt)
{
int y, d, h, m;
printk("bup_get_date: %08x\n", date);
@ -758,7 +763,7 @@ void bup_get_date(u32 date, BUPDATE *bdt)
}
u32 bup_set_date(BUPDATE *bdt)
u32 sro_bup_set_date(BUPDATE *bdt)
{
u32 date;
int y, m ,rem;
@ -793,6 +798,124 @@ u32 bup_set_date(BUPDATE *bdt)
/******************************************************************************/
int use_sys_bup = 0;
int (*sys_bup_sel_part)(int dev, int num);
int (*sys_bup_format)(int dev);
int (*sys_bup_stat)(int dev, int dsize, BUPSTAT *stat);
int (*sys_bup_write)(int dev, BUPDIR *dir, u8 *data, int mode);
int (*sys_bup_read)(int dev, char *file_name, u8 *data);
int (*sys_bup_delete)(int dev, char *file_name);
int (*sys_bup_dir)(int dev, char *file_name, int tbsize, BUPDIR *dir);
int (*sys_bup_verify)(int dev, char *file_name, u8 *data);
void (*sys_bup_get_date)(u32 date, BUPDATE *bdt);
u32 (*sys_bup_set_date)(BUPDATE *bdt);
int bup_sel_part(int dev, int num)
{
if(use_sys_bup && dev==0){
return sys_bup_sel_part(dev, num);
}else{
return sro_bup_sel_part(dev, num);
}
}
int bup_format(int dev)
{
if(use_sys_bup && dev==0){
return sys_bup_format(dev);
}else{
return sro_bup_format(dev);
}
}
int bup_stat(int dev, int dsize, BUPSTAT *stat)
{
if(use_sys_bup && dev==0){
return sys_bup_stat(dev, dsize, stat);
}else{
return sro_bup_stat(dev, dsize, stat);
}
}
int bup_write(int dev, BUPDIR *dir, u8 *data, int mode)
{
if(use_sys_bup && dev==0){
return sys_bup_write(dev, dir, data, mode);
}else{
return sro_bup_write(dev, dir, data, mode);
}
}
int bup_read(int dev, char *file_name, u8 *data)
{
if(use_sys_bup && dev==0){
return sys_bup_read(dev, file_name, data);
}else{
return sro_bup_read(dev, file_name, data);
}
}
int bup_delete(int dev, char *file_name)
{
if(use_sys_bup && dev==0){
return sys_bup_delete(dev, file_name);
}else{
return sro_bup_delete(dev, file_name);
}
}
int bup_dir(int dev, char *file_name, int tbsize, BUPDIR *dir)
{
if(use_sys_bup && dev==0){
return sys_bup_dir(dev, file_name, tbsize, dir);
}else{
return sro_bup_dir(dev, file_name, tbsize, dir);
}
}
int bup_verify(int dev, char *file_name, u8 *data)
{
if(use_sys_bup && dev==0){
return sys_bup_verify(dev, file_name, data);
}else{
return sro_bup_verify(dev, file_name, data);
}
}
void bup_get_date(u32 date, BUPDATE *bdt)
{
if(use_sys_bup){
return sys_bup_get_date(date, bdt);
}else{
return sro_bup_get_date(date, bdt);
}
}
u32 bup_set_date(BUPDATE *bdt)
{
if(use_sys_bup){
return sys_bup_set_date(bdt);
}else{
return sro_bup_set_date(bdt);
}
}
/******************************************************************************/
void bup_init(u8 *lib_addr, u8 *work_addr, void *cfg_ptr)
{
BUPCFG *cfg = (BUPCFG*)cfg_ptr;
@ -802,12 +925,28 @@ void bup_init(u8 *lib_addr, u8 *work_addr, void *cfg_ptr)
printk("bup_init: lib=%08x work=%08x\n", lib_addr, work_addr);
//memset(lib_addr, 0, 16384);
//memset(work_addr, 0, 8192);
if(use_sys_bup){
printk("sys_bup_init ... %08x\n", sys_bup_init);
sys_bup_init(lib_addr, work_addr, cfg_ptr);
printk("done.\n");
*(u32*)(BUP_WORK_ADDR) = (u32)work_addr;
sys_bup_sel_part = (void*)*(u32*)(work_addr+0x04);
sys_bup_format = (void*)*(u32*)(work_addr+0x08);
sys_bup_stat = (void*)*(u32*)(work_addr+0x0c);
sys_bup_write = (void*)*(u32*)(work_addr+0x10);
sys_bup_read = (void*)*(u32*)(work_addr+0x14);
sys_bup_delete = (void*)*(u32*)(work_addr+0x18);
sys_bup_dir = (void*)*(u32*)(work_addr+0x1c);
sys_bup_verify = (void*)*(u32*)(work_addr+0x20);
sys_bup_get_date = (void*)*(u32*)(work_addr+0x24);
sys_bup_set_date = (void*)*(u32*)(work_addr+0x28);
}else{
*(u32*)(BUP_WORK_ADDR) = (u32)work_addr;
*(u32*)(work_addr+0x00) = (u32)lib_addr;
cfg[0].unit_id = 1;
cfg[0].partition = 1;
}
*(u32*)(work_addr+0x00) = (u32)lib_addr;
*(u32*)(work_addr+0x04) = (u32)bup_sel_part;
*(u32*)(work_addr+0x08) = (u32)bup_format;
*(u32*)(work_addr+0x0c) = (u32)bup_stat;
@ -819,17 +958,17 @@ void bup_init(u8 *lib_addr, u8 *work_addr, void *cfg_ptr)
*(u32*)(work_addr+0x24) = (u32)bup_get_date;
*(u32*)(work_addr+0x28) = (u32)bup_set_date;
cfg[0].unit_id = 1;
cfg[0].partition = 1;
cfg[1].unit_id = 2;
cfg[1].partition = 1;
cfg[2].unit_id = 0;
cfg[2].partition = 0;
// Check "SaroSave"
if(BUPMEM->magic0!=0x5361726f || BUPMEM->magic1!=0x53617665){
printk(" empty bup memory, need format.\n");
bup_format(0);
if(use_sys_bup==0){
// Check "SaroSave"
if(BUPMEM->magic0!=0x5361726f || BUPMEM->magic1!=0x53617665){
printk(" empty bup memory, need format.\n");
bup_format(0);
}
}
// Check "SaroMems"

Binary file not shown.

View file

@ -6,8 +6,7 @@
int lang_id = 0;
#define LANG_STR_NR 19
#define LANG_NR 8
#define LANG_STR_NR 20
typedef struct _str_entry
{
@ -17,14 +16,14 @@ typedef struct _str_entry
struct _str_entry *next;
}STR_ENTRY;
STR_ENTRY lang_str[LANG_STR_NR];
STR_ENTRY *lang_str_table[64];
static STR_ENTRY lang_str[LANG_STR_NR];
static STR_ENTRY *lang_str_table[64];
/******************************************************************************/
char *lang_zhcn[LANG_STR_NR] = {
static char *lang_zhcn[LANG_STR_NR] = {
"选择游戏(%d/%d)",
"选择文件(%d/%d)",
"游戏启动中......",
@ -44,10 +43,11 @@ char *lang_zhcn[LANG_STR_NR] = {
"检查光盘中......",
"未发现光盘!",
"不是游戏光盘!",
"选择游戏分类",
};
char *lang_en[LANG_STR_NR] = {
static char *lang_en[LANG_STR_NR] = {
"Select Game(%d/%d)",
"Select File(%d/%d)",
"Game Booting ......",
@ -67,10 +67,11 @@ char *lang_en[LANG_STR_NR] = {
"Checking Disc ......",
"No Disc Found!",
"Not a Game Disc!",
"Select Game Category",
};
char *lang_ptbr[LANG_STR_NR] = {
static char *lang_ptbr[LANG_STR_NR] = {
"Selecionar Jogo(%d/%d)",
"Selecionar Arquivo(%d/%d)",
"Inicializando Jogo ......",
@ -90,10 +91,11 @@ char *lang_ptbr[LANG_STR_NR] = {
"Verificando o disco ......",
"Sem CD!",
"Não é um disco de jogo!",
"Selecionar categoria de jogo",
};
char *lang_ja[LANG_STR_NR] = {
static char *lang_ja[LANG_STR_NR] = {
"ゲームリスト(%d/%d)",
"ファイルリスト(%d/%d)",
"ロード中......",
@ -113,15 +115,274 @@ char *lang_ja[LANG_STR_NR] = {
"ディスクを確認しています......",
"ディスクが入っていません",
"ゲームディスクではありません",
"ジャンル選択",
};
char **lang_cur;
static char *lang_fr[LANG_STR_NR] = {
"Choisir un jeu (%d/%d)",
"Choisir un fichier (%d/%d)",
"Démarrage du jeu...",
"Erreur lors du démarrage du jeu ! %d",
"Chargement du fichier...",
"Erreur de chargement du fichier ! %d",
"Choisir un jeu",
"Lecteur CD",
"Charger un jeu CD-ROM",
"Console de débogage série",
"Charger un binaire",
"Mise à jour du firmware",
"Mise à jour... Ne pas éteindre le système !",
"Erreur de mise à jour !",
"Mise à jour terminée ! Redémarrez le système !",
"SAROO Menu de démarrage",
"Vérification du disque...",
"Aucun disque trouvé !",
"Disque de jeu non détecté !",
"Sélectionnez la catégorie de jeu",
};
static char *lang_ru[LANG_STR_NR] = {
"Выбор игры (%d/%d)",
"Выбор файла (%d/%d)",
"Запуск игры ...",
"Сбой запуска игры! %d",
"Запуск файла ...",
"Сбой запуска файла! %d",
"Выбрать игру",
"Аудио CD плеер",
"Запустить игру с CD",
"Инструмент отладки",
"Запустить исп. файл",
"Обновление ПО",
"Обновление, не отключайте ...",
"Сбой обновления!",
"Обновлено! Требуется перезапуск!",
"Главное меню SAROO",
"Проверка диска ...",
"Диск не найден!",
"Не игровой диск!",
"Выберите категорию игры",
};
static char *lang_zhtw[LANG_STR_NR] = {
"選擇遊戲(%d/%d)",
"選擇檔案(%d/%d)",
"啟動遊戲中......",
"遊戲啟動失敗! %d",
"載入檔案中......",
"檔案載入失敗! %d",
"選擇遊戲",
"系統CD播放器",
"執行遊戲光碟",
"UART除錯工具",
"執行應用程式擴充檔案",
"升級韌體",
"韌體升級中,請勿斷電...",
"韌體升級失敗!",
"韌體升級完成,請重新開機!",
"SAROO 主選單",
"檢查光碟中......",
"未發現光碟!",
"不是遊戲光碟!",
"選擇遊戲分類",
};
static char *lang_de[LANG_STR_NR] = {
"Spielauswahl(%d/%d)",
"Dateiauswahl(%d/%d)",
"Spiel wird geladen ......",
"Laden des Spiels fehlgeschlagen! %d",
"Datei wird geladen ......",
"Laden der Datei fehlgeschlagen! %d",
"Spiel auswählen",
"System CD-Player",
"Starte Spiel von CD",
"Serielles Debug Menü",
"Lade Binärdatei",
"Firmware Update",
"Update läuft... Konsole nicht ausschalten!",
"Update fehlgeschlagen!",
"Update erfolgreich! Konsole neu starten.",
"SAROO Hauptmenü",
"Prüfe CD ......",
"Keine CD gefunden!",
"Keine Spiele-CD!",
"Spielkategorie auswählen",
};
static char *lang_es[LANG_STR_NR] = {
"Seleccionar juego(%d/%d)",
"Seleccionar archivo(%d/%d)",
"Cargando juego ......",
"¡Carga del juego fallida! %d",
"Cargando archivo ......",
"¡Carga del archivo fallida! %d",
"Seleccionar juego",
"Reproductor CD del Sistema",
"Cargar disco de juego",
"Consola de depuración serie UART",
"Cargar binario",
"Actualizar firmware",
"Actualizando... ¡¡No apague la consola!!",
"¡Actualización fallida!",
"¡Actualización completada! ¡Ya puede reiniciar!",
"SAROO Menú de arranque",
"Comprobando disco .....",
"¡Disco no encontrado!",
"¡No es un disco de juego!",
"Seleccionar categoría de juego",
};
static char *lang_it[LANG_STR_NR] = {
"Seleziona gioco(%d/%d)",
"Seleziona file(%d/%d)",
"Caricamento gioco ......",
"Caricamento gioco fallito! %d",
"Caricamento file ......",
"Caricamento file fallito! %d",
"Seleziona gioco",
"Lettore CD di sistema",
"Carica disco di gioco",
"Shell di debug UART",
"Carica file binario",
"Aggiornamento firmware",
"Aggiornamento... Non spegnere la console!",
"Aggiornamento fallito!",
"Aggiornamento finito! Riavvia il sistema!",
"Menu di avvio SAROO",
"Controllo disco ......",
"Nessun disco trovato!",
"Nessun disco di gioco trovato!",
"Seleziona categoria di gioco",
};
static char *lang_pl[LANG_STR_NR] = {
"Wybierz grę(%d/%d)",
"Wybierz plik(%d/%d)",
"Uruchamianie gry ......",
"Błąd uruchamiania gry! %d",
"Wczytywanie pliku ......",
"Błąd wczytywania pliku! %d",
"Wybierz grę",
"Systemowy CDPlayer",
"Wczytaj dysk z grą",
"Powłoka debugująca po UART",
"Wczytaj dane binarne",
"Aktualizacja Firmware",
"Aktualizacja trwa... Nie wyłączaj konsoli!",
"Błąd aktualizacji!",
"Aktualizacja ukończona! Uruchom ponownie!",
"Menu rozruchowe SAROO",
"Sprawdzanie dysku ......",
"Nie znaleziono dysku!",
"Nie znaleziono płyty z grą!",
"Wybierz kategorię gry",
};
static char *lang_swe[LANG_STR_NR] = {
"Välj spel(%d/%d)",
"Välj fil(%d/%d)",
"Laddar spel ......",
"Gick inte att starta spelet! %d",
"Laddar fil ......",
"Gick inte att ladda fil! %d",
"Välj spel",
"System CD-spelare",
"Ladda spelskiva",
"Seriellt felsökningsshell",
"Ladda binär",
"Uppdatera programvaran",
"Uppdaterar... Stäng inte av maskinen.",
"Uppdatering misslyckades!",
"Uppdatering klar! Var god starta om maskinen.",
"SAROO Boot Menu",
"Kontrollerar skivan ......",
"Hittade ingen skiva!",
"Inte en giltig spel skiva!",
"Välj spelkategori",
};
static char *lang_el[LANG_STR_NR] = {
"Επίλεξε Παιχνίδι(%d/%d)",
"Επίλεξε Αρχείο(%d/%d)",
"Εκκίνηση Παιχνιδιού ......",
"Εκκίνηση Παιχνιδιού Απέτυχε! %d",
"Φόρτωση Αρχείου ......",
"Φόρτωση Αρχείου Απέτυχε! %d",
"Επίλεξε Παιχνίδι",
"CD Player Συστήματος",
"Φόρτωση Δίσκου Παιχνιδιού",
"Σειριακή Κονσόλα Debug",
"Φόρτωση Δυαδικού Αρχείου",
"Ενημέρωση Λογισμικού",
"Ενημέρωση... ΜΗΝ ΚΛΕΙΣΕΤΕ",
"Ενημέρωση Απέτυχε!",
"Ενημέρωση Ολοκληρώθηκε! Κάνε Επανακίνηση!",
"Μενού Εκκίνησης SAROO",
"Έλεγχος Δίσκου ......",
"Δεν Βρέθηκε Δίσκος!",
"Δεν Είναι Δίσκος Παιχνιδιού!",
"Επίλεξε Κατηγορία Παιχνιδιού",
};
static char *lang_ro[LANG_STR_NR] = {
"Selectați jocul(%d/%d)",
"Selectați fişierul(%d/%d)",
"Jocul porneşte ......",
"Pornirea jocului a eşuat! %d",
"Se încarcă fișierul ......",
"Încărcarea fişierului a eşuat! %d",
"Selectați jocul",
"Interfață optică interactivă pentru sistem",
"Încărcați discul jocului",
"Depanați prin interfața serială",
"Încărcați cod binar",
"Actualizarea firmware-ului",
"Se actualizează...Nu opriți alimentarea cu energie a aparatului!",
"Actualizarea a eşuat!",
"Actualizarea s-a încheiat! Vă rugăm să reporniți aparatul!",
"Meniul SAROO de pornire",
"Se verifică discul ......",
"Nu s-a detectat nici nu disc!",
"Nu s-a detectat un disc cu jocuri compatibil!",
"Selectați categoria de jocuri",
};
static char **lang_list[] = {
lang_zhcn,
lang_en,
lang_ptbr,
lang_ja,
lang_fr,
lang_ru,
lang_zhtw,
lang_de,
lang_es,
lang_it,
lang_pl,
lang_swe,
lang_el,
lang_ro,
};
static const int lang_nr = sizeof(lang_list)/4;
static char **lang_cur;
/******************************************************************************/
u32 str_hash(char *str)
static u32 str_hash(char *str)
{
int len = strlen(str);
u32 hash = 5381;
@ -136,13 +397,14 @@ u32 str_hash(char *str)
char *TT(char *str)
{
if(lang_id==0 || lang_id>=LANG_NR)
if(lang_id==0 || lang_id>=lang_nr)
return str;
u32 hash = str_hash(str);
STR_ENTRY *entry = lang_str_table[hash&0xff];
while(entry){
if(hash==entry->hash){
//printk("TT: %s(%08x) -> %d %s\n", str, hash, entry->index, lang_cur[entry->index]);
return lang_cur[entry->index];
}
entry = entry->next;
@ -175,13 +437,18 @@ void lang_init(void)
//printk("%2d: %08x %s\n", i, lang_str[i].hash, lang_str[i].str);
}
lang_cur = NULL;
if(lang_id==1){
lang_cur = lang_en;
}else if(lang_id==2){
lang_cur = lang_ptbr;
}else if(lang_id==3){
lang_cur = lang_ja;
}
if(lang_id>=lang_nr)
lang_id = 0;
lang_cur = lang_list[lang_id];
}
void lang_next(void)
{
lang_id += 1;
if(lang_id==lang_nr)
lang_id = 0;
lang_cur = lang_list[lang_id];
}

View file

@ -43,5 +43,10 @@ SECTIONS
__bss_end = .;
}
. = __ip_start + 0x20000-4;
.pad_128k :
{
LONG(0);
}
}

View file

@ -16,6 +16,7 @@
u32 mcu_ver;
u32 debug_flag;
int bios_type;
/**********************************************************/
@ -27,6 +28,13 @@ u32 BE32(void *ptr)
}
u32 LE16(void *ptr)
{
u8 *b = (u8*)ptr;
return (b[1]<<8) | b[0];
}
u32 LE32(void *ptr)
{
u8 *b = (u8*)ptr;
@ -46,7 +54,9 @@ void LE32W(void *ptr, u32 val)
/**********************************************************/
u32 pad_read(void)
static int pad_state;
int pad_read(void)
{
u32 bits = 0;
@ -57,17 +67,31 @@ u32 pad_read(void)
PDR1 = 0x00; bits |= (PDR1 & 0xf) << 4;
bits ^= 0xfFF8;
#else
while(SF&0x01);
SF = 0x01;
IREG0 = 0x00;
IREG1 = 0x08;
IREG2 = 0xf0;
COMREG = 0x10;
while(SF&0x01);
bits = (OREG2<<8) | (OREG3);
IREG0 = 0x40;
bits ^= 0xFFFF;
if(pad_state==0){
if((TVSTAT&0x0008)==0)
return -1;
while(SF&0x01);
SF = 0x01;
IREG0 = 0x00;
IREG1 = 0x08;
IREG2 = 0xf0;
COMREG = 0x10;
pad_state = 1;
return -1;
}else if(pad_state==1){
if(SF&1){
return -1;
}
bits = (OREG2<<8) | (OREG3);
IREG0 = 0x40;
bits ^= 0xFFFF;
pad_state = 2;
}else if(pad_state==2){
if((TVSTAT&0x0008)==0){
pad_state = 0;
}
return -1;
}
#endif
//printk("pad_read: %04x\n", bits);
@ -77,6 +101,8 @@ u32 pad_read(void)
void pad_init(void)
{
pad_state = 0;
#ifdef PADMODE_DIRECT
PDR1 = 0;
DDR1 = 0x60;
@ -129,6 +155,7 @@ void stm32_puts(char *str)
/**********************************************************/
#if 0
const int HZ = 1000000;
void reset_timer(void)
@ -141,13 +168,50 @@ u32 get_timer(void)
return SS_TIMER;
}
#else
const int HZ = 208496; /* for NTSC: 320 lines mode */
static int timer_base;
void reset_timer(void)
{
timer_base = 0;
TCR = 0x02;
FRCH = 0;
FRCL = 0;
}
u32 get_timer(void)
{
int s1, s2, th, tl;
while(1){
s1 = FTCSR&0x02;
th = FRCH;
tl = FRCL;
s2 = FTCSR&0x02;
if(s1==s2)
break;
}
th = (th<<8) | tl;
if(s2&0x02){
timer_base += 65536;
FTCSR = 0;
}
return timer_base+th;
}
#endif
void usleep(u32 us)
{
u32 now, end;
if(us==0)
us = 1;
end = us*(HZ/1000000);
end = (us*HZ)/1000000;
reset_timer();
while(1){
@ -163,7 +227,7 @@ void msleep(u32 ms)
if(ms==0)
ms = 1;
end = ms*(HZ/1000);
end = (ms*HZ)/1000;
reset_timer();
while(1){
@ -216,44 +280,121 @@ int sci_getc(int timeout)
}
/**********************************************************/
void cpu_dmemcpy(void *dst, void *src, int size, int ch)
{
int chcr = 0x5a11;
if(((u32)src&0xfff8703f)==0x25800000){
// CDBLOCK的DATA_PORT
chcr &= 0xcfff;
}
while((CHCR0&0x03)==0x01);
CHCR0 = 0;
DMAOR = 1;
SAR0 = (u32)src;
DAR0 = (u32)dst;
TCR0 = (size+3)>>2;
CHCR0 = chcr;
}
#if 1
void scu_dmemcpy(void *dst, void *src, int size, int ch)
{
volatile SCUDMA_REG *sdma = (SCUDMA_REG *)(SCU_DMA_BASE+ch*0x20);
int mask = 0x0030;
int maskh = 0x0001;
if(ch>0){ mask <<= 4; maskh <<= 1; }
if(ch>1){ mask <<= 4; maskh = 0; }
mask |= maskh<<16;
while(SDSTAT&mask); // 等待传输结束
sdma->src = (u32)src;
sdma->dst = (u32)dst;
sdma->count = size;
sdma->addv = (((u32)dst&0x00f00000)==0) ? 0x102 : 0x101;
sdma->mode = 0x07;
sdma->enable = 0x101;
}
#else
void scu_dmemcpy(void *dst, void *src, int size, int ch)
{
while(SDSTAT&0x10030); // 等待传输结束
SD0R = (u32)src;
SD0W = (u32)dst;
SD0C = size;
SD0AD = (((u32)dst&0x00f00000)==0) ? 0x102 : 0x101;
SD0MD = 0x07;
SD0EN = 0x101;
}
#endif
/**********************************************************/
int read_file (char *name, int offset, int size, void *buf)
{
int retv;
LE32W((void*)(TMPBUFF_ADDR), offset);
LE32W((void*)(TMPBUFF_ADDR+0x00), offset);
LE32W((void*)(TMPBUFF_ADDR+0x04), size);
strcpy((void*)(TMPBUFF_ADDR+0x10), name);
u32 bus_addr = (u32)buf & 0x0fffffff;
if(bus_addr>=0x02000000 && bus_addr<0x03000000){
// buf位于MCU和SS可以直接访问的空间内。
LE32W((void*)(TMPBUFF_ADDR+0x08), bus_addr);
}else{
// buf不可直接访问必须中转。
LE32W((void*)(TMPBUFF_ADDR+0x08), TMPBUFF_ADDR+0x0100);
}
SS_ARG = 0;
SS_CMD = SSCMD_FILERD;
while(SS_CMD);
retv = (signed short)SS_ARG;
int retv = (signed short)SS_ARG;
if(retv<0)
return retv;
size = LE32((void*)(TMPBUFF_ADDR+0x04));
memcpy(buf, (void*)(TMPBUFF_ADDR+0x0100), size);
if(bus_addr<0x02000000 || bus_addr>=0x03000000){
memcpy(buf, (void*)(TMPBUFF_ADDR+0x0100), size);
}
return size;
}
int write_file(char *name, int offset, int size, void *buf)
{
int retv;
LE32W((void*)(TMPBUFF_ADDR), offset);
LE32W((void*)(TMPBUFF_ADDR+0x04), size);
strcpy((void*)(TMPBUFF_ADDR+0x10), name);
memcpy((void*)(TMPBUFF_ADDR+0x0100), buf, size);
u32 bus_addr = (u32)buf & 0x0fffffff;
if(bus_addr>=0x02000000 && bus_addr<0x03000000){
// buf位于MCU和SS可以直接访问的空间内。
LE32W((void*)(TMPBUFF_ADDR+0x08), bus_addr);
}else{
// buf不可直接访问必须中转。
LE32W((void*)(TMPBUFF_ADDR+0x08), TMPBUFF_ADDR+0x0100);
memcpy((void*)(TMPBUFF_ADDR+0x0100), buf, size);
}
SS_ARG = 0;
SS_CMD = SSCMD_FILEWR;
while(SS_CMD);
retv = (signed short)SS_ARG;
int retv = (signed short)SS_ARG;
if(retv<0)
return retv;
@ -327,6 +468,121 @@ int mem_test(int size)
}
/**********************************************************/
static int last_w, last_h, last_f;
static int cover_top = 1;
void gif_timer(void)
{
if((TVSTAT&0x0008)==0)
return;
int gif_flag = *(u8*)0x22400000;
if(gif_flag){
u8 *dst = (u8*)(VDP2_VRAM+0x20000);
u8 *src = (u8*)(0x22401000);
int src_llen = (gif_flag>=3)? 128 : 512;
int img_w = LE16((u8*)0x22400004);
int img_h = LE16((u8*)0x22400006);
int img_x = (short)LE16((u8*)0x22400008);
int img_y = (short)LE16((u8*)0x2240000a);
int adj_x = (short)LE16((u8*)0x2240000c);
int adj_y = (short)LE16((u8*)0x2240000e);
//printk("img: (%d,%d) %dx%d\n", img_x, img_y, img_w, img_h);
//if( (last_f!=gif_flag) ){
// printk("gflag: %d\n", gif_flag);
//}
if( (last_f!=gif_flag) || (gif_flag>=3 && (last_w>img_w || last_h>img_h)) ){
memset(dst, 0, 240*512);
}
last_f = gif_flag;
last_w = img_w;
last_h = img_h;
src += img_y*src_llen+img_x;
img_x += adj_x;
if(img_x<0){
src -= img_x;
img_w += img_x;
img_x = 0;
}
if(img_x+img_w>fbw){
img_w = fbw-img_x;
}
img_y += adj_y;
if(img_y<0){
src -= img_y*512;
img_h += img_y;
img_y = 0;
}
if(img_y+img_h>fbh){
img_h = fbh-img_y;
}
#if 1
if(cover_top){
if(gif_flag==3){
PRINA = 0x0706;
CCCTL = 0x0000;
BGON = 0x0203;
vdp2_win0(1, 1, img_x, img_y, img_x+img_w-1, img_y+img_h-1);
}else{
vdp2_win0(-1, 0, 0, 0, 0, 0);
PRINA = 0x0707;
CCCTL = 0x0002;
BGON = 0x0003;
}
}
#endif
dst += img_y*512+img_x;
//int start = get_timer();
for(int y=0; y<img_h; y++){
scu_dmemcpy(dst, src, img_w, 2);
dst += 512;
src += src_llen;
}
//int end = get_timer();
//printk("gt: %d ms\n", TICK2MS(end-start));
*(u8*)0x22400000 = 0;
}
int pal_flag = *(u8*)0x22400002;
if(pal_flag){
int i;
u8 *pal = (u8*)0x22400100;
for(i=0; i<256; i++){
nbg1_set_cram(i, pal[2], pal[1], pal[0]);
pal += 4;
}
*(u8*)0x22400002 = 0;
}
}
static void change_cover_layer(void)
{
if(cover_top==0){
vdp2_win0(-1, 0, 0, 0, 0, 0);
PRINA = 0x0707;
CCCTL = 0x0002;
BGON = 0x0003;
}else if(last_f==3){
PRINA = 0x0706;
CCCTL = 0x0000;
BGON = 0x0203;
int x = 176;
int y = (last_h>128)? 24 : 88;
vdp2_win0(1, 1, x, y, x+last_w-1, y+last_h-1);
}
}
/**********************************************************/
static int total_disc, total_page, page;
@ -334,8 +590,6 @@ static int sel_mode; // 0:game 1:binary
MENU_DESC sel_menu;
static void fill_selmenu(void)
{
int *disc_path = (int *)(IMGINFO_ADDR+0x04);
@ -343,21 +597,20 @@ static void fill_selmenu(void)
char tmp[128];
int i;
for(i=0; i<11; i++){
int index = page*11+i;
for(i=0; i<MENU_ITEMS; i++){
int index = page*MENU_ITEMS+i;
if(index>=total_disc)
break;
char *path = path_str + LE32(&disc_path[index]);
snprintf(tmp, 128, "%2d: %s", index, path+11);
snprintf(tmp, 128, "%2d: %s", index, path);
tmp[127] = 0;
if(sel_mode==0){
// /SAROO/ISO/xxxx/xxxx.cue
// xxxx/xxxx.cue
char *p = strchr(tmp, '/');
if(p) *p = 0;
}else{
// /SAROO/ISO/xxxx
// /SAROO/ISO/xxxx@xxxx
// xxxx@xxxx
char *p = strchr(tmp, '@');
if(p) *p = 0;
}
@ -365,10 +618,20 @@ static void fill_selmenu(void)
add_menu_item(&sel_menu, tmp);
}
int disp_page = (total_page)? page+1 : 0;
if(sel_mode==0){
sprintf(sel_menu.title, TT("选择游戏(%d/%d)"), page+1, total_page);
sprintf(sel_menu.title, TT("选择游戏(%d/%d)"), disp_page, total_page);
}else{
sprintf(sel_menu.title, TT("选择文件(%d/%d)"), page+1, total_page);
sprintf(sel_menu.title, TT("选择文件(%d/%d)"), disp_page, total_page);
}
}
static void select_notify(int index)
{
if(sel_mode==0){
SS_ARG = page*MENU_ITEMS + index;
SS_CMD = SSCMD_SELECT;
}
}
@ -381,6 +644,7 @@ static void page_update(int up)
fill_selmenu();
menu->current = (up)? menu->num-1: 0;
select_notify(menu->current);
draw_menu_frame(menu);
}
@ -389,9 +653,10 @@ int run_binary(int index, int run)
{
int *disc_path = (int *)(IMGINFO_ADDR+0x04);
char *path_str = (char*)(IMGINFO_ADDR);
char *bin_name = path_str + LE32(&disc_path[index]);
char bin_name[128];
int load_addr = 0x06004000;
sprintf(bin_name, "/SAROO/BIN/%s", path_str + LE32(&disc_path[index]));
char *p = strchr(bin_name, '@');
if(p){
load_addr = strtoul(p+1, NULL, 16, NULL);
@ -423,44 +688,48 @@ static int sel_handle(int ctrl)
MENU_DESC *menu = &sel_menu;
total_disc = LE32((u8*)(IMGINFO_ADDR));
total_page = (total_disc+10)/11;
total_page = (total_disc+MENU_ITEMS-1)/MENU_ITEMS;
if(BUTTON_DOWN(ctrl, PAD_UP)){
if(menu->current>0){
menu->current -= 1;
menu_update(menu);
select_notify(menu->current-1);
menu_update(menu, menu->current-1);
}else if(page>0){
page -= 1;
page_update(1);
}else{
}else if(total_page>1){
page = total_page-1;
page_update(1);
}
}else if(BUTTON_DOWN(ctrl, PAD_DOWN)){
if(menu->current<(menu->num-1)){
menu->current += 1;
menu_update(menu);
select_notify(menu->current+1);
menu_update(menu, menu->current+1);
}else if((page+1)<total_page){
page += 1;
page_update(0);
}else{
}else if(total_page>1){
page = 0;
page_update(0);
}
}else if(BUTTON_DOWN(ctrl, PAD_LT)){
page -= 1;
if(page<0){
page = total_page-1;
if(total_page>1){
page -= 1;
if(page<0){
page = total_page-1;
}
page_update(0);
}
page_update(0);
}else if(BUTTON_DOWN(ctrl, PAD_RT)){
page += 1;
if(page>=total_page){
page = 0;
if(total_page>1){
page += 1;
if(page>=total_page){
page = 0;
}
page_update(0);
}
page_update(0);
}else if(BUTTON_DOWN(ctrl, PAD_A)){
int index = page*11 + menu->current;
}else if(BUTTON_DOWN(ctrl, PAD_A) && (total_page>0)){
int index = page*MENU_ITEMS + menu->current;
int retv;
if(sel_mode==0){
@ -470,7 +739,10 @@ static int sel_handle(int ctrl)
SS_CMD = SSCMD_LOADDISC;
while(SS_CMD);
retv = bios_cd_cmd(0);
retv = SS_ARG;
if(retv==0){
retv = bios_cd_cmd(0);
}
if(retv){
char buf[40];
sprintf(buf, TT("游戏启动失败! %d"), retv);
@ -486,13 +758,31 @@ static int sel_handle(int ctrl)
}
}
}else if(BUTTON_DOWN(ctrl, PAD_Z)){
int index = page*11 + menu->current;
int index = page*MENU_ITEMS + menu->current;
int retv;
SS_ARG = index;
SS_CMD = SSCMD_LOADDISC;
while(SS_CMD);
if(sel_mode==0){
int index = page*MENU_ITEMS + menu->current;
my_cdplayer();
SS_ARG = index;
SS_CMD = SSCMD_LOADDISC;
while(SS_CMD);
use_sys_load = 0;
my_cdplayer();
}else{
menu_status(menu, TT("加载文件中......"));
cdblock_on(0);
retv = run_binary(index, 1);
if(retv){
char buf[40];
sprintf(buf, TT("文件加载失败! %d"), retv);
menu_status(menu, buf);
}
}
}else if(BUTTON_DOWN(ctrl, PAD_LEFT)){
cover_top ^= 1;
change_cover_layer();
}else if(BUTTON_DOWN(ctrl, PAD_C)){
return MENU_EXIT;
}
@ -504,15 +794,18 @@ static int sel_handle(int ctrl)
void select_game(void)
{
total_disc = LE32((u8*)(IMGINFO_ADDR));
total_page = (total_disc+10)/11;
total_page = (total_disc+MENU_ITEMS-1)/MENU_ITEMS;
page = 0;
memset(&sel_menu, 0, sizeof(sel_menu));
sel_menu.handle = sel_handle;
fill_selmenu();
select_notify(sel_menu.current | SELECT_ENTER);
menu_run(&sel_menu);
select_notify(SELECT_EXIT);
}
@ -526,11 +819,63 @@ void select_bins(void)
select_game();
SS_ARG = 0;
SS_CMD = SSCMD_LISTDISC;
while(SS_CMD);
}
/**********************************************************/
MENU_DESC category_menu;
static int category_handle(int ctrl)
{
MENU_DESC *menu = &category_menu;
if(menu_default(menu, ctrl))
return 0;
if(BUTTON_DOWN(ctrl, PAD_A)){
int index = menu->current;
SS_ARG = index;
SS_CMD = SSCMD_LISTDISC;
while(SS_CMD);
select_game();
return MENU_RESTART;
}else if(BUTTON_DOWN(ctrl, PAD_C)){
return MENU_EXIT;
}
return 0;
}
void select_category(void)
{
int category_num = *(u8*)(SYSINFO_ADDR+0x0c);
if(category_num==0)
return select_game();
memset(&category_menu, 0, sizeof(category_menu));
category_menu.handle = category_handle;
int i;
for(i=0; i<category_num; i++){
char *cat_name = (char*)(SYSINFO_ADDR+0x0e80+i*32);
add_menu_item(&category_menu, cat_name);
}
strcpy(category_menu.title, TT("选择游戏分类") );
menu_run(&category_menu);
}
/**********************************************************/
@ -555,39 +900,77 @@ int main_handle(int ctrl)
if(menu_default(&main_menu, ctrl))
return 0;
if(!BUTTON_DOWN(ctrl, PAD_A))
if(BUTTON_DOWN(ctrl, PAD_LT)){
lang_next();
return MENU_EXIT;
}
if(!BUTTON_DOWN(ctrl, PAD_A) && !BUTTON_DOWN(ctrl, PAD_C))
return 0;
if(BUTTON_DOWN(ctrl, PAD_C) && index!=2)
return 0;
if(index==0){
sel_mode = 0;
select_game();
select_category();
return MENU_RESTART;
}else if(index==1){
write_file("/SAROO/SS_BUP.BIN", 0, 0x10000, (void*)0x20180000);
cdblock_on(0);
bios_run_cd_player();
use_sys_bup = 1;
use_sys_load = 1;
my_cdplayer();
return MENU_RESTART;
}else if(index==2){
int type = 4;
menu_status(&main_menu, TT("检查光盘中......"));
cdblock_on(1);
int retv = cdblock_check();
//int retv = cdblock_check();
int retv = jhl_auth_hack(100000);
if(retv<0){
menu_status(&main_menu, TT("未发现光盘!"));
cdblock_off();
return 0;
}else if(retv==1){
// 是Audio CD
use_sys_bup = 1;
use_sys_load = 1;
my_cdplayer();
}else if(retv==2){
type = 2;
}else if(retv==3){
// 是刻录游戏CD
retv = jhl_auth_hack(100000);
if(retv!=2){
char buf[64];
sprintf(buf, "%s%d", TT("不是游戏光盘!"), retv);
menu_status(&main_menu, buf);
cdblock_off();
return 0;
}
type = 2;
}else if(retv!=4){
menu_status(&main_menu, TT("不是游戏光盘!"));
// 是数据CD
char buf[64];
sprintf(buf, "%s%d", TT("不是游戏光盘!"), retv);
menu_status(&main_menu, buf);
cdblock_off();
return 0;
}
// 停止正在播放的背景音乐。
SS_ARG = 0xffff;
SS_CMD = SSCMD_LOADDISC;
menu_status(&main_menu, TT("游戏启动中......"));
retv = bios_cd_cmd(4);
if(BUTTON_DOWN(ctrl, PAD_C)){
type |= 0x80;
}
retv = bios_cd_cmd(type);
if(retv){
char buf[40];
sprintf(buf, TT("游戏启动失败! %d"), retv);
menu_status(&main_menu, buf);
// CDBlock Off, SAROOO On
smpc_cmd(CDOFF);
SS_CTRL = SAROO_EN | CS0_RAM4M;
cdblock_off();
}
return 0;
}else if(index==3){
@ -595,7 +978,9 @@ int main_handle(int ctrl)
select_bins();
return MENU_RESTART;
}else if(index==4){
menu_status(&main_menu, NULL);
menu_status(&main_menu, "Open serial console ...");
sci_init();
sci_shell();
return MENU_EXIT;
}else if(index==update_index){
menu_status(&main_menu, TT("升级中,请勿断电..."));
@ -632,6 +1017,8 @@ void menu_init(void)
{
int i;
nbg1_on();
memset(&main_menu, 0, sizeof(main_menu));
strcpy(main_menu.title, TT("SAROO Boot Menu"));
@ -645,15 +1032,78 @@ void menu_init(void)
main_menu.handle = main_handle;
sprintf(ver_buf, "MCU:%06x SS:%06x FPGA:%02x", mcu_ver&0xffffff, get_build_date()&0xffffff, SS_VER&0xff);
sprintf(ver_buf, "MCU:%06x SS:%06x FPGA:%02x", mcu_ver&0xffffff, get_build_date()&0xffffff, SS_VER&0xff);
main_menu.version = ver_buf;
reset_timer();
menu_run(&main_menu);
}
/**********************************************************/
// Sega Saturn 1.00J : BTR_1.00D1940921 0
// Victor Saturn 1.00: BTR_1.00DJ941018 1
//
// Sega Saturn 1.00a : BTR_1.000U941115 2 40417:f4
// Sega Saturn 1.01a : BTR_1.000U941115 3 40417:54
// Samsung Saturn : BTR_1.000U941115 4 40417:84
//
// Sega Saturn 1.01J : BTR_1.0191941228 5
// V-Saturn 1.01J : BTR_1.019J950703 6
// HI-Saturn 1.01J : BTR_1.019H950130 7
// HI-Saturn 1.02J : BTR_1.020H950519 8
// HI-Saturn 1.03 : BTRF1.030H950720 9
//
// Sega Saturn 1.003 : BTRD1.0032941012 10
//
static char *bvstr[12] = {"0D1","0DJ","00U","00U","00U","191","19J","19H","20H","30H","032",};
void detect_bios_type(void)
{
int i;
char *bv = (char*)0x0807;
for(i=0; i<11; i++){
if(strncmp(bv, bvstr[i], 3)==0){
bios_type = i;
break;
}
}
if(i==11){
bios_type = BIOS_UNKNOW;
return;
}
if(bios_type==BIOS_100A){
if(*(u8*)(0x40417)==0x54){
bios_type = BIOS_101A;
}else if(*(u8*)(0x40417)==0x84){
bios_type = BIOS_SAMS;
}
}
}
/**********************************************************/
int _main(void)
{
// EFSDL/EFPAN for CDDA
*(u8* )(0x25b00217) = 0xc0;
*(u8* )(0x25b00237) = 0xc0;
// Master Volume
*(u16*)(0x25b00400) = 0x020f;
detect_bios_type();
SS_ARG = 0;
SS_CMD = SSCMD_STARTUP;
conio_init();
pad_init();
@ -663,15 +1113,22 @@ int _main(void)
lang_id = LE32((void*)(SYSINFO_ADDR+0x04));
debug_flag = LE32((void*)(SYSINFO_ADDR+0x08));
// restore bios_loadcd_init1
// restore bios function
*(u32*)(0x06000288) = 0x000018a8; // bios_loadcd_boot
*(u32*)(0x0600028c) = 0x00001874; // bios_loadcd_readip
*(u32*)(0x0600029c) = 0x00001904; // bios_loadcd_init
*(u32*)(0x060002dc) = *(u32*)(0x2000111c);
*(u32*)(0x02000f04) = (u32)cdc_read_sector;
*(u32*)(0x02000f04) = (u32)cdc_read_sector;
*(u32*)(0x02000f08) = (u32)read_file;
*(u32*)(0x02000f0c) = (u32)write_file;
*(u32*)(0x02000f24) = (u32)conio_getc;
*(u32*)(0x02000f30) = (u32)bios_cd_cmd;
*(u32*)(0x02000f34) = (u32)page_update;
*(u32*)(0x02000f38) = (u32)sci_init;
*(u32*)(0x02000f3c) = (u32)printk;
sys_bup_init = (void*)*(u32*)(0x20000958);
if(debug_flag&0x0001){
// sci_putc
@ -681,6 +1138,7 @@ int _main(void)
printk(" SS ver: %08x\n", get_build_date());
printk(" FPGA ver: %08x\n", SS_VER);
printk(" lang_id: %d\n", lang_id);
printk(" bios_type: %d\n", bios_type);
}else if(debug_flag&0x0004){
// conio_putc
}else if(debug_flag&0x0008){
@ -699,9 +1157,6 @@ int _main(void)
lang_init();
while(1){
menu_init();
sci_init();
sci_shell();
}
return 0;

View file

@ -47,11 +47,17 @@ typedef unsigned long long u64;
#define SSCMD_LSAVE 0x000a
#define SSCMD_LMEMS 0x000b
#define SSCMD_SMEMS 0x000c
#define SSCMD_STARTUP 0x000d
#define SSCMD_SELECT 0x000e
#define SELECT_ENTER 0x8000
#define SELECT_EXIT 0x4000
#define IMGINFO_ADDR 0x22080000
#define SYSINFO_ADDR 0x220a0000
#define TMPBUFF_ADDR 0x220c0000
#define SYSINFO_ADDR 0x220a3000
#define SAVINFO_ADDR 0x220a4000
#define TMPBUFF_ADDR 0x220c7000
/*****************************************************************************/
@ -115,9 +121,9 @@ typedef struct {
#define bios_run_cd_player INDIRECT_CALL(0x0600026C, void, void)
#define bios_loadcd_init1 INDIRECT_CALL(0x060002dc, int, int) // 00002650
#define bios_loadcd_init INDIRECT_CALL(0x0600029c, int, int) // 00001904
#define bios_loadcd_init INDIRECT_CALL(0x0600029c, int, void) // 00001904
#define bios_loadcd_read INDIRECT_CALL(0x060002cc, int, void) // 00001912
#define bios_loadcd_boot INDIRECT_CALL(0x06000288, int, void) // 000018A8
#define bios_loadcd_boot INDIRECT_CALL(0x06000288, int, void) // 000018A8
//!< mode 0 -> check, 1 -> do auth
#define bios_check_cd_auth INDIRECT_CALL(0x06000270, int, int mode)
@ -160,6 +166,7 @@ void cdc_trans_data(u8 *buf, int length);
int cdc_auth_status(int *status);
int cdc_auth_device(void);
int jhl_auth_hack(int delay);
int cdc_change_dir(int selnum, int fid);
int cdc_read_dir(int selnum, int fid);
@ -186,19 +193,43 @@ int cdc_read_sector(int fad, int size, u8 *buf);
void my_cdplayer(void);
void bup_init(u8 *lib_addr, u8 *work_addr, void *cfg);
extern void (*sys_bup_init)(u8*, u8*, void*);
extern int use_sys_bup;
extern int use_sys_load;
enum{
BIOS_100J,
BIOS_100V,
BIOS_100A,
BIOS_101A,
BIOS_SAMS,
BIOS_101J,
BIOS_101V,
BIOS_101H,
BIOS_102H,
BIOS_103H,
BIOS_1003,
BIOS_UNKNOW,
};
extern int bios_type;
/*****************************************************************************/
extern const int HZ;
#define MS2TICK(ms) ( (ms) * HZ / 1000)
#define TICK2MS(tk) ( (tk) * 1000 / HZ)
#define TICK2US(tk) ( (tk) * 1000*1000 / HZ)
void reset_timer(void);
u32 get_timer(void);
void usleep(u32 us);
void msleep(u32 ms);
void cpu_dmemcpy(void *to, void *from, int size, int ch);
void scu_dmemcpy(void *dst, void *src, int size, int ch);
/*****************************************************************************/
@ -216,7 +247,7 @@ void msleep(u32 ms);
#define PAD_Z (1<<4)
#define PAD_LT (1<<3)
u32 pad_read(void);
int pad_read(void);
int smpc_cmd(int cmd);
@ -224,7 +255,7 @@ int smpc_cmd(int cmd);
void conio_init(void);
void conio_put_char(int x, int y, int color, int ch);
int conio_put_char(int x, int y, int color, int ch);
void conio_putc(int ch);
u32 conio_getc(void);
@ -241,6 +272,13 @@ void put_vline(int x, int y1, int y2, int c);
void put_rect (int x1, int y1, int x2, int y2, int c);
void put_box(int x1, int y1, int x2, int y2, int c);
void nbg1_on(void);
void nbg1_set_cram(int index, int r, int g, int b);
void nbg1_put_pixel(int x, int y, int color);
void vdp2_win0(int scr, int outside, int sx, int sy, int ex, int ey);
/*****************************************************************************/
@ -337,6 +375,7 @@ u32 crc32(u8 *buf, int len, u32 crc);
u32 get_sr(void);
void set_sr(u32 sr);
void set_imask(u32 imask);
void install_isr(int type);
void break_in_game(int break_pc, void *handle);
void break_in_game_next(int break_pc, void *handle);
@ -354,11 +393,13 @@ extern int game_break_pc;
/*****************************************************************************/
#define MENU_ITEMS 12
typedef struct menu_desc_t {
int num;
int current;
char title[64];
char items[11][64];
char items[MENU_ITEMS][96];
char *version;
int (*handle)(int index);
}MENU_DESC;
@ -372,12 +413,13 @@ int menu_run(MENU_DESC *menu);
void menu_status(MENU_DESC *menu, char *string);
void draw_menu_frame(MENU_DESC *menu);
void menu_update(MENU_DESC *menu);
void menu_update(MENU_DESC *menu, int new);
int menu_default(MENU_DESC *menu, int ctrl);
extern int lang_id;
void lang_init(void);
void lang_next(void);
char *TT(char *str);
/*****************************************************************************/
@ -393,6 +435,12 @@ void patch_game(char *id);
extern u32 debug_flag;
/*****************************************************************************/
void gif_timer(void);
/*****************************************************************************/
#endif

View file

@ -360,9 +360,14 @@ void sci_shell(void)
CMD(c) {
/* 打开系统光驱 */
cdblock_on(1);
}
CMD(auth){
int retv = cdblock_check();
printk("cdblock_check: %d\n", retv);
}
CMD(jhl){
jhl_auth_hack(arg[0]);
}
CMD(s) {
/* 关闭系统光驱, 打开sarooo */
cdblock_off();

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

250
Firm_Saturn/slogo.h Normal file
View file

@ -0,0 +1,250 @@
#ifndef __logo_dat__
#define __logo_dat__
static unsigned int size_logo_dat = 3872;
static unsigned char logo_dat[] __attribute__((aligned(16))) = {
0x80, 0x00, 0xc0, 0x20, 0xbc, 0xa0, 0xd0, 0xe0, 0xdd, 0x60, 0xe1, 0xc0, 0xea, 0x00, 0xd9, 0xc8,
0xf2, 0x40, 0xf6, 0xa0, 0xfe, 0xe0, 0xf2, 0xca, 0xf7, 0x32, 0xf7, 0x7a, 0xff, 0xdd, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x28, 0xdf, 0x00, 0x00, 0x8e, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x22, 0x02, 0x46, 0xbc, 0xcc,
0x5b, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x73, 0x33, 0xfb, 0x34, 0x44, 0x55,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0xcc, 0xcc, 0xcc, 0xcc,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x33, 0x33, 0x33, 0x33, 0x55, 0x55, 0x55, 0x55,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x30, 0xcc, 0xcc, 0xcc, 0x50,
0xff, 0xff, 0xff, 0x50, 0xff, 0xff, 0xff, 0x60, 0x33, 0x3c, 0xff, 0x60, 0x55, 0x4c, 0xff, 0x80,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x06, 0xcf, 0x00, 0x00, 0x5c, 0xff, 0x00, 0x02, 0xbf, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x10, 0x58, 0xbc, 0xcc, 0xb5,
0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0x43, 0x33, 0x7e, 0x44, 0x45, 0x54, 0x43,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
0xc6, 0x20, 0x00, 0x00, 0xff, 0x83, 0x00, 0x00, 0xff, 0xf8, 0x20, 0x00, 0xcf, 0xfe, 0x60, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x22, 0x22, 0x22, 0x18, 0xcc, 0xcc, 0xcc,
0x1b, 0xff, 0xff, 0xff, 0x2b, 0xff, 0xff, 0xff, 0x2b, 0xff, 0x73, 0x33, 0x2b, 0xff, 0x75, 0x55,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0xcc, 0xcc, 0xcc, 0xcc,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x33, 0x33, 0x33, 0x33, 0x55, 0x55, 0x55, 0x55,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x21, 0x00, 0xcc, 0xcc, 0xbb, 0x54,
0xff, 0xff, 0xff, 0xee, 0xff, 0xff, 0xff, 0xff, 0x33, 0x33, 0x47, 0xcf, 0x55, 0x55, 0x44, 0x43,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
0xb5, 0x20, 0x00, 0x00, 0xff, 0xb5, 0x00, 0x00, 0xff, 0xfc, 0x60, 0x00, 0xbf, 0xff, 0xd8, 0x02,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x24, 0x59,
0x00, 0x25, 0xbe, 0xff, 0x04, 0x8f, 0xff, 0xff, 0x4b, 0xff, 0xff, 0xc7, 0x9f, 0xff, 0xc3, 0x34,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0xbc, 0xcc, 0xcc, 0xcc,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x43, 0x33, 0x33, 0x33, 0x45, 0x55, 0x55, 0x55,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x21, 0x00, 0x00, 0xcc, 0xbb, 0x54, 0x20,
0xff, 0xff, 0xfe, 0xb5, 0xff, 0xff, 0xff, 0xff, 0x33, 0x47, 0xcf, 0xff, 0x55, 0x44, 0x43, 0xbf,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
0x20, 0x00, 0x02, 0x5b, 0x94, 0x00, 0x49, 0xff, 0xfb, 0x44, 0xbf, 0xff, 0xff, 0x99, 0xff, 0xfb,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x22, 0x22, 0x45, 0xbb, 0xcc, 0xcc,
0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x74, 0x33, 0x33, 0x34, 0x44, 0x55, 0x55,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x10, 0xcc, 0xcc, 0xcb, 0x95,
0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x33, 0x33, 0x34, 0x7c, 0x55, 0x55, 0x54, 0x44,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00,
0xeb, 0x52, 0x00, 0x00, 0xff, 0xf8, 0x40, 0x00, 0xff, 0xff, 0xb4, 0x00, 0x3c, 0xff, 0xf9, 0x20,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x08, 0xdf, 0xfe, 0x00, 0x6c, 0xff, 0xe4, 0x02, 0xaf, 0xff, 0x58, 0x08, 0xdf, 0xf9, 0x89,
0x0a, 0xff, 0xd6, 0xaa, 0x4c, 0xff, 0xba, 0xaa, 0x8d, 0xff, 0x8a, 0xaa, 0xaf, 0xfd, 0x9a, 0xaa,
0x44, 0x56, 0x66, 0x86, 0x58, 0x88, 0x88, 0x88, 0x98, 0x98, 0x88, 0x89, 0x99, 0x99, 0xdf, 0xff,
0xa9, 0xbf, 0xec, 0xb9, 0xaa, 0xfc, 0x66, 0x88, 0xaf, 0xd6, 0x9a, 0xaa, 0xaf, 0x89, 0xaa, 0xaa,
0x86, 0x86, 0x86, 0x86, 0x88, 0x88, 0x88, 0x88, 0x99, 0x99, 0x99, 0x99, 0xff, 0xff, 0xff, 0xff,
0x99, 0x99, 0x99, 0x99, 0x88, 0x88, 0x88, 0x88, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0x86, 0x6c, 0xff, 0x80, 0x88, 0x6c, 0xff, 0x90, 0x99, 0x8c, 0xff, 0xa0, 0xff, 0xff, 0xff, 0xa0,
0x99, 0x9d, 0xff, 0xa0, 0x88, 0x8c, 0xff, 0xa0, 0xaa, 0xac, 0xff, 0xa0, 0xaa, 0xac, 0xff, 0xa0,
0x00, 0x08, 0xef, 0xf4, 0x00, 0x2a, 0xff, 0xc5, 0x00, 0x5c, 0xff, 0x68, 0x00, 0xaf, 0xfe, 0x69,
0x02, 0xbf, 0xfc, 0x9a, 0x08, 0xdf, 0xf8, 0xaa, 0x0a, 0xff, 0xd9, 0xaa, 0x3b, 0xff, 0xba, 0xaa,
0x56, 0x68, 0x68, 0x66, 0x88, 0x88, 0x88, 0x88, 0x89, 0x88, 0x88, 0x89, 0x99, 0xaf, 0xfd, 0x99,
0xa9, 0xdd, 0x9f, 0xa9, 0xaa, 0xf8, 0x6c, 0xda, 0xac, 0xe9, 0xa9, 0xfa, 0xae, 0xca, 0xa8, 0xfb,
0x4d, 0xff, 0xb2, 0x00, 0x65, 0xff, 0xd6, 0x00, 0x86, 0xdf, 0xfa, 0x00, 0x99, 0xbf, 0xfc, 0x40,
0xa9, 0x8f, 0xfe, 0x90, 0xaa, 0x9c, 0xff, 0xa0, 0xaa, 0xab, 0xff, 0xc4, 0xaa, 0xa8, 0xff, 0xe9,
0x2b, 0xff, 0x96, 0x68, 0x2b, 0xff, 0x98, 0x88, 0x2b, 0xff, 0x98, 0x88, 0x2b, 0xff, 0xff, 0xff,
0x2b, 0xff, 0xbb, 0xbb, 0x2b, 0xff, 0x98, 0x88, 0x2b, 0xff, 0xba, 0xaa, 0x2b, 0xff, 0xba, 0xaa,
0x68, 0x68, 0x68, 0x68, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xff, 0xff, 0xff, 0xff,
0xbb, 0xbb, 0xbb, 0xbb, 0x88, 0x88, 0x88, 0x88, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0x68, 0x68, 0x68, 0x65, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xff, 0xff, 0xfc, 0x99,
0xbb, 0xbb, 0xcf, 0xfa, 0x88, 0x88, 0x66, 0xdf, 0xaa, 0xaa, 0xa9, 0x6d, 0xaa, 0xaa, 0xaa, 0x99,
0x44, 0xff, 0xfd, 0x68, 0x85, 0x4e, 0xff, 0xbb, 0x98, 0x65, 0xff, 0xfd, 0x99, 0x98, 0xbf, 0xff,
0x9a, 0xa9, 0x6d, 0xff, 0xaa, 0xaa, 0xab, 0xff, 0xea, 0xaa, 0xa8, 0xff, 0xfa, 0xaa, 0xa9, 0xdf,
0xef, 0xfb, 0x45, 0x66, 0xff, 0xc4, 0x88, 0x88, 0xff, 0x58, 0x89, 0x88, 0xfc, 0x89, 0x99, 0x9b,
0xfb, 0x9a, 0xa9, 0xbf, 0xf9, 0xaa, 0xaa, 0xfe, 0xf9, 0xaa, 0xab, 0xf9, 0xf9, 0xaa, 0xac, 0xf8,
0x68, 0x68, 0x68, 0x68, 0x88, 0x88, 0x88, 0x88, 0x88, 0x99, 0x99, 0x99, 0xef, 0xff, 0xff, 0xff,
0xfb, 0x99, 0x99, 0x99, 0x66, 0x88, 0x88, 0x88, 0x9a, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0x68, 0x68, 0x65, 0x47, 0x88, 0x88, 0x88, 0x85, 0x98, 0x88, 0x88, 0x98, 0xff, 0xeb, 0x99, 0x99,
0x9b, 0xef, 0xc9, 0xaa, 0x86, 0x5d, 0xfa, 0xaa, 0xaa, 0x98, 0xfb, 0xaa, 0xaa, 0xa8, 0xfc, 0xaa,
0xff, 0xee, 0xff, 0x74, 0xbf, 0xff, 0xfb, 0x48, 0x5f, 0xff, 0xf5, 0x88, 0x8c, 0xff, 0xc8, 0x99,
0xab, 0xff, 0x99, 0xaa, 0xa9, 0xff, 0x9a, 0xaa, 0xa9, 0xff, 0x9a, 0xaa, 0xa9, 0xfe, 0x9a, 0xaa,
0x56, 0x68, 0x68, 0x68, 0x88, 0x88, 0x88, 0x88, 0x98, 0x88, 0x89, 0x99, 0x99, 0xbf, 0xff, 0xff,
0x9c, 0xfe, 0xb9, 0x99, 0xaf, 0xd5, 0x68, 0x88, 0xcf, 0x89, 0xaa, 0xaa, 0xcf, 0x8a, 0xaa, 0xaa,
0x68, 0x68, 0x68, 0x66, 0x88, 0x88, 0x88, 0x88, 0x99, 0x99, 0x88, 0x89, 0xff, 0xff, 0xfe, 0xb9,
0x99, 0x99, 0xbf, 0xfb, 0x88, 0x88, 0x66, 0xef, 0xaa, 0xaa, 0xa9, 0x9f, 0xaa, 0xaa, 0xaa, 0x8f,
0x54, 0x7f, 0xfe, 0x80, 0x88, 0x4c, 0xff, 0xb3, 0x89, 0x85, 0xff, 0xe9, 0x99, 0x98, 0xcf, 0xfa,
0x9a, 0xa9, 0xbf, 0xfb, 0xaa, 0xaa, 0x9f, 0xfc, 0xba, 0xaa, 0x9f, 0xfc, 0xca, 0xaa, 0x9f, 0xfd,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x20, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xaf, 0xfc, 0xaa, 0xaa, 0xaf, 0xfc, 0xaa, 0xaa, 0xaf, 0xfc, 0xaa, 0xaa, 0xaf, 0xfc, 0xaa, 0xaa,
0xaf, 0xfd, 0x99, 0xaa, 0x6d, 0xff, 0x99, 0x99, 0x3c, 0xff, 0xb9, 0x99, 0x0a, 0xff, 0xd8, 0x89,
0xcf, 0x8a, 0xaa, 0xaa, 0xce, 0x9a, 0xaa, 0xaf, 0xce, 0x9a, 0xaa, 0xac, 0xbf, 0xaa, 0xaa, 0x96,
0x8f, 0xc9, 0x9a, 0x9a, 0x8c, 0xfa, 0x99, 0x99, 0x95, 0xdf, 0xc9, 0x99, 0x88, 0x5c, 0xff, 0xdb,
0xaa, 0xaa, 0xaa, 0xaa, 0xee, 0xee, 0xfe, 0xef, 0xef, 0xff, 0xff, 0xff, 0x66, 0x9c, 0xef, 0xff,
0x98, 0x86, 0x5b, 0xff, 0x99, 0x99, 0x86, 0x5d, 0x98, 0x99, 0x99, 0x85, 0x98, 0x89, 0x89, 0x98,
0xaa, 0x9c, 0xff, 0xa0, 0xff, 0xef, 0xff, 0xa0, 0xff, 0xff, 0xff, 0xa3, 0xfd, 0xdd, 0xdd, 0xa9,
0xfe, 0x98, 0x66, 0x8a, 0xff, 0xe9, 0x00, 0x3c, 0xdf, 0xfc, 0x60, 0x9e, 0x5f, 0xff, 0xa3, 0xaf,
0x9d, 0xff, 0x8a, 0xaa, 0xaf, 0xfd, 0x9a, 0xaa, 0xcf, 0xfb, 0xaa, 0xaa, 0xef, 0xf8, 0xaa, 0xaa,
0xff, 0xc9, 0xaa, 0xac, 0xff, 0xb9, 0x99, 0x9f, 0xff, 0x69, 0x99, 0xaf, 0xfc, 0x89, 0x88, 0xcd,
0xaf, 0x8a, 0xa9, 0xcd, 0xcd, 0x9a, 0xaa, 0x9f, 0xfb, 0xaa, 0xaa, 0x8e, 0xf8, 0xaa, 0xaa, 0xac,
0xd9, 0xaa, 0xaa, 0xa8, 0xb9, 0x99, 0x99, 0xa8, 0x69, 0x99, 0x99, 0x99, 0x89, 0x98, 0xc8, 0x89,
0xaa, 0xa9, 0xcf, 0xfa, 0xaa, 0xaa, 0x9f, 0xfc, 0xca, 0xaa, 0x8e, 0xff, 0xea, 0xaa, 0x9c, 0xff,
0xfa, 0xaa, 0xa8, 0xff, 0xec, 0x99, 0xa8, 0xef, 0xbf, 0x89, 0x99, 0xbf, 0x6f, 0x98, 0x89, 0x6f,
0x4b, 0xff, 0xba, 0xaa, 0x9b, 0xff, 0xba, 0xaa, 0xab, 0xff, 0xba, 0xaa, 0xab, 0xff, 0xba, 0xaa,
0xcb, 0xff, 0xba, 0xaa, 0xfa, 0xff, 0xb9, 0x99, 0xfc, 0xff, 0xb9, 0x99, 0xfe, 0xff, 0xb8, 0x89,
0xaa, 0xaa, 0xaa, 0xaa, 0xad, 0xee, 0xee, 0xee, 0xae, 0xed, 0xdd, 0xdd, 0xae, 0xc6, 0x66, 0x66,
0x9e, 0xc9, 0x9a, 0x99, 0x9e, 0xc9, 0x99, 0x99, 0x8e, 0xc9, 0x99, 0x99, 0x8e, 0xc8, 0x89, 0x89,
0xaa, 0xaa, 0xaa, 0xa8, 0xee, 0xea, 0xaa, 0xa9, 0xdd, 0xda, 0xaa, 0xa9, 0x66, 0x69, 0xaa, 0xaa,
0xa9, 0xa9, 0xa9, 0xab, 0x99, 0x99, 0x99, 0x9f, 0x99, 0x99, 0x99, 0xef, 0x89, 0xbb, 0xcf, 0xf6,
0xfc, 0xaa, 0xaa, 0xcf, 0xfc, 0xaa, 0xaa, 0xcf, 0xfc, 0xaa, 0xaa, 0xcf, 0xfb, 0xaa, 0xaa, 0xcf,
0xf9, 0xaa, 0x99, 0xdf, 0xd8, 0xa9, 0x99, 0xff, 0x69, 0x99, 0x9a, 0xff, 0x89, 0x89, 0x8d, 0xff,
0xf9, 0xaa, 0xac, 0xf9, 0xf9, 0xaa, 0xac, 0xf9, 0xf9, 0xaa, 0xac, 0xf9, 0xf9, 0xaa, 0xac, 0xf9,
0xf9, 0xaa, 0xac, 0xf9, 0xf9, 0x99, 0x9c, 0xf9, 0xf8, 0x99, 0x9c, 0xf8, 0xf8, 0x98, 0x8c, 0xf8,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xab, 0xff, 0xfb, 0xaa, 0xac, 0xff, 0xfc, 0xaa, 0xab, 0xff, 0xfc,
0xaa, 0xab, 0xff, 0xfc, 0x99, 0x9b, 0xff, 0xfc, 0x99, 0x9b, 0xff, 0xfb, 0x98, 0x8b, 0xff, 0xfb,
0xaa, 0xa9, 0xec, 0xaa, 0xaa, 0xa9, 0xec, 0xaa, 0xaa, 0xa9, 0xec, 0xaa, 0xaa, 0xaa, 0xec, 0xaa,
0xaa, 0xa9, 0xec, 0x99, 0x99, 0x99, 0xec, 0x99, 0x99, 0x98, 0xec, 0x99, 0x88, 0x88, 0xec, 0x88,
0xa9, 0xee, 0x9a, 0xaa, 0xa9, 0xee, 0xaa, 0xaa, 0xa9, 0xee, 0xaa, 0xaa, 0xaa, 0xee, 0xaa, 0xaa,
0xa9, 0xee, 0x9a, 0x99, 0x99, 0xee, 0x99, 0x99, 0x98, 0xee, 0x89, 0x99, 0x88, 0xee, 0x88, 0x88,
0xce, 0x9a, 0xaa, 0xaa, 0xce, 0xaa, 0xaa, 0xbf, 0xce, 0xaa, 0xaa, 0xcf, 0xce, 0xaa, 0xaa, 0xcf,
0xce, 0x9a, 0xaa, 0xcf, 0xce, 0x99, 0x99, 0xcf, 0xce, 0x89, 0x99, 0xcf, 0xce, 0x88, 0x88, 0xcf,
0xaa, 0xaa, 0xaa, 0x9f, 0xff, 0xaa, 0xaa, 0x9f, 0xff, 0xba, 0xaa, 0x9f, 0xff, 0xba, 0xaa, 0x9f,
0xff, 0xba, 0xaa, 0x9f, 0xff, 0xb9, 0x99, 0x9f, 0xff, 0xb9, 0x99, 0x8f, 0xff, 0xb8, 0x89, 0x8f,
0xca, 0xaa, 0x9f, 0xfd, 0xca, 0xaa, 0x9f, 0xfd, 0xca, 0xaa, 0x9f, 0xfd, 0xca, 0xaa, 0x9f, 0xfd,
0xca, 0xaa, 0x9f, 0xfd, 0xc9, 0x99, 0x9f, 0xfd, 0xc9, 0x99, 0x8f, 0xfd, 0xc8, 0x89, 0x8f, 0xfd,
0x60, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00,
0x60, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03,
0x06, 0xdf, 0xfb, 0x88, 0x01, 0x9f, 0xff, 0x88, 0x00, 0x4b, 0xff, 0xf6, 0x33, 0x36, 0xcf, 0xff,
0xbc, 0xcc, 0xbf, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xcf, 0xf3, 0x33, 0x33,
0x88, 0x85, 0x5b, 0xdf, 0x86, 0x88, 0x65, 0x44, 0x68, 0x66, 0x66, 0x66, 0xb5, 0x66, 0x66, 0x66,
0xfd, 0xb6, 0x55, 0x56, 0xff, 0xff, 0xec, 0xb6, 0xff, 0xff, 0xff, 0xfd, 0x33, 0x33, 0x43, 0x44,
0xff, 0xc8, 0x88, 0x88, 0x6b, 0xff, 0xb6, 0x88, 0x54, 0x4c, 0xfb, 0x66, 0x65, 0x54, 0xdf, 0x66,
0x66, 0x65, 0x4f, 0xb6, 0x55, 0x55, 0x4f, 0xc5, 0x55, 0x55, 0x4e, 0xc5, 0x55, 0x54, 0x4f, 0xb5,
0x67, 0xff, 0xc8, 0xcf, 0x85, 0xdf, 0xf6, 0xff, 0x66, 0xbf, 0xfb, 0xff, 0x66, 0x5f, 0xff, 0xff,
0x66, 0x4f, 0xff, 0xfe, 0x55, 0x5e, 0xff, 0xfb, 0x55, 0x4e, 0xff, 0xf4, 0x55, 0x4e, 0xff, 0xd4,
0xf8, 0x88, 0x88, 0xfb, 0xe5, 0x88, 0x8b, 0xf5, 0xc6, 0x66, 0x6d, 0xc6, 0x56, 0x66, 0x6f, 0x76,
0x46, 0x66, 0xbf, 0x46, 0x55, 0x55, 0xdc, 0x55, 0x55, 0x55, 0xf7, 0x55, 0x55, 0x5b, 0xf3, 0x55,
0x88, 0x8b, 0xf8, 0x88, 0x88, 0x8c, 0xf8, 0x88, 0x86, 0x6f, 0xfb, 0x66, 0x66, 0x9f, 0xfe, 0x56,
0x55, 0xcf, 0xff, 0x66, 0x55, 0xff, 0xff, 0xb5, 0x56, 0xff, 0xff, 0xd4, 0x4c, 0xff, 0xff, 0xf5,
0x6d, 0xc8, 0x88, 0x6d, 0x8b, 0xf6, 0x88, 0x8b, 0x85, 0xfb, 0x66, 0x85, 0x65, 0xcd, 0x66, 0x65,
0x65, 0x7f, 0x56, 0x65, 0x55, 0x4f, 0xb5, 0x55, 0x55, 0x4c, 0xd5, 0x55, 0x55, 0x45, 0xf5, 0x55,
0xff, 0xff, 0xb8, 0x88, 0xff, 0xff, 0xb8, 0x88, 0xff, 0xff, 0x96, 0x68, 0xcf, 0xff, 0x96, 0x66,
0x7f, 0xff, 0x96, 0x65, 0x4f, 0xff, 0x75, 0x55, 0x4c, 0xff, 0x75, 0x55, 0x47, 0xff, 0x75, 0x55,
0x8e, 0xc8, 0x88, 0x88, 0x6e, 0xc8, 0x88, 0x88, 0x6e, 0xc6, 0x66, 0x66, 0x5e, 0xc6, 0x66, 0x66,
0x5e, 0xc5, 0x56, 0x65, 0x5e, 0xc5, 0x55, 0x56, 0x4e, 0xc5, 0x55, 0x5c, 0x4e, 0xc4, 0x54, 0x4c,
0x88, 0xff, 0xfc, 0x56, 0x86, 0xbf, 0x54, 0x68, 0x68, 0x4f, 0xe5, 0x86, 0x66, 0x57, 0xfb, 0x66,
0x66, 0x64, 0xdf, 0x56, 0x55, 0x55, 0x4f, 0xc5, 0x55, 0x55, 0x4c, 0xf5, 0xc4, 0x55, 0x53, 0xfd,
0x88, 0x88, 0x9f, 0xff, 0x86, 0x86, 0xef, 0xff, 0x68, 0x6d, 0xff, 0xff, 0x66, 0xbf, 0xfe, 0xcf,
0x66, 0x5d, 0xff, 0xef, 0x55, 0x55, 0xff, 0xff, 0x55, 0x54, 0xcf, 0xff, 0x45, 0x55, 0x4f, 0xff,
0xf6, 0x88, 0x8c, 0xf8, 0xf6, 0x88, 0x8c, 0xf6, 0xf6, 0x86, 0x6c, 0xf6, 0xe5, 0x66, 0x6b, 0xf5,
0xe5, 0x66, 0x5c, 0xf5, 0xe5, 0x55, 0x5b, 0xf5, 0xe4, 0x55, 0x5c, 0xf4, 0xf4, 0x55, 0x4b, 0xf4,
0x88, 0x8b, 0xff, 0xfb, 0x88, 0x8b, 0xff, 0xfb, 0x86, 0x6b, 0xff, 0xfb, 0x66, 0x6b, 0xff, 0xfb,
0x66, 0x6b, 0xff, 0xfb, 0x55, 0x5b, 0xff, 0xfb, 0x55, 0x57, 0xff, 0xfb, 0x55, 0x54, 0x33, 0x34,
0x88, 0x88, 0xec, 0x88, 0x88, 0x86, 0xec, 0x88, 0x66, 0x86, 0xec, 0x66, 0x66, 0x65, 0xec, 0x66,
0x56, 0x65, 0xec, 0x56, 0x55, 0x55, 0xec, 0x55, 0x55, 0x54, 0xec, 0x55, 0x55, 0x54, 0xec, 0x45,
0x88, 0xee, 0x88, 0x88, 0x86, 0xee, 0x68, 0x88, 0x86, 0xee, 0x68, 0x66, 0x65, 0xee, 0x56, 0x66,
0x65, 0xee, 0x56, 0x55, 0x55, 0xee, 0x55, 0x55, 0x54, 0xee, 0x45, 0x55, 0x54, 0xee, 0x45, 0x54,
0xce, 0x88, 0x88, 0xcf, 0xce, 0x68, 0x88, 0xbf, 0xce, 0x68, 0x66, 0xbf, 0xce, 0x56, 0x66, 0xbf,
0xce, 0x55, 0x65, 0xbf, 0xce, 0x55, 0x55, 0xbf, 0xce, 0x45, 0x55, 0xbf, 0xce, 0x45, 0x55, 0x43,
0xff, 0xb8, 0x88, 0x8f, 0xff, 0xb8, 0x88, 0x6f, 0xff, 0xb6, 0x68, 0x6f, 0xff, 0xb6, 0x66, 0x5f,
0xff, 0xb6, 0x66, 0x5f, 0xff, 0xb5, 0x55, 0x5f, 0xff, 0x75, 0x55, 0x4f, 0x33, 0x45, 0x55, 0x4f,
0xb8, 0x88, 0x8f, 0xfd, 0xb8, 0x88, 0x6f, 0xfd, 0xb6, 0x68, 0x6f, 0xfd, 0xb6, 0x66, 0x5f, 0xfd,
0xb5, 0x66, 0x5f, 0xfd, 0xb5, 0x55, 0x5f, 0xfd, 0xb5, 0x55, 0x4f, 0xfd, 0xb4, 0x55, 0x4f, 0xfd,
0x50, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02,
0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02,
0xcf, 0xf3, 0x44, 0x44, 0xcf, 0xf4, 0x44, 0x44, 0xcf, 0xf3, 0x44, 0x44, 0xcf, 0xf3, 0x33, 0x33,
0xcf, 0xff, 0xff, 0xff, 0xcf, 0xf7, 0x77, 0x77, 0xcf, 0xf1, 0x22, 0x22, 0xcf, 0xf2, 0x33, 0x33,
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x34, 0x44, 0x34, 0x44, 0x33, 0x33, 0x33, 0x33,
0xff, 0xff, 0xff, 0xff, 0x77, 0x77, 0x77, 0x77, 0x22, 0x22, 0x22, 0x22, 0x33, 0x33, 0x33, 0x33,
0x44, 0x44, 0x5f, 0x74, 0x44, 0x43, 0xdf, 0x34, 0x44, 0x3b, 0xf7, 0x44, 0x47, 0xdf, 0x73, 0x44,
0xff, 0xd3, 0x23, 0x33, 0x73, 0x23, 0x33, 0x33, 0x22, 0x33, 0x33, 0x33, 0x33, 0x33, 0x32, 0x3f,
0x44, 0x4f, 0xff, 0x74, 0x44, 0x7f, 0xff, 0x34, 0x44, 0xcf, 0xfc, 0x34, 0x43, 0xff, 0xf7, 0x34,
0x3b, 0xff, 0xf2, 0x43, 0x4f, 0xff, 0xc3, 0x33, 0xff, 0xff, 0x43, 0x33, 0xff, 0xff, 0x13, 0x33,
0x44, 0x4e, 0xc4, 0x44, 0x44, 0x4f, 0x44, 0x44, 0x44, 0xbf, 0x34, 0x44, 0x33, 0xeb, 0x34, 0x44,
0x34, 0xf3, 0x33, 0x3b, 0x3b, 0xe2, 0x33, 0x3d, 0x2f, 0xb3, 0x33, 0x3f, 0x4f, 0x23, 0x23, 0xbf,
0x45, 0x44, 0x44, 0x45, 0x44, 0x33, 0x33, 0x34, 0x44, 0x44, 0x44, 0x44, 0x43, 0x33, 0x33, 0x33,
0xbb, 0xbb, 0xbb, 0xbb, 0xff, 0xff, 0xff, 0xff, 0x12, 0x11, 0x11, 0x11, 0x22, 0x32, 0x32, 0x32,
0x44, 0x53, 0xfb, 0x44, 0x44, 0x44, 0xbf, 0x44, 0x44, 0x44, 0x3f, 0x54, 0x33, 0x33, 0x2d, 0xc3,
0xbb, 0xbb, 0xbc, 0xf3, 0xff, 0xff, 0xff, 0xf7, 0x11, 0x11, 0x11, 0x12, 0x32, 0x32, 0x32, 0x33,
0x53, 0xff, 0x74, 0x44, 0x44, 0xbf, 0x74, 0x44, 0x44, 0x4f, 0x74, 0x44, 0x34, 0x3f, 0x74, 0x44,
0x43, 0x3b, 0x73, 0x34, 0x33, 0x33, 0x73, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
0x4e, 0xc4, 0x44, 0x4c, 0x4e, 0xc4, 0x44, 0x4c, 0x3e, 0xc4, 0x34, 0x4c, 0x3e, 0xc3, 0x44, 0x3b,
0x3e, 0xc3, 0x33, 0x3b, 0x3e, 0xc3, 0x33, 0x3b, 0x2e, 0xb3, 0x33, 0x3b, 0x2e, 0xb2, 0x33, 0x2b,
0xf5, 0x44, 0x44, 0xbf, 0xfd, 0x44, 0x44, 0x3f, 0xff, 0x74, 0x44, 0x47, 0xff, 0xf3, 0x44, 0x42,
0xff, 0xfb, 0x33, 0x33, 0xff, 0xff, 0x33, 0x33, 0xff, 0xff, 0xc2, 0x33, 0xff, 0xdf, 0xf4, 0x33,
0x74, 0x45, 0x4b, 0xff, 0xf4, 0x44, 0x43, 0xff, 0xfb, 0x44, 0x43, 0x7f, 0xdf, 0x34, 0x34, 0x2e,
0x3f, 0xc3, 0x43, 0x34, 0x2c, 0xf4, 0x33, 0x32, 0x32, 0xfd, 0x23, 0x33, 0x22, 0x7f, 0x73, 0x33,
0xf4, 0x44, 0x4b, 0xf4, 0xf4, 0x44, 0x47, 0xf4, 0xf4, 0x44, 0x43, 0xfb, 0xf7, 0x44, 0x43, 0xbf,
0xfc, 0x33, 0x33, 0x2b, 0xdf, 0x33, 0x33, 0x32, 0x3f, 0xb2, 0x33, 0x33, 0x2c, 0xf7, 0x23, 0x33,
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x34, 0x44, 0x43, 0x44, 0xb4, 0x33, 0x33, 0x33,
0xff, 0xff, 0xff, 0xff, 0x24, 0x77, 0x77, 0x77, 0x32, 0x22, 0x22, 0x22, 0x33, 0x33, 0x33, 0x33,
0x44, 0x44, 0xfc, 0x44, 0x44, 0x44, 0xfb, 0x44, 0x44, 0x37, 0xf4, 0x34, 0x34, 0xbf, 0xc3, 0x44,
0xff, 0xfb, 0x23, 0x43, 0x74, 0x22, 0x33, 0x33, 0x23, 0x23, 0x33, 0x33, 0x33, 0x33, 0x23, 0x24,
0x44, 0xee, 0x44, 0x44, 0x44, 0xff, 0x44, 0x44, 0x44, 0xff, 0x44, 0x44, 0x47, 0xff, 0x74, 0x44,
0x3b, 0xff, 0xb3, 0x33, 0x3f, 0xff, 0xf3, 0x33, 0x7f, 0xff, 0xfb, 0x33, 0xff, 0xee, 0xff, 0x42,
0xce, 0x44, 0x44, 0x44, 0xbf, 0x34, 0x44, 0x44, 0x4f, 0x73, 0x44, 0x44, 0x3c, 0xfb, 0x43, 0x33,
0x32, 0xbf, 0xff, 0xff, 0x33, 0x22, 0x47, 0x77, 0x33, 0x33, 0x22, 0x22, 0x32, 0x33, 0x33, 0x33,
0x44, 0x44, 0x44, 0x4f, 0x44, 0x44, 0x44, 0x4f, 0x34, 0x44, 0x43, 0xbf, 0x33, 0x33, 0x4b, 0xfb,
0xff, 0xff, 0xff, 0xb2, 0x77, 0x77, 0x42, 0x23, 0x22, 0x22, 0x23, 0x33, 0x33, 0x33, 0x33, 0x32,
0xb4, 0x44, 0x4f, 0xfc, 0x74, 0x44, 0x4f, 0xfc, 0x34, 0x44, 0x4f, 0xfb, 0x33, 0x44, 0x7f, 0xf7,
0x44, 0x33, 0xcf, 0xf4, 0x33, 0x33, 0xff, 0xd3, 0x33, 0x2b, 0xff, 0xb1, 0x32, 0x7f, 0xff, 0x30,
0x30, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xcf, 0xf2, 0x33, 0x33, 0xcf, 0xf1, 0x11, 0x11, 0xcf, 0xfd, 0xdd, 0xdd, 0xcf, 0xff, 0xff, 0xff,
0xbd, 0xdd, 0xdd, 0xdd, 0x11, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x33, 0x33, 0x33, 0x33, 0x11, 0x11, 0x11, 0x11, 0xdd, 0xdd, 0xdd, 0xdd, 0xff, 0xff, 0xff, 0xff,
0xdd, 0xdd, 0xdd, 0xdd, 0x11, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x32, 0x22, 0x17, 0xff, 0x11, 0x3b, 0xff, 0xff, 0xef, 0xff, 0xff, 0xf4, 0xff, 0xff, 0xfb, 0x14,
0xdc, 0xb4, 0x11, 0x1b, 0x11, 0x10, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xfb, 0x23, 0x32, 0xef, 0xf2, 0x11, 0x11, 0xef, 0xfd, 0xdd, 0xdd, 0xff, 0xff, 0xff, 0xff,
0xdd, 0xdd, 0xdd, 0xdd, 0x11, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xce, 0x13, 0x32, 0xdf, 0xf7, 0x11, 0x12, 0xff, 0xfd, 0xdd, 0xde, 0xff, 0xff, 0xff, 0xff, 0xff,
0xdd, 0xdd, 0xdd, 0xdd, 0x11, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x23, 0x33, 0x33, 0x33, 0x11, 0x11, 0x11, 0x11, 0xdd, 0xdd, 0xdd, 0xdd, 0xff, 0xff, 0xff, 0xff,
0xdd, 0xdd, 0xdd, 0xdd, 0x11, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x33, 0x33, 0x33, 0x33, 0x11, 0x11, 0x11, 0x11, 0xdd, 0xdd, 0xdd, 0xdd, 0xff, 0xff, 0xff, 0xff,
0xdd, 0xdd, 0xdd, 0xdd, 0x11, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x33, 0x33, 0x33, 0x33, 0x11, 0x11, 0x11, 0x11, 0xdd, 0xdd, 0xdd, 0xdd, 0xff, 0xff, 0xff, 0xff,
0xdd, 0xdd, 0xdd, 0xdd, 0x11, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x1e, 0xb2, 0x33, 0x2b, 0x1e, 0xb1, 0x11, 0x1b, 0xdf, 0xed, 0xdd, 0xde, 0xff, 0xff, 0xff, 0xff,
0xee, 0xdd, 0xdd, 0xdd, 0x11, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0x3f, 0xfe, 0x13, 0xff, 0x1c, 0xff, 0x71, 0xff, 0x22, 0xff, 0xfd, 0xff, 0x21, 0x7f, 0xff,
0xde, 0x20, 0x1d, 0xdd, 0x11, 0x20, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x33, 0x1f, 0xf1, 0x33, 0x11, 0x13, 0xfb, 0x11, 0xdd, 0xdd, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xff,
0xdd, 0xdd, 0xdd, 0xdd, 0x11, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x31, 0xff, 0x71, 0x22, 0x11, 0x7f, 0xfe, 0x73, 0xdd, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xdd, 0xdd, 0xdd, 0xdb, 0x11, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x23, 0x33, 0x33, 0x33, 0x11, 0x11, 0x11, 0x11, 0xfe, 0xdd, 0xdd, 0xdd, 0xff, 0xff, 0xff, 0xff,
0xcd, 0xdd, 0xdd, 0xdd, 0x11, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x33, 0x23, 0x21, 0x7f, 0x11, 0x13, 0x7e, 0xff, 0xde, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3,
0xdd, 0xcb, 0x41, 0x10, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0x77, 0xff, 0xf7, 0xfb, 0x11, 0xbf, 0xff, 0x71, 0x00, 0x17, 0xff, 0x10, 0x00, 0x01, 0x3b,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x12, 0x32, 0x33, 0x33, 0xe7, 0x31, 0x11, 0x11, 0xff, 0xff, 0xed, 0xdd, 0xff, 0xff, 0xff, 0xff,
0x14, 0xbc, 0xdd, 0xdd, 0x00, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x33, 0x33, 0x32, 0x22, 0x11, 0x11, 0x11, 0x37, 0xdd, 0xdd, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff,
0xdd, 0xdd, 0xdc, 0xb4, 0x11, 0x11, 0x11, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x17, 0xff, 0xf7, 0x10, 0xef, 0xff, 0x72, 0x00, 0xff, 0xf7, 0x10, 0x00, 0xfb, 0x21, 0x00, 0x00,
0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
#endif

View file

@ -13,6 +13,7 @@
#define SMPC_H_
/******************************************************************************/
#define SMPC_BASE 0x20100000
@ -89,12 +90,55 @@
#define RESDISA 0x1a
/******************************************************************************/
#define SCU_BASE 0x25FE0000
/* SCU A-BUS */
#define ASR0 REG(SCU_BASE+0xb0)
#define ASR1 REG(SCU_BASE+0xb4)
#define AREF REG(SCU_BASE+0xb8)
/* SCU DMA */
#define SCU_DMA_BASE (SCU_BASE+0x0000)
#define SD0R REG(SCU_BASE+0x00)
#define SD0W REG(SCU_BASE+0x04)
#define SD0C REG(SCU_BASE+0x08)
#define SD0AD REG(SCU_BASE+0x0c)
#define SD0EN REG(SCU_BASE+0x10)
#define SD0MD REG(SCU_BASE+0x14)
#define SD1R REG(SCU_BASE+0x20)
#define SD1W REG(SCU_BASE+0x24)
#define SD1C REG(SCU_BASE+0x28)
#define SD1AD REG(SCU_BASE+0x2c)
#define SD1EN REG(SCU_BASE+0x30)
#define SD1MD REG(SCU_BASE+0x34)
#define SD2R REG(SCU_BASE+0x40)
#define SD2W REG(SCU_BASE+0x44)
#define SD2C REG(SCU_BASE+0x48)
#define SD2AD REG(SCU_BASE+0x4c)
#define SD2EN REG(SCU_BASE+0x50)
#define SD2MD REG(SCU_BASE+0x54)
#define SDSTOP REG(SCU_BASE+0x60)
#define SDSTAT REG(SCU_BASE+0x7c)
typedef struct {
u32 src;
u32 dst;
u32 count;
u32 addv;
u32 enable;
u32 mode;
u32 unk_18;
u32 unk_1c;
}SCUDMA_REG;
#define SCUDMA ((volatile SCUDMA_REG *)(SCU_DMA_BASE))
/******************************************************************************/
/* CPU SCI port */
#define SMR REG8(0xfffffe00)
#define BRR REG8(0xfffffe01)
@ -129,6 +173,20 @@
#define BDMRB REG (0xffffff74)
#define BRCR REG16(0xffffff78)
/* CPU DMAC */
#define SAR0 REG (0xffffff80)
#define DAR0 REG (0xffffff84)
#define TCR0 REG (0xffffff88)
#define CHCR0 REG (0xffffff8c)
#define VCRDMA0 REG (0xffffffa0)
#define DRCR0 REG8(0xffffff71)
#define SAR1 REG (0xffffff90)
#define DAR1 REG (0xffffff94)
#define TCR1 REG (0xffffff98)
#define CHCR1 REG (0xffffff9c)
#define VCRDMA1 REG (0xffffffa8)
#define DRCR1 REG8(0xffffff72)
#define DMAOR REG (0xffffffb0)

View file

@ -4,6 +4,7 @@
#include "main.h"
#if 0
void *memset(void *s, int v, int n)
{
register char *p = (char *)s;
@ -29,6 +30,7 @@ void *memcpy(void *to, void *from, int n)
return to;
}
#endif
int memcmp(void *dst, void *src, int n)
{

View file

@ -7,15 +7,14 @@
.section .sysid
hwid: .ascii "SEGA SEGASATURN "
makerid: .ascii "ANDERS MONTONEN "
produm: .ascii "ANTIME-001"
makerid: .ascii "TPU "
produm: .ascii "T-7605781 "
version: .ascii "V1.003"
reldat: .ascii "20120610"
reldat: .ascii "20230214"
devinfo: .ascii "R 2 "
area: .ascii "JTUE "
.ascii " "
area: .ascii "JTUEABLK "
periph: .ascii "J "
title: .ascii " "
title: .ascii "SAROO firm "
.ascii " "
.ascii " "
.ascii " "
@ -38,4 +37,7 @@ firstsize: .long 0
.incbin "sega/sys_aret.bin"
.incbin "sega/sys_areu.bin"
.incbin "sega/sys_aree.bin"
.incbin "sega/sys_init.bin"
.incbin "sega/sys_area.bin"
.incbin "sega/sys_areb.bin"
.incbin "sega/sys_arel.bin"
.incbin "sega/sys_arek.bin"

View file

@ -41,7 +41,7 @@ inline void set_sr(u32 sr)
__asm volatile ( "ldc\t%0,sr":: "r" (sr) );
}
static inline void set_imask(u32 imask)
inline void set_imask(u32 imask)
{
u32 sr = get_sr();
sr &= 0xffffff0f;

View file

@ -151,6 +151,7 @@
#define LSTA0L (*(volatile unsigned short *)(VDP2_REGISTER_BASE+0xa2))
#define LSTA1U (*(volatile unsigned short *)(VDP2_REGISTER_BASE+0xa4))
#define LSTA1L (*(volatile unsigned short *)(VDP2_REGISTER_BASE+0xa6))
#define LCTA (*(volatile unsigned int *)(VDP2_REGISTER_BASE+0xa8))
#define LCTAU (*(volatile unsigned short *)(VDP2_REGISTER_BASE+0xa8))
#define LCTAL (*(volatile unsigned short *)(VDP2_REGISTER_BASE+0xaa))
#define BKTA (*(volatile unsigned int *)(VDP2_REGISTER_BASE+0xac))
@ -240,4 +241,21 @@
#define COBG (*(volatile unsigned short *)(VDP2_REGISTER_BASE+0x11c))
#define COBB (*(volatile unsigned short *)(VDP2_REGISTER_BASE+0x11e))
// VDP1
#define VDP1_RAM 0x25C00000
#define VDP1_REG_TVMR (*(volatile unsigned short *)0x25D00000)
#define VDP1_REG_FBCR (*(volatile unsigned short *)0x25D00002)
#define VDP1_REG_PTMR (*(volatile unsigned short *)0x25D00004)
#define VDP1_REG_EWDR (*(volatile unsigned short *)0x25D00006)
#define VDP1_REG_EWLR (*(volatile unsigned short *)0x25D00008)
#define VDP1_REG_EWRR (*(volatile unsigned short *)0x25D0000A)
#define VDP1_REG_ENDR (*(volatile unsigned short *)0x25D0000C)
#define VDP1_REG_EDSR (*(volatile unsigned short *)0x25D00010)
#define VDP1_REG_LOPR (*(volatile unsigned short *)0x25D00012)
#define VDP1_REG_COPR (*(volatile unsigned short *)0x25D00014)
#define VDP1_REG_MODR (*(volatile unsigned short *)0x25D00016)
#endif/* VDP2_H_ */

View file

@ -1,13 +1,15 @@
# SAROO config file
# 可用配置:
# lang_id=x
# 选择菜单语言: 0:中文 1:EN 2:PTBR 3:JA
# 选择菜单语言: 0:中文 1:EN 2:PTBR 3:JA 4:FR 5:RU 6:繁中 7:DE 8:ES 9:IT 10:PL 11:SWE
# debug=xxxxxxxx
# 各种调试选项
# auto_update:
# MCU自动升级固件
# play_delay=xxxx
# PLAY开始前的延时。十进制us单位。
# pend_delay=xxxx
# PLAY结束前的延时。十进制us单位。
# sector_delay=xxxx
# 每读一个扇区后的延时。十进制us单位。
# exmem_1M
@ -20,6 +22,10 @@
# 写16位内存
# M_xxxxxxxx=xx
# 写8位内存
# multi_disc="xxxx"
# 多盘游戏识别
# category="xxxx"
# 新增一个游戏分类
#
[global]
@ -28,27 +34,27 @@ lang_id = 0
# Final Fight Revenge
[T-1248G V1.004]
sector_delay=2000
sector_delay = 2000
# PUZZLE BOBBLE 3
[T-1109G V1.002]
sector_delay=4000
sector_delay = 4000
# D-XHIRD
[T-10307G V1.002]
sector_delay=1000
sector_delay = 1000
# TAROMARU 太郎丸
[T-4804G V1.004]
sector_delay=1000
sector_delay=2000
# SALAMANDER-DP 沙罗曼蛇合集
[T-9520G V1.010]
sector_delay=2000
sector_delay=4000
# Princess Crown 公主的皇冠
@ -60,3 +66,123 @@ sector_delay=6000
[GS-9043 V1.002]
sector_delay=4000
# The Emblem of Justice (Japan) 修复过场景时黑屏的问题
[T-21001G V1.003]
sector_delay=1000
# 信长野望天翔记威力加强版 修复花屏
[T-7643G V1.001]
sector_delay=2000
# Time Bokan
[T-20607G V1.003]
play_delay = 2000
# Gotha - Ismailia SenEki (Japan)
[GS-9009 V1.000]
play_delay = 16000
sector_delay = 5000
# Last Bronx
[GS-9152 V1.113]
play_delay = 50000
[GS-9133 V1.003]
play_delay = 16000
sector_delay = 5000
[T-31505G V1.004]
play_delay = 50000
# Bug! (USA) (R) Fixed First stage problem
[MK-81004 V1.017]
sector_delay=1000
# Bug! (USA) Fixed First stage problem
[GM-81004 V1.017]
sector_delay=1000
# Batman Forever - The Arcade Game(Japan)
[T-8118G V1.000]
play_delay = 100000
sector_delay = 4200
# DAYTONA USA (E)
# Fixes advanced and export routes booting to system
[MK_8120050V1.000]
sector_delay=500
# DAYTONA USA (U)
# Fixes advanced and export routes booting to system
[MK-81200 V1.000]
sector_delay=500
# DAYTONA USA (J)
# Fixes advanced and export routes booting to system
[GS-9013 V1.000]
sector_delay=500
# LAST GLADIATORS
# Fixes black screen when leaving options
[T-4804H V1.000]
sector_delay=1000
# Riglord Saga 2
[GS-9084 V1.100]
play_delay = 50000
sector_delay = 5000
# Hop Step Idol
[T-20507G V1.002]
play_delay = 5000
pend_delay = 5000
# Thunderhawk II
[T-6006G V1.001]
sector_delay = 8000
# Thunderhawk 2 Firestorm
[T-11501H00V1.000]
sector_delay = 8000
# Thunderstrike 2
[T-7902H V3.000]
sector_delay = 8000
# Virtual Fighter (US)
[MK-81005 V1.000]
sector_delay = 1000
# Virtual Fighter (EU)
[MK_8100550V1.000]
sector_delay = 1000
# Virtual Fighter (JP)
[GS-9001 V1.000]
sector_delay = 1000
# Magical Drop III - Toretate Zoukan-gou! (Japan) (2M)
[T-1313G V1.005]
play_delay = 8000

12
tools/bdfont/.gitignore vendored Normal file
View file

@ -0,0 +1,12 @@
/*
!/bdf
!/cbdf
!.gitignore
!bdfont.c
!Makefile
!latin.txt
!cjk.txt
!mkfont.sh

7
tools/bdfont/Makefile Normal file
View file

@ -0,0 +1,7 @@
all:
gcc -Wall -g -o bdfont bdfont.c
clean:
rm -f *.exe

54128
tools/bdfont/bdf/7x14.bdf Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

3445
tools/bdfont/bdf/char14.bdf Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

2669
tools/bdfont/bdf/crox2t.bdf Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,5 @@
Load BDF: char14.bdf
PIXEL_SIZE: 15
FONT_ASCENT: 14
Wrong PIXEL_SIZE: 15

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

4539
tools/bdfont/bdf/helv14.bdf Normal file

File diff suppressed because it is too large Load diff

13790
tools/bdfont/bdf/helvR14.bdf Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

3445
tools/bdfont/bdf/ncen14.bdf Normal file

File diff suppressed because it is too large Load diff

3454
tools/bdfont/bdf/symb14.bdf Normal file

File diff suppressed because it is too large Load diff

4221
tools/bdfont/bdf/tech14.bdf Normal file

File diff suppressed because it is too large Load diff

4520
tools/bdfont/bdf/term14.bdf Normal file

File diff suppressed because it is too large Load diff

16201
tools/bdfont/bdf/timR14.bdf Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

449908
tools/bdfont/bdf/wqy13px.bdf Normal file

File diff suppressed because it is too large Load diff

440
tools/bdfont/bdfont.c Normal file
View file

@ -0,0 +1,440 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/******************************************************************************/
typedef signed int s32;
typedef signed short s16;
typedef signed char s8;
typedef unsigned int u32;
typedef unsigned short u16;
typedef unsigned char u8;
typedef struct {
int unicode;
/* Glyph bitmap infomation */
int bw, bh;
int bx, by;
int advance;
int bitmap[24];
int bsize;
} GLYPH;
int clist[65536];
GLYPH *ctab[65536];
int total_chars;
int pixel_size;
int font_ascent;
int base_adj = 0;
u8 font_buf[0x100000];
int font_buf_size;
/******************************************************************************/
int ucs2utf8(u16 ucs, char *p)
{
if(ucs<=0x7f){
p[0] = ucs;
return 1;
}else if(ucs<=0x7ff){
p[0] = 0xc0 | ((ucs>>6)&0x1f);
p[1] = 0x80 | ((ucs>>0)&0x3f);
return 2;
}else if(ucs<=0xffff){
p[0] = 0xe0 | ((ucs>>12)&0x0f);
p[1] = 0x80 | ((ucs>>6)&0x3f);
p[2] = 0x80 | ((ucs>>0)&0x3f);
return 3;
}
return 0;
}
/******************************************************************************/
GLYPH *load_char(FILE *fp)
{
int bmp;
char lbuf[128];
GLYPH *pg;
pg = NULL;
bmp = -1;
while(1){
if(fgets(lbuf, 128, fp)==NULL)
break;
if(strncmp(lbuf, "STARTCHAR", 9)==0){
pg = (GLYPH*)malloc(sizeof(GLYPH));
memset(pg, 0, sizeof(GLYPH));
}else if(strncmp(lbuf, "ENCODING", 8)==0){
pg->unicode = atoi(lbuf+9);
}else if(strncmp(lbuf, "DWIDTH", 6)==0){
pg->advance = atoi(lbuf+7);
}else if(strncmp(lbuf, "BBX", 3)==0){
sscanf(lbuf+4, "%d %d %d %d", &pg->bw, &pg->bh, &pg->bx, &pg->by);
int ny = (font_ascent+base_adj-1) - (pg->bh - 1 + pg->by);
if(ny<0)
ny = 0;
pg->by = ny;
if(pg->bx<0){
pg->advance -= pg->bx;
pg->bx = 0;
}
}else if(strncmp(lbuf, "BITMAP", 6)==0){
bmp = 0;
}else if(strncmp(lbuf, "ENDCHAR", 7)==0){
break;
}else if(bmp>=0){
sscanf(lbuf, "%x", &pg->bitmap[bmp]);
bmp += 1;
}
}
if(pg){
pg->bsize = (pg->bw > 8)? 2*pg->bh : pg->bh;
}
return pg;
}
int load_bdf(char *bdf_name)
{
FILE *fp;
GLYPH *pg;
char lbuf[128];
total_chars = 0;
memset(ctab, 0, sizeof(ctab));
fp = fopen(bdf_name, "r");
if(fp==NULL)
return -1;
fgets(lbuf, 128, fp);
if(strncmp(lbuf, "STARTFONT", 9)){
printf("STARTFONT not found!\n");
return -1;
}
printf("\nLoad BDF: %s\n", bdf_name);
pixel_size = 0;
font_ascent = 0;
while(1){
if(fgets(lbuf, 128, fp)==NULL)
break;
if(strncmp(lbuf, "PIXEL_SIZE", 10)==0){
pixel_size = atoi(lbuf+11);
printf(" PIXEL_SIZE: %d\n", pixel_size);
}else if(strncmp(lbuf, "FONT_ASCENT", 11)==0){
font_ascent = atoi(lbuf+12);
printf(" FONT_ASCENT: %d\n", font_ascent);
}else if(strncmp(lbuf, "CHARS ", 6)==0){
break;
}
}
if(pixel_size==0 || pixel_size>14){
printf("Wrong PIXEL_SIZE: %d\n", pixel_size);
return -1;
}
while(1){
pg = load_char(fp);
if(pg==NULL)
break;
if(clist[pg->unicode]==0){
free(pg);
continue;
}
ctab[pg->unicode] = pg;
total_chars += 1;
}
printf(" Chars load: %d\n", total_chars);
fclose(fp);
return 0;
}
/******************************************************************************/
void load_list(char *name)
{
FILE *fp;
char lbuf[128];
int n;
memset(clist, 1, sizeof(clist));
if(name==NULL)
return;
fp = fopen(name, "r");
if(fp==NULL)
return;
memset(clist, 0, sizeof(clist));
n = 0;
while(1){
if(fgets(lbuf, 128, fp)==NULL)
break;
if(lbuf[0]=='#' || lbuf[0]=='\r' || lbuf[0]=='\n' || lbuf[0]==0){
continue;
}
if(lbuf[4]=='-'){
// 8123-8567
int i, start, end;
sscanf(lbuf, "%x-%x", &start, &end);
for(i=start; i<=end; i++){
clist[i] = 1;
n += 1;
}
}else{
// 8124=xx
int ucs;
lbuf[4] = 0;
sscanf(lbuf, "%x", &ucs);
clist[ucs] = 1;
n += 1;
}
}
printf("Load list form %s: %d\n", name, n);
}
/******************************************************************************/
void print_glyph(GLYPH *pg)
{
int x, y;
char ubuf[4];
*(u32*)(ubuf) = 0;
ucs2utf8(pg->unicode, ubuf);
printf("\nchar %04x [%s]\n", pg->unicode, ubuf);
printf(" bw=%-2d bh=%-2d bx=%-2d by=%-2d adv=%d\n", pg->bw, pg->bh, pg->bx, pg->by, pg->advance);
for(y=0; y<pg->bh; y++){
printf(" ");
int mask = (pg->bw>8)? 0x8000 : 0x80;
int bd = pg->bitmap[y];
for(x=0; x<pg->bw; x++){
if(bd&mask)
printf("*");
else
printf(".");
mask >>= 1;
}
printf("\n");
}
}
void dump_glyph(void)
{
int i;
for(i=0; i<65536; i++){
if(ctab[i]){
print_glyph(ctab[i]);
}
}
}
void dump_list(void)
{
int i;
char ubuf[4];
for(i=0; i<65536; i++){
if(ctab[i]){
*(u32*)(ubuf) = 0;
ucs2utf8(i, ubuf);
printf("%04x=%s\n", i, ubuf);
}
}
}
/******************************************************************************/
void write_be16(u8 *p, int val)
{
p[0] = (val>>8)&0xff;
p[1] = val&0xff;
}
void write_be24(u8 *p, int val)
{
p[0] = (val>>16)&0xff;
p[1] = (val>>8)&0xff;
p[2] = val&0xff;
}
void build_font(void)
{
int i, j, p, offset;
write_be16(font_buf, total_chars);
offset = total_chars*5+2;
p = 2;
for(i=0; i<65536; i++){
if(ctab[i]){
GLYPH *pg = ctab[i];
write_be16(font_buf+p, i);
write_be24(font_buf+p+2, offset);
p += 5;
offset += pg->bsize+3;
}
}
for(i=0; i<65536; i++){
if(ctab[i]){
GLYPH *pg = ctab[i];
font_buf[p+0] = pg->advance;
font_buf[p+1] = (pg->bw<<4) | pg->bh;
font_buf[p+2] = (pg->bx<<4) | (pg->by&0x0f);
p += 3;
for(j=0; j<pg->bh; j++){
if(pg->bw > 8){
write_be16(font_buf+p, pg->bitmap[j]);
p += 2;
}else{
font_buf[p] = pg->bitmap[j];
p += 1;
}
}
}
}
font_buf_size = p;
}
/******************************************************************************/
int bin2c(u8 *buffer, int size, char *file_name, char *label_name)
{
FILE *dest;
int i, unit=1;
if((dest = fopen(file_name, "w")) == NULL) {
printf("Failed to open/create %s.\n", file_name);
return 1;
}
fprintf(dest, "#ifndef __%s__\n", label_name);
fprintf(dest, "#define __%s__\n\n", label_name);
fprintf(dest, "#define %s_size %d\n", label_name, size);
fprintf(dest, "static unsigned char %s[] = {", label_name);
for(i=0; i<size; i+=unit) {
if((i % (16/unit)) == 0){
fprintf(dest, "\n\t");
}else{
fprintf(dest, " ");
}
if(unit==1){
fprintf(dest, "0x%02x,", buffer[i]);
}else if(unit==2){
fprintf(dest, "0x%04x,", buffer[i]);
}else{
fprintf(dest, "0x%08x,", buffer[i]);
}
}
fprintf(dest, "\n};\n\n#endif\n");
fclose(dest);
return 0;
}
/******************************************************************************/
int main(int argc, char *argv[])
{
int retv, i;
int flags = 0;
char *bdf_name = NULL;
char *font_name = NULL;
char *list_name = NULL;
char *label_name = NULL;
for(i=1; i<argc; i++){
if(strcmp(argv[i], "-dg")==0){
flags |= 1;
}else if(strcmp(argv[i], "-dl")==0){
flags |= 2;
}else if(strcmp(argv[i], "-l")==0){
list_name = argv[i+1];
i += 1;
}else if(strcmp(argv[i], "-adj")==0){
base_adj = atoi(argv[i+1]);
i += 1;
}else if(strcmp(argv[i], "-c")==0){
flags |= 4;
font_name = argv[i+1];
i += 1;
}else if(strcmp(argv[i], "-h")==0){
flags |= 8;
font_name = argv[i+1];
label_name = argv[i+2];
i += 2;
}else if(bdf_name==NULL){
bdf_name = argv[i];
}
}
load_list(list_name);
retv = load_bdf(bdf_name);
if(retv<0)
return -1;
if(flags&1){
dump_glyph();
}else if(flags&2){
dump_list();
}else if(flags&4){
build_font();
FILE *fp = fopen(font_name, "wb");
fwrite(font_buf, 1, font_buf_size, fp);
fclose(fp);
}else if(flags&8){
build_font();
bin2c(font_buf, font_buf_size, font_name, label_name);
}
return 0;
}

11312
tools/bdfont/cbdf/helvR14c.bdf Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

11074
tools/bdfont/cbdf/timR14c.bdf Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

10162
tools/bdfont/cjk.txt Normal file

File diff suppressed because it is too large Load diff

4
tools/bdfont/latin.txt Normal file
View file

@ -0,0 +1,4 @@
0000-017f
0180-024f
0370-03ff
0400-04ff

4
tools/bdfont/mkfont.sh Normal file
View file

@ -0,0 +1,4 @@
#!/bin/sh
./bdfont cbdf/helvR14c.bdf -l latin.txt -h font_latin.h font_latin
./bdfont bdf/wqy13px.bdf -l cjk.txt -adj 1 -c font_cjk.bin

View file

@ -33,27 +33,29 @@ u32 get_be16(void *p);
void put_be32(void *p, u32 v);
void put_be16(void *p, u32 v);
u32 crc32b(u8 *data, int size);
void set_bitmap(u8 *bmp, int index, int val);
SAVEINFO *load_saveraw(char *save_name);
void bup_flush(void);
int sr_bup_init(u8 *buf);
int sr_bup_list(int slot_id);
int sr_bup_export(int slot_id, int save_id);
int sr_bup_export(int slot_id, int save_id, int exp_type);
int sr_bup_import(int slot_id, int save_id, char *save_name);
int sr_bup_delete(int slot_id, int save_id);
int sr_bup_create(char *game_id);
int ss_bup_init(u8 *buf);
int ss_bup_list(int slot_id);
int ss_bup_export(int slot_id, int save_id);
int ss_bup_export(int slot_id, int save_id, int exp_type);
int ss_bup_import(int slot_id, int save_id, char *save_name);
int ss_bup_delete(int slot_id, int save_id);
int ss_bup_create(char *game_id);
int sr_mems_init(u8 *buf);
int sr_mems_list(int slot_id);
int sr_mems_export(int slot_id, int save_id);
int sr_mems_export(int slot_id, int save_id, int exp_type);
int sr_mems_import(int slot_id, int save_id, char *save_name);
int sr_mems_delete(int slot_id, int save_id);
int sr_mems_create(char *game_id);

119
tools/savetool/bup_format.h Normal file
View file

@ -0,0 +1,119 @@
/*
* bup_header.h - structure definition for the .BUP file header used
* by various Sega Saturn tools.
*
* Format developed by Cafe-Alpha (https://segaxtreme.net/threads/save-game-metadata-questions.24625/post-178534)
*
*/
/** .BUP extension is required to work wih PS Kai */
#define BUP_EXTENSION ".BUP"
/** The BUP header structure (sizeof(vmem_bup_header_t)) is exactly 64 bytes */
#define BUP_HEADER_SIZE 64
/** BUP header magic */
#define VMEM_MAGIC_STRING_LEN 4
#define VMEM_MAGIC_STRING "Vmem"
/** Max backup filename length */
#define JO_BACKUP_MAX_FILENAME_LENGTH (12)
/** Max backup file comment length */
#define JO_BACKUP_MAX_COMMENT_LENGTH (10)
/**
* Backup file metadata information. Taken from Jo Engine.
**/
typedef struct _jo_backup_file
{
unsigned char filename[JO_BACKUP_MAX_FILENAME_LENGTH];
unsigned char comment[JO_BACKUP_MAX_COMMENT_LENGTH + 1];
unsigned char language; // jo_backup_language
unsigned int date;
unsigned int datasize;
unsigned short blocksize;
unsigned short padding;
} jo_backup_file;
typedef struct _jo_backup_date {
unsigned char year; // year - 1980
unsigned char month;
unsigned char day;
unsigned char time;
unsigned char min;
unsigned char week;
} jo_backup_date;
#if defined( __GNUC__ )
#pragma pack(1)
#else
#pragma pack(push,1)
#endif
/**
* Vmem usage statistics structure.
* Statistics are reset on each vmem session, ie when Saturn is reset,
* or when game calls BUP_Init function.
**/
typedef struct _vmem_bup_stats_t
{
/* Number of times BUP_Dir function is called. */
unsigned char dir_cnt;
/* Number of times BUP_Read function is called. */
unsigned char read_cnt;
/* Number of times BUP_Write function is called. */
unsigned char write_cnt;
/* Number of times BUP_Verify function is called. */
unsigned char verify_cnt;
} vmem_bup_stats_t;
/**
* Backup data header. Multibyte values are stored as big-endian.
**/
typedef struct _vmem_bup_header_t
{
/* Magic string.
* Used in order to verify that file is in vmem format.
*/
char magic[VMEM_MAGIC_STRING_LEN];
/* Save ID.
* "Unique" ID for each save data file, the higher, the most recent.
*/
unsigned int save_id;
/* Vmem usage statistics. */
vmem_bup_stats_t stats;
/* Unused, kept for future use. */
char unused1[8 - sizeof(vmem_bup_stats_t)];
/* Backup Data Informations Record (34 bytes + 2 padding bytes). */
jo_backup_file dir;
/* Date stamp, in Saturn's BUP library format.
* Used in order to verify which save data is the most
* recent one when rebuilding index data.
* Note #1 : this information is already present in BupDir structure,
* but games are setting it, so it may be incorrect (typically, set
* to zero).
* Note #2 : this date information is the date when Pseudo Saturn Kai
* last started, not the time the save was saved, so if information in
* dir structure is available, it is more accurate.
*/
unsigned int date;
/* Unused, kept for future use. */
char unused2[8];
} vmem_bup_header_t;
#if defined( __GNUC__ )
#pragma pack()
#else
#pragma pack(pop)
#endif

View file

@ -3,6 +3,7 @@
#include "stdlib.h"
#include "string.h"
#include "bup.h"
#include "bup_format.h"
/******************************************************************************/
@ -98,22 +99,61 @@ void set_bitmap(u8 *bmp, int index, int val)
u8 save_buf[0x100000];
static SAVEINFO saveinfo;
/* This is the basic CRC-32 calculation with some optimization but no table lookup. */
u32 crc32b(u8 *data, int size)
{
int j;
u32 crc = 0xFFFFFFFF;
while (size--){
crc ^= *data++; // XOR with next byte.
for (j=0; j<8; j++){ // Do eight times.
crc = (crc >> 1) ^ (0xEDB88320 & -(crc & 1));
}
}
return ~crc;
}
static void load_savebup(SAVEINFO *sinfo, const u8 *fbuf, int fsize)
{
vmem_bup_header_t *bup_header = (vmem_bup_header_t*)fbuf;
memset(sinfo, 0, sizeof(SAVEINFO));
memcpy(sinfo->file_name, bup_header->dir.filename, 11);
memcpy(sinfo->comment, bup_header->dir.comment, 10);
sinfo->data_size = bup_header->dir.datasize;
sinfo->date = bup_header->dir.date;
sinfo->language = bup_header->dir.language;
memcpy(save_buf, fbuf+BUP_HEADER_SIZE, fsize-BUP_HEADER_SIZE);
sinfo->dbuf = save_buf;
}
SAVEINFO *load_saveraw(char *save_name)
{
SAVEINFO *sinfo = &saveinfo;
u8 *fbuf;
int fsize;
u32 crc;
fbuf = load_file(save_name, &fsize);
if(fbuf==NULL){
printf("Faield to load file %s!\n", save_name);
return NULL;
}
if(strcmp((char*)fbuf, "SSAVERAW")){
printf("%s: Not a SSAVERAW file!\n", save_name);
if(strcmp((char*)fbuf, "SSAVERAW") && memcmp(fbuf, VMEM_MAGIC_STRING, VMEM_MAGIC_STRING_LEN)){
printf("%s: Not a supported Saturn save file! (%s/%s)\n", save_name, "SSAVERAW", VMEM_MAGIC_STRING);
return NULL;
}
// check if it's a Vmem save file, and load the data
if(memcmp(fbuf, VMEM_MAGIC_STRING, VMEM_MAGIC_STRING_LEN)==0 && fsize>BUP_HEADER_SIZE){
load_savebup(sinfo, fbuf, fsize);
return sinfo;
}
memset(sinfo, 0, sizeof(SAVEINFO));
memcpy(sinfo->file_name, fbuf+0x10, 11);
memcpy(sinfo->comment, fbuf+0x20, 10);
@ -123,6 +163,12 @@ SAVEINFO *load_saveraw(char *save_name)
memcpy(save_buf, fbuf+0x40, fsize-0x40);
sinfo->dbuf = save_buf;
crc = get_be32(fbuf+0x0c);
if (crc && crc != crc32b(fbuf+0x10, fsize-0x10)){
printf("Warning: CRC32 mismatch for %s!\n", save_name);
}
return sinfo;
}
@ -146,7 +192,7 @@ void bup_flush(void)
int bup_create(char *game_id)
{
int retv;
int retv=-1;
if(bup_type==0){
retv = sr_bup_create(game_id);
@ -167,7 +213,7 @@ int bup_create(char *game_id)
int bup_import(int slot_id, int save_id, char *save_name)
{
int retv;
int retv=-1;
if(bup_type==0){
retv = sr_bup_import(slot_id, save_id, save_name);
@ -186,7 +232,7 @@ int bup_import(int slot_id, int save_id, char *save_name)
int bup_delete(int slot_id, int save_id)
{
int retv;
int retv=-1;
if(bup_type==0){
retv = sr_bup_delete(slot_id, save_id);
@ -203,14 +249,14 @@ int bup_delete(int slot_id, int save_id)
}
int bup_export(int slot_id, int save_id)
int bup_export(int slot_id, int save_id, int exp_type)
{
if(bup_type==0){
return sr_bup_export(slot_id, save_id);
return sr_bup_export(slot_id, save_id, exp_type);
}else if(bup_type==1){
return ss_bup_export(slot_id, save_id);
return ss_bup_export(slot_id, save_id, exp_type);
}else if(bup_type==2){
return sr_mems_export(slot_id, save_id);
return sr_mems_export(slot_id, save_id, exp_type);
}
return -1;
@ -265,6 +311,7 @@ int main(int argc, char *argv[])
{
int slot_id = -1;
int save_id = -1;
int exp_type = 0;
int create = 0;
int import = 0;
int delete = 0;
@ -280,6 +327,7 @@ int main(int argc, char *argv[])
printf(" -t n Select save slot(for SAROO save).\n");
printf(" -c \"gameid\" New save slot(for SAROO save).\n");
printf(" -s n Select and Export(without -i/-d) save.\n");
printf(" -x n Select and Export save as .BUP format.\n");
printf(" -i [file] Import save.\n");
printf(" -d Delete save.\n");
printf(" List save.\n");
@ -297,6 +345,8 @@ int main(int argc, char *argv[])
slot_id = atoi(argv[p+1]);
p += 1;
break;
case 'x':
exp_type = 1;
case 's':
if(p+1==argc)
goto _invalid_params;
@ -345,7 +395,7 @@ _invalid_params:
retv = bup_load(bup_name);
if(retv<0){
printf("Faield to load save file!\n");
printf("Failed to load save file!\n");
return retv;
}
@ -356,7 +406,7 @@ _invalid_params:
}else if(delete){
retv = bup_delete(slot_id, save_id);
}else if(save_id>=0){
retv = bup_export(slot_id, save_id);
retv = bup_export(slot_id, save_id, exp_type);
}else{
retv = bup_list(slot_id);
}

View file

@ -3,6 +3,7 @@
#include "stdlib.h"
#include "string.h"
#include "bup.h"
#include "bup_format.h"
/******************************************************************************/
@ -179,7 +180,7 @@ static int sr_bup_select(int slot_id)
/******************************************************************************/
int sr_bup_export(int slot_id, int save_id)
int sr_bup_export(int slot_id, int save_id, int exp_type)
{
int block, i;
u8 *bp;
@ -205,7 +206,24 @@ int sr_bup_export(int slot_id, int save_id)
char fname[16];
int fsize = get_be32(save_buf+0x1c);
sprintf(fname, "%s.bin", save_buf+0x10);
put_be32(save_buf+0x0c, crc32b(save_buf+0x10, fsize+0x30));
sprintf(fname, "%s%s", save_buf+0x10, exp_type ? BUP_EXTENSION : ".SRO");
// if Export format is .BUP, set new header
if (exp_type==1){
vmem_bup_header_t bup_header = {0};
memcpy(bup_header.magic, VMEM_MAGIC_STRING, VMEM_MAGIC_STRING_LEN);
memcpy(bup_header.dir.filename, bp, 11);
memcpy(bup_header.dir.comment, bp+0x10, 10);
memcpy(&bup_header.dir.date, bp+0x1c, 4);
memcpy(&bup_header.dir.datasize, bp+0x0c, 4);
memcpy(&bup_header.date, bp+0x1c, 4);
bup_header.dir.language = bp[0x1b];
memcpy(save_buf, &bup_header, BUP_HEADER_SIZE);
}
write_file(fname, save_buf, fsize+0x40);
printf("Export Save_%d: %s\n", i, fname);

View file

@ -3,6 +3,7 @@
#include "stdlib.h"
#include "string.h"
#include "bup.h"
#include "bup_format.h"
/******************************************************************************/
@ -94,7 +95,7 @@ static int access_data(int block, u8 *data, int type)
/******************************************************************************/
int sr_mems_export(int slot_id, int save_id)
int sr_mems_export(int slot_id, int save_id, int exp_type)
{
int block, i, index;
u8 *bp;
@ -121,7 +122,24 @@ int sr_mems_export(int slot_id, int save_id)
char fname[16];
int fsize = get_be32(save_buf+0x1c);
sprintf(fname, "%s.bin", save_buf+0x10);
put_be32(save_buf+0x0c, crc32b(save_buf+0x10, fsize+0x30));
sprintf(fname, "%s%s", save_buf+0x10, exp_type ? BUP_EXTENSION : ".SRO");
// if Export format is .BUP, set new header
if (exp_type==1){
vmem_bup_header_t bup_header = {0};
memcpy(bup_header.magic, VMEM_MAGIC_STRING, VMEM_MAGIC_STRING_LEN);
memcpy(bup_header.dir.filename, bp, 11);
memcpy(bup_header.dir.comment, bp+0x10, 10);
memcpy(&bup_header.dir.date, bp+0x1c, 4);
memcpy(&bup_header.dir.datasize, bp+0x0c, 4);
memcpy(&bup_header.date, bp+0x1c, 4);
bup_header.dir.language = bp[0x1b];
memcpy(save_buf, &bup_header, BUP_HEADER_SIZE);
}
write_file(fname, save_buf, fsize+0x40);
printf("Export Save_%d: %s\n", index, fname);

View file

@ -3,6 +3,7 @@
#include "stdlib.h"
#include "string.h"
#include "bup.h"
#include "bup_format.h"
/******************************************************************************/
@ -135,7 +136,7 @@ static void scan_save(BUPINFO *binfo)
/******************************************************************************/
int ss_bup_export(int slot_id, int index)
int ss_bup_export(int slot_id, int index, int exp_type)
{
BUPINFO *binfo = GET_BUP_INFO();
int block, i;
@ -160,7 +161,24 @@ int ss_bup_export(int slot_id, int index)
char fname[16];
int fsize = get_be32(save_buf+0x1c);
sprintf(fname, "%s.bin", save_buf+0x10);
put_be32(save_buf+0x0c, crc32b(save_buf+0x10, fsize+0x30));
sprintf(fname, "%s%s", save_buf+0x10, exp_type ? BUP_EXTENSION : ".SRO");
// if Export format is .BUP, set new header
if (exp_type==1){
vmem_bup_header_t bup_header = {0};
memcpy(bup_header.magic, VMEM_MAGIC_STRING, VMEM_MAGIC_STRING_LEN);
memcpy(bup_header.dir.filename, bp+4, 11);
memcpy(bup_header.dir.comment, bp+0x10, 10);
memcpy(&bup_header.dir.date, bp+0x1a, 4);
memcpy(&bup_header.dir.datasize, bp+0x1e, 4);
memcpy(&bup_header.date, bp+0x1a, 4);
bup_header.dir.language = bp[0x0f];
memcpy(save_buf, &bup_header, BUP_HEADER_SIZE);
}
write_file(fname, save_buf, fsize+0x40);
printf("Export Save_%d: %s\n", index, fname);