001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028 #include <sos/assert.h>
029 #include <sos/klibc.h>
030 #include <sos/thread.h>
031 #include <sos/ksynch.h>
032 #include <sos/kmalloc.h>
033 #include <drivers/x86_videomem.h>
034
035
036
037
038
039
040
041
042
043 #define MAP_X 76
044 #define MAP_Y 12
045 #define MAP_SIZE MAP_X * MAP_Y
046
047 #define MOUSE 0x01
048 #define CHEESE 0x02
049 #define OBSTACLE 0x04
050 #define INPUT 0x08
051 #define OUTPUT 0x10
052
053 #define OBSTACLE_COUNT 100
054 #define CHEESE_COUNT 650
055
056 #define MOUSE_FULL 0x01
057 #define MOUSE_EMPTY 0x02
058 #define CHEESE_FOUND 0x04
059 #define MOUSE_EXITED 0x08
060
061 #define MOUSE_SPEED_MAX 1000
062 #define MOUSE_SPEED_MIN 4
063
064 typedef unsigned int Color_t;
065
066 struct Point{
067 int X;
068 int Y;
069 };
070
071 typedef struct Point Point_t;
072
073 #define Set(Reg, Flag) Reg = (Reg | Flag)
074 #define Reset(Reg, Flag) Reg = (Reg &(~Flag))
075 #define IsSet(Reg, Flag) (Reg & Flag)
076
077
078
079
080
081 struct Element{
082 sos_ui32_t Type;
083 sos_ui32_t Status;
084 Color_t Color;
085 Point_t P;
086 struct sos_thread * ThreadID;
087 int Way;
088 };
089
090 typedef struct Element Element_t;
091
092
093
094
095 static void DrawMap(void);
096 static sos_ret_t CreateMap(void);
097 static sos_ret_t InitMapInput(Element_t * * pMap);
098 static sos_ret_t InitMapOutput(Element_t * * pMap);
099 static sos_ret_t ElementInit(Element_t * * pMap, unsigned int Type);
100 static void Mouse(unsigned long Param);
101 static void MouseMove(Point_t * P);
102 static Point_t ChoosePosition(Element_t * pMouse, int Positions[], int Count);
103 static int EvaluatePositions(Point_t Org, int Positions[], Point_t * Cheese);
104 static sos_bool_t IsCollision(Point_t Org, Point_t p, Point_t *Cheese);
105 static sos_bool_t AffectMovement(Point_t Org, Point_t p);
106 static void MouseCreator(void);
107 static sos_ret_t CreateMouse(void);
108
109
110
111
112
113 static Element_t * * pMap;
114 static struct sos_ksema SemMap;
115 static struct sos_ksema SemMouse;
116 static int MouseCount = 0;
117 static int CheeseCount = 0;
118 static int ObstacleCount = 0;
119 static int MouseSpeed = 100;
120
121
122
123
124 void DrawPixel(int x, int y, Color_t color)
125 {
126 sos_x86_videomem_putchar(y+3, x+2, color, 219);
127 }
128
129
130
131
132
133
134 void MouseSim(void)
135 {
136
137 SOS_ASSERT_FATAL(SOS_OK == sos_ksema_init(& SemMap, "SemMap", 1,
138 SOS_KWQ_ORDER_FIFO));
139
140
141 SOS_ASSERT_FATAL(SOS_OK == sos_ksema_init(& SemMouse, "SemMouse", 2,
142 SOS_KWQ_ORDER_FIFO));
143
144
145 SOS_ASSERT_FATAL(SOS_OK == CreateMap());
146
147
148 SOS_ASSERT_FATAL(sos_create_kernel_thread("MouseCreator",
149 (sos_kernel_thread_start_routine_t)MouseCreator,
150 0, SOS_SCHED_PRIO_TS_LOWEST-1) != NULL);
151
152 }
153
154
155
156
157
158
159
160 static sos_ret_t CreateMap(void)
161 {
162 pMap = (Element_t * *)sos_kmalloc(MAP_SIZE * sizeof(Element_t *), 0);
163 if(pMap == NULL) return -SOS_ENOMEM;
164
165
166 memset(pMap, 0, MAP_SIZE * sizeof(Element_t *));
167
168
169 if(SOS_OK != InitMapInput(pMap))
170 {
171 return -SOS_EFATAL;
172 }
173
174
175 if(InitMapOutput(pMap) != SOS_OK)
176 {
177 return -SOS_EFATAL;
178 }
179
180
181 if(ElementInit(pMap, CHEESE) != SOS_OK)
182 {
183 return -SOS_EFATAL;
184 }
185
186
187 if(ElementInit(pMap, OBSTACLE) != SOS_OK)
188 {
189 return -SOS_EFATAL;
190 }
191
192 DrawMap();
193
194 return SOS_OK;
195 }
196
197
198
199
200
201
202 static void DrawMap(void)
203 {
204 unsigned int I;
205
206 for(I = 0; I < MAP_SIZE; I++)
207 {
208 if(pMap[I] != NULL)
209 {
210 DrawPixel(I % MAP_X, I/MAP_X, pMap[I]->Color);
211 }
212 else DrawPixel(I % MAP_X, I/MAP_X, SOS_X86_VIDEO_FG_BLACK);
213 }
214 sos_x86_videomem_printf(23, 0, SOS_X86_VIDEO_FG_YELLOW | SOS_X86_VIDEO_BG_BLUE,
215 "Souris = %d; Fromages = %d; Obstacles = %d ",
216 MouseCount, CheeseCount, ObstacleCount);
217 }
218
219
220
221
222
223
224
225 static sos_ret_t InitMapInput(Element_t * * pMap)
226 {
227 Element_t * pElement;
228
229
230 pElement = (Element_t *)sos_kmalloc(sizeof(Element_t), 0);
231 if(pElement == NULL) return -SOS_ENOMEM;
232
233
234 pElement->Type = INPUT;
235 pElement->Status = 0;
236 pElement->Color = SOS_X86_VIDEO_FG_YELLOW | SOS_X86_VIDEO_BG_BLUE;
237 pElement->P.X = 0;
238 pElement->P.Y = MAP_Y / 2;
239 pElement->ThreadID = 0;
240
241 pMap[(pElement->P.Y * MAP_X) + pElement->P.X] = pElement;
242
243 return SOS_OK;
244 }
245
246
247
248
249
250
251
252 static sos_ret_t InitMapOutput(Element_t * * pMap)
253 {
254 Element_t * pElement;
255
256
257 pElement = (Element_t *)sos_kmalloc(sizeof(Element_t), 0);
258 if(pElement == NULL) return -SOS_ENOMEM;
259
260
261 pElement->Type = OUTPUT;
262 pElement->Status = 0;
263 pElement->Color = SOS_X86_VIDEO_FG_LTBLUE;
264 pElement->P.X = MAP_X - 1;
265 pElement->P.Y = MAP_Y / 2;
266 pElement->ThreadID = 0;
267
268 pMap[(pElement->P.Y * MAP_X) + pElement->P.X] = pElement;
269
270 return SOS_OK;
271 }
272
273
274
275
276
277
278
279
280 static sos_ret_t ElementInit(Element_t * * pMap, unsigned int Type)
281 {
282 unsigned int I, J;
283 unsigned int Max;
284 Color_t Color;
285
286 if(Type == CHEESE)
287 {
288 Max = CHEESE_COUNT;
289 Color = SOS_X86_VIDEO_FG_YELLOW;
290 }
291 else if(Type == OBSTACLE)
292 {
293 Max = OBSTACLE_COUNT;
294 Color = SOS_X86_VIDEO_FG_GREEN;
295 }
296 else
297 {
298 return -SOS_EINVAL;
299 }
300
301 for(I = 0; I < Max; I++)
302 {
303 J = random();
304 J += random();
305 J %= MAP_SIZE;
306 if(pMap[J] == NULL)
307 {
308 pMap[J] = (Element_t *)sos_kmalloc(sizeof(Element_t),
309 0);
310 if(pMap[J] == NULL) return -SOS_ENOMEM;
311
312 pMap[J]->Type = Type;
313
314 if(Type == CHEESE)
315 {
316 CheeseCount++;
317 }
318 else if(Type == OBSTACLE)
319 {
320 ObstacleCount++;
321 }
322
323 pMap[J]->Color = Color;
324 pMap[J]->Status = 0;
325 pMap[J]->Color = Color;
326 pMap[J]->P.X = J % MAP_X;
327 pMap[J]->P.Y = J / MAP_X;
328 pMap[J]->ThreadID = 0;
329 }
330 }
331
332 return SOS_OK;
333 }
334
335
336
337
338
339
340
341
342
343
344
345
346 static void Mouse(unsigned long Param)
347 {
348 Element_t * pMouse = (Element_t *)Param;
349 Point_t P;
350
351 SOS_ASSERT_FATAL(pMouse != NULL);
352
353
354 P = pMouse->P;
355 P = pMouse->P;
356
357 while(1)
358 {
359 int delay_ms;
360 struct sos_time delay;
361
362
363 sos_ksema_down(& SemMap, NULL);
364
365 MouseMove(&P);
366
367 sos_ksema_up(& SemMap);
368
369
370 if (IsSet(pMouse->Status, MOUSE_EXITED))
371
372 break;
373
374
375 delay_ms = MOUSE_SPEED_MIN + (random() % MouseSpeed);
376 delay.sec = delay_ms / 1000;
377 delay.nanosec = (delay_ms % 1000) * 1000000;
378 sos_thread_sleep(& delay);
379 }
380
381
382 sos_kfree((sos_vaddr_t)pMouse);
383 }
384
385
386
387
388
389
390
391
392 static void MouseMove(Point_t * P)
393 {
394 Point_t Org;
395 Point_t p;
396 Point_t Cheese;
397 int Positions[8];
398 int Count = 0;
399 Element_t * pMouse;
400
401 Org = *P;
402
403 pMouse = pMap[Org.X + (Org.Y * MAP_X)];
404
405 Count = EvaluatePositions(Org, Positions, &Cheese);
406
407 if(Count == 0) return;
408
409 p = Org;
410
411 if(IsSet(pMouse->Status, CHEESE_FOUND))
412 {
413 Reset(pMouse->Status, CHEESE_FOUND);
414 p = Cheese;
415 }
416 else
417 {
418 p = ChoosePosition(pMouse, Positions, Count);
419 }
420 if(AffectMovement(Org, p) == FALSE) return;
421
422 pMap[Org.X + (Org.Y * MAP_X)] = NULL;
423 pMap[p.X + (p.Y * MAP_X)] = pMouse;
424 pMouse->P = p;
425
426 DrawPixel(Org.X, Org.Y, SOS_X86_VIDEO_FG_BLACK);
427 DrawPixel(p.X, p.Y, pMouse->Color);
428 sos_x86_videomem_printf( 23,0, SOS_X86_VIDEO_FG_YELLOW | SOS_X86_VIDEO_BG_BLUE, "Souris = %d; Fromages = %d; Obstacles = %d ", MouseCount, CheeseCount, ObstacleCount);
429
430 *P = p;
431 }
432
433
434
435
436
437
438
439
440
441
442 static Point_t ChoosePosition(Element_t * pMouse, int Positions[], int Count)
443 {
444 int I, J;
445 Point_t p;
446
447 for(J = 0; J < Count; J++)
448 {
449 I = Positions[J];
450 if(I == pMouse->Way)
451 {
452 p = pMouse->P;
453 switch(I)
454 {
455 case 0:
456 p.Y++;
457 break;
458 case 1:
459 p.X++;
460 p.Y++;
461 break;
462 case 2:
463 p.X++;
464 break;
465 case 3:
466 p.Y--;
467 p.X++;
468 break;
469 case 4:
470 p.Y--;
471 break;
472 case 5:
473 p.Y--;
474 p.X--;
475 break;
476 case 6:
477 p.X--;
478 break;
479 case 7:
480 p.X--;
481 p.Y++;
482 break;
483 }
484 return p;
485 }
486 }
487
488 J = random() % Count;
489 I = Positions[J];
490 if(((I + 4) % 8) == pMouse->Way)
491 {
492 J = (J + 1) % Count;
493 I = Positions[J];
494 }
495
496 p = pMouse->P;
497 switch(I)
498 {
499 case 0:
500 p.Y++;
501 break;
502 case 1:
503 p.X++;
504 p.Y++;
505 break;
506 case 2:
507 p.X++;
508 break;
509 case 3:
510 p.Y--;
511 p.X++;
512 break;
513 case 4:
514 p.Y--;
515 break;
516 case 5:
517 p.Y--;
518 p.X--;
519 break;
520 case 6:
521 p.X--;
522 break;
523 case 7:
524 p.X--;
525 p.Y++;
526 break;
527 }
528
529 pMouse->Way = I;
530
531 return p;
532 }
533
534
535
536
537
538
539
540
541
542
543
544
545
546 static int EvaluatePositions(Point_t Org, int Positions[], Point_t * Cheese)
547 {
548 int I;
549 int Count = 0;
550 Point_t p;
551 Point_t CheesePos;
552
553 for(I = 0; I < 8; I++)
554 {
555 p = Org;
556 switch(I)
557 {
558 case 0:
559 p.Y++;
560 break;
561 case 1:
562 p.X++;
563 p.Y++;
564 break;
565 case 2:
566 p.X++;
567 break;
568 case 3:
569 p.Y--;
570 p.X++;
571 break;
572 case 4:
573 p.Y--;
574 break;
575 case 5:
576 p.Y--;
577 p.X--;
578 break;
579 case 6:
580 p.X--;
581 break;
582 case 7:
583 p.X--;
584 p.Y++;
585 break;
586 }
587
588 if(IsCollision(Org, p, &CheesePos) == FALSE)
589 {
590 Positions[Count] = I;
591 Count++;
592 }
593 }
594
595 *Cheese = CheesePos;
596
597 return Count;
598 }
599
600
601
602
603
604
605
606
607 static sos_bool_t AffectMovement(Point_t Org, Point_t p)
608 {
609 Element_t * pMouse = pMap[Org.X + (Org.Y * MAP_X)];
610 Element_t * pElement;
611
612 pElement = pMap[p.X + (p.Y * MAP_X)];
613
614
615 if(pElement == NULL) return TRUE;
616
617 switch(pElement->Type)
618 {
619 case CHEESE:
620
621 sos_kfree((sos_vaddr_t)pElement);
622 pMap[p.X + (p.Y * MAP_X)] = NULL;
623
624
625 Set(pMouse->Status, MOUSE_FULL);
626 Reset(pMouse->Status, MOUSE_EMPTY);
627 pMouse->Color = SOS_X86_VIDEO_FG_MAGENTA;
628 CheeseCount--;
629 return TRUE;
630 case OUTPUT:
631
632 pMap[Org.X + (Org.Y * MAP_X)] = NULL;
633 MouseCount--;
634 DrawPixel(Org.X, Org.Y, SOS_X86_VIDEO_FG_BLACK);
635 sos_x86_videomem_printf( 23,0, SOS_X86_VIDEO_FG_YELLOW | SOS_X86_VIDEO_BG_BLUE,
636 "Souris = %d; Fromages = %d; Obstacles = %d ",
637 MouseCount, CheeseCount,
638 ObstacleCount);
639 Set(pMouse->Status, MOUSE_EXITED);
640 return FALSE;
641 default :
642 return FALSE;
643 }
644
645 return FALSE;
646 }
647
648
649
650
651
652
653
654
655
656
657 static sos_bool_t IsCollision(Point_t Org, Point_t p, Point_t *Cheese)
658 {
659 Element_t * pMouse = pMap[Org.X + (Org.Y * MAP_X)];
660 Element_t * pElement;
661
662
663 if((p.X < 0)||(p.Y < 0)) return TRUE;
664
665 if((p.Y >= MAP_Y)||(p.X >= MAP_X)) return TRUE;
666
667 pElement = pMap[p.X + (p.Y * MAP_X)];
668
669
670 if(pElement == NULL) return FALSE;
671
672
673 if(IsSet(pMouse->Status, CHEESE_FOUND)) return FALSE;
674
675 switch(pElement->Type)
676 {
677 case CHEESE:
678 if(IsSet(pMouse->Status, MOUSE_FULL)) return TRUE;
679
680 Set(pMouse->Status, CHEESE_FOUND);
681
682 (*Cheese).X = p.X;
683 (*Cheese).Y = p.Y;
684 break;
685 case INPUT:
686 if(IsSet(pMouse->Status, MOUSE_EMPTY)) return TRUE;
687
688 Set(pMouse->Status, MOUSE_EMPTY);
689 Reset(pMouse->Status, MOUSE_FULL);
690 pMouse->Color = SOS_X86_VIDEO_FG_LTRED;
691
692 sos_ksema_up(& SemMouse);
693 return TRUE;
694 case OUTPUT:
695 break;
696 default :
697 return TRUE;
698 }
699
700 return FALSE;
701 }
702
703
704
705
706 static void MouseCreator(void)
707 {
708 while(1)
709 {
710 sos_ksema_down(& SemMouse, NULL);
711 sos_ksema_down(& SemMap, NULL);
712 CreateMouse();
713 sos_ksema_up(& SemMap);
714 }
715 }
716
717
718
719
720
721
722
723 static sos_ret_t CreateMouse(void)
724 {
725 Element_t * pElement;
726 unsigned int I;
727
728 Point_t p;
729
730 for(I = 0; I < 8; I++)
731 {
732 p.X = 0;
733 p.Y = MAP_Y / 2;
734 switch(I)
735 {
736 case 0:
737 p.Y++;
738 break;
739 case 1:
740 p.X++;
741 p.Y++;
742 break;
743 case 2:
744 p.X++;
745 break;
746 case 3:
747 p.Y--;
748 p.X++;
749 break;
750 case 4:
751 p.Y--;
752 break;
753 case 5:
754 p.Y--;
755 p.X--;
756 break;
757 case 6:
758 p.X--;
759 break;
760 case 7:
761 p.X--;
762 p.Y++;
763 break;
764 }
765 if((p.X >= 0)&&(p.Y >= 0)&&(p.X < MAP_X)&&(p.Y < MAP_Y))
766 {
767 pElement = pMap[p.X + (p.Y * MAP_X)];
768 if(pElement == NULL)
769 {
770 pElement = (Element_t *)sos_kmalloc(sizeof(Element_t), 0);
771 if(pElement != NULL)
772 {
773 pElement->Type = MOUSE;
774 Set(pElement->Status, MOUSE_EMPTY);
775 pElement->Color = SOS_X86_VIDEO_FG_LTRED;
776 pElement->P = p;
777 pElement->Way = 0;
778 pElement->ThreadID
779 = sos_create_kernel_thread("Mouse",
780 (sos_kernel_thread_start_routine_t)Mouse,
781 pElement, SOS_SCHED_PRIO_TS_LOWEST-1);
782 if(pElement->ThreadID == 0)
783 {
784 sos_kfree((sos_vaddr_t)pElement);
785 pElement = NULL;
786 return -SOS_ENOMEM;
787 }
788 pMap[p.X + (p.Y * MAP_X)] = pElement;
789 MouseCount++;
790
791 DrawPixel(p.X, p.Y, pElement->Color);
792 sos_x86_videomem_printf(23, 0, SOS_X86_VIDEO_FG_YELLOW | SOS_X86_VIDEO_BG_BLUE, "Souris = %d; Fromages = %d; Obstacles = %d ", MouseCount, CheeseCount, ObstacleCount);
793
794 return SOS_OK;
795 }
796 }
797 }
798 }
799 return -SOS_EBUSY;
800 }
801
802
803
804
805