-
Noob (active) User
Messaggi: 71 Iscritto il: 16/12/2010, 13:14
Grz inviati: 9 volte
Grz ricevuti: 2 volte
|
ADESSO BASTA ALLE SPECULAZIONI SUI GIOCHI: PROGRAMMATORI ECCO A VOI... To use this, copy the save to your wii. See the instruction manual if you need to know how. Then start the Lego Star Wars and load the first save. When the game starts, walk to the left and stand in front of the big jars of water containing the 2 custom characters. If you see "press A to hack", then press A.
this should trigger the exploit which will start the elf loader and load a boot.elf from the root of your SD card.
PAL version has only been tested on the english/german version. if there are any other version, i doubt they will work. USA has 2 versions. obviously if one of them doesnt work, try the other one. v2 is made for the 1.01 release of the game big credits to team twiizers. pretty much all of the code contained in this is theirs, only re-arranged in a different way to work with this game. and credit to segher for the checksum code. it made this much easier not having to mess with any of that. credit to whoever it was that exploited those other 2 lego games. if it werent for them, i never would have looked into this one. There is no real source code for this exploit, other than the elf loader code. it is only a long name, a return address, 5 opcodes, and then the loader which there is source code for. but, for those of you interested, i will give a brief description.
inside the save, there is FILE_V28. its some save i found on the google machine. i have overwritten whatever was originally at 0x2db0 with the 5 opcodes
#setup a stack; copied from the other legosploitz lis r1,0x8080 li r0,0 stwu r0,-64(r1)
#kill audio & video bl audiostop bl videostop
after this comes the elfloader. then seek to 0x7c74 and write the name for the first custom character "Press A to Hack" a couple times. This way the game will display some instructions for idiots. Next, seek to the start of what should be the second custom character's name at 0x7cac. from here, i have replaced all null bytes with 1 to make the string 0x124 bytes long. The game's creators were nice enough to copy the save file to ~6 places in memory for us in each version of the game. so, find one of those places in RAm while the game is running and you will find the 5 opcodes within it. after this 0x124 byte name, write the address in RAM for one of the copies of the opcodes. the elfloader is built with entrypoint = 0x14 + that address. then save it, fix the checksums with the tool in segher's git and pack it into a data.bin ( again, see segher's magical git ). video.c Copyright 2008-2009 Segher Boessenkool <segher@kernel.crashing.org> // This code is licensed to you under the terms of the GNU GPL, version 2; // see file COPYING or Registrati o effettua il Login per visualizzare il link!.#include "loader.h" static u8 *const code_buffer = (u8 *)0x90100000; static u8 *const trampoline_buffer = (u8 *)0x80001800; static void dsp_reset(void) { write16(0x0c00500a, read16(0x0c00500a) & ~0x01f8); write16(0x0c00500a, read16(0x0c00500a) | 0x0010); write16(0x0c005036, 0); } static u32 reboot_trampoline[] = { 0x3c209000, // lis 1,0x9000 0x60210020, // ori 1,1,0x0020 0x7c2903a6, // mtctr 1 0x4e800420 // bctr }; int try_sd_load(void) { int err; err = sd_init(); if (err) { printf("SD card not found (%d)\n", err); return err; } err = fat_init(); if (err == 0) printf("SD card detected\n"); else { printf("SD card not detected (%d)\n", err); return err; } // if (usbgecko_checkgecko()) // printf("USBGecko serial interface detected\n"); // else // printf("USBGecko serial interface not detected\n"); printf("Opening boot.elf:\n"); err = fat_open("boot.elf"); if (err) { printf("boot.elf not found (%d)\n", err); return err; } extern u32 fat_file_size; printf("reading %d bytes...\n", fat_file_size); err = fat_read(code_buffer, fat_file_size); if (err) { printf("Error %d reading file\n", err); return err; } printf("Done.\n"); return 0; } int try_usbgecko_load(void) { if (!usbgecko_checkgecko()) { printf("USBGecko not found\n"); return -1; } #define FLASH_OFFSET 0x30000 int i, size = usbgecko_flash_read32(FLASH_OFFSET); if (size < 0) { printf("Invalid code size in usbgecko flash (%d)\n", size); return -1; } printf("Loading %d bytes from USBGecko flash (offset=%x)\n", size, FLASH_OFFSET+4); for (i=0; i < size; i++) code_buffer[i] = usbgecko_flash_read8(FLASH_OFFSET + 4 + i); return 0; } int main(void) { dsp_reset(); exception_init(); // Install trampoline at 80001800; some payloads like to jump // there to restart. Sometimes this can even work. memcpy(trampoline_buffer, reboot_trampoline, sizeof(reboot_trampoline)); // Clear interrupt mask. write32(0x0c003004, 0); // Unlock EXI. write32(0x0d00643c, 0); video_init(); usbgecko_init(); printf("savezelda %s\n", version); printf("\n"); printf("Copyright 2008,2009 Segher Boessenkool\n"); printf("Copyright 2008 Haxx Enterprises\n"); printf("Copyright 2008 Hector Martin (\"marcan\")\n"); printf("Copyright 2003,2004 Felix Domke\n"); printf("\n"); printf("This code is licensed to you under the terms of the\n"); printf("GNU GPL, version 2; see the file COPYING\n"); printf("\n"); printf("Font and graphics by Freddy Leitner\n"); printf("\n"); printf("\n"); printf("Cleaning up environment... "); reset_ios(); printf("OK.\n"); int err; restart: err = try_sd_load(); if (err) { err = try_usbgecko_load(); if (err) { printf("No code found to load, hanging.\n"); for (;;) ; } } if (valid_elf_image(code_buffer)) { printf("Valid ELF image detected.\n"); void (*entry)() = load_elf_image(code_buffer); entry(); printf("Program returned to loader, reloading.\n"); } else printf("No valid ELF image detected, retrying.\n"); goto restart; } ecco il LOADER:// Copyright 2008-2009 Segher Boessenkool <segher@kernel.crashing.org> // This code is licensed to you under the terms of the GNU GPL, version 2; // see file COPYING or Registrati o effettua il Login per visualizzare il link!.#ifndef _LOADER_H #define _LOADER_H #include <stddef.h> // String functions. size_t strlen(const char *); size_t strnlen(const char *, size_t); void *memset(void *, int, size_t); void *memcpy(void *, const void *, size_t); int memcmp(const void *, const void *, size_t); // Basic types. typedef unsigned char u8; typedef unsigned short int u16; typedef unsigned int u32; typedef unsigned long long int u64; static inline u16 le16(const u8 *p) { return p[0] | (p[1] << 8); } static inline u32 le32(const u8 *p) { return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); } // Basic I/O. static inline u32 read32(u32 addr) { u32 x; asm volatile("lwz %0,0(%1) ; sync" : "=r"(x) : "b"(0xc0000000 | addr)); return x; } static inline void write32(u32 addr, u32 x) { asm("stw %0,0(%1) ; eieio" : : "r"(x), "b"(0xc0000000 | addr)); } static inline u16 read16(u32 addr) { u16 x; asm volatile("lhz %0,0(%1) ; sync" : "=r"(x) : "b"(0xc0000000 | addr)); return x; } static inline void write16(u32 addr, u16 x) { asm("sth %0,0(%1) ; eieio" : : "r"(x), "b"(0xc0000000 | addr)); } // Address mapping. static inline u32 virt_to_phys(const void *p) { return (u32)p & 0x7fffffff; } static inline void *phys_to_virt(u32 x) { return (void *)(x | 0x80000000); } // Cache synchronisation. void sync_before_read(void *p, u32 len); void sync_after_write(const void *p, u32 len); void sync_before_exec(const void *p, u32 len); // Time. void udelay(u32 us); // Special purpose registers. #define mtspr(n, x) do { asm("mtspr %1,%0" : : "r"(x), "i"(n)); } while (0) #define mfspr(n) ({ \ u32 x; asm volatile("mfspr %0,%1" : "=r"(x) : "i"(n)); x; \ }) // Exceptions. void exception_init(void); // USB Gecko. void usbgecko_init(void); int usbgecko_checkgecko(void); void usbgecko_console_putc(u8 c); u8 usbgecko_flash_read8(u32 offset); u32 usbgecko_flash_read32(u32 offset); // Version string. extern const char version[]; // Video. void video_init(void); void fb_putc(char); // Console. void console_init(void); int printf(const char *fmt, ...); // SD card. int sd_init(void); int sd_read_sector(u8 *data, u32 offset); int sd_close(void); // FAT. int fat_init(void); int fat_open(const char *name); int fat_read(void *data, u32 len); // ELF. int valid_elf_image(void *addr); void *load_elf_image(void *addr); // IOS. struct ioctlv { void *data; u32 len; }; int ios_open(const char *filename, u32 mode); int ios_close(int fd); int ios_read(int fd, void *data, u32 len); int ios_write(int fd, const void *data, u32 len); int ios_seek(int fd, int where, int whence); int ios_ioctl(int fd, u32 n, const void *in, u32 inlen, void *out, u32 outlen); int ios_ioctlv(int fd, u32 n, u32 in_count, u32 out_count, struct ioctlv *vec); void reset_ios(void); #endif ECCOVI sd.c// Copyright 2008 Haxx Enterprises <bushing@gmail.com> // Copyright 2008-2009 Segher Boessenkool <segher@kernel.crashing.org> // This code is licensed to you under the terms of the GNU GPL, version 2; // see file COPYING or Registrati o effettua il Login per visualizzare il link!.#include "loader.h" static int fd; static u32 rca; // 16 bottom bits are stuff bits static int sd_hc_write8(u8 reg, u8 data) { u32 param[6]; int err; memset(param, 0, sizeof param); param[0] = reg; param[3] = 1; // reg size param[4] = data; err = ios_ioctl(fd, 1, param, sizeof param, 0, 0); return err; } static int sd_hc_read8(u8 reg, u8 *x) { u32 param[6]; u32 data; int err; memset(param, 0, sizeof param); param[0] = reg; param[3] = 1; // reg size param[4] = 0; err = ios_ioctl(fd, 2, param, sizeof param, &data, sizeof data); if (err) return err; *x = data; return err; } static int sd_reset_card(void) { u32 reply; int err; err = ios_ioctl(fd, 4, 0, 0, &reply, sizeof reply); if (err) return err; rca = reply & 0xffff0000; // printf("sd_reset_card(): got reply = %08x\n", reply); return 0; } static int sd_set_clock(void) { u32 clock; int err; clock = 1; // half of the sdclk divisor: a power of two or zero, // should look at capabilities reg to compute this err = ios_ioctl(fd, 6, &clock, sizeof clock, 0, 0); return err; } static int sd_command(u32 cmd, u32 cmd_type, u32 resp_type, u32 arg, u32 block_count, u32 block_size, void *addr, u32 *outreply, u32 reply_size) { u32 param[9]; u32 reply[4]; int err; param[0] = cmd; param[1] = cmd_type; param[2] = resp_type; param[3] = arg; param[4] = block_count; param[5] = block_size; param[6] = (u32)addr; param[7] = 0; // ??? param[8] = 0; // ??? err = ios_ioctl(fd, 7, param, sizeof param, reply, sizeof reply); if (reply_size) // ??? memcpy(outreply, reply, reply_size); return err; } #define TYPE_BC 1 #define TYPE_BCR 2 #define TYPE_AC 3 #define TYPE_ADTC 4 #define RESPONSE_NONE 0 #define RESPONSE_R1 1 #define RESPONSE_R1B 2 #define RESPONSE_R2 3 #define RESPONSE_R3 4 #define RESPONSE_R4 5 #define RESPONSE_R5 6 #define RESPONSE_R6 7 static int sd_app_command(u32 cmd, u32 cmd_type, u32 resp_type, u32 arg, u32 block_count, u32 block_size, void *addr, u32 *outreply, u32 reply_size) { int err; err = sd_command(55, TYPE_AC, RESPONSE_R1, rca, 0, 0, 0, 0, 0); if (err) return err; err = sd_command(cmd, cmd_type, resp_type, arg, block_count, block_size, addr, outreply, reply_size); return err; } static int sd_data_command(u32 cmd, u32 cmd_type, u32 resp_type, u32 arg, u32 block_count, u32 block_size, void *data, u32 unk1, u32 unk2, u32 *outreply, u32 reply_size) { u32 param[9]; u32 reply[4]; struct ioctlv vec[3]; int err; param[0] = cmd; param[1] = cmd_type; param[2] = resp_type; param[3] = arg; param[4] = block_count; param[5] = block_size; param[6] = (u32)data; param[7] = unk1; // ??? param[8] = unk2; // ??? vec[0].data = param; vec[0].len = sizeof param; vec[1].data = data; vec[1].len = block_count * block_size; vec[2].data = reply; vec[2].len = sizeof reply; err = ios_ioctlv(fd, 7, 2, 1, vec); if (reply_size) // ??? memcpy(outreply, reply, reply_size); return err; } static int sd_select(void) { int err; //printf("Selecting card:\n"); err = sd_command(7, TYPE_AC, RESPONSE_R1B, rca, 0, 0, 0, 0, 0); return err; } static int sd_set_blocklength(u32 len) { int err; //printf("sd_set_blocklength(%u)\n", len); err = sd_command(16, TYPE_AC, RESPONSE_R1, len, 0, 0, 0, 0, 0); return err; } static int sd_set_bus_width(int width) { u32 arg; u8 reg; int err; // First notify the card. arg = (width == 4) ? 2 : 0; //printf("sd_set_bus_width()\n"); err = sd_app_command(6, TYPE_AC, RESPONSE_R1, arg, 0, 0, 0, 0, 0); if (err) return err; // Now change the Host Control Register. err = sd_hc_read8(0x28, ®); if (err) return err; reg = (reg & ~2) | arg; err = sd_hc_write8(0x28, reg); return err; } int sd_read_sector(u8 *data, u32 offset) { u32 reply[4]; int err; if (offset >= 0x800000) return -1; err = sd_data_command(18, TYPE_AC, RESPONSE_R1, 0x200 * offset, 1, 0x200, data, 1, 0, reply, sizeof reply); sync_before_read(data, 0x200); //printf("READ block %d\r",offset); if (err) printf("SD READ %d: err=%08x, reply=%08x %08x %08x %08x\n", offset, err, reply[0], reply[1], reply[2], reply[3]); return err; } int sd_close(void) { return ios_close(fd); } int sd_init(void) { int err; fd = ios_open("/dev/sdio/slot0", 0); if (fd < 0) return fd; err = sd_reset_card(); if (err) { printf("SD Card not present? (%d)\n", err); goto out; } // now in standby state err = sd_select(); if (err) goto out; // now in transfer state // Some broken cards require this: err = sd_set_blocklength(0x200); if (err) goto out; err = sd_set_bus_width(4); // XXX: Should check in SCR first. if (err) goto out; err = sd_set_clock(); // XXX: Should check. if (err) goto out; return 0; out: sd_close(); return err; } il MAIN PROGRAM Copyright 2008-2009 Segher Boessenkool <segher@kernel.crashing.org> // This code is licensed to you under the terms of the GNU GPL, version 2; // see file COPYING or Registrati o effettua il Login per visualizzare il link!.#include "loader.h" static u8 *const code_buffer = (u8 *)0x90100000; static u8 *const trampoline_buffer = (u8 *)0x80001800; static void dsp_reset(void) { write16(0x0c00500a, read16(0x0c00500a) & ~0x01f8); write16(0x0c00500a, read16(0x0c00500a) | 0x0010); write16(0x0c005036, 0); } static u32 reboot_trampoline[] = { 0x3c209000, // lis 1,0x9000 0x60210020, // ori 1,1,0x0020 0x7c2903a6, // mtctr 1 0x4e800420 // bctr }; int try_sd_load(void) { int err; err = sd_init(); if (err) { printf("SD card not found (%d)\n", err); return err; } err = fat_init(); if (err == 0) printf("SD card detected\n"); else { printf("SD card not detected (%d)\n", err); return err; } // if (usbgecko_checkgecko()) // printf("USBGecko serial interface detected\n"); // else // printf("USBGecko serial interface not detected\n"); printf("Opening boot.elf:\n"); err = fat_open("boot.elf"); if (err) { printf("boot.elf not found (%d)\n", err); return err; } extern u32 fat_file_size; printf("reading %d bytes...\n", fat_file_size); err = fat_read(code_buffer, fat_file_size); if (err) { printf("Error %d reading file\n", err); return err; } printf("Done.\n"); return 0; } int try_usbgecko_load(void) { if (!usbgecko_checkgecko()) { printf("USBGecko not found\n"); return -1; } #define FLASH_OFFSET 0x30000 int i, size = usbgecko_flash_read32(FLASH_OFFSET); if (size < 0) { printf("Invalid code size in usbgecko flash (%d)\n", size); return -1; } printf("Loading %d bytes from USBGecko flash (offset=%x)\n", size, FLASH_OFFSET+4); for (i=0; i < size; i++) code_buffer[i] = usbgecko_flash_read8(FLASH_OFFSET + 4 + i); return 0; } int main(void) { dsp_reset(); exception_init(); // Install trampoline at 80001800; some payloads like to jump // there to restart. Sometimes this can even work. memcpy(trampoline_buffer, reboot_trampoline, sizeof(reboot_trampoline)); // Clear interrupt mask. write32(0x0c003004, 0); // Unlock EXI. write32(0x0d00643c, 0); video_init(); usbgecko_init(); printf("savezelda %s\n", version); printf("\n"); printf("Copyright 2008,2009 Segher Boessenkool\n"); printf("Copyright 2008 Haxx Enterprises\n"); printf("Copyright 2008 Hector Martin (\"marcan\")\n"); printf("Copyright 2003,2004 Felix Domke\n"); printf("\n"); printf("This code is licensed to you under the terms of the\n"); printf("GNU GPL, version 2; see the file COPYING\n"); printf("\n"); printf("Font and graphics by Freddy Leitner\n"); printf("\n"); printf("\n"); printf("Cleaning up environment... "); reset_ios(); printf("OK.\n"); int err; restart: err = try_sd_load(); if (err) { err = try_usbgecko_load(); if (err) { printf("No code found to load, hanging.\n"); for (;;) ; } } if (valid_elf_image(code_buffer)) { printf("Valid ELF image detected.\n"); void (*entry)() = load_elf_image(code_buffer); entry(); printf("Program returned to loader, reloading.\n"); } else printf("No valid ELF image detected, retrying.\n"); goto restart; } ecco lo IOS// Copyright 2008-2009 Segher Boessenkool <segher@kernel.crashing.org> // This code is licensed to you under the terms of the GNU GPL, version 2; // see file COPYING or Registrati o effettua il Login per visualizzare il link!.#include "loader.h" // Low-level IPC access. static u32 ipc_read(u32 reg) { return read32(0x0d000000 + 4*reg); } static void ipc_write(u32 reg, u32 value) { write32(0x0d000000 + 4*reg, value); } static void ipc_bell(u32 w) { ipc_write(1, (ipc_read(1) & 0x30) | w); } static void ipc_wait_ack(void) { while ((ipc_read(1) & 0x22) != 0x22) ; } static void ipc_wait_reply(void) { while ((ipc_read(1) & 0x14) != 0x14) ; } static void ipc_irq_ack(void) { ipc_write(12, 0x40000000); } // Mid-level IPC access. static struct { u32 cmd; int result; int fd; u32 arg[5]; u32 user[8]; } ipc __attribute__((aligned(64))); static void ipc_send_request(void) { sync_after_write(&ipc, 0x40); ipc_write(0, virt_to_phys(&ipc)); ipc_bell(1); ipc_wait_ack(); ipc_bell(2); ipc_irq_ack(); } static void ipc_recv_reply(void) { for (;;) { u32 reply; ipc_wait_reply(); reply = ipc_read(2); ipc_bell(4); ipc_irq_ack(); ipc_bell(8); if (reply == virt_to_phys(&ipc)) break; } sync_before_read(&ipc, sizeof ipc); } // High-level IPC access. int ios_open(const char *filename, u32 mode) { sync_after_write(filename, strlen(filename) + 1); memset(&ipc, 0, sizeof ipc); ipc.cmd = 1; ipc.fd = 0; ipc.arg[0] = virt_to_phys(filename); ipc.arg[1] = mode; ipc_send_request(); ipc_recv_reply(); return ipc.result; } int ios_close(int fd) { memset(&ipc, 0, sizeof ipc); ipc.cmd = 2; ipc.fd = fd; ipc_send_request(); ipc_recv_reply(); return ipc.result; } #if 0 int ios_read(int fd, void *data, u32 len) { memset(&ipc, 0, sizeof ipc); ipc.cmd = 3; ipc.fd = fd; ipc.arg[0] = virt_to_phys(data); ipc.arg[1] = len; ipc_send_request(); ipc_recv_reply(); if (data) sync_before_read(data, len); return ipc.result; } int ios_seek(int fd, int where, int whence) { memset(&ipc, 0, sizeof ipc); ipc.cmd = 5; ipc.fd = fd; ipc.arg[0] = where; ipc.arg[1] = whence; ipc_send_request(); ipc_recv_reply(); return ipc.result; } #endif int ios_ioctl(int fd, u32 n, const void *in, u32 inlen, void *out, u32 outlen) { memset(&ipc, 0, sizeof ipc); if (in) sync_after_write(in, inlen); if (out) sync_after_write(out, outlen); ipc.cmd = 6; ipc.fd = fd; ipc.arg[0] = n; ipc.arg[1] = virt_to_phys(in); ipc.arg[2] = inlen; ipc.arg[3] = virt_to_phys(out); ipc.arg[4] = outlen; ipc_send_request(); ipc_recv_reply(); if (out) sync_before_read(out, outlen); return ipc.result; } int ios_ioctlv(int fd, u32 n, u32 in_count, u32 out_count, struct ioctlv *vec) { u32 i; memset(&ipc, 0, sizeof ipc); for (i = 0; i < in_count + out_count; i++) if (vec[i].data) { sync_after_write(vec[i].data, vec[i].len); vec[i].data = (void *)virt_to_phys(vec[i].data); } sync_after_write(vec, (in_count + out_count) * sizeof *vec); ipc.cmd = 7; ipc.fd = fd; ipc.arg[0] = n; ipc.arg[1] = in_count; ipc.arg[2] = out_count; ipc.arg[3] = virt_to_phys(vec); ipc_send_request(); ipc_recv_reply(); for (i = in_count; i < in_count + out_count; i++) if (vec[i].data) { vec[i].data = phys_to_virt((u32)vec[i].data); sync_before_read(vec[i].data, vec[i].len); } return ipc.result; } // Cleanup any old state. static void ipc_cleanup_reply(void) { if ((ipc_read(1) & 0x14) != 0x14) return; ipc_read(2); ipc_bell(4); ipc_irq_ack(); ipc_bell(8); } static void ipc_cleanup_request(void) { if ((ipc_read(1) & 0x22) == 0x22) ipc_bell(2); } static void releasse_old_stm_callback(void) { *((u32 *)0x80000018) = 0x00000014; sync_after_write((void*)0x80000014, 8); int fd = ios_open("/dev/stm/immediate",0); if (fd < 0) { printf("STM Immediate open failed!\n"); return; } int err = ios_ioctl(fd, 0x3002, 0, 0, 0, 0); if (err < 0 && err != -6) printf("Eventhook release failed with code %d\n", err); ios_close(fd); } void reset_ios(void) { int i; //printf("Flushing IPC transactions"); for (i = 0; i < 10; i++) { ipc_cleanup_request(); ipc_cleanup_reply(); ipc_irq_ack(); udelay(1000); //printf("."); } //printf(" Done.\n"); //printf("Closing file descriptors..."); for (i = 0; i < 32; i++) ios_close(i); //printf(" Done.\n"); releasse_old_stm_callback(); } console.c
Copyright 2009 Segher Boessenkool <segher@kernel.crashing.org> // This code is licensed to you under the terms of the GNU GPL, version 2; // see file COPYING or Registrati o effettua il Login per visualizzare il link!.#include <stdarg.h> #include "loader.h" static void put(char c) { fb_putc(c); usbgecko_console_putc(c); } // __umoddi3() and friends are very big, and more general than we need: // radix is always (very) small, so we can work by much bigger chunks // than single bits, always. static int extract_dig(u64 *x, u32 radix) { u32 hi = *x >> 32; u32 lo = *x; u32 mod = hi % radix; hi /= radix; u32 n = (mod << 16) | (lo >> 16); mod = n % radix; n /= radix; lo = (mod << 16) | (lo & 0xffff); mod = lo % radix; lo /= radix; lo |= (n << 16); *x = ((u64)hi << 32) | lo; return mod; } // This implements conversions %{0}{number}{l,ll}[%cdsux] only. // Field length is obeyed for numbers only. // Always returns 0. int printf(const char *restrict format, ...) { va_list ap; va_start(ap, format); while (*format) { if (*format != '%') { put(*format++); continue; } format++; int zero = 0; int prec = 0; if (*format == '0') { zero = 1; format++; } while (*format >= '0' && *format <= '9') prec = 10*prec + (*format++ - '0'); int ll = 0; while (*format == 'l') { ll++; format++; } int radix = 10; int is_signed = 1; switch (*format++) { case '%': put('%'); break; case 'c': put(va_arg(ap, int)); break; case 's': ; char *s = va_arg(ap, char *); while (*s) put(*s++); break; case 'x': radix = 16; case 'u': is_signed = 0; case 'd': ; u64 x; if (is_signed) { if (ll == 0) x = va_arg(ap, int); else if (ll == 1) x = va_arg(ap, long); else x = va_arg(ap, long long); } else { if (ll == 0) x = va_arg(ap, unsigned int); else if (ll == 1) x = va_arg(ap, unsigned long); else x = va_arg(ap, unsigned long long); } if (is_signed) { if ((long long)x < 0) x = -x; else is_signed = 0; } char hold[22]; char *hld = &hold[sizeof hold]; *--hld = 0; int len = 0; do { int dig = extract_dig(&x, radix); if (dig >= 10) dig += 'a' - 10; else dig += '0'; *--hld = dig; len++; } while (x); if (is_signed) *--hld = '-'; while (len < prec) { put(zero ? '0' : ' '); len++; } while (*hld) put(*hld++); } } va_end(ap); return 0; } FATE IL VOSTRO.....HACK
Ultima modifica di TURK 182 il 02/02/2011, 15:52, modificato 1 volta in totale.
|