├── .gitignore
├── iso
└── boot
│ └── grub
│ └── grub.cfg
├── src
├── cmath.asm
├── bin.ld
├── elf.ld
├── globals.asm
├── constants.asm
├── main.asm
├── player.asm
├── init.asm
├── input.asm
├── world.asm
├── interrupts.asm
├── vga.asm
├── reference.c
├── textures.asm
├── graphics.asm
└── splash.asm
├── reference
├── Makefile
└── src
│ ├── textures.c
│ └── mineassemble.c
├── LICENSE
├── Makefile
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | *.o
2 | *.d
3 | *.iso
4 | *.bin
5 | *.elf
6 |
--------------------------------------------------------------------------------
/iso/boot/grub/grub.cfg:
--------------------------------------------------------------------------------
1 | menuentry "MineAssemble" {
2 | multiboot /boot/mineassemble.bin
3 | }
4 |
--------------------------------------------------------------------------------
/src/cmath.asm:
--------------------------------------------------------------------------------
1 | ;
2 | ; This file contains an implementation of part of the C math library
3 | ;
4 |
5 | [bits 32]
6 |
7 | global sinf, cosf, absf
8 |
9 | section .text
10 | sinf:
11 | fld dword [esp + 4]
12 | fsin
13 | ret
14 |
15 | cosf:
16 | fld dword [esp + 4]
17 | fcos
18 | ret
19 |
20 | absf:
21 | fld dword [esp + 4]
22 | fabs
23 | ret
24 |
25 | section .data
26 | temp dd 0.0
--------------------------------------------------------------------------------
/reference/Makefile:
--------------------------------------------------------------------------------
1 | CC = gcc
2 | CFLAGS = -O3 -Wall -Werror
3 |
4 | bin/mineassemble: bin bin/mineassemble.o bin/textures.o
5 | $(CC) $(CFLAGS) -o bin/mineassemble bin/mineassemble.o bin/textures.o -lSDL -lm
6 |
7 | bin/mineassemble.o: src/mineassemble.c
8 | $(CC) $(CFLAGS) -c -o bin/mineassemble.o src/mineassemble.c -std=c99
9 |
10 | bin/textures.o: src/textures.c
11 | $(CC) $(CFLAGS) -c -o bin/textures.o src/textures.c
12 |
13 | bin:
14 | mkdir -p bin
15 |
16 | test:
17 | bin/mineassemble
18 |
19 | clean:
20 | rm -rf bin
--------------------------------------------------------------------------------
/src/bin.ld:
--------------------------------------------------------------------------------
1 | OUTPUT_FORMAT("binary")
2 | OUTPUT_ARCH(i386)
3 | ENTRY(start)
4 |
5 | phys = 0x00100000;
6 |
7 | SECTIONS {
8 | .text phys : AT(phys) {
9 | code = .;
10 | *(.text)
11 | src/init.o(.text)
12 | *(.rodata)
13 | . = ALIGN(4096);
14 | }
15 |
16 | .data : AT(phys + (data - code)) {
17 | data = .;
18 | *(.data)
19 | . = ALIGN(4096);
20 | }
21 |
22 | .bss : AT(phys + (bss - code)) {
23 | bss = .;
24 | *(.bss)
25 | . = ALIGN(4096);
26 | bss_end = .;
27 | }
28 |
29 | end =.;
30 | }
31 |
--------------------------------------------------------------------------------
/src/elf.ld:
--------------------------------------------------------------------------------
1 | OUTPUT_FORMAT("elf32-i386")
2 | OUTPUT_ARCH(i386)
3 | ENTRY(start)
4 |
5 | phys = 0x0100000;
6 |
7 | SECTIONS
8 | {
9 | . = phys;
10 |
11 | .text ALIGN(4096) : AT( ADDR(.text) )
12 | {
13 | code = .;
14 | src/init.o(.text)
15 | *(.text)
16 | *(.rodata)
17 | code_end = .;
18 | }
19 |
20 | .data ALIGN(4096) : AT( ADDR(.data) )
21 | {
22 | data = .;
23 | *(.data)
24 | data_end = .;
25 | }
26 |
27 | .bss ALIGN(4096) : AT( ADDR(.bss) )
28 | {
29 | bss = .;
30 | *(.bss)
31 | bss_end = .;
32 | }
33 |
34 | end = .;
35 | }
36 |
--------------------------------------------------------------------------------
/src/globals.asm:
--------------------------------------------------------------------------------
1 | ;
2 | ; This file contains all data not belonging to any particular module
3 | ;
4 |
5 | [bits 32]
6 |
7 | %include "constants.asm"
8 |
9 | ; Global variables
10 |
11 | global vga
12 |
13 | global half_pi, neg_half_pi, zero
14 |
15 | global hFov
16 | global dPitch, dYaw, velocity
17 |
18 | global colTolerance
19 |
20 | section .data
21 | ; VGA buffer address
22 | vga dd 0xa0000
23 |
24 | ; Helpful constants
25 | half_pi dd 1.57
26 | neg_half_pi dd -1.57
27 | zero dd 0.0
28 |
29 | ; Horizontal field-of-view
30 | hFov dd HOR_FOV
31 |
32 | ; Input/update related (e.g. dPitch = pitch change per second)
33 | dPitch dd 0.0
34 | dYaw dd 0.0
35 | velocity dd 0.0, 0.0, 0.0
36 |
37 | ; Collision tolerance
38 | colTolerance dd 0.1
--------------------------------------------------------------------------------
/src/constants.asm:
--------------------------------------------------------------------------------
1 | ;
2 | ; Configuration constants
3 | ;
4 |
5 | ; World block dimensions
6 | %define WORLD_SX 32
7 | %define WORLD_SY 32
8 | %define WORLD_SZ 32
9 |
10 | ; This is the direction light rays will use
11 | %define SUN_DIR_X 1.0
12 | %define SUN_DIR_Y 3.0
13 | %define SUN_DIR_Z 1.0
14 |
15 | ; Horizontal field-of-view
16 | %define HOR_FOV 90.0
17 |
18 | ;
19 | ; Internal constants
20 | ;
21 |
22 | ; Block types
23 | %define BLOCK_AIR 0
24 | %define BLOCK_DIRT 1
25 |
26 | ; Block faces
27 | %define FACE_LEFT 0
28 | %define FACE_RIGHT 1
29 | %define FACE_BOTTOM 2
30 | %define FACE_TOP 3
31 | %define FACE_BACK 4
32 | %define FACE_FRONT 5
33 |
34 | ; Key scancodes
35 | %define KEY_ESC 0x01
36 |
37 | %define KEY_Q 0x10
38 | %define KEY_E 0x12
39 |
40 | %define KEY_W 0x11
41 | %define KEY_A 0x1E
42 | %define KEY_S 0x1F
43 | %define KEY_D 0x20
44 |
45 | %define KEY_SPACE 0x39
46 | %define KEY_ENTER 0x1C
47 |
48 | %define KEY_UP 0x48
49 | %define KEY_LEFT 0x4B
50 | %define KEY_RIGHT 0x4D
51 | %define KEY_DOWN 0x50
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (C) 2013 Alexander Overvoorde
2 |
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy of
5 | this software and associated documentation files (the "Software"), to deal in
6 | the Software without restriction, including without limitation the rights to
7 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
8 | the Software, and to permit persons to whom the Software is furnished to do so,
9 | subject to the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be included in all
12 | copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
16 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
17 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
18 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/src/main.asm:
--------------------------------------------------------------------------------
1 | ;
2 | ; This file contains the game initialization and main loop code
3 | ;
4 |
5 | [bits 32]
6 |
7 | global main
8 |
9 | extern init_world, handle_input, update, draw_frame
10 | extern time
11 |
12 | section .data
13 | msPerSecond dd 1000.0
14 |
15 | ; Last update time in milliseconds
16 | lastUpdate dd 0
17 |
18 | section .text
19 |
20 | main:
21 | push ebp
22 | mov ebp, esp
23 |
24 | ; Make room for deltaTime variable
25 | sub esp, 4
26 |
27 | ; Initialize world array
28 | call init_world
29 |
30 | ; Main loop
31 | .main_loop:
32 | ; Read input buffer and update motion state
33 | call handle_input
34 |
35 | ; Calculate delta time
36 | ; (time - lastUpdate) / 1000
37 | fild dword [time]
38 | fild dword [lastUpdate]
39 | fsub
40 | fld dword [msPerSecond]
41 | fdiv
42 | fstp dword [ebp - 4]
43 |
44 | ; Update world state
45 | push dword [ebp - 4]
46 | call update
47 | add esp, 4
48 |
49 | ; Save last update time
50 | mov eax, [time]
51 | mov [lastUpdate], eax
52 |
53 | ; Draw next frame
54 | call draw_frame
55 |
56 | jmp .main_loop
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | CC=i686-pc-elf-gcc
2 | LD=i686-pc-elf-ld
3 | ASM=nasm
4 |
5 | CFLAGS:=-std=c99 -MMD
6 | CFLAGS+=-m32
7 | CFLAGS+=-g -ggdb
8 | CFLAGS+=-O3 -ffast-math
9 | CFLAGS+=-ffreestanding -nostdlib -nostdinc -fno-builtin -nostartfiles -nodefaultlibs -fno-exceptions -fno-stack-protector -static -fno-pic
10 |
11 | LDFLAGS=-m elf_i386
12 | LDLIBS=
13 |
14 | ASMFLAGS=-felf -isrc/
15 | ASMFLAGS+=-g
16 |
17 | CSRCS=$(wildcard src/*.c)
18 | ASMSRCS=$(wildcard src/*.asm)
19 | OBJS=$(CSRCS:.c=.o) $(ASMSRCS:.asm=.o)
20 | DEPS=$(OBJS:.o=.d)
21 |
22 | .PHONY: all clean
23 |
24 | all: mineassemble.bin mineassemble.elf
25 |
26 | # NOTE: linker script must be first dependency
27 | mineassemble.%: src/%.ld $(OBJS)
28 | $(LD) $(LDFLAGS) -o $@ -T $^ $(LDLIBS)
29 |
30 | %.o: %.asm
31 | $(ASM) $(ASMFLAGS) -MD $(@:.o=.d) -o $@ $<
32 |
33 | -include $(DEPS)
34 |
35 | # Test in QEMU
36 |
37 | test: mineassemble.bin
38 | qemu-system-i386 -enable-kvm -kernel mineassemble.bin
39 |
40 | .PHONY: test
41 |
42 | # Target for producing ISO image
43 |
44 | iso: mineassemble.iso
45 | mineassemble.iso: mineassemble.bin
46 | cp mineassemble.bin iso/boot/mineassemble.bin
47 | grub-mkrescue -o mineassemble.iso iso
48 |
49 | .PHONY: iso
50 |
51 | # Clean up
52 |
53 | clean:
54 | rm -f $(OBJS)
55 | rm -f $(DEPS)
56 | rm -f mineassemble.bin
57 | rm -f mineassemble.elf
58 | rm -f mineassemble.iso
59 | rm -f iso/boot/mineassemble.bin
60 |
--------------------------------------------------------------------------------
/src/player.asm:
--------------------------------------------------------------------------------
1 | ;
2 | ; This file contains all code related to the player state
3 | ;
4 |
5 | [bits 32]
6 |
7 | global set_pos, set_view
8 |
9 | global playerHeight
10 |
11 | global playerPos
12 | global pitch, pitchS, pitchC
13 | global yaw, yawS, yawC
14 |
15 | extern half_pi, neg_half_pi
16 |
17 | section .data
18 |
19 | ; Player height
20 | playerHeight dd 1.8
21 |
22 | section .bss
23 | ; Player position (3 floats)
24 | playerPos resd 3
25 |
26 | ; Player orientation (pitch and yaw + cached sine/cosine)
27 | pitch resd 1
28 | pitchS resd 1
29 | pitchC resd 1
30 |
31 | yaw resd 1
32 | yawS resd 1
33 | yawC resd 1
34 |
35 | section .text
36 |
37 | ; void set_pos(float x, float y, float z)
38 | ; Set player position
39 | set_pos:
40 | mov eax, [esp + 4]
41 | mov [playerPos + 0], eax ; x -> playerPos.x
42 | mov eax, [esp + 8]
43 | mov [playerPos + 4], eax ; y -> playerPos.y
44 | mov eax, [esp + 12]
45 | mov [playerPos + 8], eax ; z -> playerPos.z
46 |
47 | ret
48 |
49 | ; void set_view(float pitch, float yaw)
50 | ; Set player view pitch and yaw
51 | set_view:
52 | mov eax, [esp + 4]
53 | mov [pitch], eax ; p param -> pitch
54 |
55 | ; Limit pitch between -pi/2 and pi/2
56 | fld dword [pitch]
57 | fld dword [half_pi]
58 | fcomip
59 | ja .pitch_not_too_big ; jump if pitch < 1.57
60 | fld dword [half_pi]
61 | fstp dword [pitch]
62 | jmp .pitch_ok
63 | .pitch_not_too_big:
64 | fld dword [neg_half_pi]
65 | fcomip
66 | jbe .pitch_ok ; jump if pitch > -1.57
67 | fld dword [neg_half_pi]
68 | fstp dword [pitch]
69 | .pitch_ok:
70 | fstp dword [esp - 4] ; Discard original pitch still on stack
71 |
72 | ; Calculate pitch sin/cos
73 | fld dword [pitch]
74 | fsincos
75 | fstp dword [pitchC]
76 | fstp dword [pitchS]
77 |
78 | ; Calculate yaw sin/cos
79 | fld dword [yaw]
80 | fsincos
81 | fstp dword [yawC]
82 | fstp dword [yawS]
83 |
84 | mov eax, [esp + 8]
85 | mov [yaw], eax ; y param -> yaw
86 |
87 | ret
--------------------------------------------------------------------------------
/src/init.asm:
--------------------------------------------------------------------------------
1 | ;
2 | ; This file contains all initialization code (VGA mode, interrupt table, etc)
3 | ;
4 |
5 | [bits 32]
6 |
7 | global start
8 |
9 | extern init_idt, init_pic, init_input, init_time
10 | extern init_vga
11 | extern show_splash
12 | extern main
13 |
14 | extern bss, bss_end
15 |
16 | start:
17 | ; Run initialization code
18 | jmp init
19 |
20 | align 4
21 | mboot:
22 | ; Multiboot macros
23 | MULTIBOOT_PAGE_ALIGN equ 1 << 0
24 | MULTIBOOT_MEMORY_INFO equ 1 << 1
25 | MULTIBOOT_AOUT_KLUDGE equ 1 << 16
26 | MULTIBOOT_HEADER_MAGIC equ 0x1BADB002
27 | MULTIBOOT_HEADER_FLAGS equ MULTIBOOT_PAGE_ALIGN | MULTIBOOT_MEMORY_INFO | MULTIBOOT_AOUT_KLUDGE
28 | MULTIBOOT_CHECKSUM equ -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
29 |
30 | extern code, bss, end
31 |
32 | ; GRUB multiboot signature
33 | dd MULTIBOOT_HEADER_MAGIC
34 | dd MULTIBOOT_HEADER_FLAGS
35 | dd MULTIBOOT_CHECKSUM
36 |
37 | ; AOUT kludge (filled in by linker)
38 | dd mboot
39 | dd code
40 | dd bss
41 | dd end
42 | dd start
43 |
44 | ; Global Descriptor Table (GDT)
45 | gdt:
46 | dq 0x0000000000000000 ; Null
47 | dq 0x00CF9A000000FFFF ; Code
48 | dq 0x00CF92000000FFFF ; Data
49 | gdt_ptr:
50 | dw (gdt_ptr - gdt) - 1
51 | dd gdt
52 |
53 | ; void init_gdt()
54 | ; Initialize GDT
55 | init_gdt:
56 | lgdt [gdt_ptr]
57 |
58 | mov ax, 0x10
59 | mov ds, ax
60 | mov es, ax
61 | mov fs, ax
62 | mov gs, ax
63 | mov ss, ax
64 |
65 | jmp 8:init_gdt_end
66 |
67 | init_gdt_end:
68 | ret
69 |
70 | ; Initialize environment
71 | init:
72 | ; Disable interrupts
73 | cli
74 |
75 | ; Clear bss section
76 | mov al, 0
77 | mov edi, bss
78 | mov ecx, bss_end
79 | sub ecx, edi
80 | cld
81 | rep stosb
82 |
83 | ; Initialize stack
84 | mov esp, stack_top
85 |
86 | ; Clear flags
87 | push 0
88 | popf
89 |
90 | ; Load GDT, IDT and PIC
91 | call init_gdt
92 | call init_idt
93 | call init_pic
94 |
95 | ; Switch to 0x13 VGA mode
96 | call init_vga
97 |
98 | ; Enable interrupts
99 | sti
100 |
101 | ; Enable input and time interrupt handling
102 | call init_input
103 | call init_time
104 |
105 | ; Show splash screen
106 | call show_splash
107 |
108 | ; Start game
109 | call main
110 |
111 | ; Do nothing if main for some reason returns
112 | halt:
113 | cli
114 | hlt
115 | jmp halt
116 |
117 | section .bss
118 |
119 | ; 16 kB stack
120 | stack resb 0x4000
121 | stack_top:
122 |
--------------------------------------------------------------------------------
/src/input.asm:
--------------------------------------------------------------------------------
1 | ;
2 | ; This file contains all functions related to input handling
3 | ;
4 |
5 | [bits 32]
6 |
7 | %include "constants.asm"
8 |
9 | global handle_input, handle_collision
10 |
11 | extern handle_key, raytrace
12 |
13 | extern colTolerance, zero
14 |
15 | section .text
16 |
17 | ; void handle_input()
18 | ; Handle input of all key events
19 | handle_input:
20 | push dword KEY_UP
21 | call handle_key
22 |
23 | mov dword [esp], KEY_DOWN
24 | call handle_key
25 |
26 | mov dword [esp], KEY_LEFT
27 | call handle_key
28 |
29 | mov dword [esp], KEY_RIGHT
30 | call handle_key
31 |
32 | mov dword [esp], KEY_SPACE
33 | call handle_key
34 |
35 | mov dword [esp], KEY_Q
36 | call handle_key
37 |
38 | mov dword [esp], KEY_E
39 | call handle_key
40 |
41 | mov dword [esp], KEY_ESC
42 | call handle_key
43 |
44 | add esp, 4
45 |
46 | ret
47 |
48 | ; void handle_collision(vec3 pos, vec3* velocity)
49 | ; Adjust velocity to prevent any collisions
50 | handle_collision:
51 | push ebp
52 | mov ebp, esp
53 |
54 | ; Allocate space for hit info struct
55 | sub esp, 32
56 |
57 | ; Trace ray with velocity as direction to check for collision
58 | mov eax, ebp
59 | sub eax, 32
60 | push eax ; Pointer to hit info struct
61 |
62 | mov eax, [ebp + 20] ; velocity pointer
63 | push dword [eax + 8] ; Copy of velocity vec3 (in reverse because stack grows downwards)
64 | push dword [eax + 4]
65 | push dword [eax + 0]
66 |
67 | push dword [ebp + 16] ; Copy of pos vec3
68 | push dword [ebp + 12]
69 | push dword [ebp + 8]
70 |
71 | call raytrace
72 |
73 | add esp, 28
74 |
75 | ; Check for hit
76 | cmp byte [ebp - 32], 1
77 | jne .finish
78 |
79 | ; Check if distance is < 0.1
80 | fld dword [colTolerance]
81 | fld dword [ebp - 4]
82 | fcomip
83 | fstp dword [ebp + 8] ; Discard colTolerance still on stack by writing over now unused pos
84 | jae .finish
85 |
86 | ; Correct velocity to create sliding motion over surface
87 |
88 | mov ecx, [zero] ; floating point zero
89 | mov eax, [ebp + 20] ; velocity pointer
90 |
91 | cmp dword [ebp - 16], 0 ; nx != 0 -> negate x velocity
92 | je .nx_finish
93 | mov dword [eax + 0], ecx
94 | .nx_finish:
95 |
96 | cmp dword [ebp - 12], 0 ; ny != 0 -> negate y velocity
97 | je .ny_finish
98 | mov dword [eax + 4], ecx
99 | .ny_finish:
100 |
101 | cmp dword [ebp - 8], 0 ; nz != 0 -> negate z velocity
102 | je .finish
103 | mov dword [eax + 8], ecx
104 |
105 | .finish:
106 | mov esp, ebp
107 | pop ebp
108 |
109 | ret
--------------------------------------------------------------------------------
/src/world.asm:
--------------------------------------------------------------------------------
1 | ;
2 | ; This file contains all functions related to the state of the world
3 | ;
4 |
5 | [bits 32]
6 |
7 | %include "constants.asm"
8 |
9 | global init_world, set_block, get_block
10 |
11 | global world, worldSX, worldSY, worldSZ
12 | global sunDir
13 |
14 | extern init_player, set_pos, set_view
15 | extern zero, playerHeight
16 |
17 | section .data
18 |
19 | ; World block dimensions
20 | worldSX dd WORLD_SX
21 | worldSY dd WORLD_SY
22 | worldSZ dd WORLD_SZ
23 |
24 | halfWorldSX dd WORLD_SX / 2
25 | halfWorldSY dd WORLD_SY / 2
26 | halfWorldSZ dd WORLD_SZ / 2
27 |
28 | ; Sun shadows
29 | sunDir dd SUN_DIR_X, SUN_DIR_Y, SUN_DIR_Z
30 |
31 | section .bss
32 |
33 | ; World block array (1 byte per block)
34 | world resb WORLD_SX * WORLD_SY * WORLD_SZ
35 | world_end:
36 |
37 | section .text
38 |
39 | ; void init_world()
40 | ; Initialize default world blocks (flat grass)
41 | init_world:
42 | push edi
43 | push ebx
44 |
45 | ; First initialize everything to 0
46 | mov eax, world
47 | .empty_world:
48 | mov byte [eax], BLOCK_AIR
49 | inc eax
50 | cmp eax, world_end
51 | jne .empty_world
52 |
53 | ; Now fill bottom half with dirt
54 | ; Loop over x, y, z and set to BLOCK_DIRT
55 | ; Stop when y is at WORLD_SY / 2
56 | mov eax, 0
57 | mov ebx, 0
58 | mov ecx, 0
59 | .fill_x:
60 | .fill_y:
61 | .fill_z:
62 | ; Caller saved (only eax is used in set_block)
63 | push eax
64 |
65 | ; Set block value
66 | push dword BLOCK_DIRT
67 | push ecx
68 | push ebx
69 | push eax
70 | call set_block
71 | add esp, 16
72 |
73 | pop eax
74 |
75 | inc ecx
76 | cmp ecx, WORLD_SZ
77 | jne .fill_z
78 | mov ecx, 0 ; Reset inner z iterator
79 |
80 | inc ebx
81 | cmp ebx, WORLD_SY / 2
82 | jne .fill_y
83 | mov ebx, 0 ; Reset inner y iterator
84 |
85 | inc eax
86 | cmp eax, WORLD_SX
87 | jne .fill_x
88 |
89 | ; Set initial player position
90 | sub esp, 12
91 | fild dword [halfWorldSX]
92 | fstp dword [esp + 0] ; x (worldSX / 2)
93 | fild dword [halfWorldSY]
94 | fld dword [playerHeight]
95 | fadd
96 | fstp dword [esp + 4] ; y (worldSY / 2 + 1.8)
97 | fild dword [halfWorldSZ]
98 | fstp dword [esp + 8] ; z (worldSZ / 2)
99 | call set_pos
100 | add esp, 12
101 |
102 | ; And initial view
103 | sub esp, 8
104 | fldz
105 | fst dword [esp + 0] ; pitch (0)
106 | fstp dword [esp + 4] ; yaw (0)
107 | call set_view
108 | add esp, 8
109 |
110 | pop ebx
111 | pop edi
112 |
113 | ret
114 |
115 | ; byte get_block(int x, int y, int z)
116 | ; Get block value given x, y and z coordinates
117 | get_block:
118 | ; Compute index (x * worldSY * worldSZ + y * worldSZ + z)
119 | ; worldSZ can be factorized out to produce:
120 | ; (x * worldSY + y) * worldSZ + z
121 |
122 | mov eax, [esp + 4] ; x
123 | mul dword [worldSY]
124 | add eax, [esp + 8] ; y
125 | mul dword [worldSZ]
126 | add eax, [esp + 12] ; z
127 |
128 | ; Retrieve from world array;
129 | ; The other 3 bytes of eax are also zero'd
130 | movzx eax, byte [eax + world]
131 |
132 | ret
133 |
134 | ; void set_block(int x, int y, int z, byte type)
135 | ; Set block value given x, y, z and type parameters
136 | set_block:
137 | ; Compute index (x * worldSY * worldSZ + y * worldSZ + z)
138 | ; worldSZ can be factorized out to produce:
139 | ; (x * worldSY + y) * worldSZ + z
140 |
141 | mov eax, [esp + 4] ; x
142 | mul dword [worldSY]
143 | add eax, [esp + 8] ; y
144 | mul dword [worldSZ]
145 | add eax, [esp + 12] ; z
146 |
147 | ; Assign to world array
148 | mov edx, [esp + 16] ; type (can't mov from memory -> memory)
149 | mov byte [eax + world], dl
150 |
151 | ret
--------------------------------------------------------------------------------
/src/interrupts.asm:
--------------------------------------------------------------------------------
1 | ;
2 | ; This file contains all interrupt related setup and interaction
3 | ;
4 |
5 | [bits 32]
6 |
7 | global init_idt, init_pic, init_input, init_time
8 |
9 | global set_timer_frequency
10 |
11 | global set_irq_handler, clear_irq_handler, enable_irq
12 | global irq0_end, irq1_end, irq2_end, irq3_end, irq4_end, irq5_end, irq6_end, irq7_end
13 | global irq8_end, irq9_end, irqA_end, irqB_end, irqC_end, irqD_end, irqE_end, irqF_end
14 |
15 | global keys, time
16 |
17 | ; C input handler
18 | extern handleInput
19 |
20 | section .bss
21 |
22 | ; IDT memory
23 | idt resb 0x800
24 |
25 | section .text
26 |
27 | ; void init_idt()
28 | ; Initialize Interrupt Descriptor Table (IDT)
29 | idt_ptr:
30 | dw 0x800 - 1
31 | dd idt
32 |
33 | init_idt:
34 | lidt [idt_ptr]
35 | ret
36 |
37 | ; void init_pic()
38 | ; Initialize Programmable Interrupt Controllers (PIC)
39 | init_pic:
40 | mov al, 0x11 ; Init command
41 | out 0x20, al ; PIC1 command port
42 | out 0xA0, al ; PIC2 command port
43 |
44 | mov al, 0x20 ; Interrupt offset
45 | out 0x21, al ; PIC1 data port
46 | mov al, 0x28 ; Interrupt offset
47 | out 0xA1, al ; PIC2 data port
48 |
49 | mov al, 0x04 ; IR4 is connected to slave (PIC2)
50 | out 0x21, al ; PIC1 data port
51 | mov al, 0x02 ; Slave ID 2
52 | out 0xA1, al ; PIC2 data port
53 |
54 | mov al, 0x01 ; 8086/88 mode
55 | out 0x21, al ; PIC1 data port
56 | mov al, 0x01 ; 8086/88 mode
57 | out 0xA1, al ; PIC2 data port
58 |
59 | mov al, 0xFF ; Disable all IRQs
60 | out 0x21, al ; PIC1 data port
61 | mov al, 0xFF ; Disable all IRQs
62 | out 0xA1, al ; PIC1 data port
63 |
64 | push dword [spurious_interrupt_handler]
65 | push 7
66 | call set_irq_handler
67 | add esp, 4
68 | push 15
69 | call set_irq_handler
70 | add esp, 8
71 |
72 | ret
73 |
74 | ; void init_input()
75 | ; Initialize input handler
76 | init_input:
77 | push dword input_handler
78 | push 1
79 | call set_irq_handler
80 | call enable_irq
81 | add esp, 8
82 |
83 | ret
84 |
85 | ; Interrupt handler for keyboard keys
86 | input_handler:
87 | push eax
88 | push ebx
89 | push ecx
90 |
91 | ; Wait for keyboard to have scancode ready
92 | .kbwait:
93 | in al, 0x64
94 | and al, 1
95 | test al, al
96 | jz .kbwait
97 |
98 | ; Read scancode and extract down/up state
99 | xor eax, eax
100 | in al, 0x60
101 |
102 | mov bl, al
103 | shr bl, 7
104 | xor bl, 1
105 |
106 | ; Ignore repeated key presses
107 | mov cl, [keys + eax]
108 | and cl, 1
109 | cmp cl, 1
110 | jne .norepeat
111 | cmp cl, bl
112 | je .finish
113 |
114 | .norepeat:
115 | or bl, 10000000b
116 |
117 | and al, 01111111b
118 |
119 | ; Store scancode for program input handler
120 | mov [keys + eax], bl
121 |
122 | .finish:
123 | pop ecx
124 | pop ebx
125 | pop eax
126 |
127 | jmp irq1_end
128 |
129 | ; void init_time()
130 | ; Initialize timer handler
131 | init_time:
132 | push dword 1000
133 | call set_timer_frequency
134 | add esp, 4
135 |
136 | push dword time_handler
137 | push 0
138 | call set_irq_handler
139 | call enable_irq
140 | add esp, 8
141 |
142 | ret
143 |
144 | ; Interrupt handler for timer (fires every ms)
145 | time_handler:
146 | inc dword [time]
147 |
148 | jmp irq0_end
149 |
150 | ; void set_timer_frequency(int freq)
151 | ; Set IRQ0 timer frequency
152 | ; Must be at least ~18 Hz
153 | set_timer_frequency:
154 | mov edx, 0
155 | mov eax, 0x123456
156 | div dword [esp + 4]
157 | push eax
158 | call set_timer_rate
159 | add esp, 4
160 | ret
161 |
162 | ; void set_timer_rate(int rate)
163 | ; Set IRQ0 timer rate
164 | set_timer_rate:
165 | mov al, 0x34 ; Channel 0 (rate generator mode)
166 | out 0x43, al ; PIT mode/command port
167 | mov eax, [esp + 4]
168 | out 0x40, al ; PIT channel 0 data port
169 | mov al, ah
170 | out 0x40, al
171 | ret
172 |
173 | spurious_interrupt_handler:
174 | iret
175 |
176 | ; void set_interrupt_handler(int index, void (*handler))
177 | ; Create or update IDT entry
178 | set_interrupt_handler:
179 | cli
180 |
181 | mov ecx, [esp + 4] ; Interrupt index
182 | mov ax, [esp + 8]
183 | mov [0 + idt + ecx * 8], ax ; Low word of handler address
184 | mov ax, [esp + 10]
185 | mov [6 + idt + ecx * 8], ax ; High word of handler address
186 | mov ax, cs
187 | mov [2 + idt + ecx * 8], ax ; Code segment selector
188 | mov word [4 + idt + ecx * 8], 0x8E00 ; Attributes (0x8E00 = 32-bit interrupt gate)
189 |
190 | sti
191 |
192 | ret
193 |
194 | ; void clear_interrupt_handler(int index)
195 | ; Remove IDT entry
196 | clear_interrupt_handler:
197 | mov ecx, [esp + 4] ; Interrupt index
198 | mov word [4 + idt + ecx * 8], 0 ; Attributes (0 = Not used)
199 | ret
200 |
201 | ; void set_irq_handler(int index, void (*handler))
202 | ; Create or update IDT entry by IRQ index
203 | set_irq_handler:
204 | mov ecx, [esp + 4] ; Index
205 | mov esi, [esp + 8] ; Handler address
206 | add ecx, 0x20 ; Interrupt offset
207 | push esi
208 | push ecx
209 | call set_interrupt_handler
210 | add esp, 8
211 | ret
212 |
213 | ; void clear_irq_handler(int irqIndex)
214 | ; Remove IDT entry for IRQ index
215 | clear_irq_handler:
216 | mov ecx, [esp + 4]
217 | add ecx, 0x20
218 | push ecx
219 | call clear_interrupt_handler
220 | add esp, 4
221 | ret
222 |
223 | ; void enable_irq(int index)
224 | ; Enable IRQ
225 | enable_irq:
226 | mov dx, 0x21
227 | mov al, [esp + 4]
228 | shl al, 4
229 | and al, 0x80
230 | add dl, al
231 | mov cl, [esp + 4]
232 | and cl, 111b
233 | mov bl, 1
234 | shl bl, cl
235 | in al, dx
236 | not bl
237 | and al, bl
238 | out dx, al
239 | ret
240 |
241 | ; IRQ finishing
242 | irq0_end:
243 | irq1_end:
244 | irq2_end:
245 | irq3_end:
246 | irq4_end:
247 | irq5_end:
248 | irq6_end:
249 | irq7_end:
250 | ; IRQs 0 to 7 are controlled by PIC1
251 | push eax
252 | mov al, 0x20
253 | out 0x20, al
254 | pop eax
255 | iret
256 |
257 | irq8_end:
258 | irq9_end:
259 | irqA_end:
260 | irqB_end:
261 | irqC_end:
262 | irqD_end:
263 | irqE_end:
264 | irqF_end:
265 | ; IRQs 8 to F are controlled by PIC2
266 | push eax
267 | mov al, 0x20
268 | out 0xA0, al
269 | out 0x20, al
270 | pop eax,
271 | iret
272 |
273 | section .data
274 |
275 | time dd 0
276 |
277 | section .bss
278 |
279 | ; Key status buffer (128 scancodes)
280 | keys resb 0x80
--------------------------------------------------------------------------------
/src/vga.asm:
--------------------------------------------------------------------------------
1 | ;
2 | ; This file contains the VGA mode 0x13 setup and color palette
3 | ;
4 |
5 | [bits 32]
6 |
7 | global init_vga
8 |
9 | global palette
10 |
11 | section .text
12 |
13 | ; void init_vga()
14 | ; Initialize VGA mode (0x13)
15 | init_vga:
16 | pushad
17 |
18 | ; Set mode
19 | mov esi, mode0x13
20 | call set_regs
21 |
22 | ; Set up palette
23 | mov esi, palette
24 | call set_palette
25 |
26 | ; Clear screen
27 | mov edi, 0xa0000
28 | mov ax, 0x0000
29 | mov ecx, 0x20000
30 | rep stosw
31 |
32 | popad
33 | ret
34 |
35 | ; Set VGA mode
36 | set_regs:
37 | cli
38 | mov dx, 0x3C2
39 | lodsb
40 | out dx, al
41 |
42 | mov dx, 0x3DA
43 | lodsb
44 | out dx, al
45 |
46 | xor ecx, ecx
47 | mov dx, 0x3C4
48 | .l1:
49 | lodsb
50 | xchg al, ah
51 | mov al, cl
52 | out dx, ax
53 | inc ecx
54 | cmp cl, 4
55 | jbe .l1
56 |
57 | mov dx, 0x3D4
58 | mov ax, 0x0E11
59 | out dx, ax
60 |
61 | xor ecx, ecx
62 | mov dx, 0x3D4
63 | .l2:
64 | lodsb
65 | xchg al, ah
66 | mov al, cl
67 | out dx, ax
68 | inc ecx
69 | cmp cl, 0x18
70 | jbe .l2
71 |
72 | xor ecx, ecx
73 | mov dx, 0x3cE
74 | .l3:
75 | lodsb
76 | xchg al, ah
77 | mov al, cl
78 | out dx, ax
79 | inc ecx
80 | cmp cl, 8
81 | jbe .l3
82 |
83 | mov dx, 0x3DA
84 | in al, dx
85 |
86 | xor ecx, ecx
87 | mov dx, 0x3C0
88 | .l4:
89 | in ax, dx
90 | mov al, cl
91 | out dx, al
92 | lodsb
93 | out dx, al
94 | inc ecx
95 | cmp cl, 0x14
96 | jbe .l4
97 |
98 | mov al, 0x20
99 | out dx, al
100 |
101 | sti
102 | ret
103 |
104 | ; void set_palette()
105 | ; Set palette colors
106 | set_palette:
107 | push ax
108 | push cx
109 | push dx
110 |
111 | xor cx, cx
112 | .next_color:
113 | mov dx, 0x03C8
114 | mov al, cl
115 | out dx, al
116 | inc dx
117 | mov al, byte [esi]
118 | out dx, al
119 | inc esi
120 | mov al, byte [esi]
121 | out dx, al
122 | inc esi
123 | mov al, byte [esi]
124 | out dx, al
125 | inc esi
126 |
127 | inc cx
128 | cmp cx, 256
129 | jl .next_color
130 |
131 | pop dx
132 | pop cx
133 | pop ax
134 | ret
135 |
136 | section .data
137 |
138 | ; 256 color RGB palette (6 bits per channel)
139 | palette db 00, 00, 00, 63, 63, 63, 39, 51, 63, 29, 41, 22, 19, 27, 14
140 | db 25, 38, 17, 16, 25, 11, 30, 40, 21, 20, 26, 14, 22, 34, 14
141 | db 14, 22, 09, 27, 40, 18, 18, 26, 12, 27, 40, 19, 23, 35, 15
142 | db 15, 23, 10, 24, 37, 16, 16, 24, 10, 33, 44, 24, 22, 29, 16
143 | db 35, 46, 25, 23, 30, 16, 31, 41, 21, 20, 27, 14, 26, 38, 18
144 | db 17, 25, 12, 27, 40, 20, 18, 26, 13, 23, 37, 14, 15, 24, 09
145 | db 31, 43, 22, 20, 28, 14, 23, 36, 13, 15, 24, 08, 21, 34, 12
146 | db 14, 22, 08, 24, 37, 15, 26, 37, 17, 17, 24, 11, 23, 35, 14
147 | db 15, 23, 09, 26, 37, 16, 17, 24, 10, 23, 35, 13, 15, 23, 08
148 | db 26, 38, 17, 17, 25, 11, 29, 40, 19, 19, 26, 12, 25, 39, 16
149 | db 16, 26, 10, 28, 40, 19, 28, 39, 18, 26, 39, 18, 17, 26, 12
150 | db 27, 39, 19, 27, 38, 17, 18, 25, 11, 31, 42, 21, 27, 39, 18
151 | db 28, 38, 17, 32, 43, 22, 21, 28, 14, 26, 39, 17, 17, 26, 11
152 | db 23, 36, 14, 20, 33, 11, 13, 22, 07, 18, 32, 10, 12, 21, 06
153 | db 23, 36, 15, 15, 24, 10, 25, 37, 18, 16, 24, 12, 25, 36, 16
154 | db 22, 35, 13, 14, 23, 08, 23, 37, 15, 22, 36, 13, 14, 24, 08
155 | db 29, 41, 19, 19, 27, 12, 27, 39, 17, 18, 26, 11, 18, 31, 09
156 | db 12, 20, 06, 19, 32, 10, 20, 32, 12, 13, 21, 08, 25, 36, 15
157 | db 24, 38, 16, 16, 25, 10, 29, 42, 21, 19, 28, 14, 20, 34, 11
158 | db 21, 35, 12, 24, 38, 15, 29, 41, 20, 19, 27, 13, 30, 42, 20
159 | db 20, 28, 13, 20, 34, 12, 13, 22, 08, 28, 41, 19, 18, 27, 12
160 | db 24, 36, 16, 23, 34, 14, 15, 22, 09, 19, 33, 11, 12, 22, 07
161 | db 22, 34, 13, 31, 43, 21, 32, 43, 23, 21, 28, 15, 29, 41, 21
162 | db 24, 36, 15, 30, 42, 21, 17, 30, 08, 11, 20, 05, 28, 40, 20
163 | db 28, 40, 18, 27, 40, 17, 22, 36, 14, 14, 24, 09, 30, 41, 20
164 | db 20, 27, 13, 33, 45, 23, 22, 30, 15, 32, 44, 23, 21, 29, 15
165 | db 25, 40, 17, 16, 26, 11, 25, 38, 16, 25, 37, 17, 16, 24, 11
166 | db 26, 41, 18, 17, 27, 12, 26, 40, 17, 21, 33, 14, 21, 35, 13
167 | db 27, 39, 21, 18, 26, 14, 27, 37, 18, 18, 24, 12, 31, 42, 22
168 | db 30, 40, 20, 20, 26, 13, 36, 26, 18, 24, 17, 12, 23, 16, 11
169 | db 15, 10, 07, 29, 21, 14, 19, 14, 09, 21, 21, 21, 14, 14, 14
170 | db 17, 12, 08, 11, 08, 05, 26, 26, 26, 17, 17, 17, 22, 17, 13
171 | db 14, 11, 08, 22, 35, 14, 14, 23, 09, 27, 36, 18, 21, 33, 13
172 | db 27, 36, 17, 18, 24, 11, 30, 39, 21, 20, 32, 11, 13, 21, 07
173 | db 25, 34, 16, 16, 22, 10, 19, 32, 11, 12, 21, 07, 25, 35, 16
174 | db 16, 23, 10, 20, 33, 12, 21, 34, 13, 18, 31, 10, 19, 31, 11
175 | db 12, 20, 07, 28, 38, 19, 18, 25, 12, 25, 37, 16, 28, 37, 18
176 | db 28, 37, 19, 29, 38, 20, 19, 25, 13, 19, 31, 10, 17, 29, 08
177 | db 11, 19, 05, 15, 28, 07, 10, 18, 04, 21, 33, 12, 00, 00, 00
178 | db 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00
179 | db 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00
180 | db 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00
181 | db 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00
182 | db 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00
183 | db 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00
184 | db 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00
185 | db 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00
186 | db 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00
187 | db 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00
188 | db 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00
189 | db 00, 00, 00, 00, 00, 00, 00, 00, 00, 36, 25, 46, 40, 47, 52
190 | db 24, 12, 00
191 |
192 | ; VGA mode 0x13 register values
193 | mode0x13 db 0x63, 0x00, 0x03, 0x01, 0x0F, 0x00, 0x0E, 0x5F, 0x4F
194 | db 0x50, 0x82, 0x54, 0x80, 0xBF, 0x1F, 0x00, 0x41, 0x00
195 | db 0x00, 0x00, 0x00, 0x00, 0x00, 0x9C, 0x0E, 0x8F, 0x28
196 | db 0x40, 0x96, 0xB9, 0xA3, 0xFF, 0x00, 0x00, 0x00, 0x00
197 | db 0x00, 0x40, 0x05, 0x0F, 0xFF, 0x00, 0x01, 0x02, 0x03
198 | db 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C
199 | db 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00
--------------------------------------------------------------------------------
/reference/src/textures.c:
--------------------------------------------------------------------------------
1 | //
2 | // Texture images (16x16 24 bit RGB)
3 | //
4 |
5 | unsigned int texGrass[] = {
6 | 0x76a559, 0x669b44, 0x78a354, 0x598a38, 0x6ca04a, 0x6da34d, 0x5d8d3c,
7 | 0x619441, 0x5d8f3c, 0x679a46, 0x6ca24c, 0x639542, 0x84b261, 0x8db867,
8 | 0x7da455, 0x69984a, 0x6fa152, 0x5e943a, 0x7ead58, 0x5c9037, 0x558b32,
9 | 0x60963d, 0x6b9745, 0x5c8f38, 0x699642, 0x5c8e37, 0x6b9844, 0x75a34f,
10 | 0x679c43, 0x73a04c, 0x729d4a, 0x6b9d4a, 0x6c9e4f, 0x6c9946, 0x7ca854,
11 | 0x60953c, 0x6f9e49, 0x568932, 0x6d9a46, 0x709a47, 0x80ac58, 0x7fae58,
12 | 0x699d45, 0x5c9038, 0x52872f, 0x4b8028, 0x558a32, 0x5f923f, 0x669648,
13 | 0x679240, 0x5a8d37, 0x5e963c, 0x5b9037, 0x6c9946, 0x62963e, 0x5d9239,
14 | 0x77a44f, 0x639740, 0x6e9c47, 0x719d4a, 0x5b8f37, 0x487e26, 0x4d832a,
15 | 0x528332, 0x669648, 0x65913d, 0x598d35, 0x5e963c, 0x74a34e, 0x5b8e37,
16 | 0x5a9137, 0x5c9339, 0x73a04c, 0x5e933b, 0x588c35, 0x62973e, 0x639a40,
17 | 0x52872f, 0x76a44f, 0x75a854, 0x699a4b, 0x52882e, 0x568c33, 0x62983e,
18 | 0x77a550, 0x639940, 0x548b32, 0x50862e, 0x568b32, 0x6b9643, 0x7aa853,
19 | 0x5b9037, 0x5a9137, 0x538830, 0x74a14d, 0x71a44f, 0x619043, 0x538a30,
20 | 0x5a9137, 0x51862e, 0x5f8a38, 0x63963f, 0x598f36, 0x669d43, 0x77a44f,
21 | 0x77a24f, 0x63963e, 0x5c9339, 0x548b32, 0x558b32, 0x61963d, 0x6c9f4a,
22 | 0x68994a, 0x51882e, 0x599037, 0x4f852d, 0x74a04d, 0x6e9946, 0x53872f,
23 | 0x558b32, 0x6d9946, 0x598b35, 0x65923f, 0x5a8f37, 0x4d832a, 0x7dad56,
24 | 0x679c43, 0x80ae5c, 0x74a756, 0x548b31, 0x5c9339, 0x548931, 0x7aa953,
25 | 0x60933c, 0x52882f, 0x62983f, 0x7ba954, 0x5e923a, 0x7cac55, 0x679c43,
26 | 0x447821, 0x6d9a46, 0x598c35, 0x679a46, 0x71a253, 0x73a04b, 0x6ca147,
27 | 0x548b32, 0x4c8129, 0x5b9238, 0x5b9138, 0x74a24e, 0x78a551, 0x60963c,
28 | 0x548930, 0x5c9339, 0x5e943a, 0x85b65e, 0x689e45, 0x83b35f, 0x68984a,
29 | 0x719e4a, 0x79a551, 0x5e943b, 0x50862e, 0x588d34, 0x7aa853, 0x5e933b,
30 | 0x548b31, 0x5f963c, 0x67a146, 0x5b9238, 0x598e36, 0x74a24e, 0x649941,
31 | 0x5d8d3c, 0x659647, 0x5e943a, 0x77a44f, 0x679c43, 0x719f4a, 0x598c35,
32 | 0x72a14c, 0x588c34, 0x599137, 0x6ba448, 0x599037, 0x4c8229, 0x50852d,
33 | 0x649b41, 0x5b9138, 0x598b38, 0x669749, 0x51882e, 0x568b33, 0x5d933a,
34 | 0x73a04c, 0x53862f, 0x5d9239, 0x5e943b, 0x588c34, 0x5f953c, 0x5b9138,
35 | 0x50862e, 0x6a9643, 0x6ba046, 0x73a14d, 0x629341, 0x619042, 0x548b31,
36 | 0x4b8129, 0x568c33, 0x538830, 0x558b32, 0x709e49, 0x6f9a47, 0x679140,
37 | 0x77a650, 0x5c9138, 0x4f852d, 0x6c9946, 0x60923c, 0x6b9744, 0x679846,
38 | 0x578639, 0x52882e, 0x548931, 0x598f36, 0x568c33, 0x5a9137, 0x639840,
39 | 0x578b33, 0x51852e, 0x5c9239, 0x578d34, 0x4e832b, 0x4f832b, 0x709c49,
40 | 0x61953c, 0x619440, 0x6f9d54, 0x5f943e, 0x81ad5c, 0x60903f, 0x609440,
41 | 0x679b47, 0x6c9648, 0x78a254, 0x5d8d3c, 0x588b38, 0x629641, 0x609340,
42 | 0x5d8f3c, 0x7ea859, 0x78a152, 0x77a758
43 | };
44 |
45 | unsigned int texDirt[] = {
46 | 0x916848, 0x5f432d, 0x916848, 0x76553a, 0x76553a, 0x5f432d, 0x916848,
47 | 0x5f432d, 0x76553a, 0x5f432d, 0x5f432d, 0x76553a, 0x5f432d, 0x5f432d,
48 | 0x76553a, 0x76553a, 0x76553a, 0x76553a, 0x5f432d, 0x555555, 0x5f432d,
49 | 0x463020, 0x5f432d, 0x5f432d, 0x5f432d, 0x76553a, 0x76553a, 0x5f432d,
50 | 0x463020, 0x76553a, 0x5f432d, 0x5f432d, 0x76553a, 0x463020, 0x5f432d,
51 | 0x916848, 0x76553a, 0x76553a, 0x5f432d, 0x916848, 0x5f432d, 0x463020,
52 | 0x5f432d, 0x5f432d, 0x76553a, 0x5f432d, 0x463020, 0x916848, 0x5f432d,
53 | 0x5f432d, 0x463020, 0x5f432d, 0x916848, 0x76553a, 0x5f432d, 0x916848,
54 | 0x76553a, 0x5f432d, 0x916848, 0x76553a, 0x5f432d, 0x5f432d, 0x916848,
55 | 0x76553a, 0x5f432d, 0x5f432d, 0x916848, 0x76553a, 0x463020, 0x5f432d,
56 | 0x6a6a6a, 0x76553a, 0x5f432d, 0x5f432d, 0x916848, 0x76553a, 0x76553a,
57 | 0x5b4535, 0x5f432d, 0x76553a, 0x916848, 0x76553a, 0x5f432d, 0x463020,
58 | 0x76553a, 0x76553a, 0x5f432d, 0x76553a, 0x76553a, 0x463020, 0x5f432d,
59 | 0x916848, 0x76553a, 0x5f432d, 0x463020, 0x5f432d, 0x76553a, 0x6a6a6a,
60 | 0x5f432d, 0x5f432d, 0x5f432d, 0x463020, 0x5f432d, 0x5f432d, 0x5f432d,
61 | 0x463020, 0x916848, 0x5f432d, 0x916848, 0x76553a, 0x5f432d, 0x6a6a6a,
62 | 0x76553a, 0x463020, 0x5f432d, 0x916848, 0x5f432d, 0x463020, 0x916848,
63 | 0x5f432d, 0x463020, 0x5f432d, 0x76553a, 0x76553a, 0x5f432d, 0x76553a,
64 | 0x463020, 0x5f432d, 0x5f432d, 0x5f432d, 0x916848, 0x76553a, 0x76553a,
65 | 0x463020, 0x916848, 0x76553a, 0x5f432d, 0x5f432d, 0x463020, 0x555555,
66 | 0x5f432d, 0x5f432d, 0x916848, 0x76553a, 0x5f432d, 0x916848, 0x5f432d,
67 | 0x76553a, 0x463020, 0x5f432d, 0x5f432d, 0x463020, 0x76553a, 0x5f432d,
68 | 0x916848, 0x76553a, 0x5f432d, 0x463020, 0x916848, 0x76553a, 0x463020,
69 | 0x76553a, 0x5f432d, 0x5f432d, 0x5f432d, 0x5f432d, 0x916848, 0x76553a,
70 | 0x76553a, 0x5f432d, 0x916848, 0x76553a, 0x5f432d, 0x916848, 0x5f432d,
71 | 0x5f432d, 0x5f432d, 0x5f432d, 0x5f432d, 0x76553a, 0x555555, 0x463020,
72 | 0x916848, 0x76553a, 0x5f432d, 0x5f432d, 0x463020, 0x5f432d, 0x5f432d,
73 | 0x463020, 0x76553a, 0x5f432d, 0x5f432d, 0x916848, 0x463020, 0x5f432d,
74 | 0x5f432d, 0x5f432d, 0x5f432d, 0x5f432d, 0x5f432d, 0x916848, 0x76553a,
75 | 0x463020, 0x5f432d, 0x5f432d, 0x5f432d, 0x76553a, 0x916848, 0x76553a,
76 | 0x463020, 0x916848, 0x76553a, 0x5f432d, 0x76553a, 0x5f432d, 0x5f432d,
77 | 0x916848, 0x76553a, 0x76553a, 0x5f432d, 0x916848, 0x5f432d, 0x76553a,
78 | 0x5f432d, 0x463020, 0x916848, 0x76553a, 0x463020, 0x5f432d, 0x5f432d,
79 | 0x76553a, 0x463020, 0x5f432d, 0x6a6a6a, 0x5f432d, 0x916848, 0x76553a,
80 | 0x76553a, 0x5f432d, 0x916848, 0x463020, 0x5f432d, 0x5f432d, 0x5f432d,
81 | 0x916848, 0x76553a, 0x76553a, 0x5f432d, 0x76553a, 0x5f432d, 0x463020,
82 | 0x916848, 0x76553a, 0x76553a, 0x463020
83 | };
84 |
85 | unsigned int texGrassSide[] = {
86 | 0x5b8d3a, 0x5c8e3b, 0x6f9349, 0x463020, 0x76553a, 0x5f432d, 0x916848,
87 | 0x5f432d, 0x76553a, 0x5f432d, 0x5f432d, 0x76553a, 0x5f432d, 0x5f432d,
88 | 0x76553a, 0x76553a, 0x5d8f3c, 0x558734, 0x463020, 0x555555, 0x5f432d,
89 | 0x463020, 0x5f432d, 0x5f432d, 0x5f432d, 0x76553a, 0x76553a, 0x5f432d,
90 | 0x463020, 0x76553a, 0x5f432d, 0x5f432d, 0x5a8c39, 0x6c9147, 0x7a9f55,
91 | 0x463020, 0x76553a, 0x76553a, 0x5f432d, 0x916848, 0x5f432d, 0x463020,
92 | 0x5f432d, 0x5f432d, 0x76553a, 0x5f432d, 0x463020, 0x916848, 0x50822f,
93 | 0x658a40, 0x4e812d, 0x463020, 0x916848, 0x76553a, 0x5f432d, 0x916848,
94 | 0x76553a, 0x5f432d, 0x916848, 0x76553a, 0x5f432d, 0x5f432d, 0x916848,
95 | 0x76553a, 0x50822f, 0x678c41, 0x528531, 0x598b38, 0x463020, 0x5f432d,
96 | 0x6a6a6a, 0x76553a, 0x5f432d, 0x5f432d, 0x916848, 0x76553a, 0x76553a,
97 | 0x5b4535, 0x5f432d, 0x76553a, 0x578936, 0x463020, 0x463020, 0x463020,
98 | 0x76553a, 0x76553a, 0x5f432d, 0x76553a, 0x76553a, 0x463020, 0x5f432d,
99 | 0x916848, 0x76553a, 0x5f432d, 0x463020, 0x5f432d, 0x4a7d2a, 0x528431,
100 | 0x588a37, 0x463020, 0x5f432d, 0x463020, 0x5f432d, 0x5f432d, 0x5f432d,
101 | 0x463020, 0x916848, 0x5f432d, 0x916848, 0x76553a, 0x5f432d, 0x6a6a6a,
102 | 0x558734, 0x4d7f2c, 0x463020, 0x463020, 0x5f432d, 0x463020, 0x916848,
103 | 0x5f432d, 0x463020, 0x5f432d, 0x76553a, 0x76553a, 0x5f432d, 0x76553a,
104 | 0x463020, 0x5f432d, 0x639542, 0x4a7d2a, 0x5b8d3a, 0x4a7d2a, 0x463020,
105 | 0x463020, 0x916848, 0x76553a, 0x5f432d, 0x5f432d, 0x463020, 0x555555,
106 | 0x5f432d, 0x5f432d, 0x916848, 0x76553a, 0x5d8f3c, 0x73984e, 0x649643,
107 | 0x463020, 0x463020, 0x5f432d, 0x5f432d, 0x463020, 0x76553a, 0x5f432d,
108 | 0x916848, 0x76553a, 0x5f432d, 0x463020, 0x916848, 0x76553a, 0x538532,
109 | 0x71964b, 0x72974d, 0x558835, 0x463020, 0x5f432d, 0x916848, 0x76553a,
110 | 0x76553a, 0x5f432d, 0x916848, 0x76553a, 0x5f432d, 0x916848, 0x5f432d,
111 | 0x5f432d, 0x518330, 0x5a8c39, 0x769b51, 0x463020, 0x555555, 0x463020,
112 | 0x916848, 0x76553a, 0x5f432d, 0x5f432d, 0x463020, 0x5f432d, 0x5f432d,
113 | 0x463020, 0x76553a, 0x5f432d, 0x528531, 0x4c7e2b, 0x463020, 0x5f432d,
114 | 0x5f432d, 0x5f432d, 0x5f432d, 0x5f432d, 0x5f432d, 0x916848, 0x76553a,
115 | 0x463020, 0x5f432d, 0x5f432d, 0x5f432d, 0x76553a, 0x4c7e2b, 0x558734,
116 | 0x447623, 0x463020, 0x76553a, 0x5f432d, 0x76553a, 0x5f432d, 0x5f432d,
117 | 0x916848, 0x76553a, 0x76553a, 0x5f432d, 0x916848, 0x5f432d, 0x76553a,
118 | 0x3f711e, 0x518330, 0x4b7d2a, 0x463020, 0x463020, 0x5f432d, 0x5f432d,
119 | 0x76553a, 0x463020, 0x5f432d, 0x6a6a6a, 0x5f432d, 0x916848, 0x76553a,
120 | 0x76553a, 0x5f432d, 0x558835, 0x548633, 0x463020, 0x5f432d, 0x5f432d,
121 | 0x916848, 0x76553a, 0x76553a, 0x5f432d, 0x76553a, 0x5f432d, 0x463020,
122 | 0x916848, 0x76553a, 0x76553a, 0x463020
123 | };
--------------------------------------------------------------------------------
/src/reference.c:
--------------------------------------------------------------------------------
1 | // Configuration
2 | #define skyColor 0x02
3 |
4 | // Types
5 | typedef unsigned char uint8_t;
6 | typedef unsigned int uint32_t;
7 |
8 | typedef unsigned int bool;
9 |
10 | // Constants
11 | #define M_PI 3.14159265358979323846
12 |
13 | #define NULL ((void*) 0)
14 |
15 | #define true ((bool) 1)
16 | #define false ((bool) 0)
17 |
18 | // Key scancodes
19 | #define KEY_ESC 0x01
20 |
21 | #define KEY_Q 0x10
22 | #define KEY_E 0x12
23 |
24 | #define KEY_W 0x11
25 | #define KEY_A 0x1E
26 | #define KEY_S 0x1F
27 | #define KEY_D 0x20
28 |
29 | #define KEY_L 0x26
30 |
31 | #define KEY_SPACE 0x39
32 |
33 | #define KEY_UP 0x48
34 | #define KEY_LEFT 0x4B
35 | #define KEY_RIGHT 0x4D
36 | #define KEY_DOWN 0x50
37 |
38 | // Macros
39 | #define IN_WORLD(x, y, z) \
40 | (x >= 0 && y >= 0 && z >= 0 && x < worldSX && y < worldSY && z < worldSZ)
41 |
42 | // Resources
43 | extern uint8_t tex_grass[];
44 | extern uint8_t tex_dirt[];
45 | extern uint8_t tex_grass_side[];
46 |
47 | // Types
48 | typedef struct vec3_t {
49 | float x, y, z;
50 | } vec3;
51 |
52 | typedef struct hit_t {
53 | bool hit;
54 | int x, y, z;
55 | int nx, ny, nz;
56 | float dist;
57 | } hit;
58 |
59 | enum block_t {
60 | BLOCK_AIR,
61 | BLOCK_DIRT
62 | };
63 |
64 | enum face_t {
65 | FACE_LEFT,
66 | FACE_RIGHT,
67 | FACE_BOTTOM,
68 | FACE_TOP,
69 | FACE_BACK,
70 | FACE_FRONT
71 | };
72 |
73 | // Functions
74 | extern void init_world();
75 | extern uint8_t get_block(int x, int y, int z);
76 | extern void set_block(int x, int y, int z, uint8_t type);
77 |
78 | extern void handle_collision(vec3 pos, vec3* velocity);
79 |
80 | extern void set_pos(float x, float y, float z);
81 | extern void set_view(float yaw, float pitch);
82 |
83 | uint8_t raytrace(vec3 pos, vec3 dir, hit* info);
84 | extern uint8_t ray_color(int x, int y, int z, vec3 pos, int tex, int face);
85 | extern void face_normal(int face, int* x, int* y, int* z);
86 | extern int tex_index(vec3 pos, int face);
87 | extern vec3 ray_dir(int x, int y);
88 |
89 | extern float sinf(float n);
90 | extern float cosf(float n);
91 | extern float absf(float n);
92 |
93 | // Globals
94 | extern uint8_t* vga;
95 |
96 | extern uint8_t world[];
97 | extern vec3 sunDir;
98 |
99 | extern vec3 playerPos;
100 | extern float pitch, pitchS, pitchC;
101 | extern float yaw, yawS, yawC;
102 |
103 | extern float lastUpdate, dPitch, dYaw;
104 | extern vec3 velocity;
105 |
106 | extern uint8_t palette[];
107 | extern uint8_t keys[];
108 |
109 | extern uint32_t worldSX, worldSY, worldSZ;
110 |
111 | // IRQ1 interrupt handler sets keys buffer for this function to read
112 | void handle_key(uint8_t key) {
113 | hit info;
114 |
115 | // If the highest bit is not set, this key has not changed
116 | if (!(keys[key] & 0x80)) {
117 | return;
118 | }
119 |
120 | bool down = keys[key] & 1;
121 |
122 | // Mark key state as read
123 | keys[key] &= 1;
124 |
125 | switch (key) {
126 | // View
127 | case KEY_UP: dPitch += down ? 1.0f : -1.0f; break;
128 | case KEY_DOWN: dPitch += down ? -1.0f : 1.0f; break;
129 |
130 | case KEY_LEFT: dYaw += down ? 1.0f : -1.0f; break;
131 | case KEY_RIGHT: dYaw += down ? -1.0f : 1.0f; break;
132 |
133 | case KEY_SPACE:
134 | if (down) {
135 | playerPos.y += 0.1f;
136 | velocity.y += 8.0f;
137 | }
138 | break;
139 |
140 | // Check if a block was hit and place a new block next to it
141 | case KEY_Q:
142 | if (!down) {
143 | raytrace(playerPos, ray_dir(160, 100), &info);
144 |
145 | if (info.hit) {
146 | int bx = info.x + info.nx;
147 | int by = info.y + info.ny;
148 | int bz = info.z + info.nz;
149 |
150 | if (IN_WORLD(bx, by, bz)) {
151 | set_block(bx, by, bz, BLOCK_DIRT);
152 | }
153 | }
154 | }
155 | break;
156 |
157 | // Check if a block was hit and remove it
158 | case KEY_E:
159 | if (!down) {
160 | raytrace(playerPos, ray_dir(160, 100), &info);
161 |
162 | if (info.hit) {
163 | set_block(info.x, info.y, info.z, BLOCK_AIR);
164 | }
165 | }
166 | break;
167 |
168 | case KEY_ESC:
169 | init_world();
170 | break;
171 | }
172 |
173 | // Make sure view look speed doesn't add up with low framerates
174 | if (dPitch != 0.0f) dPitch /= absf(dPitch);
175 | if (dYaw != 0.0f) dYaw /= absf(dYaw);
176 | }
177 |
178 | void update(float dt) {
179 | // Update view
180 | pitch += 1.2f * dPitch * dt;
181 | yaw += 1.2f * dYaw * dt;
182 |
183 | set_view(pitch, yaw);
184 |
185 | // Set X/Z velocity depending on input
186 | velocity.x = velocity.z = 0.0f;
187 |
188 | if (keys[KEY_A] & 1) {
189 | velocity.x += 3.0f * cosf(M_PI - yaw);
190 | velocity.z += 3.0f * sinf(M_PI - yaw);
191 | }
192 | if (keys[KEY_W] & 1) {
193 | velocity.x += 3.0f * cosf(-M_PI / 2 - yaw);
194 | velocity.z += 3.0f * sinf(-M_PI / 2 - yaw);
195 | }
196 | if (keys[KEY_S] & 1) {
197 | velocity.x += 3.0f * cosf(M_PI / 2 - yaw);
198 | velocity.z += 3.0f * sinf(M_PI / 2 - yaw);
199 | }
200 | if (keys[KEY_D] & 1) {
201 | velocity.x += 3.0f * cosf(-yaw);
202 | velocity.z += 3.0f * sinf(-yaw);
203 | }
204 |
205 | // Simulate gravity
206 | velocity.y -= 20.0f * dt;
207 |
208 | // Handle block collision (head, lower body and feet)
209 | vec3 headPos = playerPos;
210 | vec3 lowerPos = playerPos; lowerPos.y -= 1.0f;
211 | vec3 footPos = playerPos; footPos.y -= 1.8f;
212 |
213 | handle_collision(headPos, &velocity);
214 | handle_collision(lowerPos, &velocity);
215 | handle_collision(footPos, &velocity);
216 |
217 | // Apply motion
218 | playerPos.x += velocity.x * dt;
219 | playerPos.y += velocity.y * dt;
220 | playerPos.z += velocity.z * dt;
221 | }
222 |
223 | // Returns final color
224 | uint8_t raytrace(vec3 pos, vec3 dir, hit* info) {
225 | // Finish early if there's no direction
226 | if (dir.x == 0.0f && dir.y == 0.0f && dir.z == 0.0f) {
227 | goto nohit;
228 | }
229 |
230 | vec3 start = pos;
231 |
232 | int x = (int) pos.x;
233 | int y = (int) pos.y;
234 | int z = (int) pos.z;
235 |
236 | int x_dir = dir.x >= 0.0f ? 1 : -1;
237 | int y_dir = dir.y >= 0.0f ? 1 : -1;
238 | int z_dir = dir.z >= 0.0f ? 1 : -1;
239 |
240 | float dx_off = x_dir > 0 ? 1.0f : 0.0f;
241 | float dy_off = y_dir > 0 ? 1.0f : 0.0f;
242 | float dz_off = z_dir > 0 ? 1.0f : 0.0f;
243 |
244 | int x_face = x_dir > 0 ? FACE_LEFT : FACE_RIGHT;
245 | int y_face = y_dir > 0 ? FACE_BOTTOM : FACE_TOP;
246 | int z_face = z_dir > 0 ? FACE_BACK : FACE_FRONT;
247 |
248 | int face = FACE_TOP;
249 |
250 | // Assumption is made that the camera is never outside the world
251 | while (IN_WORLD(x, y, z)) {
252 | // Determine if block is solid
253 | if (get_block(x, y, z) != BLOCK_AIR) {
254 | float dx = start.x - pos.x;
255 | float dy = start.y - pos.y;
256 | float dz = start.z - pos.z;
257 | float dist = dx*dx + dy*dy + dz*dz;
258 |
259 | vec3 relPos = pos;
260 | relPos.x -= x;
261 | relPos.y -= y;
262 | relPos.z -= z;
263 |
264 | // If hit info is requested, no color computation is done
265 | if (info != NULL) {
266 | int nx, ny, nz;
267 | face_normal(face, &nx, &ny, &nz);
268 |
269 | info->hit = true;
270 | info->x = x;
271 | info->y = y;
272 | info->z = z;
273 | info->nx = nx;
274 | info->ny = ny;
275 | info->nz = nz;
276 | info->dist = dist;
277 |
278 | return 0;
279 | }
280 |
281 | int tex = tex_index(relPos, face);
282 |
283 | return ray_color(x, y, z, pos, tex, face);
284 | }
285 |
286 | // Remaining distance inside this block given ray direction
287 | float dx = x - pos.x + dx_off;
288 | float dy = y - pos.y + dy_off;
289 | float dz = z - pos.z + dz_off;
290 |
291 | // Calculate distance for each dimension
292 | float t1 = dx / dir.x;
293 | float t2 = dy / dir.y;
294 | float t3 = dz / dir.z;
295 |
296 | // Find closest hit
297 | if (t1 <= t2 && t1 <= t3) {
298 | pos.x += dx;
299 | pos.y += t1 * dir.y;
300 | pos.z += t1 * dir.z;
301 | x += x_dir;
302 | face = x_face;
303 | }
304 | if (t2 <= t1 && t2 <= t3) {
305 | pos.x += t2 * dir.x;
306 | pos.y += dy;
307 | pos.z += t2 * dir.z;
308 | y += y_dir;
309 | face = y_face;
310 | }
311 | if (t3 <= t1 && t3 <= t2) {
312 | pos.x += t3 * dir.x;
313 | pos.y += t3 * dir.y;
314 | pos.z += dz;
315 | z += z_dir;
316 | face = z_face;
317 | }
318 | }
319 |
320 | nohit:
321 | if (info != NULL) {
322 | info->hit = false;
323 | }
324 |
325 | // Sky color
326 | return skyColor;
327 | }
--------------------------------------------------------------------------------
/src/textures.asm:
--------------------------------------------------------------------------------
1 | ;
2 | ; This file contains the texture images (16x16 palette coloured, light and dark versions)
3 | ;
4 |
5 | global tex_grass, tex_dirt, tex_grass_side
6 |
7 | section .data
8 |
9 | ; Grass top
10 | tex_grass db 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0E, 0x10, 0x0E, 0x05
11 | db 0x0D, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x1E, 0x20
12 | db 0x22, 0x24, 0x25, 0x27, 0x29, 0x2B, 0x2D, 0x2F, 0x31, 0x33
13 | db 0x34, 0x35, 0x37, 0x38, 0x3A, 0x24, 0x3B, 0x22, 0x38, 0x3C
14 | db 0x3D, 0x1E, 0x3F, 0x41, 0x42, 0x44, 0x22, 0x46, 0x48, 0x4A
15 | db 0x4B, 0x4D, 0x4E, 0x38, 0x24, 0x41, 0x50, 0x10, 0x52, 0x34
16 | db 0x4B, 0x54, 0x56, 0x57, 0x48, 0x59, 0x4B, 0x4D, 0x2F, 0x4B
17 | db 0x4E, 0x41, 0x33, 0x41, 0x4B, 0x24, 0x5A, 0x42, 0x50, 0x5C
18 | db 0x18, 0x5E, 0x5F, 0x60, 0x61, 0x5A, 0x22, 0x42, 0x22, 0x29
19 | db 0x63, 0x4E, 0x4E, 0x65, 0x2F, 0x67, 0x69, 0x65, 0x4E, 0x42
20 | db 0x6A, 0x24, 0x4B, 0x31, 0x50, 0x2F, 0x24, 0x41, 0x22, 0x22
21 | db 0x24, 0x3B, 0x18, 0x5E, 0x4E, 0x6C, 0x2F, 0x38, 0x42, 0x22
22 | db 0x38, 0x6E, 0x59, 0x4B, 0x56, 0x6F, 0x31, 0x70, 0x72, 0x22
23 | db 0x41, 0x22, 0x63, 0x73, 0x5E, 0x60, 0x74, 0x41, 0x6F, 0x31
24 | db 0x75, 0x38, 0x4B, 0x05, 0x77, 0x78, 0x79, 0x22, 0x56, 0x7A
25 | db 0x7A, 0x2F, 0x7C, 0x24, 0x22, 0x41, 0x1C, 0x7E, 0x3F, 0x80
26 | db 0x18, 0x34, 0x7C, 0x1C, 0x42, 0x4B, 0x63, 0x41, 0x22, 0x4D
27 | db 0x82, 0x7A, 0x4B, 0x2F, 0x84, 0x0E, 0x85, 0x1C, 0x50, 0x31
28 | db 0x34, 0x4B, 0x33, 0x4B, 0x4E, 0x87, 0x4E, 0x56, 0x42, 0x84
29 | db 0x7A, 0x09, 0x48, 0x5E, 0x22, 0x41, 0x33, 0x42, 0x41, 0x1C
30 | db 0x4B, 0x4D, 0x7A, 0x42, 0x29, 0x89, 0x33, 0x69, 0x69, 0x22
31 | db 0x44, 0x5F, 0x65, 0x22, 0x34, 0x38, 0x4A, 0x61, 0x41, 0x6C
32 | db 0x38, 0x73, 0x25, 0x05, 0x8A, 0x5E, 0x22, 0x4B, 0x5F, 0x4E
33 | db 0x5A, 0x22, 0x42, 0x41, 0x8B, 0x56, 0x56, 0x34, 0x24, 0x10
34 | db 0x8C, 0x4D, 0x70, 0x73, 0x10, 0x05, 0x8E, 0x07, 0x0E, 0x09
35 | db 0x10, 0x69, 0x0E, 0x90, 0x91, 0x03
36 |
37 | db 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0C, 0x0F, 0x11, 0x0F, 0x06
38 | db 0x0C, 0x11, 0x13, 0x15, 0x17, 0x19, 0x1B, 0x1D, 0x1F, 0x21
39 | db 0x23, 0x11, 0x26, 0x28, 0x2A, 0x2C, 0x2E, 0x30, 0x32, 0x0C
40 | db 0x0C, 0x36, 0x0C, 0x39, 0x1F, 0x11, 0x0C, 0x23, 0x39, 0x39
41 | db 0x3E, 0x1F, 0x40, 0x1D, 0x43, 0x45, 0x23, 0x47, 0x49, 0x11
42 | db 0x4C, 0x47, 0x4F, 0x39, 0x11, 0x1D, 0x51, 0x11, 0x53, 0x0C
43 | db 0x4C, 0x55, 0x45, 0x58, 0x49, 0x11, 0x4C, 0x47, 0x30, 0x4C
44 | db 0x4F, 0x1D, 0x0C, 0x1D, 0x4C, 0x11, 0x5B, 0x43, 0x51, 0x5D
45 | db 0x19, 0x43, 0x4C, 0x5B, 0x62, 0x5B, 0x23, 0x43, 0x23, 0x2A
46 | db 0x64, 0x4F, 0x4F, 0x66, 0x30, 0x68, 0x11, 0x66, 0x4F, 0x43
47 | db 0x6B, 0x11, 0x4C, 0x32, 0x51, 0x30, 0x11, 0x1D, 0x23, 0x23
48 | db 0x11, 0x0C, 0x19, 0x43, 0x4F, 0x6D, 0x30, 0x39, 0x43, 0x23
49 | db 0x39, 0x23, 0x11, 0x4C, 0x45, 0x1F, 0x32, 0x71, 0x04, 0x23
50 | db 0x1D, 0x23, 0x64, 0x11, 0x43, 0x5B, 0x1F, 0x1D, 0x1F, 0x32
51 | db 0x76, 0x39, 0x4C, 0x06, 0x1B, 0x0C, 0x53, 0x23, 0x45, 0x7B
52 | db 0x7B, 0x30, 0x7D, 0x11, 0x23, 0x1D, 0x1D, 0x7F, 0x40, 0x81
53 | db 0x19, 0x0C, 0x7D, 0x1D, 0x43, 0x4C, 0x64, 0x1D, 0x23, 0x47
54 | db 0x83, 0x7B, 0x4C, 0x30, 0x5B, 0x0F, 0x86, 0x1D, 0x51, 0x32
55 | db 0x0C, 0x4C, 0x0C, 0x4C, 0x4F, 0x88, 0x4F, 0x45, 0x43, 0x5B
56 | db 0x7B, 0x0A, 0x49, 0x43, 0x23, 0x1D, 0x0C, 0x43, 0x1D, 0x1D
57 | db 0x4C, 0x47, 0x7B, 0x43, 0x2A, 0x40, 0x0C, 0x11, 0x11, 0x23
58 | db 0x45, 0x4C, 0x66, 0x23, 0x0C, 0x39, 0x11, 0x62, 0x1D, 0x6D
59 | db 0x39, 0x11, 0x26, 0x06, 0x0A, 0x43, 0x23, 0x4C, 0x4C, 0x4F
60 | db 0x5B, 0x23, 0x43, 0x1D, 0x4C, 0x45, 0x45, 0x0C, 0x11, 0x11
61 | db 0x8D, 0x47, 0x71, 0x11, 0x11, 0x06, 0x8F, 0x08, 0x0F, 0x0A
62 | db 0x11, 0x11, 0x0F, 0x1F, 0x92, 0x04
63 |
64 | ; Dirt side/bottom
65 | tex_dirt db 0x93, 0x95, 0x93, 0x97, 0x97, 0x95, 0x93, 0x95, 0x97, 0x95
66 | db 0x95, 0x97, 0x95, 0x95, 0x97, 0x97, 0x97, 0x97, 0x95, 0x99
67 | db 0x95, 0x9B, 0x95, 0x95, 0x95, 0x97, 0x97, 0x95, 0x9B, 0x97
68 | db 0x95, 0x95, 0x97, 0x9B, 0x95, 0x93, 0x97, 0x97, 0x95, 0x93
69 | db 0x95, 0x9B, 0x95, 0x95, 0x97, 0x95, 0x9B, 0x93, 0x95, 0x95
70 | db 0x9B, 0x95, 0x93, 0x97, 0x95, 0x93, 0x97, 0x95, 0x93, 0x97
71 | db 0x95, 0x95, 0x93, 0x97, 0x95, 0x95, 0x93, 0x97, 0x9B, 0x95
72 | db 0x9D, 0x97, 0x95, 0x95, 0x93, 0x97, 0x97, 0x9F, 0x95, 0x97
73 | db 0x93, 0x97, 0x95, 0x9B, 0x97, 0x97, 0x95, 0x97, 0x97, 0x9B
74 | db 0x95, 0x93, 0x97, 0x95, 0x9B, 0x95, 0x97, 0x9D, 0x95, 0x95
75 | db 0x95, 0x9B, 0x95, 0x95, 0x95, 0x9B, 0x93, 0x95, 0x93, 0x97
76 | db 0x95, 0x9D, 0x97, 0x9B, 0x95, 0x93, 0x95, 0x9B, 0x93, 0x95
77 | db 0x9B, 0x95, 0x97, 0x97, 0x95, 0x97, 0x9B, 0x95, 0x95, 0x95
78 | db 0x93, 0x97, 0x97, 0x9B, 0x93, 0x97, 0x95, 0x95, 0x9B, 0x99
79 | db 0x95, 0x95, 0x93, 0x97, 0x95, 0x93, 0x95, 0x97, 0x9B, 0x95
80 | db 0x95, 0x9B, 0x97, 0x95, 0x93, 0x97, 0x95, 0x9B, 0x93, 0x97
81 | db 0x9B, 0x97, 0x95, 0x95, 0x95, 0x95, 0x93, 0x97, 0x97, 0x95
82 | db 0x93, 0x97, 0x95, 0x93, 0x95, 0x95, 0x95, 0x95, 0x95, 0x97
83 | db 0x99, 0x9B, 0x93, 0x97, 0x95, 0x95, 0x9B, 0x95, 0x95, 0x9B
84 | db 0x97, 0x95, 0x95, 0x93, 0x9B, 0x95, 0x95, 0x95, 0x95, 0x95
85 | db 0x95, 0x93, 0x97, 0x9B, 0x95, 0x95, 0x95, 0x97, 0x93, 0x97
86 | db 0x9B, 0x93, 0x97, 0x95, 0x97, 0x95, 0x95, 0x93, 0x97, 0x97
87 | db 0x95, 0x93, 0x95, 0x97, 0x95, 0x9B, 0x93, 0x97, 0x9B, 0x95
88 | db 0x95, 0x97, 0x9B, 0x95, 0x9D, 0x95, 0x93, 0x97, 0x97, 0x95
89 | db 0x93, 0x9B, 0x95, 0x95, 0x95, 0x93, 0x97, 0x97, 0x95, 0x97
90 | db 0x95, 0x9B, 0x93, 0x97, 0x97, 0x9B
91 |
92 | db 0x94, 0x96, 0x94, 0x98, 0x98, 0x96, 0x94, 0x96, 0x98, 0x96
93 | db 0x96, 0x98, 0x96, 0x96, 0x98, 0x98, 0x98, 0x98, 0x96, 0x9A
94 | db 0x96, 0x9C, 0x96, 0x96, 0x96, 0x98, 0x98, 0x96, 0x9C, 0x98
95 | db 0x96, 0x96, 0x98, 0x9C, 0x96, 0x94, 0x98, 0x98, 0x96, 0x94
96 | db 0x96, 0x9C, 0x96, 0x96, 0x98, 0x96, 0x9C, 0x94, 0x96, 0x96
97 | db 0x9C, 0x96, 0x94, 0x98, 0x96, 0x94, 0x98, 0x96, 0x94, 0x98
98 | db 0x96, 0x96, 0x94, 0x98, 0x96, 0x96, 0x94, 0x98, 0x9C, 0x96
99 | db 0x9E, 0x98, 0x96, 0x96, 0x94, 0x98, 0x98, 0xA0, 0x96, 0x98
100 | db 0x94, 0x98, 0x96, 0x9C, 0x98, 0x98, 0x96, 0x98, 0x98, 0x9C
101 | db 0x96, 0x94, 0x98, 0x96, 0x9C, 0x96, 0x98, 0x9E, 0x96, 0x96
102 | db 0x96, 0x9C, 0x96, 0x96, 0x96, 0x9C, 0x94, 0x96, 0x94, 0x98
103 | db 0x96, 0x9E, 0x98, 0x9C, 0x96, 0x94, 0x96, 0x9C, 0x94, 0x96
104 | db 0x9C, 0x96, 0x98, 0x98, 0x96, 0x98, 0x9C, 0x96, 0x96, 0x96
105 | db 0x94, 0x98, 0x98, 0x9C, 0x94, 0x98, 0x96, 0x96, 0x9C, 0x9A
106 | db 0x96, 0x96, 0x94, 0x98, 0x96, 0x94, 0x96, 0x98, 0x9C, 0x96
107 | db 0x96, 0x9C, 0x98, 0x96, 0x94, 0x98, 0x96, 0x9C, 0x94, 0x98
108 | db 0x9C, 0x98, 0x96, 0x96, 0x96, 0x96, 0x94, 0x98, 0x98, 0x96
109 | db 0x94, 0x98, 0x96, 0x94, 0x96, 0x96, 0x96, 0x96, 0x96, 0x98
110 | db 0x9A, 0x9C, 0x94, 0x98, 0x96, 0x96, 0x9C, 0x96, 0x96, 0x9C
111 | db 0x98, 0x96, 0x96, 0x94, 0x9C, 0x96, 0x96, 0x96, 0x96, 0x96
112 | db 0x96, 0x94, 0x98, 0x9C, 0x96, 0x96, 0x96, 0x98, 0x94, 0x98
113 | db 0x9C, 0x94, 0x98, 0x96, 0x98, 0x96, 0x96, 0x94, 0x98, 0x98
114 | db 0x96, 0x94, 0x96, 0x98, 0x96, 0x9C, 0x94, 0x98, 0x9C, 0x96
115 | db 0x96, 0x98, 0x9C, 0x96, 0x9E, 0x96, 0x94, 0x98, 0x98, 0x96
116 | db 0x94, 0x9C, 0x96, 0x96, 0x96, 0x94, 0x98, 0x98, 0x96, 0x98
117 | db 0x96, 0x9C, 0x94, 0x98, 0x98, 0x9C
118 |
119 | ; Side with grass on top
120 | tex_grass_side db 0xA1, 0x27, 0xA3, 0x9B, 0x97, 0x95, 0x93, 0x95, 0x97, 0x95
121 | db 0x95, 0x97, 0x95, 0x95, 0x97, 0x97, 0x0E, 0xA4, 0x9B, 0x99
122 | db 0x95, 0x9B, 0x95, 0x95, 0x95, 0x97, 0x97, 0x95, 0x9B, 0x97
123 | db 0x95, 0x95, 0xA1, 0xA5, 0xA7, 0x9B, 0x97, 0x97, 0x95, 0x93
124 | db 0x95, 0x9B, 0x95, 0x95, 0x97, 0x95, 0x9B, 0x93, 0xA8, 0xAA
125 | db 0xAC, 0x9B, 0x93, 0x97, 0x95, 0x93, 0x97, 0x95, 0x93, 0x97
126 | db 0x95, 0x95, 0x93, 0x97, 0xA8, 0xAE, 0xB0, 0x09, 0x9B, 0x95
127 | db 0x9D, 0x97, 0x95, 0x95, 0x93, 0x97, 0x97, 0x9F, 0x95, 0x97
128 | db 0xB1, 0x9B, 0x9B, 0x9B, 0x97, 0x97, 0x95, 0x97, 0x97, 0x9B
129 | db 0x95, 0x93, 0x97, 0x95, 0x9B, 0x95, 0xB2, 0xB0, 0x6E, 0x9B
130 | db 0x95, 0x9B, 0x95, 0x95, 0x95, 0x9B, 0x93, 0x95, 0x93, 0x97
131 | db 0x95, 0x9D, 0xA4, 0xB3, 0x9B, 0x9B, 0x95, 0x9B, 0x93, 0x95
132 | db 0x9B, 0x95, 0x97, 0x97, 0x95, 0x97, 0x9B, 0x95, 0x10, 0xB2
133 | db 0xA1, 0xB2, 0x9B, 0x9B, 0x93, 0x97, 0x95, 0x95, 0x9B, 0x99
134 | db 0x95, 0x95, 0x93, 0x97, 0x0E, 0xB5, 0xB7, 0x9B, 0x9B, 0x95
135 | db 0x95, 0x9B, 0x97, 0x95, 0x93, 0x97, 0x95, 0x9B, 0x93, 0x97
136 | db 0xB0, 0xB8, 0xB9, 0xB1, 0x9B, 0x95, 0x93, 0x97, 0x97, 0x95
137 | db 0x93, 0x97, 0x95, 0x93, 0x95, 0x95, 0x57, 0xA1, 0xBA, 0x9B
138 | db 0x99, 0x9B, 0x93, 0x97, 0x95, 0x95, 0x9B, 0x95, 0x95, 0x9B
139 | db 0x97, 0x95, 0xB0, 0xBC, 0x9B, 0x95, 0x95, 0x95, 0x95, 0x95
140 | db 0x95, 0x93, 0x97, 0x9B, 0x95, 0x95, 0x95, 0x97, 0xBC, 0xA4
141 | db 0xBD, 0x9B, 0x97, 0x95, 0x97, 0x95, 0x95, 0x93, 0x97, 0x97
142 | db 0x95, 0x93, 0x95, 0x97, 0xBF, 0x57, 0xB2, 0x9B, 0x9B, 0x95
143 | db 0x95, 0x97, 0x9B, 0x95, 0x9D, 0x95, 0x93, 0x97, 0x97, 0x95
144 | db 0xB1, 0xC1, 0x9B, 0x95, 0x95, 0x93, 0x97, 0x97, 0x95, 0x97
145 | db 0x95, 0x9B, 0x93, 0x97, 0x97, 0x9B
146 |
147 | db 0xA2, 0x28, 0x8F, 0x9C, 0x98, 0x96, 0x94, 0x96, 0x98, 0x96
148 | db 0x96, 0x98, 0x96, 0x96, 0x98, 0x98, 0x0F, 0x23, 0x9C, 0x9A
149 | db 0x96, 0x9C, 0x96, 0x96, 0x96, 0x98, 0x98, 0x96, 0x9C, 0x98
150 | db 0x96, 0x96, 0xA2, 0xA6, 0x08, 0x9C, 0x98, 0x98, 0x96, 0x94
151 | db 0x96, 0x9C, 0x96, 0x96, 0x98, 0x96, 0x9C, 0x94, 0xA9, 0xAB
152 | db 0xAD, 0x9C, 0x94, 0x98, 0x96, 0x94, 0x98, 0x96, 0x94, 0x98
153 | db 0x96, 0x96, 0x94, 0x98, 0xA9, 0xAF, 0x66, 0x0A, 0x9C, 0x96
154 | db 0x9E, 0x98, 0x96, 0x96, 0x94, 0x98, 0x98, 0xA0, 0x96, 0x98
155 | db 0x23, 0x9C, 0x9C, 0x9C, 0x98, 0x98, 0x96, 0x98, 0x98, 0x9C
156 | db 0x96, 0x94, 0x98, 0x96, 0x9C, 0x96, 0x55, 0x66, 0x23, 0x9C
157 | db 0x96, 0x9C, 0x96, 0x96, 0x96, 0x9C, 0x94, 0x96, 0x94, 0x98
158 | db 0x96, 0x9E, 0x23, 0xB4, 0x9C, 0x9C, 0x96, 0x9C, 0x94, 0x96
159 | db 0x9C, 0x96, 0x98, 0x98, 0x96, 0x98, 0x9C, 0x96, 0x11, 0x55
160 | db 0xA2, 0x55, 0x9C, 0x9C, 0x94, 0x98, 0x96, 0x96, 0x9C, 0x9A
161 | db 0x96, 0x96, 0x94, 0x98, 0x0F, 0xB6, 0x11, 0x9C, 0x9C, 0x96
162 | db 0x96, 0x9C, 0x98, 0x96, 0x94, 0x98, 0x96, 0x9C, 0x94, 0x98
163 | db 0x66, 0x8F, 0x8F, 0x23, 0x9C, 0x96, 0x94, 0x98, 0x98, 0x96
164 | db 0x94, 0x98, 0x96, 0x94, 0x96, 0x96, 0x58, 0xA2, 0xBB, 0x9C
165 | db 0x9A, 0x9C, 0x94, 0x98, 0x96, 0x96, 0x9C, 0x96, 0x96, 0x9C
166 | db 0x98, 0x96, 0x66, 0x55, 0x9C, 0x96, 0x96, 0x96, 0x96, 0x96
167 | db 0x96, 0x94, 0x98, 0x9C, 0x96, 0x96, 0x96, 0x98, 0x55, 0x23
168 | db 0xBE, 0x9C, 0x98, 0x96, 0x98, 0x96, 0x96, 0x94, 0x98, 0x98
169 | db 0x96, 0x94, 0x96, 0x98, 0xC0, 0x58, 0x55, 0x9C, 0x9C, 0x96
170 | db 0x96, 0x98, 0x9C, 0x96, 0x9E, 0x96, 0x94, 0x98, 0x98, 0x96
171 | db 0x23, 0x23, 0x9C, 0x96, 0x96, 0x94, 0x98, 0x98, 0x96, 0x98
172 | db 0x96, 0x9C, 0x94, 0x98, 0x98, 0x9C
--------------------------------------------------------------------------------
/src/graphics.asm:
--------------------------------------------------------------------------------
1 | ;
2 | ; This file contains all functions related to rendering the world
3 | ;
4 |
5 | [bits 32]
6 |
7 | %include "constants.asm"
8 |
9 | global ray_dir, face_normal, tex_index, ray_color, reticle_color, draw_frame
10 |
11 | extern vga
12 |
13 | extern hFov
14 | extern yawC, yawS, pitchC, pitchS
15 | extern playerPos
16 |
17 | extern get_block
18 | extern raytrace
19 | extern sunDir
20 |
21 | extern palette
22 | extern tex_grass, tex_dirt, tex_grass_side
23 |
24 | section .data
25 |
26 | ; Helpful constants
27 | width dd 320
28 | halfWidth dd 160
29 | height dd 200
30 | halfHeight dd 100
31 |
32 | aspect dd 1.6
33 | neg_aspect dd -1.6
34 |
35 | texture_scale dd 16
36 | texture_size dd 15
37 | two dd 2.0
38 | half dd 0.5
39 |
40 | doubleCircle dd 720.0
41 |
42 | section .text
43 |
44 | ; vec3 rayDir(int x, int y)
45 | ; Takes screen space x and y and returns ray direction
46 | ray_dir:
47 | push ebp
48 | mov ebp, esp
49 |
50 | ; Allocate local variables (vFov, fov, clipX, clipY, length)
51 | sub esp, 20
52 |
53 | ; Load struct address (x, y, z)
54 | mov eax, dword [ebp + 8]
55 |
56 | ; Calculate vertical fov and fov constant from horizontal fov
57 |
58 | ; vFov = 2.0f * atanf(tanf(hFov / 720.0f * M_PI) * 320.0f / 200.0f);
59 | ; RPN: 2.0 hFov 720.0 / pi * tan width * height / atan mul
60 | fld dword [two]
61 | fld dword [hFov]
62 | fld dword [doubleCircle]
63 | fdiv
64 | fldpi
65 | fmul
66 | fptan
67 | fstp dword [eax] ; Dump 1 the tan instruction pushes for some reason
68 | fild dword [width]
69 | fmul
70 | fild dword [height]
71 | fdiv
72 | fld1 ; 1 required for atan (takes two parameters like atan2 in C)
73 | fpatan
74 | fmul
75 | fst dword [ebp - 4] ; vFov
76 |
77 | ; fov = tanf(0.5f * vFov);
78 | ; RPN: 0.5 vFov * tan
79 | fld dword [half]
80 | fmul
81 | fptan
82 | fstp dword [eax]
83 | fstp dword [ebp - 8] ; fov
84 |
85 | ; clip X = x / 160.0f - 1.0f
86 | ; RPN: x 160.0 / 1.0 -
87 | fild dword [ebp + 12] ; x parameter
88 | fild dword [halfWidth]
89 | fdiv
90 | fld1
91 | fsub
92 | fstp dword [ebp - 12] ; clipX
93 |
94 | ; clip Y = 1.0f - y / 100.0f
95 | ; RPN: 1.0 y 100.0 / -
96 | fld1
97 | fild dword [ebp + 16] ; y parameter
98 | fild dword [halfHeight]
99 | fdiv
100 | fsub
101 | fstp dword [ebp - 16] ; clipY
102 |
103 | ; X dir = 1.6f * fov * yawC * clipX + fov * yawS * pitchS * clipY - pitchC * yawS
104 | ; RPN: 1.6 fov yawC clipX * * * fov yawS pitchS clipY * * * + pitchC yawS * -
105 | fld dword [aspect]
106 | fld dword [ebp - 8] ; fov
107 | fld dword [yawC]
108 | fld dword [ebp - 12] ; clipX
109 | fmul
110 | fmul
111 | fmul
112 | fld dword [ebp - 8] ; fov
113 | fld dword [yawS]
114 | fld dword [pitchS]
115 | fld dword [ebp - 16] ; clipY
116 | fmul
117 | fmul
118 | fmul
119 | fadd
120 | fld dword [pitchC]
121 | fld dword [yawS]
122 | fmul
123 | fsub
124 | fstp dword [eax] ; X dir
125 |
126 | ; Y dir = fov * pitchC * clipY + pitchS
127 | ; RPN: fov pitchC clipY * * pitchS +
128 | fld dword [ebp - 8] ; fov
129 | fld dword [pitchC]
130 | fld dword [ebp - 16] ; clipY
131 | fmul
132 | fmul
133 | fld dword [pitchS]
134 | fadd
135 | fstp dword [eax + 4] ; Y dir
136 |
137 | ; Z dir = -1.6f * fov * yawS * clipX + fov * yawC * pitchS * clipY - pitchC * yawC
138 | ; RPN: neg_aspect fov yawS clipX * * * fov yawC pitchS clipY * * * + pitchC yawC * -
139 | fld dword [neg_aspect]
140 | fld dword [ebp - 8] ; fov
141 | fld dword [yawS]
142 | fld dword [ebp - 12] ; clipX
143 | fmul
144 | fmul
145 | fmul
146 | fld dword [ebp - 8] ; fov
147 | fld dword [yawC]
148 | fld dword [pitchS]
149 | fld dword [ebp - 16] ; clipY
150 | fmul
151 | fmul
152 | fmul
153 | fadd
154 | fld dword [pitchC]
155 | fld dword [yawC]
156 | fmul
157 | fsub
158 | fstp dword [eax + 8] ; Z dir
159 |
160 | ; Resulting direction is not normalized, but that doesn't matter
161 | ; for the raytracing algorithm
162 |
163 | mov esp, ebp
164 | pop ebp
165 | ret 4
166 |
167 | ; void face_normal(int face, int* nx, int* ny, int* nz)
168 | ; Returns normal of given block face
169 | face_normal:
170 | ; Initialize nx, ny and nz to zero (no direction)
171 | mov eax, [esp + 8] ; nx
172 | mov dword [eax], 0
173 | mov eax, [esp + 12] ; ny
174 | mov dword [eax], 0
175 | mov eax, [esp + 16] ; nz
176 | mov dword [eax], 0
177 |
178 | ; Jump to face
179 | mov eax, [esp + 4] ; face
180 | jmp [.face_tbl + eax * 4]
181 |
182 | ; Face jump table
183 | .face_tbl:
184 | dd .face_left
185 | dd .face_right
186 | dd .face_bottom
187 | dd .face_top
188 | dd .face_back
189 | dd .face_front
190 | .face_left:
191 | mov eax, [esp + 8] ; nx = -1
192 | mov dword [eax], -1
193 | ret
194 | .face_right:
195 | mov eax, [esp + 8] ; nx = 1
196 | mov dword [eax], 1
197 | ret
198 | .face_bottom:
199 | mov eax, [esp + 12] ; ny = -1
200 | mov dword [eax], -1
201 | ret
202 | .face_top:
203 | mov eax, [esp + 12] ; ny = 1
204 | mov dword [eax], 1
205 | ret
206 | .face_back:
207 | mov eax, [esp + 16] ; nz = -1
208 | mov dword [eax], -1
209 | ret
210 | .face_front:
211 | mov eax, [esp + 16] ; nz = 1
212 | mov dword [eax], 1
213 | ret
214 |
215 | ; int tex_index(vec3 pos, int face)
216 | ; Returns index into texture image
217 | tex_index:
218 | ; First jump to face to determine (u, v) texture coordinates
219 | ; These variables will be pushed on the FPU stack
220 | mov eax, [esp + 16] ; face
221 | jmp [.face_tbl + eax * 4]
222 |
223 | ; Face jump table
224 | .face_tbl:
225 | dd .face_left
226 | dd .face_right
227 | dd .face_bottom
228 | dd .face_top
229 | dd .face_back
230 | dd .face_front
231 | .face_left:
232 | .face_right:
233 | fld dword [esp + 12] ; u = pos.z
234 | fld dword [esp + 8] ; v = pos.y
235 | jmp .uv_selected
236 | .face_bottom:
237 | .face_top:
238 | fld dword [esp + 4] ; u = pos.x
239 | fld dword [esp + 12] ; v = pos.z
240 | jmp .uv_selected
241 | .face_back:
242 | .face_front:
243 | fld dword [esp + 4] ; u = pos.x
244 | fld dword [esp + 8] ; v = pos.y
245 |
246 | .uv_selected:
247 | ; Invert v (1.0 - v)
248 | fld1
249 | fsubr
250 |
251 | ; Compute final integer index
252 |
253 | ; (int) (v * 15.0)
254 | fild dword [texture_size]
255 | fmul
256 | fistp dword [esp - 4] ; Store in temp variable
257 |
258 | ; (int) (u * 15.0) * 16
259 | fild dword [texture_size]
260 | fmul
261 | fistp dword [esp - 8]
262 | mov eax, [esp - 8]
263 | mul dword [texture_scale]
264 |
265 | ; Combine
266 | add eax, [esp - 4]
267 |
268 | ret
269 |
270 | section .text
271 |
272 | ; byte ray_color(int x, int y, int z, vec3 pos, int tex, int face)
273 | ; Return color for given block and world details
274 | ray_color:
275 | push ebp
276 | mov ebp, esp
277 | push esi
278 |
279 | ; Allocate space for hit info struct
280 | sub esp, 32
281 |
282 | ; Store texture image index
283 | mov esi, [ebp + 32] ; tex
284 |
285 | ; Do lighting ray trace and request feedback to local hit info struct
286 | mov eax, ebp
287 | sub eax, 32
288 | push eax ; Pointer to hit info struct
289 |
290 | push dword [sunDir + 8] ; Ray direction vec3 (in reverse because stack grows downwards)
291 | push dword [sunDir + 4]
292 | push dword [sunDir + 0]
293 |
294 | push dword [ebp + 28] ; Ray start position vec3
295 | push dword [ebp + 24]
296 | push dword [ebp + 20]
297 |
298 | call raytrace
299 |
300 | add esp, 28
301 |
302 | ; If light ray hit something, shift to dark texture indices
303 | cmp byte [ebp - 32], 1 ; Check if bool 'hit' in struct set to 1
304 | jne .not_shadow
305 | add esi, 256
306 | .not_shadow:
307 |
308 | ; Texture lookup based on side
309 | cmp dword [ebp + 36], FACE_BOTTOM
310 | je .dirt
311 | cmp dword [ebp + 36], FACE_TOP
312 | je .grass
313 |
314 | ; If this block is at the top of the world, nothing is above it
315 | cmp dword [ebp + 12], WORLD_SY - 1
316 | je .grass_side
317 |
318 | ; In other cases, if there is another block above this block, sides are dirt
319 | push dword [ebp + 16] ; z
320 |
321 | mov eax, [ebp + 12]
322 | add eax, 1
323 | push eax ; y + 1
324 |
325 | push dword [ebp + 8] ; x
326 |
327 | call get_block
328 |
329 | add esp, 12
330 |
331 | cmp eax, BLOCK_DIRT
332 | je .dirt
333 |
334 | ; Grassy side texture
335 | .grass_side:
336 | movzx eax, byte [esi + tex_grass_side]
337 | jmp .finish
338 |
339 | ; Grass texture
340 | .grass:
341 | movzx eax, byte [esi + tex_grass]
342 | jmp .finish
343 |
344 | ; Dirt texture
345 | .dirt:
346 | movzx eax, byte [esi + tex_dirt]
347 |
348 | .finish:
349 | pop esi
350 | mov esp, ebp
351 | pop ebp
352 |
353 | ret
354 |
355 | ; byte reticle_color(byte col)
356 | ; Return semi-inverted color for given color to draw nice aim reticle
357 | reticle_color:
358 | push ebx
359 |
360 | ; Palette index
361 | mov eax, [esp + 8]
362 |
363 | ; Find RGB channels of palette color
364 | mov bl, [eax * 3 + palette + 0] ; R
365 | mov cl, [eax * 3 + palette + 1] ; G
366 | mov dl, [eax * 3 + palette + 2] ; B
367 |
368 | ; If blue channel has the max value, it's sky
369 | cmp dl, 63
370 | je .sky
371 |
372 | ; If green is more prevalent than blue, it's grass
373 | cmp cl, bl
374 | jg .grass
375 |
376 | .dirt:
377 | ; Return inverse color for dirt
378 | mov eax, 254
379 | jmp .finish
380 |
381 | .grass:
382 | ; Return inverse color for grass
383 | mov eax, 253
384 | jmp .finish
385 |
386 | .sky:
387 | ; Return inverse color for blue sky
388 | mov eax, 255
389 |
390 | .finish:
391 | pop ebx
392 | ret
393 |
394 | ; void draw_frame()
395 | ; Draw a single frame to the VGA frame buffer
396 | draw_frame:
397 | push esi
398 | push ebx
399 | push ebp
400 | mov ebp, esp
401 |
402 | ; Allocate space for ray dir vec3
403 | sub esp, 12
404 |
405 | ; Initialize local variables
406 | mov edi, 0 ; x
407 | mov ebx, 0 ; y
408 | mov ecx, [vga] ; pixel
409 | mov edx, 0 ; pixel index
410 |
411 | ; Draw a pixel
412 | .pixel:
413 | ; Calculate ray direction (ECX not used by ray_dir)
414 | push ebx
415 | push edi
416 |
417 | mov esi, ebp
418 | sub esi, 12
419 | push esi ; Pointer to local vec3
420 |
421 | call ray_dir
422 |
423 | ; No need to pop struct pointer, done by callee
424 | add esp, 8
425 |
426 | ; Perform ray trace
427 | push ecx
428 | push edx
429 |
430 | push dword 0 ; Not interested in hit info
431 |
432 | push dword [ebp - 4] ; Copy of ray dir vec3 (in reverse because stack grows downwards)
433 | push dword [ebp - 8]
434 | push dword [ebp - 12]
435 |
436 | push dword [playerPos + 8] ; Copy of playerPos vec3
437 | push dword [playerPos + 4]
438 | push dword [playerPos + 0]
439 |
440 | call raytrace
441 |
442 | add esp, 28
443 |
444 | pop edx
445 | pop ecx
446 |
447 | ; Assign pixel color
448 | mov [ecx], al
449 |
450 | ; Draw aim reticle
451 | cmp edi, 157
452 | jle .vertical_reticle
453 | cmp edi, 163
454 | jge .vertical_reticle
455 | cmp ebx, 100
456 | jne .vertical_reticle
457 |
458 | ; x > 157 && x < 163 && y == 100? Draw horizontal reticle line
459 | push ecx
460 | push edx
461 | push eax
462 | call reticle_color
463 | add esp, 4
464 | pop edx
465 | pop ecx
466 |
467 | mov [ecx], al
468 |
469 | jmp .no_reticle
470 | .vertical_reticle:
471 | cmp ebx, 97
472 | jle .no_reticle
473 | cmp ebx, 103
474 | jge .no_reticle
475 | cmp edi, 160
476 | jne .no_reticle
477 |
478 | ; y > 97 && y < 103 && x == 160? Draw vertical reticle line
479 | push ecx
480 | push edx
481 | push eax
482 | call reticle_color
483 | add esp, 4
484 | pop edx
485 | pop ecx
486 |
487 | mov [ecx], al
488 | .no_reticle:
489 |
490 |
491 | ; Update XY coordinates
492 | inc edi
493 | cmp edi, 320
494 | jl .next_pixel
495 | mov edi, 0
496 | inc ebx
497 |
498 | ; Go to next pixel
499 | .next_pixel:
500 | inc ecx
501 | inc edx
502 | cmp edx, 320 * 200
503 | jl .pixel
504 |
505 | mov esp, ebp
506 | pop ebp
507 | pop ebx
508 | pop esi
509 |
510 | ret
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | MineAssemble
2 | ============
3 |
4 |
5 |
6 |
7 | **[Prebuilt ISO](https://while.io/mineassemble.iso) - [Video](http://www.youtube.com/watch?v=HDcr5dnellM)**
8 |
9 | MineAssemble is a tiny bootable Minecraft clone written partly in x86 assembly.
10 | I made it first and foremost because a university assignment required me to
11 | implement a game in assembly for a computer systems course. Because I had never
12 | implemented anything more complex than a "Hello World" bootloader before, I
13 | decided I wanted to learn about writing my own kernel code at the same time.
14 |
15 | Note that the goal of this project was **not** to write highly efficient
16 | hand-optimized assembly code, but rather to have fun and write code that
17 | balances readability and speed. This is primarily accomplished by proper
18 | commenting and consistent code structuring.
19 |
20 | Starting in assembly right away would be a bit too insane, so I first wrote a
21 | reference implementation in C using the SDL library, which can be found in the
22 | *reference* directory. I started writing it with the idea that if it was longer
23 | than 150 statements excluding boilerplate, it wouldn't be worth doing it in
24 | assembly. Like all estimates in the world of programming, this limit turned out
25 | to be a gross underestimate, reaching about 134 lines before adding the texture
26 | or even the input code.
27 |
28 | After completing the reference code, I wrote the kernel boilerplate code
29 | (setting up VGA, interrupts, etc.) and changed the reference C code to work with
30 | this. Then I began slowly porting everything to handwritten assembly.
31 |
32 | Unfortunately this turned out to be a lot more work than I expected, so
33 | currently a large fraction of the codebase is still in C. Slowly porting
34 | everything to assembly is an ongoing process. The code also isn't fully
35 | compatible with all systems yet. It seems to cause floating point exceptions on
36 | some setups.
37 |
38 | How to play
39 | -----------
40 |
41 | ### QEMU
42 |
43 | To run the game with QEMU, simply run `make test` This is a quick and easy way
44 | to play around with it.
45 |
46 | ### Virtual machine
47 |
48 | If you want to use virtualization software like VirtualBox, you can produce an
49 | .iso image with `make iso` and mount it. The virtual machine doesn't need a hard
50 | drive and requires no more than 4 MB of RAM.
51 |
52 | You can also burn this image to a CD or DVD, but that is rather wasteful. Use
53 | the USB stick method to try it on real hardware unless it really isn't an option
54 | for some reason.
55 |
56 | ### USB stick
57 |
58 | Booting from an USB stick is an excellent way to try it on real hardware, but
59 | does involve a little bit more work. Note that this process will remove all data
60 | currently on the USB stick. Also, make sure to get the drive name right or you
61 | might accidentally wipe your hard drive!
62 |
63 | 1. Format your USB stick to FAT32 with 1 MB free space preceding.
64 | 2. Mount it using `mount /dev/sdx1 /mnt` where `sdx` is the drive name.
65 | 3. Turn it into a GRUB rescue disk with `grub-install --no-floppy --root-directory=/mnt /dev/sdx`.
66 | 4. Run `make iso` and copy the contents of the *iso* directory to the USB stick.
67 | 5. Unmount with `umount -l /dev/sdx1`.
68 |
69 | Now reboot your PC and boot from USB.
70 |
71 | ### Debugging with GDB and QEMU
72 |
73 | ```
74 | qemu-system-i368 -gdb tcp::1234 -S -kernel mineassemble.elf
75 | i686-pc-elf-gdb mineassemble.elf
76 | (gdb) target remote :1234
77 | (gdb) continue
78 | ```
79 |
80 | Building a cross compiler toolchain
81 | -----------------------------------
82 |
83 | In order to build MineAssemble, you need to have a cross compiler toolchain
84 | consisting of the [GNU Binutils](http://www.gnu.org/software/binutils/) and
85 | [GNU C Compiler](http://gcc.gnu.org/) (GCC).
86 | The toolchain must be built for **i686-pc-elf** target.
87 | For legacy reasons, GNU GCC and Binutils are configured at compile time and
88 | you will need to compile them from source to create a cross compiler
89 | toolchain.
90 | You will also need the NASM Assembler.
91 |
92 | In addition, you might need [QEMU](http://www.qemu.org/) for testing
93 | MineAssemble in an emulator and the
94 | [GNU Debugger](http://www.gnu.org/software/gdb/) (GDB) for debugging.
95 |
96 | ### Installing prerequisites
97 |
98 | You will need to install a handful of utility libraries to build Binutils,
99 | GCC, QEMU and GDB.
100 |
101 | Use your operating system's equivalent for apt-get or compile from source.
102 |
103 | #### Install [libmpc](http://www.multiprecision.org/), [libgmp](http://gmplib.org/), [libmpfr](http://www.mpfr.org/) (required for binutils, gcc and gdb)
104 |
105 | ```
106 | sudo apt-get install libmpc-dev libgmp-dev libmpfr-dev
107 | ```
108 |
109 | #### Install [flex](http://flex.sourceforge.net/) and [bison](http://www.gnu.org/software/bison/) (required for GCC)
110 |
111 | ```
112 | sudo apt-get install flex bison
113 | ```
114 |
115 | #### Install [libsdl](http://www.libsdl.org) (optional front end for qemu)
116 |
117 | ```
118 | sudo apt-get install libsdl-dev
119 | ```
120 |
121 | #### Install [NASM](http://www.nasm.us/)
122 |
123 | NASM does not need to be configured at compile time, you can install it using your package manager.
124 |
125 | ```
126 | sudo apt-get install nasm
127 | ```
128 |
129 | #### Create directories for source, build files and binaries
130 |
131 | ```
132 | mkdir ~/src # Source code
133 | mkdir ~/i686-pc-elf-build # Temporary build files
134 | mkdir ~/i686-pc-elf # Toolchain install destination
135 | ```
136 |
137 | #### Get source code for Binutils, GCC, QEMU and GDB
138 |
139 | ```
140 | git clone git://sourceware.org/git/binutils.git ~/src/binutils
141 | git clone git://gcc.gnu.org/git/gcc.git ~/src/gcc
142 | git clone git://git.qemu-project.org/qemu.git ~/src/qemu
143 | git clone git://sourceware.org/git/gdb.git ~/src/gdb
144 | ```
145 |
146 | #### Check out latest release versions
147 |
148 | ```
149 | cd ~/src/binutils ; git checkout binutils-2_23_1
150 | cd ~/src/gcc ; git checkout gcc-4_8-branch
151 | cd ~/src/qemu ; git checkout v1.5.0
152 | cd ~/src/gdb ; git checkout gdb_7_6-branch
153 | ```
154 |
155 | #### Build binutils for target i686-pc-elf
156 |
157 | ```
158 | mkdir ~/i686-pc-elf-build/binutils ; cd ~/i686-pc-elf-build/binutils
159 | ~/src/binutils/configure --prefix=$HOME/i686-pc-elf --target=i686-pc-elf --disable-shared --disable-nls
160 | make -j 4 # parallel make for 4 cpus
161 | make install
162 | ```
163 |
164 | #### Build GCC (C compiler only) for target i686-pc-elf
165 |
166 | ```
167 | mkdir ~/i686-pc-elf-build/gcc ; cd ~/i686-pc-elf-build/gcc
168 | ~/src/gcc/configure --prefix=$HOME/i686-pc-elf --target=i686-pc-elf --enable-languages=c --disable-shared --disable-nls
169 | make -j 4 all-gcc
170 | make install-gcc
171 | ```
172 |
173 | #### Build qemu with i386-softmmu target (with SDL front end)
174 |
175 | ```
176 | mkdir ~/i686-pc-elf-build/qemu ; cd ~/i686-pc-elf-build/qemu
177 | ~/src/qemu/configure --prefix=$HOME/i686-pc-elf --target-list=i386-softmmu --enable-sdl
178 | make -j 4
179 | make install
180 | ```
181 |
182 | #### Build GDB for i686-pc-elf target
183 |
184 | ```
185 | mkdir ~/i686-pc-elf-build/gdb ; cd ~/i686-pc-elf-build/gdb
186 | ~/src/gdb/configure --prefix=$HOME/i686-pc-elf --target=i686-pc-elf
187 | make -j 4
188 | make install
189 | ```
190 |
191 | #### Add toolchain to $PATH
192 |
193 | ```
194 | export PATH=$HOME/i686-pc-elf/bin:$PATH
195 | ```
196 |
197 |
198 | Style conventions
199 | -----------------
200 |
201 | With something as low-level as assembly, you quickly risk writing unreadable
202 | code if you don't have proper style conventions. This project uses the following
203 | identifier name conventions:
204 |
205 | WORLD_SX - C-style define, usually allowing you to configure things
206 | worldSX - Non-local variable (local vars are referred to by stack offsets)
207 | init_world - Subroutine (uses underscores instead of camelCase)
208 | .main_loop - Local label, only used from within subroutine
209 |
210 | Variable names carry no type prefix, because it is almost always very clear what
211 | type a variable uses from its name or usage. Here are some examples:
212 |
213 | float - vectors, angles, distance
214 | int - time, block coordinates, block normal
215 | byte - palette color, block type
216 |
217 | Directives that apply to segments of a file or the whole file, such as
218 |
219 | [bits 32]
220 | section .text
221 |
222 | have no indentation. Subroutines and local labels have one level of indentation
223 | and code or data within have two levels of indentation. One level of indentation
224 | is equal to 4 spaces.
225 |
226 | Code is commonly separated in blocks with a comment above describing what is
227 | done in the block. If a line requires extra explanation, a comment is placed
228 | after the instruction.
229 |
230 | Floating point math expressions are systematically converted from the reference
231 | infix expression to RPN (Reverse Polish Notation) to FPU instructions. Any
232 | optimizations are applied afterwards if deemed necessary. This systematic
233 | approach makes converting single-line C expressions to dozens of assembly
234 | instructions bearable and relatively error-free.
235 |
236 | Explanation
237 | -----------
238 |
239 | The inner workings of this demo are really quite straight-forward. The code can
240 | be divided into four different components.
241 |
242 | ### World
243 |
244 | The world is stored as an *unsigned byte* array where every block has a value of
245 | either `BLOCK_AIR` or `BLOCK_DIRT`. The array is stored in the BSS section and
246 | is initialized by the `init_world` function. It loops over every x, y and z and
247 | creates a world where the lower half is dirt and the upper half is air.
248 |
249 | While playing, other code calls `set_block` or `get_block` to interact with
250 | the world. These simply calculate the correct index and write to or read from
251 | the array.
252 |
253 | ### Input and collision
254 |
255 | Keyboard input is collected by an IRQ1 interrupt handler. It writes the up/down
256 | state to a 128-byte array indexed by the [scan code](http://www.win.tue.nl/~aeb/linux/kbd/scancodes-1.html).
257 | It also sets the upper bit to `1` to mark that key as updated. It ignores a key
258 | down event if the key is already set to down to ignore automatic key repeats.
259 |
260 | Because the input handling needs to be independent of performance, an IRQ0
261 | interrupt handler increases a `time` variable by 1 every millisecond to keep
262 | track of time. This is used to compute a delta time to scale movement by.
263 |
264 | Before every frame is rendered, the `handle_input` function is called and
265 | collects the values from the `keys` array written to by the interrupt handler.
266 | If the upper bit of a cell is set to `1`, then it knows that the key state has
267 | changed and processes it accordingly. All keys except for the movement keys
268 | (AWSD) are handled here.
269 |
270 | After that, the update function is called to move the player according to the
271 | current velocity. This velocity is controlled partly by the `handle_input`
272 | function and partly by checking the down state of the AWSD keys in this
273 | function. The Y velocity is decreased to simulate gravity. Then the next player
274 | position is determined by adding the velocity multiplied by delta time.
275 |
276 | Before the new position is assigned, the code first runs the `handle_collision`
277 | function for the head, center of the body and feet. It calls the raytrace
278 | function from these positions with the velocity as direction to determine if
279 | a collision will occur if the player moves to the new position. If that is the
280 | case, the velocity is corrected to *mostly* prevent collision. (The algorithm
281 | is not perfect, but it works pretty well.)
282 |
283 | ### Rendering
284 |
285 | Normally games use rasterization to render and this is very fast. Unfortunately
286 | a graphics library like OpenGL is not available at this level. Instead, code
287 | needs to be written that writes directly to the graphics memory. At this point,
288 | I had two choices: write my own rasterizer or implement a raytracer. I decided
289 | to go with raytracing, because:
290 |
291 | - It's much more straight-forward by simply computing the color per pixel
292 | - It's cool, because it allows for easy effects like raytraced shadows
293 | - It's *fast enough*, because we have a uniform 3D grid
294 |
295 | The raytrace algorithm computes the distance to reach the sides of the block
296 | the ray starts in for every dimension. The shortest distance wins and the ray
297 | position is moved by that distance times the ray direction. This is repeated
298 | until the position is inside a `BLOCK_DIRT` or if it's out of the world. The
299 | final position is used to compute the side that was hit and the texture
300 | coordinates. The `ray_color` function is then called to let the block decide
301 | what color it's going to output. This function calls the `raytrace` function
302 | again to decide whether the pixel is shadowed or not by using the `sunDir`
303 | direction for the ray. It prevents infinite recursion by requesting an *info*
304 | raytrace instead of a color raytrace. This alternative returns a struct with
305 | hit info instead of a color.
306 |
307 | ### Resources
308 |
309 | One of the details you deal with when using a low-level VGA mode (mode `0x13`)
310 | is that you can't just specify 24-bit or 32-bit RGB color for every pixel.
311 | Instead, you have to decide on a 256 color palette and specify an index for
312 | every pixel. The easy solution here is to use 3-2-3 bit channels and use an RGB
313 | color as index into the palette. Unfortunately this doesn't work at all, because
314 | with only 4 options for the green color channel, there's no way to represent all
315 | the subtle different shades of a grass block.
316 |
317 | So I decided to generate a palette that could represent every color that the
318 | textures used exactly, well almost exactly. The palette does allow you to
319 | specify RGB colors, but with only 6 bits per channel instead of 8. That means
320 | that colors will be slightly off, but this is pretty much unnoticeable.
321 |
322 | I wrote a program in C# that took the grass, dirt and side textures along with
323 | the reserved colors black, white and sky and automatically generated a palette
324 | and a palette colored representation of the three textures. This ended up
325 | working perfectly!
326 |
327 | The splash screen works slightly differently. The reason that it's a bitmap
328 | instead of just using text mode is to make things a bit more streamlined. I
329 | first tried encoding it the same way as the textures, but this resulted in a
330 | 6400 line C file. Then I changed it to simply write a string of 1's and 0's for
331 | every line, which works much better. It even allows you to view the splash
332 | screen using a text editor! :-)
333 |
334 | The bitmap of the splash screen is copied directly to VGA memory where `'0'` is
335 | subtracted from every byte. The `keys` array is then checked for an ENTER key
336 | press before the game is loaded. A problem here is that the user has to press
337 | ENTER in the GRUB bootloader menu as well, which means it would skip the splash
338 | screen immediately. That problem is currently solved by waiting for an ENTER key
339 | press twice. Somehow this even works when booting with Ctrl-X or another
340 | combination.
341 |
342 | License
343 | -------
344 |
345 | This project is licensed under the MIT license.
346 |
347 | Some derived work with compatible licensing is also included:
348 |
349 | - **init.asm**, **interrupts.asm** - Derived from [code by Maarten de Vries and Maurice Bos](https://github.com/m-ou-se/bootlib) (licensed under the MIT license)
350 | - **vga.asm** - Derived from [code by Christoffer Bubach](http://bos.asmhackers.net/docs/vga_without_bios/snippet_5/vga.php) (public domain)
351 |
352 | Derived work here means that the code was adapted to fit the requirements of this project.
353 |
--------------------------------------------------------------------------------
/reference/src/mineassemble.c:
--------------------------------------------------------------------------------
1 | // putenv declaration
2 | #define _XOPEN_SOURCE
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 |
10 | // SDL library
11 | #include
12 | #include
13 |
14 | // Configuration
15 | #define worldSX 16
16 | #define worldSY 16
17 | #define worldSZ 16
18 |
19 | #define skyColor RGB(158, 207, 255)
20 |
21 | #define hFov 90
22 |
23 | // Macros
24 | #define IN_WORLD(x, y, z) \
25 | (x >= 0 && y >= 0 && z >= 0 && x < worldSX && y < worldSY && z < worldSZ)
26 |
27 | #define RGB(r, g, b) ((0xff << 24) | ((r) << 16) | ((g) << 8) | (b))
28 |
29 | #define RED(col) (((col) & 0xff0000) >> 16)
30 | #define GREEN(col) (((col) & 0x00ff00) >> 8)
31 | #define BLUE(col) ((col) & 0x0000ff)
32 |
33 | #define INV_COLOR(col) RGB(255 - RED(col), 255 - GREEN(col), 255 - BLUE(col))
34 |
35 | #define UNLIT_COL(col) (UNLIT_RED(col) | UNLIT_GREEN(col) | UNLIT_BLUE(col))
36 | #define UNLIT_RED(col) ((RED(col) * 2 / 3) << 16)
37 | #define UNLIT_GREEN(col) ((GREEN(col) * 2 / 3) << 8)
38 | #define UNLIT_BLUE(col) (BLUE(col) * 2 / 3)
39 |
40 | #define CURTIME() (clock() / (float) CLOCKS_PER_SEC)
41 |
42 | // Resources
43 | extern unsigned int texGrass[];
44 | extern unsigned int texDirt[];
45 | extern unsigned int texGrassSide[];
46 |
47 | // Types
48 | typedef struct vec3_t {
49 | float x, y, z;
50 | } vec3;
51 |
52 | typedef struct hit_t {
53 | bool hit;
54 | int x, y, z;
55 | int nx, ny, nz;
56 | float dist;
57 | } hit;
58 |
59 | enum block_t {
60 | BLOCK_AIR,
61 | BLOCK_DIRT
62 | };
63 |
64 | enum face_t {
65 | FACE_LEFT,
66 | FACE_RIGHT,
67 | FACE_BOTTOM,
68 | FACE_TOP,
69 | FACE_BACK,
70 | FACE_FRONT
71 | };
72 |
73 | // Functions
74 | void initVideo();
75 | void mainLoop();
76 |
77 | void initWorld();
78 | int getLight(int x, int z);
79 | Uint8 getBlock(int x, int y, int z);
80 | void setBlock(int x, int y, int z, Uint8 type);
81 |
82 | void handleInput(SDLKey key, bool down);
83 | void update(float dt);
84 | void handleCollision(vec3 pos, vec3* velocity);
85 | void drawFrame(Uint32* pixels);
86 |
87 | void setPos(float x, float y, float z);
88 | void setView(float yaw, float pitch);
89 | Uint32 raytrace(vec3 pos, vec3 dir, hit* info);
90 | Uint32 rayColor(int x, int y, int z, int tex, int face);
91 | void faceNormal(int face, int* x, int* y, int* z);
92 | int texIndex(vec3 pos, int face);
93 | vec3 rayDir(int x, int y);
94 |
95 | // Globals
96 | SDL_Surface* screen;
97 |
98 | Uint8 world[worldSX * worldSY * worldSZ] = {0};
99 | Uint8 lighting[worldSX * worldSY] = {0};
100 |
101 | vec3 playerPos = {8, 10, 8};
102 |
103 | // The sine and cosine are the same for all pixels
104 | float pitch = 0.0f;
105 | float pitchC = 1.0f;
106 | float pitchS = 0.0f;
107 |
108 | float yaw = 0.0f;
109 | float yawC = 1.0f;
110 | float yawS = 0.0f;
111 |
112 | // Input
113 | float lastUpdate = 0.0f;
114 |
115 | float dPitch = 0.0f;
116 | float dYaw = 0.0f;
117 |
118 | bool keyA = false;
119 | bool keyW = false;
120 | bool keyS = false;
121 | bool keyD = false;
122 |
123 | vec3 velocity = {0, 0, 0};
124 |
125 | int main() {
126 | initVideo();
127 |
128 | initWorld();
129 |
130 | mainLoop();
131 |
132 | return EXIT_SUCCESS;
133 | }
134 |
135 | void initVideo() {
136 | putenv("SDL_VIDEO_CENTERED=1");
137 |
138 | SDL_Init(SDL_INIT_VIDEO);
139 | atexit(SDL_Quit);
140 |
141 | screen = SDL_SetVideoMode(320, 200, 32, SDL_SWSURFACE);
142 | }
143 |
144 | void mainLoop() {
145 | SDL_Event event;
146 |
147 | int frames = 0;
148 | int lsec = 0;
149 | char titleBuf[64];
150 |
151 | while (true) {
152 | // Handle input and other events
153 | while (SDL_PollEvent(&event)) {
154 | switch (event.type) {
155 | case SDL_QUIT:
156 | return;
157 |
158 | case SDL_KEYDOWN:
159 | handleInput(event.key.keysym.sym, true);
160 | break;
161 |
162 | case SDL_KEYUP:
163 | handleInput(event.key.keysym.sym, false);
164 | break;
165 | }
166 | }
167 |
168 | // Update
169 | update(CURTIME() - lastUpdate);
170 | lastUpdate = CURTIME();
171 |
172 | // Draw frame
173 | SDL_LockSurface(screen);
174 |
175 | drawFrame((Uint32*) screen->pixels);
176 |
177 | SDL_UnlockSurface(screen);
178 |
179 | SDL_UpdateRect(screen, 0, 0, 320, 200);
180 |
181 | frames++;
182 | if (lsec != time(0)) {
183 | sprintf(titleBuf, "MineAssemble (FPS: %d)", frames);
184 | SDL_WM_SetCaption(titleBuf, 0);
185 |
186 | frames = 0;
187 | lsec = time(0);
188 | }
189 | }
190 | }
191 |
192 | //
193 | // Code below this line is not part of boilerplate
194 | //
195 |
196 | void initWorld() {
197 | // Make flat grass landscape
198 | for (int x = 0; x < worldSX; x++) {
199 | for (int y = 0; y < worldSY; y++) {
200 | for (int z = 0; z < worldSZ; z++) {
201 | setBlock(x, y, z, y >= worldSY / 2 ? BLOCK_AIR : BLOCK_DIRT);
202 | }
203 | }
204 | }
205 |
206 | // Add arch
207 | setBlock(11, 8, 4, BLOCK_DIRT);
208 | setBlock(11, 9, 4, BLOCK_DIRT);
209 | setBlock(11, 10, 4, BLOCK_DIRT);
210 | setBlock(10, 10, 4, BLOCK_DIRT);
211 | setBlock(9, 10, 4, BLOCK_DIRT);
212 | setBlock(9, 9, 4, BLOCK_DIRT);
213 | setBlock(9, 8, 4, BLOCK_DIRT);
214 | setBlock(9, 12, 4, BLOCK_DIRT);
215 |
216 | // Initial player position
217 | setPos(8.0f, 9.8f, 8.0f);
218 | setView(0.0f, -0.35f);
219 | }
220 |
221 | int getLight(int x, int z) {
222 | return lighting[x * worldSZ + z];
223 | }
224 |
225 | Uint8 getBlock(int x, int y, int z) {
226 | return world[x * worldSY * worldSZ + y * worldSZ + z];
227 | }
228 |
229 | void setBlock(int x, int y, int z, Uint8 type) {
230 | world[x * worldSY * worldSZ + y * worldSZ + z] = type;
231 |
232 | // Update lightmap
233 | int lightIdx = x * worldSZ + z;
234 |
235 | if (type != BLOCK_AIR && lighting[lightIdx] < y) {
236 | lighting[lightIdx] = y;
237 | } else if (type == BLOCK_AIR && lighting[lightIdx] <= y) {
238 | y = worldSY - 1;
239 |
240 | while (y > 0 && getBlock(x, y, z) == BLOCK_AIR) {
241 | y--;
242 | }
243 |
244 | lighting[lightIdx] = y;
245 | }
246 | }
247 |
248 | void handleInput(SDLKey key, bool down) {
249 | hit info;
250 |
251 | switch (key) {
252 | // View
253 | case SDLK_UP: dPitch += down ? 1.0f : -1.0f; break;
254 | case SDLK_DOWN: dPitch += down ? -1.0f : 1.0f; break;
255 |
256 | case SDLK_LEFT: dYaw += down ? 1.0f : -1.0f; break;
257 | case SDLK_RIGHT: dYaw += down ? -1.0f : 1.0f; break;
258 |
259 | // Movement
260 | case SDLK_a: keyA = down; break;
261 | case SDLK_w: keyW = down; break;
262 | case SDLK_s: keyS = down; break;
263 | case SDLK_d: keyD = down; break;
264 |
265 | case SDLK_SPACE:
266 | if (down) {
267 | velocity.y += 8.0f;
268 | }
269 | break;
270 |
271 | // Check if a block was hit and place a new block next to it
272 | case SDLK_q:
273 | if (!down) {
274 | raytrace(playerPos, rayDir(160, 100), &info);
275 |
276 | if (info.hit) {
277 | int bx = info.x + info.nx;
278 | int by = info.y + info.ny;
279 | int bz = info.z + info.nz;
280 |
281 | if (IN_WORLD(bx, by, bz)) {
282 | setBlock(bx, by, bz, BLOCK_DIRT);
283 | }
284 | }
285 | }
286 | break;
287 |
288 | // Check if a block was hit and remove it
289 | case SDLK_e:
290 | if (!down) {
291 | raytrace(playerPos, rayDir(160, 100), &info);
292 |
293 | if (info.hit) {
294 | setBlock(info.x, info.y, info.z, BLOCK_AIR);
295 | }
296 | }
297 | break;
298 |
299 | default: break;
300 | }
301 | }
302 |
303 | void update(float dt) {
304 | // Update view
305 | pitch += 1.2f * dPitch * dt;
306 | yaw += 1.2f * dYaw * dt;
307 |
308 | setView(pitch, yaw);
309 |
310 | // Set X/Z velocity depending on input
311 | velocity.x = velocity.z = 0.0f;
312 |
313 | if (keyA) {
314 | velocity.x += 2.0f * cos(M_PI - yaw);
315 | velocity.z += 2.0f * sin(M_PI - yaw);
316 | }
317 | if (keyW) {
318 | velocity.x += 2.0f * cos(-M_PI / 2 - yaw);
319 | velocity.z += 2.0f * sin(-M_PI / 2 - yaw);
320 | }
321 | if (keyS) {
322 | velocity.x += 2.0f * cos(M_PI / 2 - yaw);
323 | velocity.z += 2.0f * sin(M_PI / 2 - yaw);
324 | }
325 | if (keyD) {
326 | velocity.x += 2.0f * cos(-yaw);
327 | velocity.z += 2.0f * sin(-yaw);
328 | }
329 |
330 | // Simulate gravity
331 | velocity.y -= 20.0f * dt;
332 |
333 | // Handle block collision (head, lower body and feet)
334 | vec3 headPos = playerPos;
335 | vec3 lowerPos = playerPos; lowerPos.y -= 1.0f;
336 | vec3 footPos = playerPos; footPos.y -= 1.8f;
337 |
338 | handleCollision(headPos, &velocity);
339 | handleCollision(lowerPos, &velocity);
340 | handleCollision(footPos, &velocity);
341 |
342 | // Apply motion
343 | playerPos.x += velocity.x * dt;
344 | playerPos.y += velocity.y * dt;
345 | playerPos.z += velocity.z * dt;
346 | }
347 |
348 | void handleCollision(vec3 pos, vec3* velocity) {
349 | // Check if new position is not inside block
350 | hit info;
351 | raytrace(pos, *velocity, &info);
352 |
353 | // If it is, create sliding motion by negating velocity based on hit normal
354 | if (info.hit && info.dist < 0.1f) {
355 | if (info.nx != 0) velocity->x = 0.0f;
356 | if (info.ny != 0) velocity->y = 0.0f;
357 | if (info.nz != 0) velocity->z = 0.0f;
358 | }
359 | }
360 |
361 | void drawFrame(Uint32* pixels) {
362 | int x = 0;
363 | int y = 0;
364 |
365 | // Draw world
366 | Uint32* pixel = pixels;
367 | for (int i = 0; i < 320 * 200; i++) {
368 | *pixel = raytrace(playerPos, rayDir(x, y), NULL);
369 |
370 | pixel++;
371 | x++;
372 | if (x == 320) {
373 | x = 0;
374 | y++;
375 | }
376 | }
377 |
378 | // Inverse colors in the center of screen to form an aim reticle
379 | for (x = 155; x < 165; x++) {
380 | pixels[99 * 320 + x] = INV_COLOR(pixels[99 * 320 + x]);
381 | pixels[100 * 320 + x] = INV_COLOR(pixels[100 * 320 + x]);
382 | }
383 | for (y = 95; y < 105; y++) {
384 | if (y == 99 || y == 100) continue;
385 |
386 | pixels[y * 320 + 159] = INV_COLOR(pixels[y * 320 + 159]);
387 | pixels[y * 320 + 160] = INV_COLOR(pixels[y * 320 + 160]);
388 | }
389 | }
390 |
391 | void setPos(float x, float y, float z) {
392 | playerPos.x = x;
393 | playerPos.y = y;
394 | playerPos.z = z;
395 | }
396 |
397 | void setView(float p, float y) {
398 | pitch = p;
399 |
400 | if (pitch > 1.57f) pitch = 1.57f;
401 | else if (pitch < -1.57f) pitch = -1.57f;
402 |
403 | pitchS = sinf(pitch);
404 | pitchC = cosf(pitch);
405 |
406 | yaw = y;
407 | yawS = sinf(yaw);
408 | yawC = cosf(yaw);
409 | }
410 |
411 | // Returns final color
412 | Uint32 raytrace(vec3 pos, vec3 dir, hit* info) {
413 | // Finish early if there's no direction
414 | if (dir.x == 0.0f && dir.y == 0.0f && dir.z == 0.0f) {
415 | goto nohit;
416 | }
417 |
418 | vec3 start = pos;
419 |
420 | int x = (int) pos.x;
421 | int y = (int) pos.y;
422 | int z = (int) pos.z;
423 |
424 | int x_dir = dir.x >= 0.0f ? 1 : -1;
425 | int y_dir = dir.y >= 0.0f ? 1 : -1;
426 | int z_dir = dir.z >= 0.0f ? 1 : -1;
427 |
428 | float dx_off = x_dir > 0 ? 1.0f : 0.0f;
429 | float dy_off = y_dir > 0 ? 1.0f : 0.0f;
430 | float dz_off = z_dir > 0 ? 1.0f : 0.0f;
431 |
432 | int x_face = x_dir > 0 ? FACE_LEFT : FACE_RIGHT;
433 | int y_face = y_dir > 0 ? FACE_BOTTOM : FACE_TOP;
434 | int z_face = z_dir > 0 ? FACE_BACK : FACE_FRONT;
435 |
436 | int face = FACE_TOP;
437 |
438 | // Assumption is made that the camera is never outside the world
439 | while (IN_WORLD(x, y, z)) {
440 | // Determine if block is solid
441 | if (getBlock(x, y, z) != BLOCK_AIR) {
442 | float dx = start.x - pos.x;
443 | float dy = start.y - pos.y;
444 | float dz = start.z - pos.z;
445 | float dist = sqrt(dx*dx + dy*dy + dz*dz);
446 |
447 | pos.x -= x;
448 | pos.y -= y;
449 | pos.z -= z;
450 |
451 | // If hit info is requested, no color computation is done
452 | if (info != NULL) {
453 | int nx, ny, nz;
454 | faceNormal(face, &nx, &ny, &nz);
455 |
456 | info->hit = true;
457 | info->x = x;
458 | info->y = y;
459 | info->z = z;
460 | info->nx = nx;
461 | info->ny = ny;
462 | info->nz = nz;
463 | info->dist = dist;
464 |
465 | return 0;
466 | }
467 |
468 | int tex = texIndex(pos, face);
469 |
470 | return rayColor(x, y, z, tex, face);
471 | }
472 |
473 | // Remaining distance inside this block given ray direction
474 | float dx = x - pos.x + dx_off;
475 | float dy = y - pos.y + dy_off;
476 | float dz = z - pos.z + dz_off;
477 |
478 | // Calculate distance for each dimension
479 | float t1 = dx / dir.x;
480 | float t2 = dy / dir.y;
481 | float t3 = dz / dir.z;
482 |
483 | // Find closest hit
484 | if (t1 <= t2 && t1 <= t3) {
485 | pos.x += dx;
486 | pos.y += t1 * dir.y;
487 | pos.z += t1 * dir.z;
488 | x += x_dir;
489 | face = x_face;
490 | }
491 | if (t2 <= t1 && t2 <= t3) {
492 | pos.x += t2 * dir.x;
493 | pos.y += dy;
494 | pos.z += t2 * dir.z;
495 | y += y_dir;
496 | face = y_face;
497 | }
498 | if (t3 <= t1 && t3 <= t2) {
499 | pos.x += t3 * dir.x;
500 | pos.y += t3 * dir.y;
501 | pos.z += dz;
502 | z += z_dir;
503 | face = z_face;
504 | }
505 | }
506 |
507 | nohit:
508 | if (info != NULL) {
509 | info->hit = false;
510 | }
511 |
512 | return skyColor;
513 | }
514 |
515 | Uint32 rayColor(int x, int y, int z, int tex, int face) {
516 | // Get normal
517 | int nx, ny, nz;
518 | faceNormal(face, &nx, &ny, &nz);
519 |
520 | // Block is dirt if there's another block directly on top of it
521 | bool isDirt = y < worldSY - 1 && getBlock(x, y + 1, z) != BLOCK_AIR;
522 |
523 | // Texture lookup
524 | Uint32 texColor;
525 |
526 | if (face == FACE_BOTTOM || isDirt) {
527 | texColor = texDirt[tex];
528 | } else if (face == FACE_TOP) {
529 | texColor = texGrass[tex];
530 | } else {
531 | texColor = texGrassSide[tex];
532 | }
533 |
534 | // Side is dark if there are higher blocks in the column faced by it
535 | // Left and back sides are always dark to simulate a sun angle
536 | if (IN_WORLD(x + nx, y, z + nz) && getLight(x + nx, z + nz) > y) {
537 | return UNLIT_COL(texColor);
538 | } else if (face == FACE_BOTTOM || face == FACE_LEFT || face == FACE_BACK) {
539 | return UNLIT_COL(texColor);
540 | } else {
541 | return texColor;
542 | }
543 | }
544 |
545 | void faceNormal(int face, int* x, int* y, int* z) {
546 | *x = 0;
547 | *y = 0;
548 | *z = 0;
549 |
550 | switch (face) {
551 | case FACE_LEFT: *x = -1; break;
552 | case FACE_RIGHT: *x = 1; break;
553 | case FACE_BOTTOM: *y = -1; break;
554 | case FACE_TOP: *y = 1; break;
555 | case FACE_BACK: *z = -1; break;
556 | case FACE_FRONT: *z = 1; break;
557 | }
558 | }
559 |
560 | int texIndex(vec3 pos, int face) {
561 | float u = 0, v = 0;
562 |
563 | switch (face) {
564 | case FACE_LEFT: u = pos.z; v = pos.y; break;
565 | case FACE_RIGHT: u = pos.z; v = pos.y; break;
566 | case FACE_BOTTOM: u = pos.x; v = pos.z; break;
567 | case FACE_TOP: u = pos.x; v = pos.z; break;
568 | case FACE_BACK: u = pos.x; v = pos.y; break;
569 | case FACE_FRONT: u = pos.x; v = pos.y; break;
570 | }
571 |
572 | v = 1.0f - v;
573 |
574 | return ((int) (u * 15.0f)) * 16 + (int) (v * 15.0f);
575 | }
576 |
577 | vec3 rayDir(int x, int y) {
578 | static float vFov = -1, fov;
579 |
580 | // Calculate vertical fov and fov constant from specified horizontal fov
581 | if (vFov == -1) {
582 | vFov = 2.0f * atan(tan(hFov / 720.0f * M_PI) * 320.0f / 200.0f);
583 | fov = tan(0.5f * vFov);
584 | }
585 |
586 | // This is simply a precomputed version of the actual linear
587 | // transformation, which is the inverse of the common view and
588 | // projection transformation used in rasterization.
589 | float clipX = x / 160.0f - 1.0f;
590 | float clipY = 1.0f - y / 100.0f;
591 |
592 | vec3 d = {
593 | 1.6f * fov * yawC * clipX + fov * yawS * pitchS * clipY - pitchC * yawS,
594 | fov * pitchC * clipY + pitchS,
595 | -1.6f * fov * yawS * clipX + fov * yawC * pitchS * clipY - pitchC * yawC
596 | };
597 |
598 | // Normalize
599 | float length = sqrtf(d.x * d.x + d.y * d.y + d.z * d.z);
600 | d.x /= length;
601 | d.y /= length;
602 | d.z /= length;
603 |
604 | return d;
605 | }
--------------------------------------------------------------------------------
/src/splash.asm:
--------------------------------------------------------------------------------
1 | ;
2 | ; This file contains the splash screen code and bitmap
3 | ;
4 |
5 | [bits 32]
6 |
7 | %include "constants.asm"
8 |
9 | global show_splash
10 |
11 | extern keys
12 |
13 | section .text
14 |
15 | ; void show_splash()
16 | ; Show splash screen and wait for user to press ENTER
17 | show_splash:
18 | push ecx
19 | push esi
20 | push edi
21 |
22 | mov ecx, 64000 ; 320 x 200 pixels
23 | mov esi, splash_bitmap ; Source address
24 | mov edi, 0xa0000 ; Destination address (VGA buffer)
25 |
26 | write_pixel:
27 | sub byte [esi], 0x30 ; Subtract '0' from value
28 | movsb
29 | dec ecx
30 | cmp ecx, 0
31 | jne write_pixel
32 |
33 | ; Ignore first ENTER press (leftover from GRUB menu)
34 | ignore_grub_enter:
35 | cmp byte [keys + KEY_ENTER], 0
36 | je ignore_grub_enter
37 | mov byte [keys + KEY_ENTER], 0
38 |
39 | ; Wait for user to press ENTER to continue
40 | wait_enter2:
41 | cmp byte [keys + KEY_ENTER], 0
42 | je wait_enter2
43 |
44 | pop edi
45 | pop esi
46 | pop ecx
47 |
48 | ret
49 |
50 | section .data
51 |
52 | ; This is the bitmap data of the splash screen (320x200 pixels, palette colored)
53 | ; Each pixel value is subtracted by '0' (0x30) to get the palette index
54 |
55 | splash_bitmap db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
56 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
57 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
58 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
59 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
60 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
61 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
62 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
63 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
64 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
65 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
66 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
67 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
68 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
69 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
70 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
71 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
72 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
73 | db "00000000000000000000000000010000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000100000100000000000000000100000000000000011100000000000000000000000000100000000000000000000000000000111000000000000100000000000000000000000000100000000000000000000000000000000000000000000000000"
74 | db "00000000000010001000100000010000000000000000000000000000000100000000000010000010000000000000000001000000000000000000000000000000100000100000000000001000100000000000000100000000000001000000100000100000000000000000000000000000000100100000000000100000000000000000000001000100000000000100000000000000000000000000000000000000"
75 | db "00000000000010001000100000010000000000000000000000000000000100000000000011000110000000000000000010100000000000000000000000000000100000100000000000001000100000000000000100000000000001000000110001100000000000000000000000000000000100100000000000100000000000000000000001000100000000000100000000000000000000000000000000000000"
76 | db "00000000000001010101001110010011100111001111011100011100001111001110000011000110010111100011100010100011110111100111001111011100111100100111000000011110111100011100001111101110111111110000110001100101111000111000111011100111001111111000001110100111001111000111000011110111100011101111000000000000000000000000000000000000"
77 | db "00000000000001010101010001010100001000101000100010100010000100010001000010101010010100010100010100010010000100001000101000100010100010101000100000001000100010100010000100101000100001000000101010100101000101000101000010000000100100100000010000101000101000101000100001000100010000010100000000000000000000000000000000000000"
78 | db "00000000000001010101011111010100001000101000100010111110000100010001000010101010010100010111110111110001110011101111101000100010100010101111100000001000100010111110000100101000011101000000101010100101000101111101000010000111100100100000010000101000101000101111100001000100010011110100000000000000000000000000000000000000"
79 | db "00000000000000100010010000010100001000101000100010100000000100010001000010010010010100010100000100010000010000101000001000100010100010101000000000001000100010100000000100101000000101000000100100100101000101000001000010001000100100100000010000101000101000101000000001000100010100010100000000000000000000000000000000000000"
80 | db "00000000000000100010001111010011100111001000100010011110000111001110000010000010010100010011111000001011110111100111101000100010111100100111101000001110100010011110000100101000111101110000100000100101000100111100111010001111100100111000001110100111001000100111100001110100010111110111000000000000000000000000000000000000"
81 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
82 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
83 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
84 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
85 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
86 | db "00000000000000000100000000000000000000000000000000000000000000000000000000100000000000000000000000100000000000000000010000000010000010000000000000000000000000000000000010000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000"
87 | db "00000000000000000100000000000000000000000010010000000000000000000000000000000000000000000000000000100000000000000000010000000010000000000000000000000100000000000000000010000000000000010000011110000000000000000000000000100000100000010000000000000000000000000000000001000000000000000000000000000000000000000000000000000000"
88 | db "00000000000000000100000000000000000000000010010000000000000000000000000000000000000000000000000000100000000000000000010000000010000000000000000000000100000000000000000010000000000000010000010001000000000000000000000000100000100000010000000000000000000000000000000001000000000000000000000000000000000000000000000000000000"
89 | db "00000000000000111100111000111001111011110010111100001110011100011110100010101110011100000011100000111100011100111011110000011110111010100010011100001111001110000011110010011100100010010000010001001110011100100010011110111101111000111100111000001000100111001000100001111001000100000000000000000000000000000000000000000000"
90 | db "00000000000001000101000101000101000010001000010000001000100010100010100010101000100010000000010000100010000010100100010000100010100010100010100010000100010001000010001010000010100010010000011110001000100010100010100010100010100000010001000100001000101000101000100001000101000100000000000000000000000000000000000000000000"
91 | db "00000000000001000101000101111100111010001000010000001000111110100010100010101000111110000011110000100010011110100100010000100010100010010100111110000100010001000010001010011110010100010000010001001000100010100010100010100010100000010001000100000101001000101000100001000100101000000000000000000000000000000000000000000000"
92 | db "00000000000001000101000101000000001010001000010000001000100000100010100010101000100000000100010000100010100010100100010000100010100010010100100000000100010001000010001010100010010100000000010001001000100010100010100010100010100000010001000100000101001000101000100001000100101000000000000000000000000000000000000000000000"
93 | db "00000000000000111100111000111101111010001000011100001000011110011110011110101000011110000111110000100010111110100011110000011110100010001000011110000111001110000011110010111110001000010000011110001000011100011110011110100010111000011100111000000010000111000111100001111000010000000000000000000000000000000000000000000000"
94 | db "00000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000001000000000000000000000000000000000000010000000000000000000000000000010000000000000000000000000010000000000000000000000000000000000000000000000"
95 | db "00000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000110000000000000000000000000000000000011100000000000000000000000000001100000000000000000000000001100000000000000000000000000000000000000000000000"
96 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
97 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
98 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
99 | db "00000000000000000000100000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
100 | db "00000000000000010000100000000000000000000000000000100000000000000011110000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
101 | db "00000000000000101000100000000000000000000000000000100000000000000110011000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
102 | db "00000000000000101000100111001000100111001111000111100111001110000100001001000100111001110100010011100011100111001111001110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
103 | db "00000000000001000100101000100101000000101000101000101000101000000100001001000101000101000100010100010100010100010001010001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
104 | db "00000000000001111100101111100010000111101000101000101111101000000100001000101001111101000010100100010100010100010001011111000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
105 | db "00000000000001000100101000000101001000101000101000101000001000000110011000101001000001000010100100010100010100010001010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
106 | db "00000000000010000010100111101000101111101000100111100111101000000011110000010000111101000001000011100011100100001111001111010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
107 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
108 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
109 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
110 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
111 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
112 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
113 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
114 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
115 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
116 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
117 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
118 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
119 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
120 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
121 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
122 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
123 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
124 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
125 | db "00000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
126 | db "00000000000000011100000000000000010000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
127 | db "00000000000000100010000000000000010000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
128 | db "00000000000001000000001110011110111101110011100101111010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
129 | db "00000000000001000000010001010001010001000100010101000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
130 | db "00000000000001000000010001010001010001000100010100111000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
131 | db "00000000000000100010010001010001010001000100010100001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
132 | db "00000000000000011100001110010001011101000011100101111010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
133 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
134 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
135 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
136 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
137 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
138 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
139 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
140 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
141 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
142 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
143 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
144 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
145 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
146 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
147 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
148 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
149 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
150 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
151 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
152 | db "00000000000010001000100100000111000111110000000000000100000100000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
153 | db "00000000000010001000101010001000100100011000000000000110001100000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
154 | db "00000000000001010101001010001000000100001000000000000110001100011100100010011100111101110001110011110111100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
155 | db "00000000000001010101010001000111000100001000000000000101010100100010100010100010100010001010001010001010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
156 | db "00000000000001010101011111000000100100001000001110000101010100100010010100111110100010001011111010001010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
157 | db "00000000000000100010010001001000100100011000000000000100100100100010010100100000100010001010000010001010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
158 | db "00000000000000100010100000100111000111110000000000000100000100011100001000011110100010001001111010001011100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
159 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
160 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
161 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
162 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
163 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
164 | db "00000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000001000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
165 | db "00000000000000010000000000000000000000000000010000000000000000000000000000001000000000000000001000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
166 | db "00000000000000101000000000000000000000000000010000000000000000000000000000001000000000000000001000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
167 | db "00000000000000101000111011100111001001001000010010111001000101111000000000001000000111000111001001000001110011100111001000101111000111100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
168 | db "00000000000001000100100010001000101010101000010101000101000101000000000000001000001000101000101010000000001010001000101000101000101000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
169 | db "00000000000001111100100010001000101010101000011001111100101000111000011100001000001000101000101100000001111010001000101000101000101000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
170 | db "00000000000001000100100010001000100100010000010101000000101000001000000000001000001000101000101010000010001010001000101000101000101000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
171 | db "00000000000010000010100010000111000100010000010010111100010001111000000000001111100111000111001001000011111010000111000111101000100111100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
172 | db "00000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
173 | db "00000000000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
174 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
175 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
176 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
177 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000011110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
178 | db "00000000000000111000000000000000000000000000000000000100000000000000000000000001010010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
179 | db "00000000000001000100000000000000000000000000000000000100000000000000000000000001010010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
180 | db "00000000000001000000111100011100011100111000000000000100100010111101110011110010111010010001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
181 | db "00000000000000111000100010000010100001000100000000000100100010100010001010001010010010010001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
182 | db "00000000000000000100100010011110100001111100001110000100100010100010001010001010010010001010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
183 | db "00000000000001000100100010100010100001000000000000000100100010100010001010001010010010001010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
184 | db "00000000000000111000111100111110011100111100000000000100011110100010001011110100010010000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
185 | db "00000000000000000000100000000000000000000000000000000100000000000000000010000100000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
186 | db "00000000000000000000100000000000000000000000000000011000000000000000000010000000000000011000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
187 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
188 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
189 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
190 | db "00000000000000000000000000000000000000000000000010000000000000000000000000000000000000100000000100000000000000000000000000000000000100000100000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
191 | db "00000000000000111100001011111000000000000111100010000000000000000000000000000000000000100000000100000000000010000000000000000000000100000100000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
192 | db "00000000000001100110001010000000000000000100010010000000000000000000000000000000000000100000000100000000000010000000000000000000000100000100000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
193 | db "00000000000001000010010010000000000000000100010010011100011100111000000111001111000111100000111100111001111111101110011100100010000111100100111000111010010111100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
194 | db "00000000000001000010010011111000000000000111100010000010100001000100000000101000101000100001000101000101000010001000100010100010000100010101000101000010100100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
195 | db "00000000000001000010010010000000001110000100000010011110100001111100000111101000101000100001000101111100111010001000100010010100000100010101000101000011000011100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
196 | db "00000000000001100100010010000000000000000100000010100010100001000000001000101000101000100001000101000000001010001000100010010100000100010101000101000010100000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
197 | db "00000000000000111000100011111000000000000100000010111110011100111100001111101000100111100000111100111101111011101000011100001000000111100100111000111010010111100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
198 | db "00000000000000000100100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
199 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
200 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
201 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
202 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
203 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
204 | db "00000000000001111100011100000111000000000000011110000000000000000000010000000000000000000000001000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
205 | db "00000000000001000000100010001000100000000000010001000000000000000000010000000000000000000000001000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
206 | db "00000000000001000000100000010000000000000000010001000111001111001110111100001001001001110011101001111000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
207 | db "00000000000001111100011100010000000000000000011110001000101000010001010000001010101010001010001010001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
208 | db "00000000000001000000000010010000000000111000010010001111100111011111010000001010101010001010001010001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
209 | db "00000000000001000000100010001000100000000000010001001000000001010000010000000100010010001010001010001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
210 | db "00000000000001111100011100000111000000000000010000100111101111001111011100000100010001110010001001111000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
211 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
212 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
213 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
214 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
215 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
216 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
217 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
218 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
219 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
220 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
221 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
222 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
223 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
224 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
225 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
226 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
227 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
228 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
229 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
230 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001111000000000000000000000000001111100100001011111011111001111000000100000000000000000100000000000001000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
231 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000100000000000000000000000001000000110001000100010000001000100000100000000000000000100000000000001000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
232 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000100111001110011110111100001000000101001000100010000001000100001111001110000011111111001110011111110000111100100111001000101011110001111000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
233 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001111000100010001010000100000001111100101001000100011111001111000000100010001000010000100000001010001000000100010100000101000101010001010001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
234 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000100011111001110011100001000000100101000100010000001001000000100010001000001110100001111010001000000100010100111100101001010001010001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
235 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000100010000000010000100001000000100011000100010000001000100000100010001000000010100010001010001000000100010101000100101001010001010001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
236 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000100001111011110111100001111100100001000100011111001000010000111001110000011110111011111010001110000111100101111100010001010001001111000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
237 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000010000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
238 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000001100000000000001110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
239 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
240 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
241 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
242 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
243 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
244 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
245 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
246 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
247 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
248 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
249 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
250 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
251 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
252 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
253 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
254 | db "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
--------------------------------------------------------------------------------