Skip to content

Instantly share code, notes, and snippets.

@stadaki
Last active December 24, 2015 17:39
Show Gist options
  • Save stadaki/6837214 to your computer and use it in GitHub Desktop.
Save stadaki/6837214 to your computer and use it in GitHub Desktop.
Tetris ktap script
#!/usr/bin/env ktap
#
# Tetris KTAP Script
#
# Copyright (C) 2013/OCT/05 Tadaki SAKAI
#
# based on stapgames (Systemtap Game Collection)
# https://github.com/mhiramat/stapgames/blob/master/games/tetris.stp
#
# - Requirements
# Kernel Configuration: CONFIG_KPROBE_EVENT=y
# CONFIG_EVENT_TRACING=y
# CONFIG_PERF_EVENTS=y
# CONFIG_DEBUG_FS=y
# CPU Architecture : x86_64
#
# - Setup
# $ sudo mount -t debugfs none /sys/kernel/debug/
#
# $ git clone https://github.com/ktap/ktap
# $ cd ktap
# $ make 2>&1 | tee ../make.log
# $ sudo make load
# $ sudo sh -c 'echo 50000 > /sys/module/ktapvm/parameters/max_exec_count'
#
# - Run Tetris
# $ sudo ./ktap samples/game/tetris.kp
#
#
# global value
#
var empty = -1
var key_code = 0
var point = 0
var block_number = 0
var height = 0
var height_update = 0
var destination_position = {}
var block_data0 = {}
var block_data1 = {}
var block_data2 = {}
var block_data3 = {}
var block_data4 = {}
var block_data5 = {}
var block_data6 = {}
var block_table = {}
var display_buffer = {}
#
# utils
#
function rand(max) {
r = gettimeofday_us()
if (r < 0) {
r = r * -1
}
return r % max
}
function update_display() {
for (i = 0, 239, 1) {
if ((i % 12 - 11) != 0) {
tmp = ""
} else {
tmp = "\n"
}
if (display_buffer[240 + i] == empty) {
printf(" %s", tmp)
} else {
color = display_buffer[240 + i] + 40
ansi.set_color2(color, color)
printf(" %s", tmp)
ansi.reset_color()
}
# clear the display buffer
display_buffer[240 + i] = display_buffer[i]
}
printf("%d\n",point)
}
#
# Initialize
#
# Create blocks
# block is represented by the position from the center.
# Every block has "L" part in the center except for a bar.
block_data0[0] = -11 # non-"L" part for each block
block_data1[0] = -24
block_data2[0] = 2
block_data3[0] = 13
block_data4[0] = -13
block_data5[0] = -1
block_data6[0] = 2
block_table[0] = block_data0
block_table[1] = block_data1
block_table[2] = block_data2
block_table[3] = block_data3
block_table[4] = block_data4
block_table[5] = block_data5
block_table[6] = block_data6
for (i = 0, len(block_table) - 1, 1) {
# common "L" part
block_table[i][1] = 0
block_table[i][2] = 1
block_table[i][3] = -12
}
block_table[6][3] = -1 # bar is not common
# Position: 1 row has 12 columns,
# and (x, y) is represented by h = x + y * 12.p
height = 17 # First block position (center)
for (i = 0, 240, 1) {
# Wall and Floor (sentinel)
if (((i % 12) < 2) || (i > 228)) {
tmp = 7 # White
} else {
tmp = empty
}
display_buffer[i - 1] = tmp
display_buffer[240 + i - 1] = tmp
}
block_number = rand(7)
ansi.clear_screen()
#
# Key Input
#
trace probe:kbd_event handle=%di event_type=%si event_code=%dx value=%cx {
# Only can run it in x86_64
#
# Register follow x86_64 call conversion:
#
# x86_64:
# %rcx 4 argument
# %rdx 3 argument
# %rsi 2 argument
# %rdi 1 argument
var event_code = arg4
var value = arg5
if (value != 0) {
if ((event_code - 4) != 0) {
key_code = event_code
}
}
}
#
# timer
#
tick-200ms {
ansi.clear_screen()
f = 0 # move/rotate flag
if (key_code != 0) { # if key is pressed
if(key_code != 103) { #move left or right
# d: movement direction
if ((key_code - 105) != 0) {
if ((key_code - 106) != 0) {
d = 0
} else {
d = 1
}
} else {
d = -1
}
for (i = 0, 3, 1) { # check if the block can be moved
# destination is free
if (display_buffer[height +
block_table[block_number][i] + d]
!= empty) {
f = 1
}
}
# move if destinations of every block are free
if (f == 0) {
height = height + d
}
} else { # rotate
for (i = 0, 3, 1) { # check if block can be rotated
# each block position
p = block_table[block_number][i]
# destination x pos(p/12 rounded)
v = (p * 2 + 252) / 24 - 10
w = p - v * 12 # destination y pos
# destination position
destination_position[i] = w * 12 - v
# check if desetination is free
if (display_buffer[height +
destination_position[i]] != empty) {
f = 1
}
}
if (f == 0) {
# rotate if destinations of every block
# are free
for (i = 0, 3, 1) {
block_table[block_number][i] =
destination_position[i]
}
}
}
}
key_code = 0 # clear the input key
f = 0
for (i = 0, 3, 1) { # drop 1 row
# check if destination is free
p = height + block_table[block_number][i]
if (display_buffer[12 + p] != empty) {
f = 1
}
# copy the moving block to display buffer
display_buffer[240 + p] = block_number
}
if ((f == 1) && (height == 17)) {
update_display()
exit() # exit if there are block at initial position
}
height_update = !height_update
if (height_update != 0) {
if(f != 0) { # the block can't drop anymore
for (i = 0, 3, 1) {
# fix the block
display_buffer[height +
block_table[block_number][i]] = block_number
}
# determin the next block
block_number = rand(7)
height = 17 # make the block to initial position
} else {
height = height + 12 # drop the block 1 row
}
}
k = 1
for (i = 18, 0, -1) { #check if line is filled
# search for filled line
j = 10
while ((j > 0) &&
(display_buffer[i * 12 + j] != empty)) {
j = j - 1
}
if (j == 0) { # filled!
# add a point: 1 line - 1 point, ..., tetris - 10points
point = point + k
k = k + 1
# drop every upper block
j = (i + 1) * 12
i = i + 1
while (j > 2 * 12) {
j = j - 1
display_buffer[j] = display_buffer[j - 12]
}
}
}
update_display()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment