add flag computer wp temp
@@ -1 +1,53 @@
|
|||||||
# Flag 计算机
|
# Flag 计算机
|
||||||
|
|
||||||
|
此题目基于 [https://github.com/skeeto/dosdefender-ld31](https://github.com/skeeto/dosdefender-ld31) 修改而成。
|
||||||
|
|
||||||
|
```
|
||||||
|
由于我太菜了,所以引入了一个 BUG 导致题目下线修改后上线。给大家带来了不便,十分抱歉。
|
||||||
|
```
|
||||||
|
|
||||||
|
这道题主要想展现的效果是在 DOS 和 Windows 上都能运行的程序。在 Windows 上运行将弹出一个对话框。
|
||||||
|

|
||||||
|
这和我们在 DOS 上运行 Windows PE 程序在 DOS 中输出"This program cannot be run in DOS mode"相照应。如果我们把程序载入 010editor就会发现一些猫腻。
|
||||||
|

|
||||||
|
我们会发现原来的 DOS stub 充满了代码。实际上我是先编译了一个 COM 可执行文件,然后手动为 COM 文件加上 DOS 头。所以在此过程中 DOS 中的一些值是手工进行设置的。
|
||||||
|
然后我将能够运行的 DOS 可执行文件设置为 visual studio 2019 中的 exe 的 DOS stub。最终编译成了你们现在看到的样子。
|
||||||
|
|
||||||
|
## 逆向分析
|
||||||
|
|
||||||
|
我们将它拖入ida
|
||||||
|

|
||||||
|
我们选择让 IDA 分析 MS-DOS executeble。
|
||||||
|
然后我们观察 start 函数。
|
||||||
|

|
||||||
|
我们发现它调用了一个函数,然后执行了 DOS exit 中断,IDA 已经将其标注了出来。
|
||||||
|
|
||||||
|
```
|
||||||
|
这里用了一个 CPU 指令前缀的编译方法,使得我们的 80386 能够在实模式使用 32 位操作数。0x66
|
||||||
|
:它属于 Prefix group 3,Operand-size override prefix。
|
||||||
|
```
|
||||||
|
有了这样一个 opcode 会有怎么样的行为呢?
|
||||||
|

|
||||||
|
可以看到 operand size 变为了 32bit。
|
||||||
|
我们分析 102f 这个函数。
|
||||||
|

|
||||||
|
可以看到使用了大量使用这个技巧的痕迹,这就是为什么我们能在实模式使用 32bit 寄存器的原因。
|
||||||
|
|
||||||
|
```
|
||||||
|
asm (".code16gcc\n"
|
||||||
|
"call dosmain\n"
|
||||||
|
"mov $0x4C,%ah\n"
|
||||||
|
"int $0x21\n");
|
||||||
|
```
|
||||||
|
最先展开的 include 项目中有我们的 init.h 。
|
||||||
|
这个文件中的一个伪指令 ".code16cc" 代表着让gcc生成 16bit realmode 模式的汇编指令。所以这是为什么大量指令前都有 0x66 的原因。当我们的操作数是类似于 uint32 声明时,0x66 就会起作用。
|
||||||
|
逆向的核心过程就是明白程序干了哪些事情,橙色的操作数代表着地址,我们将鼠标悬停在上面,然后右键把它类型转换一下。
|
||||||
|

|
||||||
|
IDA 就能识别字符串了。
|
||||||
|
ps: 作为一个CTF玩家,我最喜欢的事情就是按 F5 ,hackergame 是为了让人能学到东西,而不是千篇一律的难题,不是为了难而难。所以我程序在 realmode 下,IDA 失效了,这样大家都能从 “0” 接触汇编。
|
||||||
|
显而易见的是,参数是字符串的一般就是我们的类似的 printf 函数。只不过这里是 vga 的输出而已。
|
||||||
|

|
||||||
|
我们看整个控制流,发现程序并不复杂,大多数都是控制显示的逻辑。
|
||||||
|
大家可以对着源代码再看一遍,这个函数就是对应的 main 函数。
|
||||||
|
|
||||||
|
下面讲下程序的核心逻辑。
|
||||||
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 355 KiB |
|
After Width: | Height: | Size: 270 KiB |
|
After Width: | Height: | Size: 161 KiB |
|
After Width: | Height: | Size: 140 KiB |
|
After Width: | Height: | Size: 470 KiB |
|
After Width: | Height: | Size: 363 KiB |
|
After Width: | Height: | Size: 64 KiB |
@@ -0,0 +1,2 @@
|
|||||||
|
*.com
|
||||||
|
*.o
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
CC = gcc
|
||||||
|
DOS = dosbox
|
||||||
|
CFLAGS = -std=gnu99 -w -O0 -nostdlib -m32 -march=i386 \
|
||||||
|
-Wno-unused-function \
|
||||||
|
-ffreestanding -fomit-frame-pointer -fwrapv -fno-strict-aliasing \
|
||||||
|
-fno-leading-underscore -fno-pic -fno-stack-protector \
|
||||||
|
-Wl,--nmagic,-static,-Tcom.ld
|
||||||
|
|
||||||
|
dosdef.com : dosdef.c *.h
|
||||||
|
|
||||||
|
.PHONY : all clean test
|
||||||
|
|
||||||
|
clean :
|
||||||
|
$(RM) *.com
|
||||||
|
|
||||||
|
test : dosdef.com
|
||||||
|
$(DOS) $^
|
||||||
|
|
||||||
|
%.com : %.c
|
||||||
|
$(CC) -o $@ $(CFLAGS) $<
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
---
|
||||||
|
enabled: true
|
||||||
|
name: Flag 计算机
|
||||||
|
category: binary
|
||||||
|
url: files/get_flag_system.exe
|
||||||
|
index: 270
|
||||||
|
flags:
|
||||||
|
- name: ''
|
||||||
|
score: 300
|
||||||
|
type: text
|
||||||
|
flag: flag{g3tfl4g_0p3r4t1ng_syst3m}
|
||||||
|
---
|
||||||
|
|
||||||
|
一个玄学的 flag 计算机,平常的时候只会摸鱼,但如果在**合适的时间**运行它的话,它就可以告诉你真正的 flag。
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
This is free and unencumbered software released into the public domain.
|
||||||
|
|
||||||
|
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||||
|
distribute this software, either in source code form or as a compiled
|
||||||
|
binary, for any purpose, commercial or non-commercial, and by any
|
||||||
|
means.
|
||||||
|
|
||||||
|
In jurisdictions that recognize copyright laws, the author or authors
|
||||||
|
of this software dedicate any and all copyright interest in the
|
||||||
|
software to the public domain. We make this dedication for the benefit
|
||||||
|
of the public at large and to the detriment of our heirs and
|
||||||
|
successors. We intend this dedication to be an overt act of
|
||||||
|
relinquishment in perpetuity of all present and future rights to this
|
||||||
|
software under copyright law.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||||
|
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||||
|
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
For more information, please refer to <http://unlicense.org/>
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
#ifndef ALLOC_H
|
||||||
|
#define ALLOC_H
|
||||||
|
|
||||||
|
#include "int.h"
|
||||||
|
|
||||||
|
extern char _heap;
|
||||||
|
static char *hbreak = &_heap;
|
||||||
|
|
||||||
|
static void *sbrk(size_t size)
|
||||||
|
{
|
||||||
|
char *ptr = hbreak;
|
||||||
|
for (size_t i = 0; i < size; i++)
|
||||||
|
ptr[i] = 0;
|
||||||
|
hbreak += size;
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void free(void)
|
||||||
|
{
|
||||||
|
hbreak = &_heap;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
OUTPUT_FORMAT(binary)
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
. = 0x0100;
|
||||||
|
.text :
|
||||||
|
{
|
||||||
|
*(.text);
|
||||||
|
}
|
||||||
|
.data :
|
||||||
|
{
|
||||||
|
*(.data);
|
||||||
|
*(.bss);
|
||||||
|
*(.rodata);
|
||||||
|
}
|
||||||
|
_heap = ALIGN(4);
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
# Suggested DOSBox configuration for DOS Defender
|
||||||
|
# Usage: dosbox -conf dosbox.conf dosdef.com
|
||||||
|
|
||||||
|
[sdl]
|
||||||
|
output=opengl
|
||||||
|
windowresolution=1280x800
|
||||||
|
|
||||||
|
[cpu]
|
||||||
|
core=dynamic
|
||||||
|
cycles=max
|
||||||
@@ -0,0 +1,261 @@
|
|||||||
|
#include "init.h"
|
||||||
|
#include "print.h"
|
||||||
|
#include "joystick.h"
|
||||||
|
#include "vga.h"
|
||||||
|
#include "rand.h"
|
||||||
|
#include "time.h"
|
||||||
|
#include "alloc.h"
|
||||||
|
#include "keyboard.h"
|
||||||
|
#include "speaker.h"
|
||||||
|
|
||||||
|
#define SCALE 1000
|
||||||
|
#define BACKGROUND 17
|
||||||
|
#define PLAYER 14
|
||||||
|
#define BULLET_SPEED 3
|
||||||
|
#define PARTICLE_MAX_AGE 50
|
||||||
|
#define MAX_PLAYERS 2
|
||||||
|
|
||||||
|
typedef unsigned int tick_t;
|
||||||
|
typedef void (*ai_t)(int id);
|
||||||
|
typedef void (*power_t)(int id);
|
||||||
|
|
||||||
|
static tick_t ticks;
|
||||||
|
static unsigned score;
|
||||||
|
static unsigned best_score;
|
||||||
|
static struct speaker speaker;
|
||||||
|
|
||||||
|
struct ship {
|
||||||
|
int32_t x, y, dx, dy;
|
||||||
|
tick_t last_fire;
|
||||||
|
ai_t ai;
|
||||||
|
struct sample *fx_fire;
|
||||||
|
uint16_t score;
|
||||||
|
uint16_t hp, hp_max;
|
||||||
|
uint8_t radius;
|
||||||
|
uint8_t fire_delay;
|
||||||
|
uint8_t fire_damage;
|
||||||
|
uint8_t drop_rate;
|
||||||
|
uint8_t color_a, color_b;
|
||||||
|
bool is_player;
|
||||||
|
union {
|
||||||
|
int target_ship;
|
||||||
|
struct {
|
||||||
|
uint32_t x, y;
|
||||||
|
} target_position;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct bullet {
|
||||||
|
int32_t x, y, dx, dy;
|
||||||
|
tick_t birthtick;
|
||||||
|
uint8_t color;
|
||||||
|
uint8_t damage;
|
||||||
|
bool alive;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct particle {
|
||||||
|
int32_t x, y;
|
||||||
|
tick_t birthtick;
|
||||||
|
bool alive;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct powerup {
|
||||||
|
int32_t x, y;
|
||||||
|
tick_t birthtick;
|
||||||
|
power_t power;
|
||||||
|
bool alive;
|
||||||
|
uint8_t color;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct bullet *bullets;
|
||||||
|
static size_t bullets_max = 32;
|
||||||
|
|
||||||
|
static struct particle *particles;
|
||||||
|
static size_t particles_max = 64;
|
||||||
|
|
||||||
|
static struct ship *ships;
|
||||||
|
static size_t ships_max = 12;
|
||||||
|
|
||||||
|
static struct powerup *powerups;
|
||||||
|
static size_t powerups_max = 8;
|
||||||
|
|
||||||
|
static bool joystick_detected()
|
||||||
|
{
|
||||||
|
struct joystick joystick;
|
||||||
|
joystick_read(&joystick);
|
||||||
|
return joystick.axis[0] != 0 || joystick.axis[1] != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void burn(int32_t x, int32_t y);
|
||||||
|
static void ship_draw(int id, bool clear);
|
||||||
|
static void powerup_random(int id);
|
||||||
|
|
||||||
|
|
||||||
|
// #define VGA_PWIDTH 320
|
||||||
|
// #define VGA_PHEIGHT 200
|
||||||
|
// 53 character a line
|
||||||
|
|
||||||
|
static unsigned short strlen(const char * in)
|
||||||
|
{
|
||||||
|
short ret=0;
|
||||||
|
while(in[ret] != 0)
|
||||||
|
{
|
||||||
|
ret++;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned short str_line_middle(unsigned short length)
|
||||||
|
{
|
||||||
|
return (53 - length) / 2 * 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void delay()
|
||||||
|
{
|
||||||
|
for(unsigned short i = 0; i<0xf;i++)
|
||||||
|
{
|
||||||
|
usleep(800);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// static uint32_t rand_seed = 375226057;
|
||||||
|
|
||||||
|
// static uint32_t rand(void)
|
||||||
|
// {
|
||||||
|
// rand_seed = rand_seed * 1103515245 + 12345;
|
||||||
|
// return rand_seed;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// static uint32_t randn(uint32_t n)
|
||||||
|
// {
|
||||||
|
// return (rand() >> 7) % n;
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t a,x0,b;
|
||||||
|
|
||||||
|
static uint32_t gen_random_a()
|
||||||
|
{
|
||||||
|
a = get_time() % 58379;
|
||||||
|
// a = 26141;
|
||||||
|
x0 = 1103515245;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t myrand(void)
|
||||||
|
{
|
||||||
|
x0 = x0 * a + 12345678;
|
||||||
|
return x0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// flag{g3tfl4g_0p3r4t1ng_syst3m}
|
||||||
|
uint32_t get_matrix[15];
|
||||||
|
uint32_t my_matrix[15*15]={20597,19141,29258,17804,29076,28746,24890,28979,26196,31833,26624,24774,18916,29028,24033,22913,23436,25750,26539,21652,31296,22446,16506,21949,22761,30221,29477,29617,16497,23022,23179,30781,23877,29171,31665,26534,32159,22583,27525,28708,31216,17158,31988,32190,23747,21272,21278,24727,29984,25303,23445,23119,23155,26346,26389,30747,28948,31418,21323,31758,30911,18790,21312,25099,22348,25409,29357,22180,23588,28794,18133,25624,21972,23401,24821,31369,25187,31517,19840,28836,20794,20239,24523,30814,24016,17954,21227,16691,30290,23391,20482,24822,31968,30651,27908,22690,30875,31003,31747,19978,25482,18563,30143,27788,26658,26295,23244,27086,26456,24251,28647,22783,27460,19187,23252,24078,19203,26251,18113,19542,24533,16666,24038,32744,28670,30438,26379,18591,30109,26509,20947,27696,22945,27542,32128,25416,21675,19389,27085,29380,20163,21102,30936,30862,18230,21904,16938,16579,20641,27551,22740,24666,16836,23306,27661,26506,28623,29816,20166,29405,23982,30046,19365,24926,19029,32448,17567,17156,18678,28594,19769,28631,25769,31309,24457,30625,21825,29811,17112,31370,25345,24333,24005,31606,30942,21441,30599,22894,18015,19994,27901,26868,21948,27614,23449,21289,19588,19955,28133,16696,31509,26219,19946,27895,28760,28547,28315,16614,26006,17129,24769,24608,17714,17682,18532,17597,29247,28789,27011,29841,32640,17508,27662,23548,29514};
|
||||||
|
|
||||||
|
|
||||||
|
int dosmain(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
vga_on();
|
||||||
|
vga_clear(BACKGROUND);
|
||||||
|
vga_vsync();
|
||||||
|
|
||||||
|
vga_print((struct point){str_line_middle(strlen("WWWWWWWWWWWWWOOOOOOOOOOWWWWWOO OOOOOOOWWWWWWWWWWWWWWW")), 14}, MAGENTA, "WWWWWWWWWWWWWOOOOOOOOOOWWWWWOO OOOOOOOWWWWWWWWWWWWWWW");
|
||||||
|
vga_print((struct point){str_line_middle(strlen("WWWWWWWWOOO OONWWWWWOOO OOOWWWWWWWWWW")), 23}, MAGENTA, "WWWWWWWWOOO OONWWWWWOOO OOOWWWWWWWWWW");
|
||||||
|
vga_print((struct point){str_line_middle(strlen("WWWWWWOOO OOOdOOWWWWMMWOOdOOO OdOWWWWWWWW")), 32}, MAGENTA, "WWWWWWOOO OOOdOOWWWWMMWOOdOOO OdOWWWWWWWW");
|
||||||
|
vga_print((struct point){str_line_middle(strlen("WWWWWOO OOdONWOOOdOOOOOdOOOWNOOO OOWWWWWWW")), 41}, MAGENTA, "WWWWWOO OOdONWOOOdOOOOOdOOOWNOOO OOWWWWWWW");
|
||||||
|
vga_print((struct point){str_line_middle(strlen("WWWNOO OONWOOOOO OOOOOWOOO OOWWWWWW")), 50}, MAGENTA, "WWWNOO OONWOOOOO OOOOOWOOO OOWWWWWW");
|
||||||
|
vga_print((struct point){str_line_middle(strlen("WWWOO OOOWOOO OdOWOOO OOWWWWW")), 59}, MAGENTA, "WWWOO OOOWOOO OdOWOOO OOWWWWW");
|
||||||
|
vga_print((struct point){str_line_middle(strlen("WWOO OONWOO OOWNdO OOWWWW")), 68}, MAGENTA, "WWOO OONWOO OOWNdO OOWWWW");
|
||||||
|
vga_print((struct point){str_line_middle(strlen("WNO OONWOO OOWNOO OONWWW")), 77}, MAGENTA, "WNO OONWOO OOWNOO OONWWW");
|
||||||
|
vga_print((struct point){str_line_middle(strlen("WOO OOWOO OOWOO OOMWW")), 86}, MAGENTA, "WOO OOWOO OOWOO OOMWW");
|
||||||
|
vga_print((struct point){str_line_middle(strlen("WOO OOMOO OOWOO OOWWW")), 95}, MAGENTA, "WOO OOMOO OOWOO OOWWW");
|
||||||
|
vga_print((struct point){str_line_middle(strlen("WOO OOWNdO OOWWOO ONMWO")), 104}, MAGENTA, "WOO OOWNdO OOWWOO ONMWO");
|
||||||
|
vga_print((struct point){str_line_middle(strlen("WWOO OOWOOO OdNWOO OOWWWO")), 113}, MAGENTA, "WWOO OOWOOO OdNWOO OOWWWO");
|
||||||
|
vga_print((struct point){str_line_middle(strlen("WWNOO OOWNOO OOOWNOO OdNMWWW")), 122}, MAGENTA, "WWNOO OOWNOO OOOWNOO OdNMWWW");
|
||||||
|
vga_print((struct point){str_line_middle(strlen("WWWOOO OOOWOOOO OOONWOOO OONWWWWW")), 131}, MAGENTA, "WWWOOO OOOWOOOO OOONWOOO OONWWWWW");
|
||||||
|
vga_print((struct point){str_line_middle(strlen("WWWWOdO OOONWOOdOOOOOOOOOdOOWNOOO OdNWWWWWW")), 140}, MAGENTA, "WWWWOdO OOONWOOdOOOOOOOOOdOOWNOOO OdNWWWWWW");
|
||||||
|
vga_print((struct point){str_line_middle(strlen("WWWWWNOOO OOOOOOWWNNNNWWNOOOOOO OOOWWWWWWWW")), 149}, MAGENTA, "WWWWWNOOO OOOOOOWWNNNNWWNOOOOOO OOOWWWWWWWW");
|
||||||
|
vga_print((struct point){str_line_middle(strlen("WWWWWWWOOOO OOdNWWWWMNdOO OOONWWWWWWWWW")), 158}, MAGENTA, "WWWWWWWOOOO OOdNWWWWMNdOO OOONWWWWWWWWW");
|
||||||
|
vga_print((struct point){str_line_middle(strlen("WWWWWWWWWWWWOOOOOO OOMWWWWOO OOOOOOWWWWWMWWWWWWWW")), 167}, MAGENTA, "WWWWWWWWWWWWOOOOOO OOMWWWWOO OOOOOOWWWWWMWWWWWWWW");
|
||||||
|
vga_print((struct point){str_line_middle(strlen("WWWWWWWWWWWWWWWNOOOOOONWWWWWNOOdOOONWWWWWWWWWWWWWWWWW")), 176}, MAGENTA, "WWWWWWWWWWWWWWWNOOOOOONWWWWWNOOdOOONWWWWWWWWWWWWWWWWW");
|
||||||
|
delay();
|
||||||
|
vga_clear(BACKGROUND);
|
||||||
|
gen_random_a();
|
||||||
|
uint32_t rand_gen[15];
|
||||||
|
for(uint32_t i=0;i<15;i++)
|
||||||
|
{
|
||||||
|
rand_gen[i] = myrand();
|
||||||
|
}
|
||||||
|
for(uint32_t i=0;i<15;i++)
|
||||||
|
{
|
||||||
|
for(uint32_t j=0;j<15;j++)
|
||||||
|
{
|
||||||
|
get_matrix[i] += (my_matrix[i*15+j] * rand_gen[j]) & (0xffff);
|
||||||
|
get_matrix[i] = get_matrix[i] & 0xffff;
|
||||||
|
vga_clear(BACKGROUND);
|
||||||
|
vga_print((struct point){str_line_middle(strlen("GETFLAG OPERATING SYSTEM")), 5}, MAGENTA, "GETFLAG OPERATING SYSTEM");
|
||||||
|
vga_print((struct point){0, 15}, MAGENTA, "OPERATING SYSTEM USE AI TECH");
|
||||||
|
vga_print((struct point){0, 25}, MAGENTA, "SETTING A RANDOM FLAG SEED");
|
||||||
|
vga_print((struct point){0, 35}, RED, "CHECKED YOU ARE PLAYING USTC HACKERGAME");
|
||||||
|
vga_print((struct point){0, 45}, MAGENTA, "LET ME COMPUTE FLAG FOR YOU");
|
||||||
|
vga_print((struct point){0, 55}, MAGENTA, "IF I FIND THE FLAG I WILL PRINT IT");
|
||||||
|
for(short k=0; k<0xff;k++)
|
||||||
|
{
|
||||||
|
vga_print((struct point){0, 65}, RED, "COMPUTING PLEASE WAIT");
|
||||||
|
usleep(800);
|
||||||
|
vga_print((struct point){0, 65}, BLACK, "COMPUTING PLEASE WAIT");
|
||||||
|
usleep(800);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vga_clear(BACKGROUND);
|
||||||
|
vga_print((struct point){str_line_middle(strlen("GETFLAG OPERATING SYSTEM")), 5}, MAGENTA, "GETFLAG OPERATING SYSTEM");
|
||||||
|
vga_print((struct point){0, 15}, MAGENTA, "FOUND A SOLUTION");
|
||||||
|
vga_print((struct point){0, 25}, MAGENTA, "FLAG IS IN PRINTABLE FORMAT");
|
||||||
|
vga_print((struct point){0, 35}, MAGENTA, "THE SYSTEM MAY GET WRONG SEED");
|
||||||
|
vga_print((struct point){0, 45}, MAGENTA, "YOU SHOULD RESET IT");
|
||||||
|
for(int i=0; i < 0xff; i++)
|
||||||
|
{
|
||||||
|
for(int j=0; j < 0xa0; j++)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delay();
|
||||||
|
vga_off();
|
||||||
|
// 187 49114 12533 39320 44039 25566 22160 10990 15801 27249 45757 55153 58050 7065 14228
|
||||||
|
// printl(get_matrix[0]);
|
||||||
|
// printl(get_matrix[1]);
|
||||||
|
// printl(get_matrix[2]);
|
||||||
|
// printl(get_matrix[3]);
|
||||||
|
// printl(get_matrix[4]);
|
||||||
|
// printl(get_matrix[5]);
|
||||||
|
// printl(get_matrix[6]);
|
||||||
|
// printl(get_matrix[7]);
|
||||||
|
// printl(get_matrix[8]);
|
||||||
|
// printl(get_matrix[9]);
|
||||||
|
// printl(get_matrix[10]);
|
||||||
|
// printl(get_matrix[11]);
|
||||||
|
// printl(get_matrix[12]);
|
||||||
|
// printl(get_matrix[13]);
|
||||||
|
// printl(get_matrix[14]);
|
||||||
|
char out[40];
|
||||||
|
|
||||||
|
out[30] = '$';
|
||||||
|
out[31] = '$';
|
||||||
|
out[32] = '$';
|
||||||
|
out[33] = '$';
|
||||||
|
print("\nYOU SHOULD CHECK PRINT OUT STRING ASCII$$");
|
||||||
|
print("\nDOS ONLY PRINT UPPERCASE LETTERS$$");
|
||||||
|
print("\n$$$$");
|
||||||
|
unsigned short aim[30]={221, 49078, 12436, 39423, 44156, 25529, 22179, 10906, 15839, 27165, 45705, 55062, 58013, 7081, 14308, 136, 49064, 12481, 39404, 44086, 25520, 22263, 10929, 15818, 27144, 45774, 55045, 58097, 7156, 14313};
|
||||||
|
for(short i=0; i<30;i++)
|
||||||
|
{
|
||||||
|
out[i] = (char)(aim[i] ^ get_matrix[i%15]);
|
||||||
|
}
|
||||||
|
print(out);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
/* NOTICE: This must be included first! */
|
||||||
|
asm (".code16gcc\n"
|
||||||
|
"call dosmain\n"
|
||||||
|
"mov $0x4C,%ah\n"
|
||||||
|
"int $0x21\n");
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
#ifndef INT_H
|
||||||
|
#define INT_H
|
||||||
|
|
||||||
|
typedef unsigned char uint8_t;
|
||||||
|
typedef char int8_t;
|
||||||
|
typedef unsigned short uint16_t;
|
||||||
|
typedef short int16_t;
|
||||||
|
typedef unsigned long int uint32_t;
|
||||||
|
typedef long int int32_t;
|
||||||
|
typedef unsigned long long int uint64_t;
|
||||||
|
typedef long long int int64_t;
|
||||||
|
typedef unsigned short size_t;
|
||||||
|
|
||||||
|
#define true 1
|
||||||
|
#define false 0
|
||||||
|
typedef char bool;
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
#include "math.h"
|
||||||
|
#include "int.h"
|
||||||
|
|
||||||
|
struct joystick {
|
||||||
|
uint16_t axis[4];
|
||||||
|
bool button[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct joystick_config {
|
||||||
|
uint16_t min[4];
|
||||||
|
uint16_t max[4];
|
||||||
|
uint16_t center[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct joystick_config joystick_config = {
|
||||||
|
{0xffff, 0xffff, 0xffff, 0xffff},
|
||||||
|
{0x0000, 0x0000, 0x0000, 0x0000},
|
||||||
|
{0x0000, 0x0000, 0x0000, 0x0000},
|
||||||
|
};
|
||||||
|
|
||||||
|
static void joystick_read(struct joystick *joystick)
|
||||||
|
{
|
||||||
|
asm volatile ("mov $0x84, %%ah\n"
|
||||||
|
"mov $1, %%dx\n"
|
||||||
|
"int $0x15\n"
|
||||||
|
: "=a"(joystick->axis[0]), "=b"(joystick->axis[1]),
|
||||||
|
"=c"(joystick->axis[2]), "=d"(joystick->axis[3]));
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
joystick_config.min[i] =
|
||||||
|
min(joystick_config.min[i], joystick->axis[i]);
|
||||||
|
joystick_config.max[i] =
|
||||||
|
max(joystick_config.max[i], joystick->axis[i]);
|
||||||
|
}
|
||||||
|
uint16_t buttons = 0;
|
||||||
|
asm volatile ("mov $0x84, %%ah\n"
|
||||||
|
"mov $0, %%dx\n"
|
||||||
|
"int $0x15\n"
|
||||||
|
: "=a"(buttons)
|
||||||
|
: /**/
|
||||||
|
: "bx", "cx", "dx");
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
joystick->button[i] = !(buttons & (1 << (i + 4)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "vga.h"
|
||||||
|
#include "vga_font.h"
|
||||||
|
|
||||||
|
static void joystick_crosshair(struct point c, uint8_t color)
|
||||||
|
{
|
||||||
|
vga_line((struct point){c.x - 2, c.y},
|
||||||
|
(struct point){c.x + 2, c.y}, color);
|
||||||
|
vga_line((struct point){c.x, c.y - 2},
|
||||||
|
(struct point){c.x, c.y + 2}, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void joystick_calibrate()
|
||||||
|
{
|
||||||
|
vga_clear(BLUE);
|
||||||
|
int32_t scaled[4] = {};
|
||||||
|
struct joystick joy;
|
||||||
|
do {
|
||||||
|
vga_vsync();
|
||||||
|
joystick_crosshair((struct point){scaled[0], scaled[1]}, BLUE);
|
||||||
|
joystick_crosshair((struct point){scaled[2], scaled[3]}, BLUE);
|
||||||
|
joystick_read(&joy);
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
int32_t scale = joystick_config.max[i] - joystick_config.min[i];
|
||||||
|
if (scale != 0) {
|
||||||
|
scaled[i] = joy.axis[i] - joystick_config.min[i];
|
||||||
|
scaled[i] *= (i & 0x01) ? VGA_PHEIGHT : VGA_PWIDTH;
|
||||||
|
scaled[i] /= scale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
joystick_crosshair((struct point){scaled[0], scaled[1]}, WHITE);
|
||||||
|
joystick_crosshair((struct point){scaled[2], scaled[3]}, YELLOW);
|
||||||
|
vga_print((struct point){55, 80}, YELLOW,
|
||||||
|
"MOVE JOYSTICK AROUND ITS FULL RANGE");
|
||||||
|
vga_print((struct point){43, 113}, YELLOW,
|
||||||
|
"THEN CENTER JOYSTICK AND PRESS BUTTON A");
|
||||||
|
vga_pixel((struct point){VGA_PWIDTH / 2, VGA_PHEIGHT / 2}, BLACK);
|
||||||
|
} while (!joy.button[0]);
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
joystick_config.center[i] = joy.axis[i];
|
||||||
|
vga_clear(LIGHT_BLUE);
|
||||||
|
do
|
||||||
|
joystick_read(&joy);
|
||||||
|
while (joy.button[0]);
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
#include "int.h"
|
||||||
|
|
||||||
|
static bool kbhit()
|
||||||
|
{
|
||||||
|
bool result;
|
||||||
|
asm volatile ("mov $1, %%ah\n"
|
||||||
|
"int $0x16\n"
|
||||||
|
"jnz set%=\n"
|
||||||
|
"mov $0, %0\n"
|
||||||
|
"jmp done%=\n"
|
||||||
|
"set%=:\n"
|
||||||
|
"mov $1, %0\n"
|
||||||
|
"done%=:\n"
|
||||||
|
: "=rm"(result));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint16_t kb_read()
|
||||||
|
{
|
||||||
|
uint16_t key;
|
||||||
|
asm volatile ("mov $1, %%ah\n"
|
||||||
|
"int $0x16\n"
|
||||||
|
"jnz get%=\n"
|
||||||
|
"mov $0, %%ax\n"
|
||||||
|
"jmp done%=\n"
|
||||||
|
"get%=:\n"
|
||||||
|
"mov $0, %%ah\n"
|
||||||
|
"int $0x16\n"
|
||||||
|
"jmp done%=\n"
|
||||||
|
"done%=:\n"
|
||||||
|
: "=a"(key));
|
||||||
|
return key;
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
#ifndef MATH_H
|
||||||
|
#define MATH_H
|
||||||
|
|
||||||
|
static inline int abs(int x)
|
||||||
|
{
|
||||||
|
return x < 0 ? -x : x;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int max(int a, int b)
|
||||||
|
{
|
||||||
|
return a < b ? b : a;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int min(int a, int b)
|
||||||
|
{
|
||||||
|
return b < a ? b : a;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
20597,19141,29258,17804,29076,28746,24890,28979,26196,31833,26624,24774,18916,29028,24033,22913,23436,25750,26539,21652,31296,22446,16506,21949,22761,30221,29477,29617,16497,23022,23179,30781,23877,29171,31665,26534,32159,22583,27525,28708,31216,17158,31988,32190,23747,21272,21278,24727,29984,25303,23445,23119,23155,26346,26389,30747,28948,31418,21323,31758,30911,18790,21312,25099,22348,25409,29357,22180,23588,28794,18133,25624,21972,23401,24821,31369,25187,31517,19840,28836,20794,20239,24523,30814,24016,17954,21227,16691,30290,23391,20482,24822,31968,30651,27908,22690,30875,31003,31747,19978,25482,18563,30143,27788,26658,26295,23244,27086,26456,24251,28647,22783,27460,19187,23252,24078,19203,26251,18113,19542,24533,16666,24038,32744,28670,30438,26379,18591,30109,26509,20947,27696,22945,27542,32128,25416,21675,19389,27085,29380,20163,21102,30936,30862,18230,21904,16938,16579,20641,27551,22740,24666,16836,23306,27661,26506,28623,29816,20166,29405,23982,30046,19365,24926,19029,32448,17567,17156,18678,28594,19769,28631,25769,31309,24457,30625,21825,29811,17112,31370,25345,24333,24005,31606,30942,21441,30599,22894,18015,19994,27901,26868,21948,27614,23449,21289,19588,19955,28133,16696,31509,26219,19946,27895,28760,28547,28315,16614,26006,17129,24769,24608,17714,17682,18532,17597,29247,28789,27011,29841,32640,17508,27662,23548,29514,
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
#ifndef PORT_H
|
||||||
|
#define PORT_H
|
||||||
|
|
||||||
|
#include "int.h"
|
||||||
|
|
||||||
|
static inline int16_t inportb(int16_t port)
|
||||||
|
{
|
||||||
|
volatile uint8_t value;
|
||||||
|
asm volatile ("in %%dx, %%ax\n"
|
||||||
|
: "=a"(value)
|
||||||
|
: "d"(port));
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void outportb(int16_t port, uint8_t value)
|
||||||
|
{
|
||||||
|
asm volatile ("out %%al, %%dx\n"
|
||||||
|
: /* no output */
|
||||||
|
: "d"(port), "a"(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
static void print(char *string)
|
||||||
|
{
|
||||||
|
asm volatile ("mov $0x09, %%ah\n"
|
||||||
|
"int $0x21\n"
|
||||||
|
: /* no output */
|
||||||
|
: "d"(string)
|
||||||
|
: "ah");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void printl(unsigned long n)
|
||||||
|
{
|
||||||
|
volatile char buffer[12];
|
||||||
|
int i = sizeof(buffer);
|
||||||
|
buffer[--i] = '$';
|
||||||
|
if (n == 0)
|
||||||
|
buffer[--i] = '0';
|
||||||
|
else
|
||||||
|
for (; n > 0; n /= 10)
|
||||||
|
buffer[--i] = '0' + (n % 10);
|
||||||
|
print((char *) buffer + i);
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
#ifndef RANDOM_H
|
||||||
|
#define RANDOM_H
|
||||||
|
|
||||||
|
#include "int.h"
|
||||||
|
|
||||||
|
#define RAND_MAX 4294967295
|
||||||
|
|
||||||
|
static uint32_t rand_seed = 375226057;
|
||||||
|
|
||||||
|
static uint32_t rand(void)
|
||||||
|
{
|
||||||
|
rand_seed = rand_seed * 1103515245 + 12345;
|
||||||
|
return rand_seed;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t randn(uint32_t n)
|
||||||
|
{
|
||||||
|
return (rand() >> 7) % n;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,229 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "int.h"
|
||||||
|
#include "tone.h"
|
||||||
|
|
||||||
|
struct note {
|
||||||
|
unsigned frequency;
|
||||||
|
uint16_t length;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sample {
|
||||||
|
int priority;
|
||||||
|
size_t length;
|
||||||
|
struct note notes[];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sample fx_menu_toggle = {
|
||||||
|
.priority = 50,
|
||||||
|
.length = 3,
|
||||||
|
{
|
||||||
|
{600, 2},
|
||||||
|
{1000, 1},
|
||||||
|
{700, 2}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sample fx_menu_select = {
|
||||||
|
.priority = 55,
|
||||||
|
.length = 4,
|
||||||
|
{
|
||||||
|
{800, 2},
|
||||||
|
{900, 3},
|
||||||
|
{1000, 4},
|
||||||
|
{0, 10}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sample fx_intro_music = {
|
||||||
|
.priority = 100,
|
||||||
|
.length = 11,
|
||||||
|
{
|
||||||
|
{262, 10},
|
||||||
|
{247, 10},
|
||||||
|
{220, 10},
|
||||||
|
{196, 10},
|
||||||
|
{247, 10},
|
||||||
|
{220, 10},
|
||||||
|
{196, 10},
|
||||||
|
{247, 10},
|
||||||
|
{220, 10},
|
||||||
|
{0, 10},
|
||||||
|
{110, 20},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sample fx_end_music = {
|
||||||
|
.priority = 200,
|
||||||
|
.length = 15,
|
||||||
|
{
|
||||||
|
{62, 50},
|
||||||
|
{0, 2},
|
||||||
|
{62, 50},
|
||||||
|
{0, 2},
|
||||||
|
{62, 50},
|
||||||
|
{0, 2},
|
||||||
|
{73, 25},
|
||||||
|
{0, 2},
|
||||||
|
{65, 20},
|
||||||
|
{0, 2},
|
||||||
|
{62, 50},
|
||||||
|
{0, 2},
|
||||||
|
{55, 50},
|
||||||
|
{0, 2},
|
||||||
|
{62, 100},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sample fx_explode = {
|
||||||
|
.priority = 10,
|
||||||
|
.length = 11,
|
||||||
|
{
|
||||||
|
{62, 1},
|
||||||
|
{47, 1},
|
||||||
|
{20, 1},
|
||||||
|
{96, 1},
|
||||||
|
{47, 1},
|
||||||
|
{20, 1},
|
||||||
|
{96, 1},
|
||||||
|
{47, 1},
|
||||||
|
{20, 1},
|
||||||
|
{89, 1},
|
||||||
|
{60, 1},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sample fx_fire0 = {
|
||||||
|
.priority = 0,
|
||||||
|
.length = 4,
|
||||||
|
{
|
||||||
|
{200, 1},
|
||||||
|
{190, 1},
|
||||||
|
{180, 1},
|
||||||
|
{170, 1}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sample fx_fire1 = {
|
||||||
|
.priority = -10,
|
||||||
|
.length = 5,
|
||||||
|
{
|
||||||
|
{150, 1},
|
||||||
|
{120, 1},
|
||||||
|
{100, 1},
|
||||||
|
{120, 1},
|
||||||
|
{135, 1}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sample fx_fire2 = {
|
||||||
|
.priority = -5,
|
||||||
|
.length = 5,
|
||||||
|
{
|
||||||
|
{300, 1},
|
||||||
|
{320, 1},
|
||||||
|
{330, 1},
|
||||||
|
{335, 1},
|
||||||
|
{340, 1}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sample fx_fire3 = {
|
||||||
|
.priority = 1,
|
||||||
|
.length = 14,
|
||||||
|
{
|
||||||
|
{50, 7},
|
||||||
|
{75, 7},
|
||||||
|
{100, 7},
|
||||||
|
{150, 7},
|
||||||
|
{200, 1},
|
||||||
|
{250, 1},
|
||||||
|
{300, 1},
|
||||||
|
{370, 1},
|
||||||
|
{360, 1},
|
||||||
|
{350, 1},
|
||||||
|
{340, 1},
|
||||||
|
{330, 1},
|
||||||
|
{320, 1},
|
||||||
|
{310, 1}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sample fx_hit = {
|
||||||
|
.priority = 5,
|
||||||
|
.length = 5,
|
||||||
|
{
|
||||||
|
{120, 3},
|
||||||
|
{130, 3},
|
||||||
|
{140, 3},
|
||||||
|
{150, 3},
|
||||||
|
{160, 3}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sample fx_powerup = {
|
||||||
|
.priority = 50,
|
||||||
|
.length = 2,
|
||||||
|
{
|
||||||
|
{800, 3},
|
||||||
|
{900, 3}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sample fx_boss = {
|
||||||
|
.priority = 500,
|
||||||
|
.length = 13,
|
||||||
|
{
|
||||||
|
{110, 15},
|
||||||
|
{0, 2},
|
||||||
|
{110, 15},
|
||||||
|
{0, 2},
|
||||||
|
{110, 5},
|
||||||
|
{175, 30},
|
||||||
|
{0, 2},
|
||||||
|
{175, 15},
|
||||||
|
{0, 2},
|
||||||
|
{175, 15},
|
||||||
|
{0, 2},
|
||||||
|
{175, 5},
|
||||||
|
{110, 30},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct speaker {
|
||||||
|
struct sample *sample;
|
||||||
|
int index, step;
|
||||||
|
};
|
||||||
|
|
||||||
|
void speaker_play(struct speaker *speaker, struct sample *sample)
|
||||||
|
{
|
||||||
|
if (!speaker->sample || speaker->sample->priority < sample->priority) {
|
||||||
|
speaker->sample = sample;
|
||||||
|
speaker->index = -1;
|
||||||
|
speaker->step = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void speaker_step(struct speaker *speaker)
|
||||||
|
{
|
||||||
|
if (speaker->sample) {
|
||||||
|
if (speaker->step) {
|
||||||
|
speaker->step--;
|
||||||
|
} else {
|
||||||
|
speaker->index++;
|
||||||
|
if (speaker->index >= speaker->sample->length) {
|
||||||
|
speaker->sample = 0;
|
||||||
|
tone_off();
|
||||||
|
} else {
|
||||||
|
struct note note = speaker->sample->notes[speaker->index];
|
||||||
|
if (note.frequency == 0)
|
||||||
|
tone_off();
|
||||||
|
else {
|
||||||
|
tone(note.frequency);
|
||||||
|
tone_on();
|
||||||
|
}
|
||||||
|
speaker->step = note.length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
#ifndef TIME_H
|
||||||
|
#define TIME_H
|
||||||
|
|
||||||
|
static uint32_t get_tick()
|
||||||
|
{
|
||||||
|
unsigned long result;
|
||||||
|
asm volatile ("push %%es\n"
|
||||||
|
"mov $0,%%bx\n"
|
||||||
|
"mov %%bx,%%es\n"
|
||||||
|
"mov $0x046C,%%bx\n"
|
||||||
|
"mov %%es:(%%bx),%%eax\n"
|
||||||
|
"pop %%es\n"
|
||||||
|
: "=a"(result)
|
||||||
|
: /* no inputs */
|
||||||
|
: "bx");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t get_time()
|
||||||
|
{
|
||||||
|
uint16_t high, low;
|
||||||
|
asm volatile ("mov $0x2C, %%ah\n"
|
||||||
|
"int $0x21\n"
|
||||||
|
: "=c"(high), "=d"(low)
|
||||||
|
:
|
||||||
|
: "ah");
|
||||||
|
return (((uint32_t) high) << 16) | low;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Granularity of 976 usec and doesn't work in DOSBox. */
|
||||||
|
static void usleep(uint32_t us)
|
||||||
|
{
|
||||||
|
asm volatile ("mov $0x86, %%ah\n"
|
||||||
|
"int $0x15\n"
|
||||||
|
: /* no outputs */
|
||||||
|
: "c"(us >> 16), "d"(us & 0x16)
|
||||||
|
: "ah", "flags");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Granularity of 55 msec. */
|
||||||
|
static void msleep(int ms)
|
||||||
|
{
|
||||||
|
uint32_t count = ms / 54; // 18.2 Hz
|
||||||
|
uint32_t last = get_tick();
|
||||||
|
while (count) {
|
||||||
|
uint32_t now = get_tick();
|
||||||
|
if (now != last) {
|
||||||
|
last = now;
|
||||||
|
count--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
#include "port.h"
|
||||||
|
|
||||||
|
static void tone_on()
|
||||||
|
{
|
||||||
|
outportb(0x61, inportb(0x61) | 0x03);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tone_off()
|
||||||
|
{
|
||||||
|
outportb(0x61, inportb(0x61) & ~0x03);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tone(unsigned frequency)
|
||||||
|
{
|
||||||
|
uint16_t period = 1193180 / frequency;
|
||||||
|
outportb(0x42, period & 0xff);
|
||||||
|
outportb(0x42, period >> 8);
|
||||||
|
}
|
||||||
@@ -0,0 +1,117 @@
|
|||||||
|
#ifndef VGA_H
|
||||||
|
#define VGA_H
|
||||||
|
|
||||||
|
#include "math.h"
|
||||||
|
|
||||||
|
#define VGA_PWIDTH 320
|
||||||
|
#define VGA_PHEIGHT 200
|
||||||
|
|
||||||
|
enum VGA_COLOR {
|
||||||
|
BLACK, BLUE, GREEN, CYAN, RED, MAGENTA, BROWN, LIGHT_GRAY, DARK_GRAY,
|
||||||
|
LIGHT_BLUE, LIGHT_GREEN, LIGHT_CYAN, LIGHT_RED, LIGHT_MAGENTA,
|
||||||
|
YELLOW, WHITE
|
||||||
|
};
|
||||||
|
|
||||||
|
struct point {
|
||||||
|
short x, y;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rect {
|
||||||
|
struct point tl, br;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Switch to VGA mode 13 and set ES. */
|
||||||
|
static void vga_on()
|
||||||
|
{
|
||||||
|
asm volatile ("mov $0x0013, %%ax\n"
|
||||||
|
"int $0x10\n"
|
||||||
|
"mov $0xA000, %%ax\n"
|
||||||
|
"mov %%ax, %%es\n"
|
||||||
|
: /* no outputs */
|
||||||
|
: /* no inputs */
|
||||||
|
: "ax");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vga_off()
|
||||||
|
{
|
||||||
|
asm volatile ("mov $0x0003, %%ax\n"
|
||||||
|
"int $0x10\n"
|
||||||
|
"mov $0xA000, %%dx\n"
|
||||||
|
"mov %%dx, %%es\n"
|
||||||
|
: /* no outputs */
|
||||||
|
: /* no inputs */
|
||||||
|
: "ax", "dx");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vga_pixel(volatile struct point p, uint8_t color)
|
||||||
|
{
|
||||||
|
if (p.x >= 0 && p.x < VGA_PWIDTH && p.y >= 0 && p.y < VGA_PHEIGHT)
|
||||||
|
asm volatile ("imul $320, %%bx\n"
|
||||||
|
"add %%ax, %%bx\n"
|
||||||
|
"mov %%cl, %%es:(%%bx)\n"
|
||||||
|
: /* no outputs */
|
||||||
|
: "a"(p.x), "b"(p.y), "c"(color)
|
||||||
|
: "dx");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vga_clear(char color)
|
||||||
|
{
|
||||||
|
asm volatile ("mov %%al, %%ah\n"
|
||||||
|
"mov $0, %%di\n"
|
||||||
|
"push %%ax\n"
|
||||||
|
"shl $16, %%eax\n"
|
||||||
|
"pop %%ax\n"
|
||||||
|
"mov $16000, %%cx\n"
|
||||||
|
"rep\n"
|
||||||
|
"stosl\n"
|
||||||
|
: /* no outputs */
|
||||||
|
: "a"(color)
|
||||||
|
: "cx", "di");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vga_line(struct point a, struct point b, uint8_t color)
|
||||||
|
{
|
||||||
|
int dx = abs(b.x - a.x), sx = a.x < b.x ? 1 : -1;
|
||||||
|
int dy = abs(b.y - a.y), sy = a.y < b.y ? 1 : -1;
|
||||||
|
int err = (dx > dy ? dx : -dy) / 2, e2;
|
||||||
|
for(;;) {
|
||||||
|
vga_pixel(a, color);
|
||||||
|
if (a.x == b.x && a.y == b.y)
|
||||||
|
break;
|
||||||
|
e2 = err;
|
||||||
|
if (e2 > -dx) {
|
||||||
|
err -= dy;
|
||||||
|
a.x += sx;
|
||||||
|
}
|
||||||
|
if (e2 < dy) {
|
||||||
|
err += dx;
|
||||||
|
a.y += sy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vga_rect(struct rect r, uint8_t color)
|
||||||
|
{
|
||||||
|
vga_line(r.tl, (struct point){r.br.x, r.tl.y}, color);
|
||||||
|
vga_line(r.tl, (struct point){r.tl.x, r.br.y}, color);
|
||||||
|
vga_line(r.br, (struct point){r.br.x, r.tl.y}, color);
|
||||||
|
vga_line(r.br, (struct point){r.tl.x, r.br.y}, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vga_vsync()
|
||||||
|
{
|
||||||
|
asm volatile ("mov $0x03DA, %%dx\n"
|
||||||
|
"current%=:"
|
||||||
|
"in %%dx, %%al\n"
|
||||||
|
"and $0x8, %%al\n"
|
||||||
|
"jnz current%=\n"
|
||||||
|
"restart%=:"
|
||||||
|
"in %%dx, %%al\n"
|
||||||
|
"and $0x8, %%al\n"
|
||||||
|
"jz restart%=\n"
|
||||||
|
: /* no outputs */
|
||||||
|
: /* no inputs */
|
||||||
|
: "al", "dx");
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
#include "int.h"
|
||||||
|
#include "vga.h"
|
||||||
|
|
||||||
|
/* Letters are 7 pixels tall and 5 pixels wide. */
|
||||||
|
|
||||||
|
/* http://redd.it/2ba3g3 */
|
||||||
|
static const char LINES[] = "BCDEIKOPQRSTUVYZ\\_`";
|
||||||
|
static const char LETTERS[] =
|
||||||
|
"DFJSJJJRJJRJJRGJIIIJGRJJJJJRSIIRIISSIIRIIIHIILJJHJJJSJJJGDDDD"
|
||||||
|
"DGAAAAAJHJKMOMKJIIIIIISJQNJJJJJJPNLJJGJJJJJGRJJRIIIGJJJNGCRJJ"
|
||||||
|
"RMKJGJIGAJGSDDDDDDJJJJJJGJJJJJFDJJJNQJJJJFDFJJJJFDDDDSABDEIS";
|
||||||
|
|
||||||
|
static int vga_font_line(int c, int row) {
|
||||||
|
return c == ' ' ? 0 : LINES[LETTERS[(c - 'A') * 7 + row] - 'A'] - 'A';
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vga_print(struct point p, uint8_t color, const char *message)
|
||||||
|
{
|
||||||
|
for (int y = 0; y < 7; y++) {
|
||||||
|
for (int x = 0; message[x]; x++) {
|
||||||
|
int c = message[x];
|
||||||
|
int line = vga_font_line(c, y);
|
||||||
|
for (int i = 0; i < 5; i++) {
|
||||||
|
if ((line >> i) & 0x01) {
|
||||||
|
int dx = p.x + x * 6 + (4 - i);
|
||||||
|
int dy = p.y + y;
|
||||||
|
vga_pixel((struct point){dx, dy}, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||