void task_sleep(TASK* task) { if (task->flags != RUNNING) return; // TODO: Need to prevent interrupt? TASK* now_task = task_now(); task_remove(task); // This makes the task ALLOCATED (sleep). if (task == now_task) { // Sleep by self => need task switch. task_switchsub(); now_task = task_now(); farjmp(0, now_task->sel); } }
void task_sleep(task_t* task) { task_t* now_task; if (task->flags == 2) { /* 活动中 */ now_task = task_now(); task_remove(task); /* flags变1 */ if (task == now_task) { /* 如果是让自己休眠,则需要切换任务 */ task_switchsub(); now_task = task_now(); /* 设置后获取当前任务值 */ farjmp(0, now_task->sel); } } }
void task_sleep(struct TASK *task) { struct TASK *now_task; if (task->flags == 2) { // if specified task is waken now_task = task_now(); task_remove (task); if (task == now_task) { task_switchsub (); now_task = task_now (); farjmp (0, now_task->sel); } } return; }
void cons_newline(struct CONSOLE *cons) { int x, y; struct SHEET *sheet = cons->sht; struct TASK *task = task_now(); if (cons->cur_y < 28 + 112) { cons->cur_y += 16; /* 次の行へ */ } else { /* スクロール */ if (sheet != 0) { for (y = 28; y < 28 + 112; y++) { for (x = 8; x < 8 + 240; x++) { sheet->buf[x + y * sheet->bxsize] = sheet->buf[x + (y + 16) * sheet->bxsize]; } } for (y = 28 + 112; y < 28 + 128; y++) { for (x = 8; x < 8 + 240; x++) { sheet->buf[x + y * sheet->bxsize] = COL8_000000; } } sheet_refresh(sheet, 8, 28, 8 + 240, 28 + 128); } } cons->cur_x = 8; if (task->langmode == 1 && task->langbyte1 != 0) { cons->cur_x = 16; } return; }
void task_sleep(struct TASK *task) { struct TASK *now_task; if (task->flags == 2) { /* 動作中だったら */ now_task = task_now(); task_remove(task); /* これを実行するとflagsは1になる */ if (task == now_task) { /* 自分自身のスリープだったので、タスクスイッチが必要 */ task_switchsub(); now_task = task_now(); /* 設定後での、「現在のタスク」を教えてもらう */ farjmp(0, now_task->sel); } } return; }
void task_sleep(task_t* task) { task_t* now_task; if (2 == task->flags) { /* the task in the wake state */ now_task = task_now(); task_del(task); if (task == now_task) { /* if task sleep, then need to switch task */ task_switch_sub(); now_task = task_now(); farjump(0, now_task->sel); } } }
/* 使某任务睡眠 */ void task_sleep(struct TASK *task) { struct TASK *now_task; if (task->flags == 2) { /* 如果处于活动状态 */ now_task = task_now(); /* 获得当前正在运行的任务的task指针 */ task_remove(task); /* 执行词语句的话flag会等于1 */ if (task == now_task) { /* 如果是让自己休眠 则需要任务切换 */ task_switchsub(); now_task = task_now(); /* 在设定后获取新的level中待运行的任务 */ farjmp(0, now_task->sel); /* 切换任务 */ } } return; }
//当程序想要非法访问操作系统的内容的时候,会产生这个中断 int *inthandler0d(int *esp) { CONSOLE *console = (CONSOLE *) *((int *) 0x0fec); TASK *task = task_now(); console_putstring_toend(console, "\nINT0D : \nGeneral Protected Exception!\n"); return &(task->tss.esp0); //让程序在这里强制结束 }
//处理栈异常的中断处理函数 int *inthandler0c(int *esp) { CONSOLE *console = (CONSOLE *) *((int *) 0x0fec); TASK *task = task_now(); console_putstring_toend(console, "\nINT0C : \nStack Exception!\n"); return &(task->tss.esp0); //让程序在这里强制结束 }
void console_task(struct SHEET *sheet) { struct TIMER *timer; struct TASK *task = task_now(); int i, fifobuf[128], cursor_x = 16, cursor_c = COL8_000000; char s[2]; fifo32_init(&task->fifo, 128, fifobuf, task); timer = timer_alloc(); timer_init(timer, &task->fifo, 1); timer_settime(timer, 50); /* 显示提示符 */ putfonts8_asc_sht(sheet, 8, 28, COL8_FFFFFF, COL8_000000, ">", 1); for (;;) { io_cli(); if (fifo32_status(&task->fifo) == 0) { task_sleep(task); io_sti(); } else { i = fifo32_get(&task->fifo); io_sti(); if (i <= 1) { /* 光标用定时器 */ if (i != 0) { timer_init(timer, &task->fifo, 0); /* 下次置0 */ cursor_c = COL8_FFFFFF; } else { timer_init(timer, &task->fifo, 1); /* 下次置1 */ cursor_c = COL8_000000; } timer_settime(timer, 50); } if (256 <= i && i <= 511) { /* 键盘数据(通过任务A) */ if (i == 8 + 256) { /* 退格键 */ if (cursor_x > 16) { /* 用空白擦除光标后将光标前移一位 */ putfonts8_asc_sht(sheet, cursor_x, 28, COL8_FFFFFF, COL8_000000, " ", 1); cursor_x -= 8; } } else { /* 一般字符 */ if (cursor_x < 240) { /* 显示一个字符之后将光标后移一位 */ s[0] = i - 256; s[1] = 0; putfonts8_asc_sht(sheet, cursor_x, 28, COL8_FFFFFF, COL8_000000, s, 1); cursor_x += 8; } } } /* 重新显示光标 */ boxfill8(sheet->buf, sheet->bxsize, cursor_c, cursor_x, 28, cursor_x + 7, 43); sheet_refresh(sheet, cursor_x, 28, cursor_x + 8, 44); } } }
/* remove task from its level */ void task_sleep(struct TASK *task) { struct TASK *current_task; /* if the task is running then we remove it from running buffer and mark it as not running */ if(task->flags == 2) { current_task = task_now(); /*task->flags would become 1 */ task_remove(task); /* if a task is termination it self, need to explicitly jump to the new running task */ if(task == current_task) { task_switchsub(); current_task = task_now(); farjmp(0, current_task->sel); } } return; }
/** * @description 休眠任务 * @param task:欲休眠的任务 * @notice 休眠任务自己将会引起任务切换 */ void task_sleep(struct TASK *task){ struct TASK *now_task; //TODO 任务有效性检查 if (task->flags == 2) { now_task = task_now(); task_remove(task); if (task == now_task) { //TODO 当前任务,则立即休眠 task_switchsub(); //TODO 获得跳转的目标任务,以跳转 now_task = task_now(); farjmp(0, now_task->sel); } } return; }
//任务休眠 void task_sleep(TASK *task) { TASK *now_task; if (task->flags == RUNNING) { now_task = task_now(); task_remove(task); //执行这行代码之后只是把task从level中移除了,并且flags变成SLEEP状态,但是task本身并没有被释放 if (task == now_task) { /*如果是自己让自己休眠的情况还需要任务转换*/ level_switch(); now_task = task_now(); farjmp(0, now_task->selector); } } return; }
int cmd_app(struct CONSOLE *cons, int *fat, char *cmdline) { struct MEMMAN *memman = (struct MEMMAN *) MEMMAN_ADDR; struct FILEINFO *finfo; struct SEGMENT_DESCRIPTOR *gdt = (struct SEGMENT_DESCRIPTOR *) ADR_GDT; char name[13], *p, *q; struct TASK *task = task_now(); int i, segsiz, datsiz, esp, dathrb; /* コマンドラインからファイル名を生成 */ for (i = 0; i < 8; i++) { if (cmdline[i] <= ' ') { break; } name[i] = cmdline[i]; } name[i] = 0; /* とりあえずファイル名の後ろを0にする */ /* ファイルを探す */ finfo = file_search(name, (struct FILEINFO *) (ADR_DISKIMG + 0x002600), 224); if (finfo == 0) { /* 見つからなかったので後ろに".HRB"をつけてもう一度探してみる */ name[i ] = '.'; name[i + 1] = 'H'; name[i + 2] = 'R'; name[i + 3] = 'B'; name[i + 4] = 0; finfo = file_search(name, (struct FILEINFO *) (ADR_DISKIMG + 0x002600), 224); } if (finfo != 0) { /* ファイルが見つかった場合 */ p = (char *) memman_alloc_4k(memman, finfo->size); file_loadfile(finfo->clustno, finfo->size, p, fat, (char *) (ADR_DISKIMG + 0x003e00)); if (finfo->size >= 36 && strncmp(p + 4, "Hari", 4) == 0 && *p == 0x00) { segsiz = *((int *) (p + 0x0000)); esp = *((int *) (p + 0x000c)); datsiz = *((int *) (p + 0x0010)); dathrb = *((int *) (p + 0x0014)); q = (char *) memman_alloc_4k(memman, segsiz); *((int *) 0xfe8) = (int) q; set_segmdesc(gdt + 1003, finfo->size - 1, (int) p, AR_CODE32_ER + 0x60); set_segmdesc(gdt + 1004, segsiz - 1, (int) q, AR_DATA32_RW + 0x60); for (i = 0; i < datsiz; i++) { q[esp + i] = p[dathrb + i]; } start_app(0x1b, 1003 * 8, esp, 1004 * 8, &(task->tss.esp0)); memman_free_4k(memman, (int) q, segsiz); } else { cons_putstr0(cons, ".hrb file format error.\n"); } memman_free_4k(memman, (int) p, finfo->size); cons_newline(cons); return 1; } /* ファイルが見つからなかった場合 */ return 0; }
void console_task(struct SHEET *sheet) { struct TIMER *timer; struct TASK *task = task_now(); int i, fifobuf[128], cursor_x = 16, cursor_c = COL8_000000; char s[2]; fifo32_init(&task->fifo, 128, fifobuf, task); timer = timer_alloc(); timer_init(timer, &task->fifo, 1); timer_settime(timer, 50); /* プロンプト表示 */ putfonts8_asc_sht(sheet, 8, 28, COL8_FFFFFF, COL8_000000, ">", 1); for (;;) { io_cli(); if (fifo32_status(&task->fifo) == 0) { task_sleep(task); io_sti(); } else { i = fifo32_get(&task->fifo); io_sti(); if (i <= 1) { /* カーソル用タイマ */ if (i != 0) { timer_init(timer, &task->fifo, 0); /* 次は0を */ cursor_c = COL8_FFFFFF; } else { timer_init(timer, &task->fifo, 1); /* 次は1を */ cursor_c = COL8_000000; } timer_settime(timer, 50); } if (256 <= i && i <= 511) { /* キーボードデータ(タスクA経由) */ if (i == 8 + 256) { /* バックスペース */ if (cursor_x > 16) { /* カーソルをスペースで消してから、カーソルを1つ戻す */ putfonts8_asc_sht(sheet, cursor_x, 28, COL8_FFFFFF, COL8_000000, " ", 1); cursor_x -= 8; } } else { /* 一般文字 */ if (cursor_x < 240) { /* 一文字表示してから、カーソルを1つ進める */ s[0] = i - 256; s[1] = 0; putfonts8_asc_sht(sheet, cursor_x, 28, COL8_FFFFFF, COL8_000000, s, 1); cursor_x += 8; } } } /* カーソル再表示 */ boxfill8(sheet->buf, sheet->bxsize, cursor_c, cursor_x, 28, cursor_x + 7, 43); sheet_refresh(sheet, cursor_x, 28, cursor_x + 8, 44); } } }
////将该任务从可裕兴队列中移除,同时设置为参数指定的状态 //参数:task -- 需要操作的任务, task_status -- task被设成这个任务状态 static void _task_change_status(struct TASK *task, enum TASK_STATUS task_status) { struct TASK *now_task; if (task->flags == TASK_STATUS_RUNNING) { /* 如果处于活动状态 */ now_task = task_now(); task_remove(task, task_status); if (task == now_task) { /* 如果是让自己休眠,则需要进行任务切换 */ task_switchsub(); now_task = task_now(); /* 在设定后获取当前任务的值 */ //debug("process[%d,%s] go to sleep, process[%d,%s] is running",task->pid,task->name,now_task->pid,now_task->name); farjmp(0, now_task->sel); } } return; }
int *int_handler_0c(int *esp){ struct CONSOLE *cons = (struct CONSOLE *)*((int *)0x0fec); struct TASK *task = task_now(); char s[30]; sprintf(s,"\nEIP = 0x%08X", esp[11]); cons_puts(cons, s); cons_puts(cons,"\nInt 0x0C :\n\tStack Exception\n"); return &(task->tss.esp0); }
int *inthandler0d(int *esp) { struct CONSOLE *cons = (struct CONSOLE *) *((int *) 0x0fec); struct TASK *task = task_now(); char s[30]; cons_putstr0(cons, "\nINT 0D :\n General Protected Exception.\n"); sprintf(s, "EIP = %08X\n", esp[11]); cons_putstr0(cons, s); return &(task->tss.esp0); /* 異常終了させる */ }
int inthandler0c (int *esp) { struct CONSOLE *cons = (struct CONSOLE *) *((int *) 0x0fec); struct TASK *task = task_now(); char s[30]; cons_putstr0 (cons, "\nINT 0C : \n Stack Exception.\n"); sprintf (s, "EIP = %x\n", esp[11]); cons_putstr0 (cons, s); return &(task->tss.esp0); }
void task_sleep(struct _task *task) { struct _task *now_task; if (task->flags == TASK_RUNNING) { /* If current task is running */ now_task = task_now(); /* Set 'task' back to READY state */ task_remove(task); /* Sleep yourself */ if (task == now_task) { /* Recalebrate Level */ task_switchsub(); /* Switch Current Task */ now_task = task_now(); /* JMP */ farjmp(0, now_task->sel); } } return; }
int* interrupt_handler0d(int* esp) { console_t* console = (console_t*)*((int*)0x0fec); task_t* task = task_now(); char buf[32]; console_putstr0(console, "\nint 0d :\n General protected exception.\n"); sprintf(buf, "EIP = %08X\n", esp[11]); console_putstr0(console, buf); return &task->tss.esp0; /* force to stop the application */ }
int* interrupt_handler0c(int* esp) { console_t* console = (console_t*)*((int*)0x0fec); task_t* task = task_now(); char buf[32]; console_putstr0(console, "\nint 0c :\n stack exception.\n"); sprintf(buf, "EIP = %08X\n", esp[11]); console_putstr0(console, buf); return &task->tss.esp0; }
void cmd_langmode(struct CONSOLE *cons, char *cmdline) { struct TASK *task = task_now(); unsigned char mode = cmdline[9] - '0'; if (mode <= 2) { task->langmode = mode; } else { cons_putstr0(cons, "mode number error.\n"); } cons_newline(cons); return; }
int *hrb_api(int edi, int esi, int ebp, int esp, int ebx, int edx, int ecx, int eax) { int ds_base = *((int *) 0xfe8); struct TASK *task = task_now(); struct CONSOLE *cons = (struct CONSOLE *) *((int *) 0x0fec); struct SHTCTL *shtctl = (struct SHTCTL *) *((int *) 0x0fe4); struct SHEET *sht; int *reg = &eax + 1; /* eaxの次の番地 */ /* 保存のためのPUSHADを強引に書き換える */ /* reg[0] : EDI, reg[1] : ESI, reg[2] : EBP, reg[3] : ESP */ /* reg[4] : EBX, reg[5] : EDX, reg[6] : ECX, reg[7] : EAX */ if (edx == 1) { cons_putchar(cons, eax & 0xff, 1); } else if (edx == 2) { cons_putstr0(cons, (char *) ebx + ds_base); } else if (edx == 3) { cons_putstr1(cons, (char *) ebx + ds_base, ecx); } else if (edx == 4) { return &(task->tss.esp0); } else if (edx == 5) { sht = sheet_alloc(shtctl); sheet_setbuf(sht, (char *) ebx + ds_base, esi, edi, eax); make_window8((char *) ebx + ds_base, esi, edi, (char *) ecx + ds_base, 0); sheet_slide(sht, 100, 50); sheet_updown(sht, 3); /* 3という高さはtask_aの上 */ reg[7] = (int) sht; } else if (edx == 6) { sht = (struct SHEET *) ebx; putfonts8_asc(sht->buf, sht->bxsize, esi, edi, eax, (char *) ebp + ds_base); sheet_refresh(sht, esi, edi, esi + ecx * 8, edi + 16); } else if (edx == 7) { sht = (struct SHEET *) ebx; boxfill8(sht->buf, sht->bxsize, ebp, eax, ecx, esi, edi); sheet_refresh(sht, eax, ecx, esi + 1, edi + 1); } else if (edx == 8) { memman_init((struct MEMMAN *) (ebx + ds_base)); ecx &= 0xfffffff0; /* 16バイト単位に */ memman_free((struct MEMMAN *) (ebx + ds_base), eax, ecx); } else if (edx == 9) { ecx = (ecx + 0x0f) & 0xfffffff0; /* 16バイト単位に切り上げ */ reg[7] = memman_alloc((struct MEMMAN *) (ebx + ds_base), ecx); } else if (edx == 10) { ecx = (ecx + 0x0f) & 0xfffffff0; /* 16バイト単位に切り上げ */ memman_free((struct MEMMAN *) (ebx + ds_base), eax, ecx); } else if (edx == 11) { sht = (struct SHEET *) ebx; sht->buf[sht->bxsize * edi + esi] = eax; sheet_refresh(sht, esi, edi, esi + 1, edi + 1); } return 0; }
void putfonts8_asc_sht(struct SHEET *sht, int x, int y, int c, int b, char *s, int l) { struct TASK *task = task_now(); boxfill8(sht->buf, sht->bxsize, b, x, y, x + l * 8 - 1, y + 15); if (task->langmode != 0 && task->langbyte1 != 0) { putfonts8_asc(sht->buf, sht->bxsize, x, y, c, s); sheet_refresh(sht, x - 8, y, x + l * 8, y + 16); } else { putfonts8_asc(sht->buf, sht->bxsize, x, y, c, s); sheet_refresh(sht, x, y, x + l * 8, y + 16); } return; }
void displayStrings_CS(unsigned char *vram, int scrnx, int x, int y, char color, unsigned char *strings) { extern char charset[4096]; TASK *task = task_now(); char *hzset = (char *) *((int *) 0xfe8), *font; int k, t; //如果是英文模式 if(0 == task->lanmode) { for(; *strings != 0x00; strings++) { displayfont(vram, scrnx, x, y, color, charset + *strings * 16); //charset中有256个字符,每个字符占16个字节,编码顺序与ASCII码一样,所以如果要显示字母“A”,只需要在charset这个地址基础上加上65*16即可,也可以写成"A"*16 x += 8; //一个字符占用八个像素的宽度 //这个部分是自己写的,如果像素数超过了scrnx,即屏宽,那么要向下移动16个像素,并把x归0 if(x + 8 > scrnx) { y += 16; x = 0; } } } else if(1 == task->lanmode) { for(; *strings != 0x00; strings++) { //如果现在的是宽字符的第一个字节,那么就先不打印;如果是半角字符就直接打印出来 if(0 == task->lanbyte1) { if(0x81 <= *strings && *strings <= 0xfe) { task->lanbyte1 = *strings; } else { displayfont(vram, scrnx, x, y, color, hzset + *strings * 16); } } else { k = task->lanbyte1 - 0xa1; t = *strings - 0xa1; task->lanbyte1 = 0; font = hzset + 16 * 256 + 32 * (k * 94 + t); display_widefont(vram, scrnx, x - 8, y, color, font); display_widefont(vram, scrnx, x - 8, y + 8, color, font + 16); } x += 8; } } return ; }
int cmd_app(struct CONSOLE *cons, int *fat, char *cmdline) { struct MEMMAN *memman = (struct MEMMAN *) MEMMAN_ADDR; struct FILEINFO *finfo; struct SEGMENT_DESCRIPTOR *gdt = (struct SEGMENT_DESCRIPTOR *) ADR_GDT; char name[18], *p, *q; struct TASK *task = task_now(); int i; /* コマンドラインからファイル名を生成 */ for (i = 0; i < 13; i++) { if (cmdline[i] <= ' ') { break; } name[i] = cmdline[i]; } name[i] = 0; /* とりあえずファイル名の後ろを0にする */ /* ファイルを探す */ finfo = file_search(name, (struct FILEINFO *) (ADR_DISKIMG + 0x002600), 224); if (finfo == 0 && name[i - 1] != '.') { /* 見つからなかったので後ろに".HRB"をつけてもう一度探してみる */ name[i ] = '.'; name[i + 1] = 'H'; name[i + 2] = 'R'; name[i + 3] = 'B'; name[i + 4] = 0; finfo = file_search(name, (struct FILEINFO *) (ADR_DISKIMG + 0x002600), 224); } if (finfo != 0) { /* ファイルが見つかった場合 */ p = (char *) memman_alloc_4k(memman, finfo->size); q = (char *) memman_alloc_4k(memman, 64 * 1024); *((int *) 0xfe8) = (int) p; file_loadfile(finfo->clustno, finfo->size, p, fat, (char *) (ADR_DISKIMG + 0x003e00)); set_segmdesc(gdt + 1003, finfo->size - 1, (int) p, AR_CODE32_ER + 0x60); set_segmdesc(gdt + 1004, 64 * 1024 - 1, (int) q, AR_DATA32_RW + 0x60); if (finfo->size >= 8 && strncmp(p + 4, "Hari", 4) == 0) { start_app(0x1b, 1003 * 8, 64 * 1024, 1004 * 8, &(task->tss.esp0)); } else { start_app(0, 1003 * 8, 64 * 1024, 1004 * 8, &(task->tss.esp0)); } memman_free_4k(memman, (int) p, finfo->size); memman_free_4k(memman, (int) q, 64 * 1024); cons_newline(cons); return 1; } /* ファイルが見つからなかった場合 */ return 0; }
int cmd_app (struct CONSOLE *cons, int *fat, char *cmdline) { struct MEMMAN *memman = (struct MEMMAN *)MEMMAN_ADDR; struct FILEINFO *finfo; struct SEGMENT_DESCRIPTOR *gdt = (struct SEGMENT_DESCRIPTOR *)ADR_GDT; char name [18]; int i; struct TASK *task = task_now (); for (i = 0; i < 13; i++) { if (cmdline[i] <= ' ') { break; } name[i] = cmdline[i]; } name[i] = 0; finfo = file_search (name, (struct FILEINFO *)(ADR_DISKIMG + 0x002600), 224); if (finfo == 0 && name[i-1] != '.') { name [i+0] = '.'; name [i+1] = 'H'; name [i+2] = 'R'; name [i+3] = 'B'; name [i+4] = 0; finfo = file_search (name, (struct FILEINFO *)(ADR_DISKIMG + 0x002600), 224); } if (finfo != 0) { char *p = (char *)memman_alloc_4k (memman, finfo->size); char *q = (char *)memman_alloc_4k (memman, 64 * 1024); *((int *) 0xfe8) = (int) p; file_loadfile (finfo->clustno, finfo->size, p, fat, (char *) (ADR_DISKIMG + 0x003e00)); set_segmdesc (gdt + 1003, finfo->size - 1, (int) p, AR_CODE32_ER + 0x60); set_segmdesc (gdt + 1004, 64 * 1024 - 1, (int) q, AR_DATA32_RW + 0x60); if (finfo->size >= 8 && strncmp (p + 4, "Hari", 4) == 0) { p[0] = 0xe8; p[1] = 0x16; p[2] = 0x00; p[3] = 0x00; p[4] = 0x00; p[5] = 0xcb; } start_app (0, 1003 * 8, 64 * 1024, 1004 * 8, &(task->tss.esp0)); memman_free_4k (memman, (int) p, finfo->size); memman_free_4k (memman, (int) q, 64 * 1024); cons_newline (cons); return 1; } return 0; }
int *hrb_api(int edi, int esi, int ebp, int esp, int ebx, int edx, int ecx, int eax) { int cs_base = *((int *) 0xfe8); struct TASK *task = task_now(); struct CONSOLE *cons = (struct CONSOLE *) *((int *) 0x0fec); if (edx == 1) { cons_putchar(cons, eax & 0xff, 1); } else if (edx == 2) { cons_putstr0(cons, (char *) ebx + cs_base); } else if (edx == 3) { cons_putstr1(cons, (char *) ebx + cs_base, ecx); } else if (edx == 4) { return &(task->tss.esp0); } return 0; }
//在指定图层的指定位置显示指定颜色的指定文字,这样就不用管这个图层在哪里显示了,只需要在它上面显示好文字就行 void displayStrings_atLayer(LAYER *layer, int x, int y, int color, int bg_color, char *strings) { int length = strlen(strings); TASK *task = task_now(); drawRectangle(layer->buffer, layer->length, bg_color, x, y, 8 * length,15); if(0 != task->lanmode && 0 != task->lanbyte1) { displayStrings_CS(layer->buffer, layer->length, x, y, color,strings); layer_part_refresh(layer, x - 8, y, x + length * 8, y + 16); } else { displayStrings_CS(layer->buffer, layer->length, x, y, color,strings); layer_part_refresh(layer, x, y, x + length * 8, y + 16); } return ; }