├── LICENSE ├── Makefile ├── README.md ├── gfx └── img_keyboard.png └── source └── main.c /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 "Sanqui" 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | #--------------------------------------------------------------------------------- 2 | .SUFFIXES: 3 | #--------------------------------------------------------------------------------- 4 | 5 | ifeq ($(strip $(DEVKITARM)),) 6 | $(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") 7 | endif 8 | 9 | TOPDIR ?= $(CURDIR) 10 | include $(DEVKITARM)/3ds_rules 11 | 12 | #--------------------------------------------------------------------------------- 13 | # TARGET is the name of the output 14 | # BUILD is the directory where object files & intermediate files will be placed 15 | # SOURCES is a list of directories containing source code 16 | # DATA is a list of directories containing data files 17 | # INCLUDES is a list of directories containing header files 18 | # 19 | # NO_SMDH: if set to anything, no SMDH file is generated. 20 | # APP_TITLE is the name of the app stored in the SMDH file (Optional) 21 | # APP_DESCRIPTION is the description of the app stored in the SMDH file (Optional) 22 | # APP_AUTHOR is the author of the app stored in the SMDH file (Optional) 23 | # ICON is the filename of the icon (.png), relative to the project folder. 24 | # If not set, it attempts to use one of the following (in this order): 25 | # - .png 26 | # - icon.png 27 | # - /default_icon.png 28 | #--------------------------------------------------------------------------------- 29 | TARGET := $(notdir $(CURDIR)) 30 | BUILD := build 31 | SOURCES := source 32 | DATA := data 33 | INCLUDES := include 34 | GRAPHICS := gfx 35 | 36 | #--------------------------------------------------------------------------------- 37 | # options for code generation 38 | #--------------------------------------------------------------------------------- 39 | ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard 40 | 41 | CFLAGS := -g -Wall -O2 -mword-relocations \ 42 | -fomit-frame-pointer -ffast-math -Wimplicit-function-declaration \ 43 | $(ARCH) 44 | 45 | CFLAGS += $(INCLUDE) -DARM11 -D_3DS 46 | 47 | CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11 48 | 49 | ASFLAGS := -g $(ARCH) 50 | LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) 51 | 52 | LIBS := -lctru -lm 53 | 54 | #--------------------------------------------------------------------------------- 55 | # list of directories containing libraries, this must be the top level containing 56 | # include and lib 57 | #--------------------------------------------------------------------------------- 58 | LIBDIRS := $(CTRULIB) 59 | 60 | #--------------------------------------------------------------------------------- 61 | # no real need to edit anything past this point unless you need to add additional 62 | # rules for different file extensions 63 | #--------------------------------------------------------------------------------- 64 | ifneq ($(BUILD),$(notdir $(CURDIR))) 65 | #--------------------------------------------------------------------------------- 66 | 67 | export OUTPUT := $(CURDIR)/$(TARGET) 68 | export TOPDIR := $(CURDIR) 69 | 70 | export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ 71 | $(foreach dir,$(DATA),$(CURDIR)/$(dir)) \ 72 | $(foreach dir,$(GRAPHICS),$(CURDIR)/$(dir)) 73 | 74 | export DEPSDIR := $(CURDIR)/$(BUILD) 75 | 76 | CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) 77 | CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) 78 | SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) 79 | BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) 80 | PNGFILES := $(foreach dir,$(GRAPHICS),$(notdir $(wildcard $(dir)/*.png))) 81 | 82 | #--------------------------------------------------------------------------------- 83 | # use CXX for linking C++ projects, CC for standard C 84 | #--------------------------------------------------------------------------------- 85 | ifeq ($(strip $(CPPFILES)),) 86 | #--------------------------------------------------------------------------------- 87 | export LD := $(CC) 88 | #--------------------------------------------------------------------------------- 89 | else 90 | #--------------------------------------------------------------------------------- 91 | export LD := $(CXX) 92 | #--------------------------------------------------------------------------------- 93 | endif 94 | #--------------------------------------------------------------------------------- 95 | 96 | export OFILES := $(addsuffix .o,$(BINFILES)) \ 97 | $(PNGFILES:.png=.bgr.o) \ 98 | $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) 99 | 100 | export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ 101 | $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ 102 | -I$(CURDIR)/$(BUILD) 103 | 104 | export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) 105 | 106 | ifeq ($(strip $(ICON)),) 107 | icons := $(wildcard *.png) 108 | ifneq (,$(findstring $(TARGET).png,$(icons))) 109 | export APP_ICON := $(TOPDIR)/$(TARGET).png 110 | else 111 | ifneq (,$(findstring icon.png,$(icons))) 112 | export APP_ICON := $(TOPDIR)/icon.png 113 | endif 114 | endif 115 | else 116 | export APP_ICON := $(TOPDIR)/$(ICON) 117 | endif 118 | 119 | IMAGEMAGICK := $(shell which convert) 120 | 121 | ifeq ($(strip $(NO_SMDH)),) 122 | export _3DSXFLAGS += --smdh=$(CURDIR)/$(TARGET).smdh 123 | endif 124 | 125 | .PHONY: $(BUILD) clean all 126 | 127 | #--------------------------------------------------------------------------------- 128 | all: $(BUILD) 129 | 130 | $(BUILD): 131 | @[ -d $@ ] || mkdir -p $@ 132 | @make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile 133 | 134 | #--------------------------------------------------------------------------------- 135 | clean: 136 | @echo clean ... 137 | @rm -fr $(BUILD) $(TARGET).3dsx $(OUTPUT).smdh $(TARGET).elf 138 | 139 | 140 | #--------------------------------------------------------------------------------- 141 | else 142 | 143 | DEPENDS := $(OFILES:.o=.d) 144 | 145 | #--------------------------------------------------------------------------------- 146 | # main targets 147 | #--------------------------------------------------------------------------------- 148 | ifeq ($(strip $(NO_SMDH)),) 149 | $(OUTPUT).3dsx : $(OUTPUT).elf $(OUTPUT).smdh 150 | else 151 | $(OUTPUT).3dsx : $(OUTPUT).elf 152 | endif 153 | $(OUTPUT).elf : $(OFILES) 154 | 155 | #--------------------------------------------------------------------------------- 156 | # you need a rule like this for each extension you use as binary data 157 | #--------------------------------------------------------------------------------- 158 | %.bin.o : %.bin 159 | #--------------------------------------------------------------------------------- 160 | @echo $(notdir $<) 161 | @$(bin2o) 162 | 163 | 164 | 165 | #--------------------------------------------------------------------------------- 166 | %.bgr.o: %.bgr 167 | #--------------------------------------------------------------------------------- 168 | @echo $(notdir $<) 169 | @$(bin2o) 170 | 171 | #--------------------------------------------------------------------------------- 172 | %.bgr: %.png 173 | #--------------------------------------------------------------------------------- 174 | @echo $(notdir $<) 175 | @convert $< -rotate 90 $@ 176 | 177 | 178 | 179 | # WARNING: This is not the right way to do this! TODO: Do it right! 180 | #--------------------------------------------------------------------------------- 181 | %.vsh.o : %.vsh 182 | #--------------------------------------------------------------------------------- 183 | @echo $(notdir $<) 184 | @python $(AEMSTRO)/aemstro_as.py $< ../$(notdir $<).shbin 185 | @bin2s ../$(notdir $<).shbin | $(PREFIX)as -o $@ 186 | @echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > `(echo $(notdir $<).shbin | tr . _)`.h 187 | @echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> `(echo $(notdir $<).shbin | tr . _)`.h 188 | @echo "extern const u32" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> `(echo $(notdir $<).shbin | tr . _)`.h 189 | @rm ../$(notdir $<).shbin 190 | 191 | -include $(DEPENDS) 192 | 193 | #--------------------------------------------------------------------------------------- 194 | endif 195 | #--------------------------------------------------------------------------------------- 196 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This is an extremely early 3DS IRC client. It can only join one channel 2 | on one server and has no commands. But some people wanted it already, so 3 | here it is. Enjoy! 4 | 5 | ![Crappy screenshot](https://i.imgur.com/Xk3w2dC.png) 6 | 7 | Binary download (may not be the latest release): http://sanqui.rustedlogic.net/etc/irctr.3dsx 8 | -------------------------------------------------------------------------------- /gfx/img_keyboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sanqui/irctr/100f374c922456d6cd1e2326d00231136839a0a4/gfx/img_keyboard.png -------------------------------------------------------------------------------- /source/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | hi 3 | */ 4 | 5 | const char* DEFAULT_SERVER = "irc."; 6 | const char* DEFAULT_NICK = "irctr"; 7 | 8 | #define SOC_ALIGN 0x1000 9 | #define SOC_BUFFERSIZE 0x100000 10 | 11 | #define STATE_ASK_SERVER 0 12 | #define STATE_GET_SERVER 1 13 | #define STATE_ASK_NICK 2 14 | #define STATE_GET_NICK 3 15 | #define STATE_CONNECT 4 16 | #define STATE_ASK_CHANNEL 5 17 | #define STATE_GET_CHANNEL 6 18 | #define STATE_ASK_MSG 7 19 | #define STATE_GET_MSG 8 20 | 21 | #include <3ds.h> 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | #include "img_keyboard_bgr.h" 37 | 38 | PrintConsole window_log, window_input; 39 | 40 | int KEY_WIDTH = 25; 41 | int KEY_HEIGHT = 22; 42 | int KBD_OFF_TOP = 128; 43 | int KBD_OFF_LEFT = 3; 44 | int KBD_FIRST_EXTRA[] = {0, 4, 10, 14, 0}; 45 | char* KBD_CHARS[] = {"1234567890-\b\b", 46 | "qwertyuiop\n\n\n", 47 | "asdfghjkl'=//", 48 | "zxcvbnm,.?!@"}; 49 | char* KBD_SHIFT[] = {"1234567890_\b\b", 50 | "QWERTYUIOP\n\n\n", 51 | "ASDFGHJKL\"*\\\\", 52 | "ZXCVBNM<>:;#"}; 53 | 54 | 55 | 56 | u32 key_down; 57 | u32 key_held; 58 | u32 key_up; 59 | touchPosition touch; 60 | touchPosition last_touch; 61 | 62 | static void *SOC_buffer = NULL; 63 | 64 | void get_input() { 65 | hidScanInput(); 66 | 67 | key_down = hidKeysDown(); 68 | key_held = hidKeysHeld(); 69 | key_up = hidKeysUp(); 70 | last_touch = touch; 71 | hidTouchRead(&touch); 72 | } 73 | 74 | int sockfd; 75 | 76 | char ds_username[256] = {}; 77 | 78 | char server_address[256] = {}; 79 | char nick[256] = {}; 80 | char channel[256] = {}; 81 | char message[256] = {}; 82 | 83 | 84 | int kbd_pos = 0; 85 | bool kbd_done = false; 86 | char kbd_input[256] = {}; 87 | char kbd_query[256] = {}; 88 | bool kbd_shift = false; 89 | 90 | void kbd_setup(char* query) { 91 | consoleSelect(&window_input); 92 | consoleClear(); 93 | kbd_done = false; 94 | kbd_pos = 0; 95 | memset(kbd_input, 0, sizeof(kbd_input)); 96 | strcpy(kbd_query, query); 97 | kbd_shift = false; 98 | } 99 | 100 | void do_kbd() { 101 | if (kbd_done) { 102 | consoleSelect(&window_input); 103 | consoleClear(); 104 | return; 105 | } 106 | if (key_up & KEY_TOUCH) { 107 | char key = '\0'; 108 | if (last_touch.py >= KBD_OFF_TOP) { 109 | int row = (last_touch.py - KBD_OFF_TOP) / KEY_HEIGHT; 110 | int col = (last_touch.px - KBD_OFF_LEFT - KBD_FIRST_EXTRA[row]) / KEY_WIDTH; 111 | if (row == 4 && col >= 4) { 112 | key = ' '; 113 | } else if (row == 4) { 114 | kbd_shift = true; 115 | } 116 | else { 117 | if (kbd_shift) 118 | key = KBD_SHIFT[row][col]; 119 | else 120 | key = KBD_CHARS[row][col]; 121 | kbd_shift = false; 122 | } 123 | } 124 | if (key != '\0') { 125 | if (key == '\n') kbd_done = true; 126 | else if (key == '\b') { 127 | if (kbd_pos > 0) { 128 | kbd_pos-=1; 129 | kbd_input[kbd_pos] = '\0'; 130 | } 131 | } else { 132 | if (kbd_pos < 255) { 133 | kbd_input[kbd_pos] = key; 134 | kbd_pos++; 135 | } 136 | } 137 | } 138 | } 139 | consoleSelect(&window_input); 140 | if (kbd_done) { 141 | consoleClear(); 142 | return; 143 | } 144 | printf("\x1b[0;0H%s %s ", kbd_query, kbd_input); 145 | } 146 | 147 | void parse_irc(char* str) { 148 | consoleSelect(&window_log); 149 | char out[1024] = {}; 150 | 151 | //strtok(str, ":"); 152 | if (strstr(str, "PING") == str) { 153 | sprintf(out, "PONG %s\n", str+5); 154 | send(sockfd, out, strlen(out), 0); 155 | return; 156 | } 157 | str++; 158 | char* source = strtok(str, " "); 159 | 160 | if(strstr(source, "!")) { 161 | strstr(source, "!")[0] = '\0'; 162 | } 163 | 164 | char* command = strtok(NULL, " "); 165 | if (!strcmp(command, "PRIVMSG")) { 166 | char* target = strtok(NULL, " "); 167 | char* rest = strtok(NULL, "\r"); 168 | if (!strcmp(target+1, channel)) { 169 | printf("\x1b[1m<%s> %s\x1b[0m\n", source, rest+1); 170 | } else { 171 | printf("\x1b[1m[->%s] <%s> %s\x1b[0m\n", target, source, rest+1); 172 | } 173 | } else if (!strcmp(command, "JOIN")) { 174 | char* rest = strtok(NULL, "\r"); 175 | printf("\x1b[32m > %s has joined %s\x1b[0m\n", source, rest+1); 176 | } else if (!strcmp(command, "QUIT")) { 177 | printf("\x1b[31m x %s has quit\x1b[0m\n", source); 178 | } else if (!strcmp(command, "PART")) { 179 | char* rest = strtok(NULL, "\r"); 180 | printf("\x1b[31m < %s has parted %s\x1b[0m\n", source, rest+1); 181 | } else { 182 | char* rest = strtok(NULL, "\r"); 183 | printf(" * %s %s %s\n", source, command, rest); 184 | } 185 | } 186 | 187 | 188 | int main(int argc, char **argv) 189 | { 190 | int state, ret; 191 | cfguInit(); 192 | //uint16_t tmp = CFGU_GetConfigInfoBlk2(0x1C, 0xA0000, ds_username); 193 | //utf16_to_utf8((uint8_t *)ds_username, &tmp, 16); 194 | gfxInitDefault(); 195 | 196 | consoleInit(GFX_TOP, &window_log); 197 | consoleInit(GFX_TOP, &window_input); 198 | // 3ds is 50x30 199 | consoleSetWindow(&window_log, 0, 0, 50, 28); 200 | consoleSetWindow(&window_input, 0, 29, 50, 1); 201 | 202 | //consoleClear(); 203 | consoleSelect(&window_log); 204 | printf("\x1b[0;0H * irctr v0.1 * \n\n"); 205 | 206 | SOC_buffer = (void*) memalign(0x1000, 0x100000); 207 | if(SOC_buffer == NULL) 208 | return -1; 209 | 210 | 211 | if ((ret = socInit(SOC_buffer, SOC_BUFFERSIZE)) != 0) { 212 | // need to free the shared memory block if something goes wrong 213 | socExit(); 214 | free(SOC_buffer); 215 | SOC_buffer = NULL; 216 | return -1; 217 | } 218 | 219 | int n = 0; 220 | char recv[8192]; 221 | char out[1024] = {}; 222 | struct sockaddr_in serv_addr; 223 | memset(recv, 0, sizeof(recv)); 224 | memset(&serv_addr, 0, sizeof(serv_addr)); 225 | 226 | 227 | gfxSetDoubleBuffering(GFX_BOTTOM, false); 228 | u8* fb = gfxGetFramebuffer(GFX_BOTTOM, GFX_LEFT, NULL, NULL); 229 | memcpy(fb, img_keyboard_bgr, img_keyboard_bgr_size); 230 | 231 | state = STATE_ASK_SERVER; 232 | bool connected = false; 233 | 234 | // Main loop 235 | while (aptMainLoop()) 236 | { 237 | if (connected) { 238 | memset(recv, 0, sizeof(recv)); 239 | n = read(sockfd, recv, 8192); 240 | if (n < 0 && errno == EAGAIN) { 241 | 242 | } else { 243 | //parse_irc(recv); 244 | char* lines = recv; 245 | consoleSelect(&window_log); 246 | //printf("Recv: %s", command); 247 | while (true) { 248 | char* line = lines; 249 | lines = strpbrk(lines, "\n"); 250 | line[strcspn(line, "\n")] = '\0'; 251 | if (line[0] == '\0') break; 252 | //printf("### Parsing: %s\n", line); 253 | parse_irc(line); 254 | if (!lines) break; 255 | lines++; 256 | } 257 | //printf(recv); 258 | } 259 | } 260 | 261 | get_input(); 262 | if (key_down & KEY_START) break; 263 | 264 | do_kbd(); 265 | 266 | if (state == STATE_ASK_SERVER) { 267 | kbd_setup("Server address:"); 268 | state = STATE_GET_SERVER; 269 | strcpy(kbd_input, DEFAULT_SERVER); 270 | kbd_pos = strlen(kbd_input); 271 | } else if (state == STATE_GET_SERVER) { 272 | if (kbd_done) { 273 | strcpy(server_address, kbd_input); 274 | consoleSelect(&window_log); 275 | printf("Server address: %s\n", server_address); 276 | if (!gethostbyname(server_address)) { 277 | printf("Resolving address failed\n"); 278 | state = STATE_ASK_SERVER; 279 | } else { 280 | state = STATE_ASK_NICK; 281 | } 282 | } 283 | } else if (state == STATE_ASK_NICK) { 284 | kbd_setup("Nick:"); 285 | strcpy(kbd_input, DEFAULT_NICK); 286 | kbd_pos = strlen(kbd_input); 287 | state = STATE_GET_NICK; 288 | } else if (state == STATE_GET_NICK) { 289 | if (kbd_done) { 290 | strcpy(nick, kbd_input); 291 | consoleSelect(&window_log); 292 | printf("Nick: %s\n", nick); 293 | state = STATE_CONNECT; 294 | } 295 | } else if (state == STATE_CONNECT) { 296 | consoleSelect(&window_log); 297 | 298 | sockfd = socket(AF_INET, SOCK_STREAM, 0); 299 | if (sockfd < 0) { 300 | printf("socket() failed: %d\n", errno); 301 | state = STATE_ASK_SERVER; 302 | continue; 303 | } 304 | 305 | serv_addr.sin_family = AF_INET; 306 | serv_addr.sin_port = htons(6667); 307 | struct hostent* host_info; 308 | host_info = gethostbyname(server_address); 309 | if (!host_info) { 310 | printf("gethostbyname() failed\n"); 311 | state = STATE_ASK_SERVER; 312 | continue; 313 | } 314 | memcpy(&serv_addr.sin_addr, host_info->h_addr_list[0], host_info->h_length); 315 | 316 | int result = connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)); 317 | if(result < 0) { 318 | printf("connect() failed: %d\n", errno); 319 | state = STATE_ASK_SERVER; 320 | continue; 321 | } 322 | 323 | printf("connected\n"); 324 | 325 | sprintf(out, "NICK %s\r\n", nick); 326 | send(sockfd, out, strlen(out), 0); 327 | sprintf(out, "USER %s irctr irctr :irctr\r\n", nick); 328 | send(sockfd, out, strlen(out), 0); 329 | 330 | printf("sent NICK and USER\n"); 331 | connected = true; 332 | result = fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL, 0) | O_NONBLOCK); 333 | if (result < 0) { 334 | printf("fcntl failed: %d?", errno); 335 | } 336 | 337 | state = STATE_ASK_CHANNEL; 338 | printf("------------------\n"); 339 | } else if (state == STATE_ASK_CHANNEL) { 340 | kbd_setup("Join channel: #"); 341 | state = STATE_GET_CHANNEL; 342 | } else if (state == STATE_GET_CHANNEL) { 343 | if (kbd_done) { 344 | strcpy(channel, kbd_input); 345 | 346 | sprintf(out, "JOIN #%s\r\n", channel); 347 | send(sockfd, out, strlen(out), 0); 348 | 349 | state = STATE_ASK_MSG; 350 | } 351 | } else if (state == STATE_ASK_MSG) { 352 | char tmp[512]; 353 | sprintf(tmp, "[#%s] <%s>", channel, nick); 354 | kbd_setup(tmp); 355 | state = STATE_GET_MSG; 356 | } else if (state == STATE_GET_MSG) { 357 | if (key_down & KEY_B) { 358 | sprintf(out, "PART #%s\r\n", channel); 359 | send(sockfd, out, strlen(out), 0); 360 | consoleSelect(&window_log); 361 | printf(" < Parted #%s\n", channel); 362 | state = STATE_ASK_CHANNEL; 363 | } 364 | if (kbd_done) { 365 | strcpy(message, kbd_input); 366 | 367 | sprintf(out, "PRIVMSG #%s :%s\r\n", channel, message); 368 | send(sockfd, out, strlen(out), 0); 369 | consoleSelect(&window_log); 370 | printf("<%s> %s\n", nick, message); 371 | 372 | state = STATE_ASK_MSG; 373 | } 374 | } 375 | 376 | 377 | gfxFlushBuffers(); 378 | gfxSwapBuffers(); 379 | 380 | gspWaitForVBlank(); 381 | } 382 | 383 | //char* outquit = "QUIT :start pressed\r\n"; 384 | //send(sockfd, outquit, strlen(outquit), 0); 385 | 386 | // Exit services 387 | gfxExit(); 388 | cfguExit(); 389 | 390 | ret = socExit(); 391 | if(ret != 0) 392 | return -1; 393 | return 0; 394 | } 395 | --------------------------------------------------------------------------------