fix for some tvs not displaying the first letter of each line
[svpe-wii.git] / tcploader / wii / main.c
blobcd5a192c791057f5ab9ce70e62099734f6b27850
1 /*-------------------------------------------------------------
3 tcploader -- a very small tcp elf loader for the wii
5 Copyright (C) 2008 Sven Peter
7 This software is provided 'as-is', without any express or implied
8 warranty. In no event will the authors be held liable for any
9 damages arising from the use of this software.
11 Permission is granted to anyone to use this software for any
12 purpose, including commercial applications, and to alter it and
13 redistribute it freely, subject to the following restrictions:
15 1.The origin of this software must not be misrepresented; you
16 must not claim that you wrote the original software. If you use
17 this software in a product, an acknowledgment in the product
18 documentation would be appreciated but is not required.
20 2.Altered source versions must be plainly marked as such, and
21 must not be misrepresented as being the original software.
23 3.This notice may not be removed or altered from any source
24 distribution.
26 -------------------------------------------------------------*/
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <ogcsys.h>
32 #include <gccore.h>
33 #include <ogc/ipc.h>
34 #include <network.h>
36 #define READ_SIZE (1 << 10)
38 #include "asm.h"
39 #include "processor.h"
40 #include "elf.h"
41 #include "dol.h"
44 static void *xfb = NULL;
45 static GXRModeObj *rmode = NULL;
47 u8 *data = (u8 *)0x92000000;
49 static inline u32 wait_for(u32 btn)
51 u32 btns;
52 while(1)
54 PAD_ScanPads();
55 btns = PAD_ButtonsHeld(0);
56 if(btns & btn)
57 return btns;
58 VIDEO_WaitVSync();
63 extern s32 __STM_Init();
64 extern void __exception_closeall();
65 extern s32 __IOS_ShutdownSubsystems();
67 /* code to establish a socket; originally from bzs@bu-cs.bu.edu
70 int establish(unsigned short portnum) {
71 int s;
72 struct sockaddr_in sa;
74 memset(&sa, 0, sizeof(struct sockaddr_in)); /* clear our address */
75 sa.sin_family= AF_INET; /* this is our host address */
76 sa.sin_port= htons(portnum); /* this is our port number */
77 sa.sin_addr.s_addr = net_gethostip();
78 sa.sin_len = 8;
79 if ((s= net_socket(AF_INET, SOCK_STREAM, 0)) < 0) /* create socket */
80 return(-1);
81 if (net_bind(s,(struct sockaddr *)&sa,8) < 0) {
82 net_close(s);
83 return(-1); /* bind address to socket */
85 net_listen(s, 3); /* max # of queued connects */
86 return(s);
89 // wait for a connection to occur on a socket created with establish()
91 int get_connection(int s, struct sockaddr_in *sa)
93 int t; /* socket of connection */
94 // struct sockaddr_in sa;
95 sa->sin_len = 8;
96 sa->sin_family = AF_INET;
97 u32 buflen = 8;
98 t = net_accept(s,(struct sockaddr *)sa, &buflen);
99 printf(" Incoming connection from %d.%d.%d.%d\n",
100 (sa->sin_addr.s_addr >> 24) & 0xFF,
101 (sa->sin_addr.s_addr >> 16) & 0xFF,
102 (sa->sin_addr.s_addr >> 8) & 0xFF,
103 (sa->sin_addr.s_addr) & 0xFF);
105 return t;
108 int read_data(int s, /* connected socket */
109 char *buf, /* pointer to the buffer */
110 int n /* number of characters (bytes) we want */
112 { int bcount; /* counts bytes read */
113 int br; /* bytes read this pass */
115 bcount= 0;
116 br= 0;
117 while (bcount < n) { /* loop until full buffer */
118 if ((br= net_read(s,buf,n-bcount)) > 0) {
119 bcount += br; /* increment byte counter */
120 buf += br; /* move buffer ptr for next read */
122 else if (br < 0) /* signal an error to the caller */
123 return br;
125 // debug_printf("read_data(%d, %p, %d): \n", s, buf, n);
126 // printf("read_data(%d, %p, %d): %d\n", s, buf, n, bcount);
127 return bcount;
130 int write_data(int s, char *buf, int n)
132 int bcount;
133 int br;
134 bcount = 0;
135 br = 0;
136 while(bcount < n) {
137 if ((br = net_write(s,buf,n-bcount)) > 0) {
138 bcount += br;
139 buf += br;
141 else if (br < 0)
142 return br;
144 // debug_printf("write_data(%d, %p, %d): \n", s, buf, n);
145 // hexdump(buf, bcount);
146 return (bcount);
149 int main(int argc, char **argv)
151 unsigned long level;
152 u32 res, offset, read, size, ip, client, btn;
153 u8 *oct = (u8 *)&ip;
154 u8 *bfr[READ_SIZE];
155 struct sockaddr_in addr;
156 void (*ep)();
158 VIDEO_Init();
159 PAD_Init();
161 switch(VIDEO_GetCurrentTvMode())
163 case VI_PAL:
164 rmode = &TVPal528IntDf;
165 break;
166 case VI_MPAL:
167 rmode = &TVMpal480IntDf;
168 break;
169 case VI_EURGB60:
170 rmode = &TVNtsc480Prog;
171 break;
172 default:
173 case VI_NTSC:
174 rmode = &TVNtsc480IntDf;
175 break;
178 xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
179 console_init(xfb, 20, 20, rmode->fbWidth, rmode->xfbHeight, rmode->fbWidth * VI_DISPLAY_PIX_SZ);
181 VIDEO_Configure(rmode);
182 VIDEO_SetBlack(FALSE);
183 VIDEO_SetNextFramebuffer(xfb);
184 VIDEO_Flush();
185 VIDEO_WaitVSync();
186 if(rmode->viTVMode & VI_NON_INTERLACE)
187 VIDEO_WaitVSync();
189 __STM_Init();
191 printf("\n\n TCP ELF Loader\n");
192 printf(" (c) 2008 Sven Peter\n");
193 printf(" Based on bushing's title_listener.c and his networking code.\n");
194 printf(" (c) 2008 bushing\n\n");
196 redo:
197 printf(" Press A to continue.\n");
198 wait_for(PAD_BUTTON_A);
200 printf(" net_init(), please wait...\n");
201 net_init();
204 printf(" Opening socket on port 8080\n");
205 s32 listen = establish(8080);
207 if(listen < 0)
209 printf(" establish() returned < 0.\n");
210 goto redo;
213 ip = net_gethostip();
214 printf(" fd = %d\n", listen);
215 printf(" You Wii's ip address is %d.%d.%d.%d\n", oct[0], oct[1], oct[2], oct[3]);
217 while(1)
219 printf(" Waiting for connection\n");
220 client = get_connection(listen, &addr);
222 if(client > 0)
224 printf(" client connected..\n");
225 printf(" Please check the IP address and press A to continue and Z to abort\n");
226 btn = wait_for(PAD_BUTTON_A | PAD_TRIGGER_Z);
227 if(btn & PAD_TRIGGER_Z)
229 net_close(client);
230 continue;
233 if(((addr.sin_addr.s_addr >> 24) & 0xFF) != oct[0] || ((addr.sin_addr.s_addr >> 16) & 0xFF) != oct[1])
235 printf(" WARNING: the client is not connecting from your local network.\n");
236 printf(" Please check if you really want to run a file from this IP as it\n");
237 printf(" may be something that bricks your wii from someone you don't even know!!\n");
238 printf(" Press Z if you really want to continue!\n");
239 printf(" Press A to deny the connection and wait for a new client\n");
240 btn = wait_for(PAD_TRIGGER_Z | PAD_BUTTON_A);
241 if(btn & PAD_BUTTON_A)
243 net_close(client);
244 continue;
248 if(read_data(client, (char *)&size, 4) < 0)
250 printf(" read_data() error while reading filesize\n");
251 net_close(client);
252 net_close(listen);
253 goto redo;
256 printf(" size: %d\n", size);
257 printf(" reading data, please wait...\n");
259 offset = 0;
260 while(offset < size && (read = read_data(client, (char *)bfr, (size - offset) > READ_SIZE ? READ_SIZE : (size - offset))) > 0)
262 memcpy(data + offset, bfr, READ_SIZE);
263 offset += read;
265 net_close(client);
266 net_close(listen);
268 res = valid_elf_image(data);
269 if(res != 1)
271 printf(" Invalid ELF image.\n");
272 printf(" assuming DOL image. your wii will crash if this is just some random file...\n");
273 ep = (void(*)())load_dol_image(data, 1);
275 else
277 printf(" Loading ELF image...\n");
278 ep = (void(*)())load_elf_image(data);
280 printf(" entry point: 0x%08X\n", (unsigned int)ep);
281 printf(" shutting down...\n");
282 __IOS_ShutdownSubsystems();
283 _CPU_ISR_Disable(level);
284 __exception_closeall();
285 printf(" jumping to entry point now...\n\n\n\n");
286 ep();
287 _CPU_ISR_Restore(level);
288 printf(" this should not happen :/\n\n");
289 goto redo;
293 // never reached but fixes a gcc warning
294 return 0;