Update of /cvsroot/gc-linux/ipl/io In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv5953/io Added Files: console.c console_font.c console_font_8x8.c dvd.c exi.c network.c pad.c sram.c video.c vsprintf.c Log Message: Sorted all source files int / into the following directories: io, lowlevel, loadand ipl Did some cleaning in the source files, but there is still much to be done --- NEW FILE: console.c --- #include "console.h" #include "exi.h" #include "pad.h" #include "color.h" #include <linux/string.h> static struct console_data_s *default_console; void (*my_puts)(const char *s); void (*my_putstring)(const char *s); void (*my_putchar)(char c); void c_putstring(const char *s) { console_puts(default_console, s); } void c_puts(const char *s) { console_puts(default_console, s); console_putc(default_console, '\n'); } void c_putchar(char c) { console_putc(default_console, c); } #if 0 void s_putc(unsigned char c); void s_putstring(const char *s) { while (*s) { if (*s == '\n') s_putc('\r'); s_putc(*s++); } } void s_puts(const char *s) { s_putstring(s); s_putstring("\n"); } void s_putchar(char c) { s_putc(c); } #endif void puts(const char *s) { if (my_puts) my_puts(s); } void putstring(const char *s) { if (my_putstring) my_putstring(s); } void putchar(char c) { if (my_putchar) my_putchar(c); } int set_color(int background, int foreground) { default_console->foreground = foreground; default_console->background = background; return 0; } void set_position(int x, int y) { default_console->cursor_y = y; default_console->cursor_x = x; } struct console_data_s console; extern unsigned char console_font_8x8[]; extern unsigned char console_font_8x16[]; void console_init(struct console_data_s *con, void *framebuffer, int xres, int yres, int stride) { con->framebuffer = framebuffer; con->xres = xres; con->yres = yres; con->border_left = 0; con->border_top = 0; con->border_right = con->xres; con->border_bottom = con->yres; con->stride = stride; con->cursor_x = con->cursor_y = 0; con->font = console_font_8x16; con->foreground = COLOR_WHITE; con->background = COLOR_BLACK; con->scrolled_lines = 0; int c = con->xres * con->yres / 2; unsigned long *p = (unsigned long*)con->framebuffer; while (c--) *p++ = con->background; default_console = con; my_puts = c_puts; my_putstring = c_putstring; my_putchar = c_putchar; /* my_puts = s_puts; my_putstring = s_putstring; my_putchar = s_putchar; */ } #define FONT_XSIZE 8 #define FONT_YSIZE 16 #define FONT_XFACTOR 1 #define FONT_YFACTOR 1 #define FONT_XGAP 2 #define FONT_YGAP 0 void console_drawc(struct console_data_s *con, int x, int y, unsigned char c) { x >>= 1; int ax, ay; unsigned long *ptr = (unsigned long*)(con->framebuffer + con->stride * y + x * 4); for (ay = 0; ay < FONT_YSIZE; ay++) { #if FONT_XFACTOR == 2 for (ax = 0; ax < 8; ax++) { unsigned long color; if ((con->font[c * FONT_YSIZE + ay] << ax) & 0x80) color = con->foreground; else color = con->background; #if FONT_YFACTOR == 2 // pixel doubling: we write u32 ptr[ay * 2 * con->stride/4 + ax] = color; // line doubling ptr[(ay * 2 +1) * con->stride/4 + ax] = color; #else ptr[ay * con->stride/4 + ax] = color; #endif } #else for (ax = 0; ax < 4; ax ++) { unsigned long color[2]; int bits = (con->font[c * FONT_YSIZE + ay] << (ax*2)); if (bits & 0x80) color[0] = con->foreground; else color[0] = con->background; if (bits & 0x40) color[1] = con->foreground; else color[1] = con->background; ptr[ay * con->stride/4 + ax] = (color[0] & 0xFFFF00FF) | (color[1] & 0x0000FF00); } #endif for (ax = 0; ax < FONT_XGAP/2; ++ax) { ptr[ay * con->stride/4 + ax + 4] = con->background; } } } void console_puts(struct console_data_s *con, const char *string) { while (*string) console_putc(con, *string++); } void console_putc(struct console_data_s *con, char c) { switch (c) { case '\n': con->cursor_y += FONT_YSIZE * FONT_YFACTOR + FONT_YGAP; con->cursor_x = con->border_left; break; case '\r': con->cursor_x = con->border_left; break; default: console_drawc(con, con->cursor_x, con->cursor_y, c); con->cursor_x += FONT_XSIZE * FONT_XFACTOR + FONT_XGAP; if ((con->cursor_x + (FONT_XSIZE * FONT_XFACTOR)) > con->border_right) { con->cursor_y += FONT_YSIZE * FONT_YFACTOR + FONT_YGAP; con->cursor_x = con->border_left; } } if ((con->cursor_y + FONT_YSIZE * FONT_YFACTOR) >= con->border_bottom) { #if 0 if (con->scrolled_lines == con->yres / (FONT_YSIZE * FONT_YFACTOR + FONT_YGAP)) { struct PAD pad; while (1) { PAD_ReadState(&pad, 0); if (pad.Digital.A) break; } while (1) { PAD_ReadState(&pad, 0); if (!pad.Digital.A) break; } con->scrolled_lines = 0; } con->scrolled_lines++; #endif memcpy(con->framebuffer, con->framebuffer + con->stride * (FONT_YSIZE * FONT_YFACTOR + FONT_YGAP), con->stride * con->yres - FONT_YSIZE); int cnt = (con->stride * (FONT_YSIZE * FONT_YFACTOR + FONT_YGAP)) / 4; int a = 0; unsigned long *ptr = con->framebuffer + con->stride * (con->yres - FONT_YSIZE); while (cnt--) *ptr++ = con->background; con->cursor_y -= FONT_YSIZE * FONT_YFACTOR + FONT_YGAP; } } --- NEW FILE: console_font.c --- unsigned char console_font_8x16[] = { /* 0 0x00 '^@' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ [...4574 lines suppressed...] 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ }; --- NEW FILE: console_font_8x8.c --- unsigned char console_font_8x8[] = { /* 0 0x00 '^@' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 1 0x01 '^A' */ 0x7e, /* 01111110 */ 0x81, /* 10000001 */ 0xa5, /* 10100101 */ 0x81, /* 10000001 */ 0xbd, /* 10111101 */ 0x99, /* 10011001 */ [...2526 lines suppressed...] 0x3c, /* 00111100 */ 0x3c, /* 00111100 */ 0x3c, /* 00111100 */ 0x3c, /* 00111100 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 255 0xff 'ÿ' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ }; --- NEW FILE: dvd.c --- #include <console.h> #include <time.h> #include <cache.h> volatile long *dvd=(volatile long *)0xCC006000; void dvd_reset(void) { *(unsigned long*)0xcc006004 = 2; unsigned long v = *(unsigned long*)0xcc003024; *(unsigned long*)0xcc003024 = (v &~4) | 1; mdelay(1); *(unsigned long*)0xcc003024 = v | 5; } unsigned int dvd_read(void *dst, int len, unsigned int offset) { if ((((int)dst) & 0xC0000000) == 0x80000000) // cached? dcache_inv(dst, len); dvd[0] = 0x2E; dvd[1] = 0; dvd[2] = 0xA8000000; dvd[3] = offset >> 2; dvd[4] = len; dvd[5] = (unsigned long)dst; dvd[6] = len; dvd[7] = 3; // enable reading! while (dvd[7] & 1); if (dvd[0] & 0x4) return 1; return 0; } int dvd_seek(int offset) { dvd[0] = 0x2E; dvd[1] = 0; dvd[2] = 0xAB000000; dvd[3] = offset >> 2; dvd[4] = 0; dvd[7] = 1; while (dvd[7] & 1); if (dvd[0] & 0x4) return 1; return 0; } unsigned int dvd_read_id(void *dst) { if ((((int)dst) & 0xC0000000) == 0x80000000) // cached? dcache_inv(dst, 0x20); dvd[0] = 0x2E; dvd[1] = 0; dvd[2] = 0xA8000040; dvd[3] = 0; dvd[4] = 0x20; dvd[5] = (unsigned long)dst; dvd[6] = 0x20; dvd[7] = 3; // enable reading! while (dvd[7] & 1); if (dvd[0] & 0x4) return 1; return 0; } void dvd_motor_off() { dvd[0] = 0x2E; dvd[1] = 0; dvd[2] = 0xe3000000; dvd[3] = 0; dvd[4] = 0; dvd[5] = 0; dvd[6] = 0; dvd[7] = 1; // enable reading! while (dvd[7] & 1); } unsigned int dvd_init() { dvd_reset(); if (dvd_read_id(0x80000000)) return -1; dcache_inv(0x80000000, 0x20); return 0; } void dvd_set_audio(int enable, int len) { enable = !!enable; dvd[2] = 0xE4000000 | (enable<<16) | len; dvd[7] = 1; while (dvd[7] & 1); } void dvd_set_streaming(void) { int streaming_enable = *(unsigned char*)0x80000008; dvd[1] = dvd[1]; if (!streaming_enable) dvd_set_audio(0, 0); else dvd_set_audio(1, (*(unsigned char*)0x80000009) ? 0 : 0xA); while (dvd[7] & 1); } unsigned int dvd_get_error(void) { dvd[2] = 0xE0000000; dvd[8] = 0; dvd[7] = 1; while (dvd[7] & 1); return dvd[8]; } unsigned int dvd_get_diconfig(void) { return dvd[9]; } const char *dvd_get_error_message(void) { switch (dvd_get_error()>>24) { /* as documented in NinDoc */ case 0x00: return "Ready."; case 0x01: return "Cover is opened."; case 0x02: return "Disk change."; case 0x03: return "No Disk."; case 0x04: return "Motor stop."; case 0x05: return "Disk ID not read."; default: return "unknown"; } } /**************** NPDP STUFF ***************/ /* by Dr.Matrix */ /* Note by tmbinc: I wasn't able to test this stuff, as i don't have a NPDP. But Dr.Matrix usually does things which work, i trust in him! */ unsigned int npdp_getid(unsigned char *dst) { static unsigned char id[256] __attribute__((__aligned__(32))); dcache_inv(id, 0x40); dvd[0] = 0x2E; dvd[1] = 0; memcpy(dvd + 2, "NPDP-ID", 8); dvd[4] = 0x40; dvd[5] = (unsigned long)id; dvd[6] = 0x40; dvd[7] = 3; // enable reading! while (dvd[7] & 1); if (dvd[6]) return 1; memcpy(dst, id, 0x40); return 0; } --- NEW FILE: exi.c --- #include "exi.h" #include <irq.h> #include <console.h> #include "cache.h" static int flags; /* exi_select: enable chip select, set speed */ void exi_select(int channel, int device, int freq) { volatile unsigned long *exi = (volatile unsigned long *)0xCC006800; long d; cli(flags); // exi_select d = exi[channel * 5]; d &= 0x405; d |= ((1<<device)<<7) | (freq << 4); exi[channel*5] = d; } /* disable chipselect */ void exi_deselect(int channel) { volatile unsigned long *exi = (volatile unsigned long *)0xCC006800; exi[channel * 5] &= 0x405; sti(flags); } /* dirty way for asynchronous reads */ static void *exi_last_addr; static int exi_last_len; /* mode?Read:Write len bytes to/from channel */ /* when read, data will be written back in exi_sync */ inline void exi_imm(int channel, void *data, int len, int mode, int zero) { volatile unsigned long *exi = (volatile unsigned long *)0xCC006800; if (mode == EXI_WRITE) exi[channel * 5 + 4] = *(unsigned long*)data; else exi[channel * 5 + 4] = -1; exi[channel * 5 + 3] = ((len-1)<<4)|(mode<<2)|1; if (mode == EXI_READ) { exi_last_addr = data; exi_last_len = len; } else { exi_last_addr = 0; exi_last_len = 0; } } /* Wait until transfer is done, write back data */ void exi_sync(int channel) { volatile unsigned long *exi = (volatile unsigned long *)0xCC006800; while (exi[channel * 5 + 3] & 1); if (exi_last_addr) { int i; unsigned long d; d = exi[channel * 5 + 4]; for (i=0; i<exi_last_len; ++i) ((unsigned char*)exi_last_addr)[i] = (d >> ((3-i)*8)) & 0xFF; } } /* simple wrapper for transfers > 4bytes */ void exi_imm_ex(int channel, void *data, int len, int mode) { unsigned char *d = (unsigned char*)data; while (len) { int tc = len; if (tc > 4) tc = 4; exi_imm(channel, d, tc, mode, 0); exi_sync(channel); len-=tc; d+=tc; } } void exi_dma_start(int channel, void *data, int len, int mode) { volatile unsigned long *exi = (volatile unsigned long *)0xCC006800; if (len < 0) { printf("!!! len is %d\n", len); while (1); } exi[channel * 5 + 1] = (unsigned long)data; exi[channel * 5 + 2] = len; exi[channel * 5 + 3] = (mode<<2)|3; } void exi_imm_fast(int channel, void *data, int len, int mode) { unsigned long addr = (unsigned long)data; unsigned char *d = (unsigned char*)data; int addr_misalign = (-addr) & 31; if ((len - addr_misalign) < 32) return exi_imm_ex(channel, data, len, mode); if (addr_misalign) /* fix misalignment with normal transfers */ { exi_imm_ex(channel, data, addr_misalign, mode); len -= addr_misalign; addr += addr_misalign; } int len_align = len & ~31; dcache_flush((void*)addr, len_align); exi_dma_start(channel, (void*)addr, len_align, mode); exi_sync(channel); if (mode == EXI_READ) dcache_inv((void*)addr, len_align); len -= len_align; if (len) exi_imm_ex(channel, (void*)(addr + len_align), len, mode); } static exi_irq_handler_t *exi_handler[3 * 3]; // 3 channels, 3 events static void *exi_handler_context[3 * 3]; static unsigned long exi_enable_mask[3]; void exi_refresh_enable() { int channel; for (channel = 0; channel < 3; ++channel) *(unsigned long*)(0xcc006800 + channel*0x14) |= 0x401; // exi_enable_mask[channel]; } static inline int have_irq(int t) { if (exi_handler[t]) { exi_handler[t](t/3, t%3, exi_handler_context[t]); return 1; } else { printf("unhandled exi irq!\n"); return 0; } } int exi_interrupt_handler(int irq, void *c) { int ch; for (ch = 0; ch < 3; ++ch) { unsigned long v = (*(unsigned long*)(0xcc006800 + ch * 0x14)); // & 0xC0F; v &= v<<1; *(unsigned long*)(0xcc006800 + ch * 0x14) |= v; if (v & 0x800) have_irq(ch * 3 + EXI_EVENT_INSERT); if (v & 8) have_irq(ch * 3 + EXI_EVENT_TC); if (v & 2) have_irq(ch * 3 + EXI_EVENT_IRQ); } return 1; } void exi_init() { *(unsigned long*)(0xcc006800) |= 1<<13; // disable decryption and rom mapping printf("EXI: init interrupts\n"); request_irq(IRQ_EXI, exi_interrupt_handler, 0); *(unsigned long*)(0xcc006814) |= 3<<10; // enable&clear irq for insertion } int exi_request_irq(int channel, int event, exi_irq_handler_t *handler, void *context) { if (exi_handler[channel * 3 + event]) { printf("EXI: irq %d:%d already used!\n", channel, event); return -1; } exi_handler[channel * 3 + event] = handler; exi_handler_context[channel * 3 + event] = context; switch (event) { case EXI_EVENT_TC: *(unsigned long*)(0xcc006800 + channel*0x14) |= 3<<2; // enable&clear irq exi_enable_mask[channel] |= 1 << 2; break; case EXI_EVENT_INSERT: *(unsigned long*)(0xcc006800 + channel*0x14) |= 3<<10; exi_enable_mask[channel] |= 1 << 10; break; case EXI_EVENT_IRQ: *(unsigned long*)(0xcc006800 + channel*0x14) |= 3<<0; exi_enable_mask[channel] |= 1 << 0; break; } return 0; } int exi_free_irq(int channel, int event) { exi_handler[channel * 3 + event] = 0; switch (event) { case EXI_EVENT_TC: *(unsigned long*)(0xcc006800 + channel*0x14) &= ~(3<<2); // enable&clear irq exi_enable_mask[channel] &= ~(1 << 2); break; case EXI_EVENT_INSERT: *(unsigned long*)(0xcc006800 + channel*0x14) &= ~(3<<10); exi_enable_mask[channel] &= ~(1 << 10); break; case EXI_EVENT_IRQ: *(unsigned long*)(0xcc006800 + channel*0x14) &= ~(3<<0); exi_enable_mask[channel] &= ~(1 << 0); break; } return 0; } void exi_read(int channel, void *data, int len) { exi_imm_ex(channel, data, len, EXI_READ); } void exi_write(int channel, const void *data, int len) { exi_imm_ex(channel, data, len, EXI_WRITE); } unsigned long exi_rw(int channel,unsigned long data,int len) { volatile unsigned long *exi = (volatile unsigned long *)0xCC006800; exi[channel * 5 + 4] = data<<(8*(4-len)); exi[channel * 5 + 3] = ((len-1)<<4)|(2<<2)|1; while (exi[channel * 5 + 3] & 1); return exi[channel * 5 + 4]>>(8*(4-len)); } --- NEW FILE: network.c --- #include "time.h" #include "lwip/debug.h" #include "lwip/mem.h" #include "lwip/memp.h" #include "lwip/sys.h" #include "lwip/stats.h" #include "lwip/ip.h" #include "lwip/udp.h" #include "lwip/tcp.h" #include "lwip/arch/gc/include/netif/gcif.h" #include "netif/etharp.h" #include "dolup.h" #include "irq.h" #include "console.h" extern void httpd_start(); struct ip_addr *sram_get_ip(int w); static struct netif netif; static tb_t now, start; void network_init() { struct ip_addr *ipaddr = sram_get_ip(0), *netmask = sram_get_ip(1), *gw = sram_get_ip(2); #ifdef STATS stats_init(); #endif /* STATS */ mem_init(); memp_init(); pbuf_init(); netif_init(); ip_init(); // udp_init(); tcp_init(); etharp_init(); if (!netif_add(&netif, ipaddr, netmask, gw, NULL, gcif_init, ip_input)) { printf("netif_add failed!\n"); return; } netif_set_default(&netif); dolup_init(); httpd_start(); mftb(&start); } void network_poll() { mftb(&now); if (tb_diff_msec(&now, &start) >= 250) { unsigned long flags; mftb(&start); cli(flags); tcp_tmr(); sti(flags); } } --- NEW FILE: pad.c --- #include "pad.h" void pad_init() { *(volatile unsigned long*)0xCC006430 = 0x00000000; *(volatile unsigned long*)0xCC006438 = 0x80000000; *(volatile unsigned long*)0xCC006430 = 0x00f70200; *(volatile unsigned long*)0xCC006438 = 0x80000000; *(volatile unsigned long*)0xCC006480 = 0x00000000; *(volatile unsigned long*)0xCC006434 = 0xc0010301; *(volatile unsigned long*)0xCC006438 = 0x00000000; (void)*(volatile unsigned long*)0xCC006434; *(volatile unsigned long*)0xCC006430 |= 0xF0; // enable all four controller ports *(volatile unsigned long*)0xCC006400 = 0x00400300; *(volatile unsigned long*)0xCC00640C = 0x00400300; *(volatile unsigned long*)0xCC006418 = 0x00400300; *(volatile unsigned long*)0xCC006424 = 0x00400300; udelay(1000); *(volatile unsigned long*)0xCC006430 = 0x00000000; *(volatile unsigned long*)0xCC006438 = 0x80000000; *(volatile unsigned long*)0xCC006430 = 0x00f70200; *(volatile unsigned long*)0xCC006438 = 0x80000000; *(volatile unsigned long*)0xCC006480 = 0x00000000; *(volatile unsigned long*)0xCC006434 = 0xc0010301; *(volatile unsigned long*)0xCC006438 = 0x00000000; (void)*(volatile unsigned long*)0xCC006434; *(volatile unsigned long*)0xCC006430 |= 0xF0; // enable all four controller ports *(volatile unsigned long*)0xCC006400 = 0x00400300; *(volatile unsigned long*)0xCC00640C = 0x00400300; *(volatile unsigned long*)0xCC006418 = 0x00400300; *(volatile unsigned long*)0xCC006424 = 0x00400300; *(volatile unsigned long*)0xCC006430 = 0x000701f0; *(volatile unsigned long*)0xCC006438 = 0x80000000; while (!((*(volatile unsigned long*) 0xCC006438)&0x20000000)); } /* ripped from: Author: Peter (www.console-dev.de) */ void PAD_ReadState(PAD *pPad, u8 PadChannel) { u32 Value32[3]; u8 Value8[2]; s8 ValueS8[2]; //u32 PadChannelAddr = 0xCC006400 + (PadChannel*12); u32 PadChannelAddr = MEM_PAD_CHANNEL(PadChannel); /* added in 0.2 */ PAD_BUTTONS_DIGITAL *pDigital=&pPad->Digital; Value32[0] = *(u32 *)(PadChannelAddr+0); Value32[1] = *(u32 *)(PadChannelAddr+4); Value32[2] = *(u32 *)(PadChannelAddr+8); // digital buttons Value8[0] = (Value32[1] >> 16); Value8[1] = (Value32[1] >> 16) >> 8; // digital buttons pDigital->Left = Value8[0] & 0x01; pDigital->Right = Value8[0] & 0x02; pDigital->Down = Value8[0] & 0x04; pDigital->Up = Value8[0] & 0x08; pDigital->Z = Value8[0] & 0x10; pDigital->L = Value8[0] & 0x20; pDigital->R = Value8[0] & 0x40; pDigital->A = Value8[1] & 0x01; pDigital->B = Value8[1] & 0x02; pDigital->X = Value8[1] & 0x04; pDigital->Y = Value8[1] & 0x08; pDigital->Start = Value8[1] & 0x10; // analog stick ValueS8[0] = ((Value32[1]) & 0xff); ValueS8[1] = ((Value32[1]) & 0xff00) >> 8; pPad->Analog.X = 0x80+ValueS8[1]; pPad->Analog.Y = 0x80-ValueS8[0]; // trigger L and R Value8[0] = ((Value32[2]) & 0xff); Value8[1] = ((Value32[2]) & 0xff00) >> 8; pPad->Trigger.L = Value8[0]; pPad->Trigger.R = Value8[1]; // analoc C stick ValueS8[0] = (Value32[2] >> 16); ValueS8[1] = (Value32[2] >> 16) >> 8; pPad->AnalogC.X = 0x80+ValueS8[1]; pPad->AnalogC.Y = 0x80-ValueS8[0]; } --- NEW FILE: sram.c --- #include "ipl.h" #include "pad.h" #include "lwip/ip_addr.h" #include "lwip/inet.h" void sram_set_videomode(int v) { sram_data[33] = v; } int sram_get_videomode(void) { return sram_data[33]; } void sram_set_autoboot(int v) { sram_data[34] = v; } int sram_get_autoboot(void) { return sram_data[34]; } struct ip_addr *sram_get_ip(int w) { return (struct ip_addr*)(sram_data + 0x24 + w * 4); } void sram_load_defaults(void) { sram_data[32] = '!'; sram_set_autoboot(0); sram_set_videomode(1); IP4_ADDR(sram_get_ip(0), 10,0,0,203); IP4_ADDR(sram_get_ip(1), 255,255,255,0); IP4_ADDR(sram_get_ip(2), 10,0,0,1); } void read_sram(void) { //TODO: this somewhere else struct PAD pad; PAD_ReadState(&pad, 0); if (!pad.Digital.Start) exi_sram_read(sram_data); else memset(sram_data + 32, 0, 32); if (sram_data[32] != '!') sram_load_defaults(); } void write_sram(void) { exi_sram_write(sram_data); } --- NEW FILE: video.c --- #include "video.h" #define MEM_VIDEO_BASE (0xCC002000) #define MEM_VIDEO_BASE_PTR (u32*)MEM_VIDEO_BASE #define R_VIDEO_FRAMEBUFFER_1 *(vu32*)(MEM_VIDEO_BASE+0x1C) #define R_VIDEO_FRAMEBUFFER_2 *(vu32*)(MEM_VIDEO_BASE+0x24) #define R_VIDEO_HALFLINE_1 *(vu16*)(MEM_VIDEO_BASE+0x2C) #define R_VIDEO_HALFLINE_2 *(vu16*)(MEM_VIDEO_BASE+0x2E) #define R_VIDEO_STATUS *(vu16*)(MEM_VIDEO_BASE+0x6C) /* ripped from libogc. */ // VIDEO_640X480_NTSC_YUV16 static const u32 VIDEO_Mode640X480NtscYUV16[32] = { 0x0F060001, 0x476901AD, 0x02EA5140, 0x00030018, 0x00020019, 0x410C410C, 0x40ED40ED, 0x00435A4E, 0x00000000, 0x00435A4E, 0x00000000, 0x00000000, 0x110701AE, 0x10010001, 0x00010001, 0x00010001, 0x00000000, 0x00000000, 0x28500100, 0x1AE771F0, 0x0DB4A574, 0x00C1188E, 0xC4C0CBE2, 0xFCECDECF, 0x13130F08, 0x00080C0F, 0x00FF0000, 0x00000000, 0x02800000, 0x000000FF, 0x00FF00FF, 0x00FF00FF}; // VIDEO_640X480_PAL50_YUV16 static const u32 VIDEO_Mode640X480Pal50YUV16[32] = { 0x11F50101, 0x4B6A01B0, 0x02F85640, 0x00010023, 0x00000024, 0x4D2B4D6D, 0x4D8A4D4C, 0x00435A4E, 0x00000000, 0x00435A4E, 0x00000000, 0x013C0144, 0x113901B1, 0x10010001, 0x00010001, 0x00010001, 0x00000000, 0x00000000, 0x28500100, 0x1AE771F0, 0x0DB4A574, 0x00C1188E, 0xC4C0CBE2, 0xFCECDECF, 0x13130F08, 0x00080C0F, 0x00FF0000, 0x00000000, 0x02800000, 0x000000FF, 0x00FF00FF, 0x00FF00FF}; // VIDEO_640X480_PAL60_YUV16 static const u32 VIDEO_Mode640X480Pal60YUV16[32] = { 0x0F060001, 0x476901AD, 0x02EA5140, 0x00030018, 0x00020019, 0x410C410C, 0x40ED40ED, 0x00435A4E, 0x00000000, 0x00435A4E, 0x00000000, 0x00050176, 0x110701AE, 0x10010001, 0x00010001, 0x00010001, 0x00000000, 0x00000000, 0x28500100, 0x1AE771F0, 0x0DB4A574, 0x00C1188E, 0xC4C0CBE2, 0xFCECDECF, 0x13130F08, 0x00080C0F, 0x00FF0000, 0x00000000, 0x02800000, 0x000000FF, 0x00FF00FF, 0x00FF00FF}; void video_init(u32 VideoMode) { u32 Counter=0; u32 *pSrcAddr=NULL; u32 *pDstAddr=MEM_VIDEO_BASE_PTR; switch(VideoMode) { case VIDEO_640X480_NTSC_YUV16: pSrcAddr = (u32*)VIDEO_Mode640X480NtscYUV16; break; case VIDEO_640X480_PAL50_YUV16: pSrcAddr = (u32*)VIDEO_Mode640X480Pal50YUV16; break; case VIDEO_640X480_PAL60_YUV16: pSrcAddr = (u32*)VIDEO_Mode640X480Pal60YUV16; break; } for(Counter=0; Counter<32; Counter++) { if ((Counter != 7) && (Counter != 9)) pDstAddr[Counter] = pSrcAddr[Counter]; } } void video_set_framebuffer(u32 Which, u32 FrameBufferAddr) { switch(Which) { case VIDEO_FRAMEBUFFER_1: R_VIDEO_FRAMEBUFFER_1 = FrameBufferAddr; break; case VIDEO_FRAMEBUFFER_2: R_VIDEO_FRAMEBUFFER_2 = FrameBufferAddr; break; case VIDEO_FRAMEBUFFER_BOTH: R_VIDEO_FRAMEBUFFER_1 = FrameBufferAddr; R_VIDEO_FRAMEBUFFER_2 = FrameBufferAddr; break; } } void video_wait_vsync(void) { while(R_VIDEO_HALFLINE_1 >= 200); while(R_VIDEO_HALFLINE_1 < 200); } --- NEW FILE: vsprintf.c --- /* * linux/lib/vsprintf.c * * Copyright (C) 1991, 1992 Linus Torvalds */ /* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */ /* * Wirzenius wrote this portably, Torvalds fucked it up :-) */ #include <stdarg.h> #include <linux/types.h> #include <linux/string.h> #include <linux/ctype.h> #include "console.h" unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base) { unsigned long result = 0,value; if (*cp == '0') { cp++; if ((*cp == 'x') && isxdigit(cp[1])) { base = 16; cp++; } if (!base) { base = 8; } } if (!base) { base = 10; } while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp) ? toupper(*cp) : *cp)-'A'+10) < base) { result = result*base + value; cp++; } if (endp) *endp = (char *)cp; return result; } long simple_strtol(const char *cp,char **endp,unsigned int base) { if(*cp=='-') return -simple_strtoul(cp+1,endp,base); return simple_strtoul(cp,endp,base); } /* we use this so that we can do without the ctype library */ #define is_digit(c) ((c) >= '0' && (c) <= '9') static int skip_atoi(const char **s) { int i=0; while (is_digit(**s)) i = i*10 + *((*s)++) - '0'; return i; } #define ZEROPAD 1 /* pad with zero */ #define SIGN 2 /* unsigned/signed long */ #define PLUS 4 /* show plus */ #define SPACE 8 /* space if plus */ #define LEFT 16 /* left justified */ #define SPECIAL 32 /* 0x */ #define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */ #define do_div(n,base) ({ \ int __res; \ __res = ((unsigned long) n) % (unsigned) base; \ n = ((unsigned long) n) / (unsigned) base; \ __res; }) static char * number(char * str, long num, int base, int size, int precision ,int type) { char c,sign,tmp[66]; const char *digits="0123456789abcdefghijklmnopqrstuvwxyz"; int i; if (type & LARGE) digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; if (type & LEFT) type &= ~ZEROPAD; if (base < 2 || base > 36) return 0; c = (type & ZEROPAD) ? '0' : ' '; sign = 0; if (type & SIGN) { if (num < 0) { sign = '-'; num = -num; size--; } else if (type & PLUS) { sign = '+'; size--; } else if (type & SPACE) { sign = ' '; size--; } } if (type & SPECIAL) { if (base == 16) size -= 2; else if (base == 8) size--; } i = 0; if (num == 0) tmp[i++]='0'; else while (num != 0) tmp[i++] = digits[do_div(num,base)]; if (i > precision) precision = i; size -= precision; if (!(type&(ZEROPAD+LEFT))) while(size-->0) *str++ = ' '; if (sign) *str++ = sign; if (type & SPECIAL) { if (base==8) *str++ = '0'; else if (base==16) { *str++ = '0'; *str++ = digits[33]; } } if (!(type & LEFT)) while (size-- > 0) *str++ = c; while (i < precision--) *str++ = '0'; while (i-- > 0) *str++ = tmp[i]; while (size-- > 0) *str++ = ' '; return str; } /* Forward decl. needed for IP address printing stuff... */ int sprintf(char * buf, const char *fmt, ...); int vsprintf(char *buf, const char *fmt, va_list args) { int len; unsigned long num; int i, base; char * str; const char *s; int flags; /* flags to number() */ int field_width; /* width of output field */ int precision; /* min. # of digits for integers; max number of chars for from string */ int qualifier; /* 'h', 'l', or 'L' for integer fields */ for (str=buf ; *fmt ; ++fmt) { if (*fmt != '%') { *str++ = *fmt; continue; } /* process flags */ flags = 0; repeat: ++fmt; /* this also skips first '%' */ switch (*fmt) { case '-': flags |= LEFT; goto repeat; case '+': flags |= PLUS; goto repeat; case ' ': flags |= SPACE; goto repeat; case '#': flags |= SPECIAL; goto repeat; case '0': flags |= ZEROPAD; goto repeat; } /* get field width */ field_width = -1; if (is_digit(*fmt)) field_width = skip_atoi(&fmt); else if (*fmt == '*') { ++fmt; /* it's the next argument */ field_width = va_arg(args, int); if (field_width < 0) { field_width = -field_width; flags |= LEFT; } } /* get the precision */ precision = -1; if (*fmt == '.') { ++fmt; if (is_digit(*fmt)) precision = skip_atoi(&fmt); else if (*fmt == '*') { ++fmt; /* it's the next argument */ precision = va_arg(args, int); } if (precision < 0) precision = 0; } /* get the conversion qualifier */ qualifier = -1; if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') { qualifier = *fmt; ++fmt; } /* default base */ base = 10; switch (*fmt) { case 'c': if (!(flags & LEFT)) while (--field_width > 0) *str++ = ' '; *str++ = (unsigned char) va_arg(args, int); while (--field_width > 0) *str++ = ' '; continue; case 's': s = va_arg(args, char *); if (!s) s = "<NULL>"; len = strnlen(s, precision); if (!(flags & LEFT)) while (len < field_width--) *str++ = ' '; for (i = 0; i < len; ++i) *str++ = *s++; while (len < field_width--) *str++ = ' '; continue; case 'p': if (field_width == -1) { field_width = 2*sizeof(void *); flags |= ZEROPAD; } str = number(str, (unsigned long) va_arg(args, void *), 16, field_width, precision, flags); continue; case 'n': if (qualifier == 'l') { long * ip = va_arg(args, long *); *ip = (str - buf); } else { int * ip = va_arg(args, int *); *ip = (str - buf); } continue; case '%': *str++ = '%'; continue; /* integer number formats - set up the flags and "break" */ case 'o': base = 8; break; case 'X': flags |= LARGE; case 'x': base = 16; break; case 'd': case 'i': flags |= SIGN; case 'u': break; default: *str++ = '%'; if (*fmt) *str++ = *fmt; else --fmt; continue; } if (qualifier == 'l') num = va_arg(args, unsigned long); else if (qualifier == 'h') { num = (unsigned short) va_arg(args, int); if (flags & SIGN) num = (short) num; } else if (flags & SIGN) num = va_arg(args, int); else num = va_arg(args, unsigned int); str = number(str, num, base, field_width, precision, flags); } *str = '\0'; return str-buf; } int sprintf(char * buf, const char *fmt, ...) { va_list args; int i; va_start(args, fmt); i=vsprintf(buf,fmt,args); va_end(args); return i; } int printf( const char *fmt, ...) { va_list args; char buffer[1024]; int i; va_start(args, fmt); i=vsprintf(buffer, fmt,args); va_end(args); putstring (buffer); return i; } |