diff --git a/programs/emulator/chip8/chip8.asm b/programs/emulator/chip8/chip8.asm index ca997e46b9..db68c4d0b7 100644 --- a/programs/emulator/chip8/chip8.asm +++ b/programs/emulator/chip8/chip8.asm @@ -18,6 +18,9 @@ include 'constants.inc' ; application's entry point align 4 start: + mcall 68, 11 + mcall 68, 12, IMGBUF_SIZE + mov dword [imgbuf_ptr], eax stdcall chip8_init ; initialize @@ -46,7 +49,7 @@ start: ; mov byte [gfx + 64*2 + 3], 1 .event_loop: - mcall 23, CLOCK_RATE ; wait for event with CLOCK_RATE timeout + mcall 23, CLOCK_RATE ; wait for event with CLOCK_RATE timeout ;DEBUGF DBG_INFO, "evenp loop iter i\n" cmp eax, 1 diff --git a/programs/emulator/chip8/constants.inc b/programs/emulator/chip8/constants.inc index 7245a375bd..448009c184 100644 --- a/programs/emulator/chip8/constants.inc +++ b/programs/emulator/chip8/constants.inc @@ -16,7 +16,15 @@ KEY_SIZE = 16 GFX_ROWS = 32 GFX_COLS = 64 GFX_SIZE = GFX_ROWS * GFX_COLS -GFX_PIX_SIZE = 10 +GFX_PIX_SIZE = 10 ; gfx cell size in pixels + +COLOR_BACK = 0x000000 +COLOR_CELL = 0xade8f4 ;0xFFFFFF + +IMGBUF_WIDTH = GFX_COLS * GFX_PIX_SIZE ; width in pixels +IMGBUF_HEIGHT = GFX_ROWS * GFX_PIX_SIZE ; height in pixels +IMGBUF_SIZE = IMGBUF_WIDTH * IMGBUF_HEIGHT * 3 + 16 ; size in bytes for in-memory image buffer + CLOCK_RATE = 1 ; in 10^-2 seconds diff --git a/programs/emulator/chip8/data.inc b/programs/emulator/chip8/data.inc index c0df58a45c..f74733da51 100644 --- a/programs/emulator/chip8/data.inc +++ b/programs/emulator/chip8/data.inc @@ -45,6 +45,8 @@ sys_colors system_colors main_window_title db 'CHIP-8 Emulator',0 + imgbuf_ptr dd ? ; pointer to in-memory image buffer + ;========================================= align 16 _i_end: diff --git a/programs/emulator/chip8/emu.inc b/programs/emulator/chip8/emu.inc index dbd3e0c45e..24f160cb34 100644 --- a/programs/emulator/chip8/emu.inc +++ b/programs/emulator/chip8/emu.inc @@ -16,7 +16,7 @@ proc chip8_init stdcall stdcall _memset, key, 0, KEY_SIZE ;DEBUGF DBG_INFO, "ESP = %x\n", esp - mcall 66, 1 ; set scancode keyboard mode + mcall 66, 1, 0 ; set ASCII keyboard mode xor ecx, ecx @@: diff --git a/programs/emulator/chip8/gui.inc b/programs/emulator/chip8/gui.inc index 0928768c4f..27a7a89428 100644 --- a/programs/emulator/chip8/gui.inc +++ b/programs/emulator/chip8/gui.inc @@ -37,31 +37,88 @@ proc draw_screen stdcall div ecx ; eax = row index, edx = col index mov dword [row_ind], eax mov dword [col_ind], edx - mov dword [color], 0x80FFFFFF ; white + mov dword [color], COLOR_CELL ; white cmp byte [esi + gfx], 0 ; check if cell is 0 or not 0 jne @f - mov dword [color], 0x80000000 ; black + mov dword [color], COLOR_BACK ; black @@: mov ebx, dword [col_ind] - imul ebx, GFX_PIX_SIZE - ;add ebx, WINDOW_BORDER - shl ebx, 16 - add ebx, GFX_PIX_SIZE - + imul ebx, GFX_PIX_SIZE ; now ebx - x coord of rect mov ecx, dword [row_ind] - imul ecx, GFX_PIX_SIZE - ;add ecx, WINDOW_BORDER - shl ecx, 16 - add ecx, GFX_PIX_SIZE - - mov eax, 13 + imul ecx, GFX_PIX_SIZE ; now ecx - y coord of rect mov edx, dword [color] - int 0x40 + stdcall imgbuf_draw_rect, ebx, ecx, edx inc esi jmp .loop1 .loop1_end: + stdcall imgbuf_send_to_window popad ret -endp \ No newline at end of file +endp + +; copy imgbuf contents to the emulator window +align 4 +proc imgbuf_send_to_window stdcall + DEBUGF DBG_INFO, "sending to window...\n" + push eax ebx ecx edx + mov eax, 7 + mov ebx, dword [imgbuf_ptr] + mov ecx, IMGBUF_WIDTH + shl ecx, 16 + add ecx, IMGBUF_HEIGHT + xor edx, edx + int 0x40 + pop edx ecx ebx eax + ret +endp + + +; in internal buffer draw rect filled with given color at position (rect_x, rect_y) within window +align 4 +proc imgbuf_draw_rect stdcall, rect_x: dword, rect_y: dword, rect_color: dword + DEBUGF DBG_INFO, "imgbuf_draw_rect(%u, %u, %x)\n", [rect_x], [rect_y], [rect_color] + push eax ebx ecx edx esi edi ebp + + mov ebx, dword [rect_y] + imul ebx, IMGBUF_WIDTH + add ebx, dword [rect_x] ; now ebx - index of first pixel of rect + + mov edi, dword [imgbuf_ptr] + mov ebp, dword [rect_color] + + xor ecx, ecx +.for_i: + cmp ecx, GFX_PIX_SIZE + jae .ret + + xor edx, edx +.for_j: + cmp edx, GFX_PIX_SIZE + jae .for_j_end + + mov esi, edx + + add edx, ebx + mov eax, ecx + imul eax, IMGBUF_WIDTH + add edx, eax ; now edx is index of edx'th pixel of ecx'th row of rect + + lea edx, [edx*3] + add edx, edi + + mov dword [edx], ebp ; put color to pixel + + mov edx, esi + inc edx + jmp .for_j +.for_j_end: + + inc ecx + jmp .for_i + +.ret: + pop ebp edi esi edx ecx ebx eax + ret +endp diff --git a/programs/emulator/chip8/readme.txt b/programs/emulator/chip8/readme.txt index 37ff265f24..188f3c2659 100644 --- a/programs/emulator/chip8/readme.txt +++ b/programs/emulator/chip8/readme.txt @@ -1,12 +1,46 @@ -CHIP-8 Emulator for KolibriOS. -Author: rgimad -Year: 2021 - -How to use: - -Open shell in current directory (in Eolite Ctrl+G). -Type for example: - -chip8 roms/ibm.ch8 - -P.S. ROMs from https://github.com/dmatlack/chip8/tree/master/roms +CHIP8 - Chip-8 systems emulator, written specially for KolibriOS in pure FASM from scratch. +Author: rgimad (rustem.gimadutdinov@gmail.com) +License: GNU GPL v2 + +== Usage == +Open shell in emulator directory (in Eolite Ctrl+G opens shell). + +Type for example: + + chip8 roms/ibm.ch8 + +== Keys == + +CHIP8 emulator can process 16 keys, they are: 0-9, a, b, c, d, e, f + +== ROMs == + +Emulator goes with some ROMs: games, demos, programs, etc. +Some of them you can see below: + +=== TETRIS (roms/tetris1.ch8) === + +How to play: +4 key is left rotate +5 - left move +6 - right move + +After every 5 lines, the speed increases slightly and peaks at 45 lines. + +=== SPACE INVADERS (roms/invaders1.ch8) === + +Very famous game + +=== MAZE (roms/maze_alt.ch8) === +A random maze generator + +=== RND (roms/rnd.ch8) === +Generates and prints out a random number. Press any key to generate one more. + +=== IBM (roms/ibm.ch8) === +Prints out the IBM logo + +=== CHIP8 (roms/chip8.ch8) === +Prints out the CHIP8 logo + +More ROMs you can find here: https://github.com/dmatlack/chip8/tree/master/roms