123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484 |
- #import "win32.odin"
- #import "fmt.odin"
- #import "os.odin"
- CANVAS_WIDTH :: 128
- CANVAS_HEIGHT :: 128
- CANVAS_SCALE :: 3
- FRAME_TIME :: 1.0/30.0
- WINDOW_TITLE : string : "Punity\x00"
- _ := compile_assert(CANVAS_WIDTH % 16 == 0)
- WINDOW_WIDTH :: CANVAS_WIDTH * CANVAS_SCALE
- WINDOW_HEIGHT :: CANVAS_HEIGHT * CANVAS_SCALE
- STACK_CAPACITY :: 1<<20
- STORAGE_CAPACITY :: 1<<20
- DRAW_LIST_RESERVE :: 128
- MAX_KEYS :: 256
- Core :: struct {
- stack: ^Bank
- storage: ^Bank
- running: bool
- key_modifiers: u32
- key_states: [MAX_KEYS]byte
- key_deltas: [MAX_KEYS]byte
- perf_frame,
- perf_frame_inner,
- perf_step,
- perf_audio,
- perf_blit,
- perf_blit_cvt,
- perf_blit_gdi: Perf_Span
- frame: i64
- canvas: Canvas
- draw_list: ^Draw_List
- }
- Perf_Span :: struct {
- stamp: f64
- delta: f32
- }
- Bank :: struct {
- memory: []byte
- cursor: int
- }
- Bank_State :: struct {
- state: Bank
- bank: ^Bank
- }
- Color :: raw_union {
- using channels: struct{ a, b, g, r: byte }
- rgba: u32
- }
- Palette :: struct {
- colors: [256]Color
- colors_count: byte
- }
- Rect :: raw_union {
- using minmax: struct {
- min_x, min_y, max_x, max_y: int
- }
- using pos: struct {
- left, top, right, bottom: int
- }
- e: [4]int
- }
- Bitmap :: struct {
- pixels: []byte
- width: int
- height: int
- }
- Font :: struct {
- using bitmap: Bitmap
- char_width: int
- char_height: int
- }
- Canvas :: struct {
- using bitmap: ^Bitmap
- palette: Palette
- translate_x: int
- translate_y: int
- clip: Rect
- font: ^Font
- }
- DrawFlag :: enum {
- NONE = 0,
- FLIP_H = 1<<0,
- FLIP_V = 1<<1,
- MASK = 1<<2,
- }
- Draw_List :: struct {
- Item :: struct {
- }
- items: []Item
- }
- Key :: enum {
- MOD_SHIFT = 0x0001,
- MOD_CONTROL = 0x0002,
- MOD_ALT = 0x0004,
- MOD_SUPER = 0x0008,
- UNKNOWN =-1,
- INVALID =-2,
- LBUTTON = 1,
- RBUTTON = 2,
- CANCEL = 3,
- MBUTTON = 4,
- BACK = 8,
- TAB = 9,
- CLEAR = 12,
- RETURN = 13,
- SHIFT = 16,
- CONTROL = 17,
- MENU = 18,
- PAUSE = 19,
- CAPITAL = 20,
- KANA = 0x15,
- HANGEUL = 0x15,
- HANGUL = 0x15,
- JUNJA = 0x17,
- FINAL = 0x18,
- HANJA = 0x19,
- KANJI = 0x19,
- ESCAPE = 0x1B,
- CONVERT = 0x1C,
- NONCONVERT = 0x1D,
- ACCEPT = 0x1E,
- MODECHANGE = 0x1F,
- SPACE = 32,
- PRIOR = 33,
- NEXT = 34,
- END = 35,
- HOME = 36,
- LEFT = 37,
- UP = 38,
- RIGHT = 39,
- DOWN = 40,
- SELECT = 41,
- PRINT = 42,
- EXEC = 43,
- SNAPSHOT = 44,
- INSERT = 45,
- DELETE = 46,
- HELP = 47,
- LWIN = 0x5B,
- RWIN = 0x5C,
- APPS = 0x5D,
- SLEEP = 0x5F,
- NUMPAD0 = 0x60,
- NUMPAD1 = 0x61,
- NUMPAD2 = 0x62,
- NUMPAD3 = 0x63,
- NUMPAD4 = 0x64,
- NUMPAD5 = 0x65,
- NUMPAD6 = 0x66,
- NUMPAD7 = 0x67,
- NUMPAD8 = 0x68,
- NUMPAD9 = 0x69,
- MULTIPLY = 0x6A,
- ADD = 0x6B,
- SEPARATOR = 0x6C,
- SUBTRACT = 0x6D,
- DECIMAL = 0x6E,
- DIVIDE = 0x6F,
- F1 = 0x70,
- F2 = 0x71,
- F3 = 0x72,
- F4 = 0x73,
- F5 = 0x74,
- F6 = 0x75,
- F7 = 0x76,
- F8 = 0x77,
- F9 = 0x78,
- F10 = 0x79,
- F11 = 0x7A,
- F12 = 0x7B,
- F13 = 0x7C,
- F14 = 0x7D,
- F15 = 0x7E,
- F16 = 0x7F,
- F17 = 0x80,
- F18 = 0x81,
- F19 = 0x82,
- F20 = 0x83,
- F21 = 0x84,
- F22 = 0x85,
- F23 = 0x86,
- F24 = 0x87,
- NUMLOCK = 0x90,
- SCROLL = 0x91,
- LSHIFT = 0xA0,
- RSHIFT = 0xA1,
- LCONTROL = 0xA2,
- RCONTROL = 0xA3,
- LMENU = 0xA4,
- RMENU = 0xA5,
- APOSTROPHE = 39, /* ' */
- COMMA = 44, /* , */
- MINUS = 45, /* - */
- PERIOD = 46, /* . */
- SLASH = 47, /* / */
- NUM0 = 48,
- NUM1 = 49,
- NUM2 = 50,
- NUM3 = 51,
- NUM4 = 52,
- NUM5 = 53,
- NUM6 = 54,
- NUM7 = 55,
- NUM8 = 56,
- NUM9 = 57,
- SEMICOLON = 59, /* ; */
- EQUAL = 61, /* = */
- A = 65,
- B = 66,
- C = 67,
- D = 68,
- E = 69,
- F = 70,
- G = 71,
- H = 72,
- I = 73,
- J = 74,
- K = 75,
- L = 76,
- M = 77,
- N = 78,
- O = 79,
- P = 80,
- Q = 81,
- R = 82,
- S = 83,
- T = 84,
- U = 85,
- V = 86,
- W = 87,
- X = 88,
- Y = 89,
- Z = 90,
- LEFT_BRACKET = 91, /* [ */
- BACKSLASH = 92, /* \ */
- RIGHT_BRACKET = 93, /* ] */
- GRAVE_ACCENT = 96, /* ` */
- }
- key_down :: proc(k: Key) -> bool {
- return _core.key_states[k] != 0
- }
- key_pressed :: proc(k: Key) -> bool {
- return (_core.key_deltas[k] != 0) && key_down(k)
- }
- win32_perf_count_freq := win32.GetQueryPerformanceFrequency()
- time_now :: proc() -> f64 {
- assert(win32_perf_count_freq != 0)
- counter: i64
- win32.QueryPerformanceCounter(^counter)
- result := counter as f64 / win32_perf_count_freq as f64
- return result
- }
- _core: Core
- run :: proc(user_init, user_step: proc(c: ^Core)) {
- using win32
- _core.running = true
- win32_proc :: proc(hwnd: HWND, msg: u32, wparam: WPARAM, lparam: LPARAM) -> LRESULT #no_inline #stdcall {
- win32_app_key_mods :: proc() -> u32 {
- mods: u32 = 0
- if is_key_down(Key_Code.SHIFT) {
- mods |= Key.MOD_SHIFT as u32;
- }
- if is_key_down(Key_Code.CONTROL) {
- mods |= Key.MOD_CONTROL as u32;
- }
- if is_key_down(Key_Code.MENU) {
- mods |= Key.MOD_ALT as u32;
- }
- if is_key_down(Key_Code.LWIN) || is_key_down(Key_Code.RWIN) {
- mods |= Key.MOD_SUPER as u32;
- }
- return mods
- }
- match msg {
- case WM_KEYDOWN:
- _core.key_modifiers = win32_app_key_mods()
- if wparam < MAX_KEYS {
- _core.key_states[wparam] = 1
- _core.key_deltas[wparam] = 1
- }
- return 0
- case WM_KEYUP:
- _core.key_modifiers = win32_app_key_mods()
- if wparam < MAX_KEYS {
- _core.key_states[wparam] = 0
- _core.key_deltas[wparam] = 1
- }
- return 0
- case WM_CLOSE:
- PostQuitMessage(0)
- _core.running = false
- return 0
- }
- return DefWindowProcA(hwnd, msg, wparam, lparam)
- }
- window_class := WNDCLASSEXA{
- class_name = ("Punity\x00" as string).data, // C-style string
- size = size_of(WNDCLASSEXA) as u32,
- style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC,
- instance = GetModuleHandleA(null) as HINSTANCE,
- wnd_proc = win32_proc,
- // wnd_proc = DefWindowProcA,
- background = GetStockObject(BLACK_BRUSH) as HBRUSH,
- }
- if RegisterClassExA(^window_class) == 0 {
- fmt.fprintln(os.stderr, "RegisterClassExA failed")
- return
- }
- screen_width := GetSystemMetrics(SM_CXSCREEN)
- screen_height := GetSystemMetrics(SM_CYSCREEN)
- rc: RECT
- rc.left = (screen_width - WINDOW_WIDTH) / 2
- rc.top = (screen_height - WINDOW_HEIGHT) / 2
- rc.right = rc.left + WINDOW_WIDTH
- rc.bottom = rc.top + WINDOW_HEIGHT
- style: u32 = WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX
- assert(AdjustWindowRect(^rc, style, 0) != 0)
- wt := WINDOW_TITLE
- win32_window := CreateWindowExA(0,
- window_class.class_name,
- wt.data,
- style,
- rc.left, rc.top,
- rc.right-rc.left, rc.bottom-rc.top,
- null, null, window_class.instance,
- null);
- if win32_window == null {
- fmt.fprintln(os.stderr, "CreateWindowExA failed")
- return
- }
- window_bmi: BITMAPINFO;
- window_bmi.size = size_of(BITMAPINFO.HEADER) as u32
- window_bmi.width = CANVAS_WIDTH
- window_bmi.height = CANVAS_HEIGHT
- window_bmi.planes = 1
- window_bmi.bit_count = 32
- window_bmi.compression = BI_RGB
- user_init(^_core)
- ShowWindow(win32_window, SW_SHOW)
- window_buffer := new_slice(u32, CANVAS_WIDTH * CANVAS_HEIGHT);
- assert(window_buffer.data != null)
- defer free(window_buffer.data)
- for i := 0; i < window_buffer.count; i++ {
- window_buffer[i] = 0xff00ff
- }
- prev_time, curr_time,dt: f64
- prev_time = time_now()
- curr_time = time_now()
- total_time : f64 = 0
- offset_x := 0;
- offset_y := 0;
- message: MSG
- for _core.running {
- curr_time = time_now()
- dt = curr_time - prev_time
- prev_time = curr_time
- total_time += dt
- offset_x += 1
- offset_y += 2
- {
- data: [128]byte
- buf := data[:0]
- fmt.bprintf(^buf, "Punity: % ms\x00", dt*1000)
- win32.SetWindowTextA(win32_window, buf.data)
- }
- for y := 0; y < CANVAS_HEIGHT; y++ {
- for x := 0; x < CANVAS_WIDTH; x++ {
- g := (x % 32) * 8
- b := (y % 32) * 8
- window_buffer[x + y*CANVAS_WIDTH] = (g << 8 | b) as u32
- }
- }
- memory_zero(^_core.key_deltas[0], size_of_val(_core.key_deltas[0]))
- for PeekMessageA(^message, null, 0, 0, PM_REMOVE) != 0 {
- if message.message == WM_QUIT {
- _core.running = false
- }
- TranslateMessage(^message)
- DispatchMessageA(^message)
- }
- user_step(^_core)
- dc := GetDC(win32_window);
- StretchDIBits(dc,
- 0, 0, CANVAS_WIDTH * CANVAS_SCALE, CANVAS_HEIGHT * CANVAS_SCALE,
- 0, 0, CANVAS_WIDTH, CANVAS_HEIGHT,
- window_buffer.data,
- ^window_bmi,
- DIB_RGB_COLORS,
- SRCCOPY)
- ReleaseDC(win32_window, dc)
- {
- delta := time_now() - prev_time
- ms := ((FRAME_TIME - delta) * 1000) as i32
- if ms > 0 {
- win32.Sleep(ms)
- }
- }
- _core.frame++
- }
- }
|