mirror of
https://github.com/array-in-a-matrix/SAROO.git
synced 2025-04-02 10:31:43 -04:00
542 lines
11 KiB
C
542 lines
11 KiB
C
/*
|
||
* Sega Saturn cartridge flash tool
|
||
* by Anders Montonen, 2012
|
||
*
|
||
* Original software by ExCyber
|
||
* Graphics routines by Charles MacDonald
|
||
*
|
||
* Creative Commons Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)
|
||
*/
|
||
|
||
#include "main.h"
|
||
#include "vdp2.h"
|
||
|
||
/******************************************************************************/
|
||
|
||
|
||
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
|
||
};
|
||
|
||
#include "font_8x16.h"
|
||
|
||
|
||
static int pos_x, pos_y;
|
||
static int text_color;
|
||
|
||
static int llen;
|
||
int fbw = 320;
|
||
int fbh = 224;
|
||
u8 *fbptr = (u8*)VDP2_VRAM;
|
||
|
||
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;
|
||
|
||
RAMCTL = RAMCTL & (~0x3000);
|
||
|
||
// Map Offset Register: Bitmap screen will be located at VRAM offset 0
|
||
MPOFN = 0;
|
||
|
||
// Character Control Register: 256 colors, enable NBG0 as a bitmap. |8 for 1024x256 bitmap
|
||
CHCTLA = 0x0012|8;
|
||
|
||
// Screen Scroll Value Registers: No scroll
|
||
SCXIN0 = 0;
|
||
SCXDN0 = 0;
|
||
SCYIN0 = 0;
|
||
|
||
// BackScreen mode
|
||
BKTA = 0x7fffe>>1;
|
||
|
||
// Screen Display Enable Register: Invalidate the transparency code for
|
||
// NBG0 and display NBG0
|
||
BGON = 0x0001;
|
||
|
||
/* Clear VRAM */
|
||
for (ii = 0; ii < 0x40000; ii++)
|
||
vdp2_vram[ii] = 0x0000;
|
||
|
||
/* Clear CRAM */
|
||
for (ii = 0; ii < 0x0800; ii++)
|
||
vdp2_cram[ii] = 0x0000;
|
||
}
|
||
|
||
|
||
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;
|
||
|
||
pos_x = 0;
|
||
pos_y = 0;
|
||
text_color = 0xf0;
|
||
printk_putc = conio_putc;
|
||
|
||
TVMD = 0x8000;
|
||
|
||
void fbtest();
|
||
fbtest();
|
||
}
|
||
|
||
|
||
/******************************************************************************/
|
||
|
||
void fbtest(void)
|
||
{
|
||
int i;
|
||
|
||
put_rect(0, 0, fbw-1, fbh-1, 15);
|
||
|
||
for(i=0; i<16; i++){
|
||
int x = 10+i*16;
|
||
int y = 32;
|
||
put_box(x, y, x+10, y+10, i);
|
||
}
|
||
|
||
}
|
||
|
||
|
||
|
||
/******************************************************************************/
|
||
|
||
static u8 *find_ucs(int ucs)
|
||
{
|
||
u8 *hzk14u = (u8*)0x02020000;
|
||
u16 total = *(u16*)(hzk14u);
|
||
u16 *ucslist = (u16*)0x02020002;
|
||
u8 *font_data = hzk14u+2+total*2;
|
||
|
||
int low, high, mp;
|
||
|
||
low = 0;
|
||
high = total-1;
|
||
while(low<=high){
|
||
mp = (low+high)/2;
|
||
if(ucs==ucslist[mp]){
|
||
return font_data+mp*28;
|
||
}else if(ucs>ucslist[mp]){
|
||
low = mp+1;
|
||
}else{
|
||
high = mp-1;
|
||
}
|
||
}
|
||
|
||
return NULL;
|
||
}
|
||
|
||
|
||
|
||
void conio_put_char(int x, int y, int color, int v)
|
||
{
|
||
int r, c;
|
||
u8 *bmp, *font_data;
|
||
unsigned char fg = (color >> 4) & 0x0F;
|
||
unsigned char bg = (color >> 0) & 0x0F;
|
||
|
||
bmp = fbptr+y*llen+x;
|
||
|
||
if(v>=0x0100){
|
||
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{
|
||
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;
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
|
||
static int utf8_to_ucs(char **ustr)
|
||
{
|
||
u8 *str = (u8*)*ustr;
|
||
int ucs = 0;
|
||
|
||
if(*str==0){
|
||
return 0;
|
||
}else if(*str<0x80){
|
||
*ustr = str+1;
|
||
return *str;
|
||
}else if(*str<0xe0){
|
||
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;
|
||
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'){
|
||
pos_x = 0;
|
||
}else if(ch=='\n'){
|
||
pos_y += 16;
|
||
if(pos_y>=fbh){
|
||
pos_x = 0;
|
||
pos_y = 0;
|
||
}
|
||
}else{
|
||
conio_put_char(pos_x, pos_y, text_color, ch);
|
||
|
||
pos_x += (ch>=0x100)? 16 : 8;;
|
||
if(pos_x>=fbw){
|
||
pos_x = 0;
|
||
pos_y += 16;
|
||
}
|
||
if(pos_y>=fbh){
|
||
pos_x = 0;
|
||
pos_y = 0;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
/******************************************************************************/
|
||
|
||
|
||
void put_pixel(int x, int y, int c)
|
||
{
|
||
volatile unsigned char *bmp = (volatile unsigned char*)VDP2_VRAM;
|
||
*(bmp + y*llen + x) = c;
|
||
}
|
||
|
||
|
||
void put_line (int x1, int y1, int x2, int y2, int c)
|
||
{
|
||
int tmp;
|
||
int dx = x2 - x1;
|
||
int dy = y2 - y1;
|
||
|
||
if (abs (dx) < abs (dy)) {
|
||
if (y1 > y2) {
|
||
tmp = x1; x1 = x2; x2 = tmp;
|
||
tmp = y1; y1 = y2; y2 = tmp;
|
||
dx = -dx; dy = -dy;
|
||
}
|
||
x1 <<= 16;
|
||
/* dy is apriori >0 */
|
||
dx = (dx << 16) / dy;
|
||
while (y1 <= y2) {
|
||
put_pixel (x1 >> 16, y1, c);
|
||
x1 += dx;
|
||
y1++;
|
||
}
|
||
} else {
|
||
if (x1 > x2) {
|
||
tmp = x1; x1 = x2; x2 = tmp;
|
||
tmp = y1; y1 = y2; y2 = tmp;
|
||
dx = -dx; dy = -dy;
|
||
}
|
||
y1 <<= 16;
|
||
dy = dx ? (dy << 16) / dx : 0;
|
||
while (x1 <= x2) {
|
||
put_pixel (x1, y1 >> 16, c);
|
||
y1 += dy;
|
||
x1++;
|
||
}
|
||
}
|
||
}
|
||
|
||
void put_hline(int y, int x1, int x2, int c)
|
||
{
|
||
volatile unsigned char *bmp = (volatile unsigned char*)VDP2_VRAM;
|
||
int x;
|
||
|
||
if(x2>x1){
|
||
x2 = x2-x1+1;
|
||
}else{
|
||
x = x2;
|
||
x2 = x1-x2+1;
|
||
x1 = x;
|
||
}
|
||
|
||
bmp += y*llen+x1;
|
||
for(x=0; x<x2; x++){
|
||
bmp[x] = c;
|
||
}
|
||
}
|
||
|
||
void put_vline(int x, int y1, int y2, int c)
|
||
{
|
||
volatile unsigned char *bmp = (volatile unsigned char*)VDP2_VRAM;
|
||
int y;
|
||
|
||
if(y2>y1){
|
||
y2 = y2-y1+1;
|
||
}else{
|
||
y = y2;
|
||
y2 = y1-y2+1;
|
||
y1 = y;
|
||
}
|
||
|
||
bmp += y1*llen+x;
|
||
for(y=0; y<y2; y++){
|
||
*bmp = c;
|
||
bmp += llen;
|
||
}
|
||
}
|
||
|
||
void put_rect (int x1, int y1, int x2, int y2, int c)
|
||
{
|
||
put_hline (y1, x1, x2, c);
|
||
put_hline (y2, x1, x2, c);
|
||
put_vline (x1, y1, y2, c);
|
||
put_vline (x2, y1, y2, c);
|
||
}
|
||
|
||
void put_box(int x1, int y1, int x2, int y2, int c)
|
||
{
|
||
int y;
|
||
|
||
for(y=y1; y<=y2; y++){
|
||
put_hline(y, x1, x2, c);
|
||
}
|
||
}
|
||
|
||
/******************************************************************************/
|
||
|
||
static u32 last_pdat = 0;
|
||
static u32 last_value;
|
||
static u32 curr_pdat = 0;
|
||
static int pdat_state = 0;
|
||
static int pdat_count = 0;
|
||
static int pdat_wait;
|
||
|
||
u32 conio_getc(void)
|
||
{
|
||
u32 pdat = pad_read();
|
||
|
||
switch(pdat_state){
|
||
case 0:
|
||
// <20><><EFBFBD>м<EFBFBD><D0BC><EFBFBD>
|
||
if(pdat != curr_pdat){
|
||
curr_pdat = pdat;
|
||
pdat_state = 1;
|
||
pdat_count = 0;
|
||
}
|
||
break;
|
||
case 1:
|
||
// <20>ȴ<EFBFBD><C8B4>ȶ<EFBFBD>
|
||
if(pdat == curr_pdat){
|
||
pdat_count += 1;
|
||
if(pdat_count==2){
|
||
pdat_state = 2;
|
||
}
|
||
}else{
|
||
pdat_state = 0;
|
||
}
|
||
break;
|
||
case 2:
|
||
// <20>ȶ<EFBFBD>״̬
|
||
pdat = last_pdat ^ curr_pdat;
|
||
last_pdat = curr_pdat;
|
||
if(curr_pdat){
|
||
// ת<><D7AA><EFBFBD>ظ<EFBFBD>״̬
|
||
pdat_state = 3;
|
||
pdat_count = 0;
|
||
pdat_wait = 500;
|
||
}else{
|
||
pdat_state = 0;
|
||
}
|
||
last_value = (pdat<<16) | curr_pdat;
|
||
//printk("key0: %08x\n", last_value);
|
||
return last_value;
|
||
case 3:
|
||
// <20>ظ<EFBFBD>״̬
|
||
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);
|
||
return last_value;
|
||
}
|
||
}
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
/******************************************************************************/
|
||
|
||
|
||
static void draw_menu_item(int index, char *item, int select)
|
||
{
|
||
int mx = 16;
|
||
int my = 24+index*16;
|
||
int color = text_color;
|
||
|
||
if(select){
|
||
color = 0x0f;
|
||
}
|
||
put_box(mx, my, mx+36*8-1, my+16-1, (color&0x0f));
|
||
|
||
conio_put_string(mx, my, color, item);
|
||
}
|
||
|
||
|
||
void menu_update(MENU_DESC *menu)
|
||
{
|
||
int i, select;
|
||
|
||
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);
|
||
}
|
||
|
||
|
||
void draw_menu_frame(MENU_DESC *menu)
|
||
{
|
||
memset(fbptr, 0, fbh*llen);
|
||
conio_put_string(32, 4, text_color, menu->title);
|
||
|
||
put_rect(10, 19, 309, 205, 0x0f);
|
||
put_rect(13, 22, 306, 202, 0x0f);
|
||
|
||
menu_update(menu);
|
||
}
|
||
|
||
|
||
void menu_status(MENU_DESC *menu, char *string)
|
||
{
|
||
int mx = 16;
|
||
int my = 224-16;
|
||
|
||
put_box(mx, my, mx+36*8-1, my+16-1, 0);
|
||
if(string){
|
||
conio_put_string(mx, my, text_color, string);
|
||
}
|
||
}
|
||
|
||
|
||
void add_menu_item(MENU_DESC *menu, char *item)
|
||
{
|
||
strncpy(menu->items[menu->num], item, 64);
|
||
menu->items[menu->num][36] = 0;
|
||
menu->num += 1;
|
||
}
|
||
|
||
|
||
int menu_default(MENU_DESC *menu, int ctrl)
|
||
{
|
||
if(BUTTON_DOWN(ctrl, PAD_UP)){
|
||
if(menu->current>0){
|
||
menu->current -= 1;
|
||
menu_update(menu);
|
||
}
|
||
return 1;
|
||
}else if(BUTTON_DOWN(ctrl, PAD_DOWN)){
|
||
if(menu->current<(menu->num-1)){
|
||
menu->current += 1;
|
||
menu_update(menu);
|
||
}
|
||
return 1;
|
||
}else{
|
||
return 0;
|
||
}
|
||
}
|
||
|
||
|
||
int menu_run(MENU_DESC *menu)
|
||
{
|
||
u32 ctrl;
|
||
int retv;
|
||
|
||
_restart:
|
||
draw_menu_frame(menu);
|
||
|
||
#if 1
|
||
while(1){
|
||
ctrl = conio_getc();
|
||
if(ctrl==0)
|
||
continue;
|
||
retv = menu->handle(ctrl);
|
||
if(retv==MENU_EXIT)
|
||
break;
|
||
if(retv==MENU_RESTART){
|
||
goto _restart;
|
||
}
|
||
}
|
||
#endif
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
/******************************************************************************/
|
||
|
||
|