forked from KolibriOS/kolibrios
add chip8 emulator + to iso autobuild
git-svn-id: svn://kolibrios.org@8725 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
parent
bb845a71ca
commit
7f7312d98b
@ -201,6 +201,9 @@ extra_files = {
|
||||
{"kolibrios/emul/e80/keyboard.png", PROGS .. "/emulator/e80/trunk/keyboard.png"},
|
||||
{"kolibrios/emul/fceu/fceu", PROGS .. "/emulator/fceu/fceu"},
|
||||
{"kolibrios/emul/fceu/FCEU ReadMe.txt", PROGS .. "/emulator/fceu/FCEU ReadMe.txt"},
|
||||
{"kolibrios/emul/chip8/chip8", PROGS .. "/emulator/chip8/chip8"},
|
||||
{"kolibrios/emul/chip8/readme.txt", PROGS .. "/emulator/chip8/readme.txt"},
|
||||
{"kolibrios/emul/chip8/roms/", PROGS .. "/emulator/chip8/roms/*"},
|
||||
{"kolibrios/emul/kwine/kwine", PROGS .. "/emulator/kwine/bin/kwine"},
|
||||
{"kolibrios/emul/kwine/lib/", PROGS .. "/emulator/kwine/bin/lib/*"},
|
||||
{"kolibrios/emul/uarm/", "common/emul/uarm/*"},
|
||||
|
6
programs/emulator/chip8/Tupfile.lua
Normal file
6
programs/emulator/chip8/Tupfile.lua
Normal file
@ -0,0 +1,6 @@
|
||||
if tup.getconfig("NO_FASM") ~= "" then return end
|
||||
HELPERDIR = (tup.getconfig("HELPERDIR") == "") and "../../.." or tup.getconfig("HELPERDIR")
|
||||
tup.include(HELPERDIR .. "/use_fasm.lua")
|
||||
|
||||
tup.rule("chip8.asm", FASM .. " %f %o " .. tup.getconfig("KPACK_CMD"), "chip8")
|
||||
|
1
programs/emulator/chip8/build.sh
Executable file
1
programs/emulator/chip8/build.sh
Executable file
@ -0,0 +1 @@
|
||||
fasm chip8.asm chip8
|
114
programs/emulator/chip8/chip8.asm
Normal file
114
programs/emulator/chip8/chip8.asm
Normal file
@ -0,0 +1,114 @@
|
||||
; Author: rgimad (2021)
|
||||
; License: GNU GPL v2
|
||||
|
||||
format binary as ""
|
||||
use32
|
||||
org 0
|
||||
db 'MENUET01' ; signature
|
||||
dd 1 ; header version
|
||||
dd start ; entry point
|
||||
dd _i_end ; end of image
|
||||
dd _mem ; required memory size
|
||||
dd _stacktop ; address of stack top
|
||||
dd cmdline ; buffer for command line arguments
|
||||
dd 0 ; buffer for path
|
||||
|
||||
include 'constants.inc'
|
||||
|
||||
; application's entry point
|
||||
align 4
|
||||
start:
|
||||
|
||||
stdcall chip8_init ; initialize
|
||||
|
||||
DEBUGF DBG_INFO, "app started, args = %s\n", cmdline
|
||||
DEBUGF DBG_INFO, "MAX_GAME_SIZE = %x = %u\n", MAX_GAME_SIZE, MAX_GAME_SIZE
|
||||
|
||||
; xor ecx, ecx
|
||||
; @@:
|
||||
; mov al, byte [chip8_fontset + ecx]
|
||||
; DEBUGF DBG_INFO, "%x ", al
|
||||
; cmp ecx, 79
|
||||
; je @f
|
||||
; inc ecx
|
||||
; jmp @b
|
||||
; @@:
|
||||
|
||||
mov dword [fread_struct.filename], cmdline
|
||||
stdcall chip8_loadgame, fread_struct
|
||||
jz .file_not_found
|
||||
|
||||
DEBUGF DBG_INFO, "file was read. bytes: %x %x %x..\n", [memory + 0x200], [memory + 0x200 + 4], [memory + 0x200 + 8]
|
||||
|
||||
; mov byte [gfx + 5], 1
|
||||
; mov byte [gfx + 64], 1
|
||||
; mov byte [gfx + 65], 1
|
||||
; mov byte [gfx + 64*2 + 3], 1
|
||||
|
||||
.event_loop:
|
||||
mcall 23, CLOCK_RATE ; wait for event with CLOCK_RATE timeout
|
||||
;DEBUGF DBG_INFO, "evenp loop iter i\n"
|
||||
|
||||
cmp eax, 1
|
||||
je .event_redraw
|
||||
|
||||
cmp eax, 2
|
||||
je .event_key
|
||||
|
||||
cmp eax, 3
|
||||
je .event_button
|
||||
|
||||
jmp .event_default
|
||||
|
||||
.event_redraw:
|
||||
stdcall draw_main_window
|
||||
jmp .event_default
|
||||
|
||||
.event_key:
|
||||
mcall 2
|
||||
stdcall keyboard_update, eax
|
||||
DEBUGF DBG_INFO, "key scancode %x\n", eax:4
|
||||
jmp .event_default
|
||||
|
||||
.event_button:
|
||||
mcall 17
|
||||
cmp ah, 1
|
||||
jne .event_default
|
||||
mcall -1
|
||||
|
||||
.event_default:
|
||||
stdcall chip8_emulatecycle
|
||||
cmp byte [chip8_draw_flag], 0
|
||||
jz @f
|
||||
|
||||
; mov byte [gfx + 64*2 + 3], 1 ; DBG
|
||||
|
||||
stdcall draw_screen
|
||||
mov byte [chip8_draw_flag], 0
|
||||
@@:
|
||||
stdcall chip8_tick
|
||||
jmp .event_loop
|
||||
|
||||
.file_not_found:
|
||||
DEBUGF DBG_ERR, "Unable to open game file! eax = %u\n", eax
|
||||
jmp .exit
|
||||
|
||||
.exit:
|
||||
mov eax, -1
|
||||
int 0x40
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
|
||||
include 'gui.inc'
|
||||
|
||||
include 'emu.inc'
|
||||
|
||||
include 'utils.inc'
|
||||
|
||||
include 'data.inc'
|
||||
rb 4096 ; reserve for main thread stack
|
||||
align 16
|
||||
_stacktop:
|
||||
|
||||
_mem:
|
29
programs/emulator/chip8/constants.inc
Normal file
29
programs/emulator/chip8/constants.inc
Normal file
@ -0,0 +1,29 @@
|
||||
; constants for formatted debug
|
||||
__DEBUG__ = 1 ; 0 - disable debug output / 1 - enable debug output
|
||||
__DEBUG_LEVEL__ = DBG_ERR ; set the debug level
|
||||
|
||||
DBG_ALL = 0 ; all messages
|
||||
DBG_INFO = 1 ; info and errors
|
||||
DBG_ERR = 2 ; only errors
|
||||
|
||||
; emulator constants
|
||||
MAX_GAME_SIZE = 0x1000 - 0x200
|
||||
FONTSET_ADDRESS = 0x00
|
||||
FONTSET_BYTES_PER_CHAR = 5
|
||||
MEM_SIZE = 4096
|
||||
STACK_SIZE = 16
|
||||
KEY_SIZE = 16
|
||||
GFX_ROWS = 32
|
||||
GFX_COLS = 64
|
||||
GFX_SIZE = GFX_ROWS * GFX_COLS
|
||||
GFX_PIX_SIZE = 10
|
||||
CLOCK_RATE = 1 ; in 10^-2 seconds
|
||||
|
||||
|
||||
include '../../macros.inc'
|
||||
purge mov, add, sub
|
||||
|
||||
include '../../debug-fdo.inc'
|
||||
include '../../proc32.inc'
|
||||
|
||||
;=========================================
|
57
programs/emulator/chip8/data.inc
Normal file
57
programs/emulator/chip8/data.inc
Normal file
@ -0,0 +1,57 @@
|
||||
;=========================================
|
||||
; initialized data
|
||||
include_debug_strings ; for debug-fdo
|
||||
|
||||
chip8_fontset db \
|
||||
0xF0, 0x90, 0x90, 0x90, 0xF0, \ ; 0
|
||||
0x20, 0x60, 0x20, 0x20, 0x70, \ ; 1
|
||||
0xF0, 0x10, 0xF0, 0x80, 0xF0, \ ; 2
|
||||
0xF0, 0x10, 0xF0, 0x10, 0xF0, \ ; 3
|
||||
0x90, 0x90, 0xF0, 0x10, 0x10, \ ; 4
|
||||
0xF0, 0x80, 0xF0, 0x10, 0xF0, \ ; 5
|
||||
0xF0, 0x80, 0xF0, 0x90, 0xF0, \ ; 6
|
||||
0xF0, 0x10, 0x20, 0x40, 0x40, \ ; 7
|
||||
0xF0, 0x90, 0xF0, 0x90, 0xF0, \ ; 8
|
||||
0xF0, 0x90, 0xF0, 0x10, 0xF0, \ ; 9
|
||||
0xF0, 0x90, 0xF0, 0x90, 0x90, \ ; A
|
||||
0xE0, 0x90, 0xE0, 0x90, 0xE0, \ ; B
|
||||
0xF0, 0x80, 0x80, 0x80, 0xF0, \ ; C
|
||||
0xE0, 0x90, 0x90, 0x90, 0xE0, \ ; D
|
||||
0xF0, 0x80, 0xF0, 0x80, 0xF0, \ ; E
|
||||
0xF0, 0x80, 0xF0, 0x80, 0x80 ; F
|
||||
|
||||
opcode dw 0 ; operation code
|
||||
V db 16 dup(0) ; 16 8-bit registers
|
||||
I dw 0 ; additional register (usually used for storing addresses)
|
||||
P_C dw 0 ; program counter
|
||||
S_P dw 0 ; stack pointer
|
||||
delay_timer db 0
|
||||
sound_timer db 0
|
||||
stackmem dw STACK_SIZE dup(0) ; stack memory
|
||||
key db KEY_SIZE dup (0) ; keyboard
|
||||
chip8_draw_flag db 0
|
||||
next_rand dd 1
|
||||
|
||||
align 4
|
||||
fread_struct:
|
||||
.subfunction dd 0 ; + 0
|
||||
.offset_low dd 0 ; + 4
|
||||
.offset_high dd 0 ; + 8
|
||||
.size dd MAX_GAME_SIZE ; + 12
|
||||
.buffer dd memory + 0x200 ; + 16
|
||||
db 0 ; + 20
|
||||
.filename: dd 0 ; + 24
|
||||
|
||||
sys_colors system_colors
|
||||
main_window_title db 'CHIP-8 Emulator',0
|
||||
|
||||
;=========================================
|
||||
align 16
|
||||
_i_end:
|
||||
; uninitialized data
|
||||
cmdline rb 1024 ; reserve for command line arguments
|
||||
|
||||
memory rb MEM_SIZE
|
||||
gfx rb GFX_SIZE
|
||||
|
||||
;tmp_buf rb 128
|
779
programs/emulator/chip8/emu.inc
Normal file
779
programs/emulator/chip8/emu.inc
Normal file
@ -0,0 +1,779 @@
|
||||
; initalize the emulator
|
||||
align 4
|
||||
proc chip8_init stdcall
|
||||
; destroys: nothing, mb flags
|
||||
push eax ecx
|
||||
mov word [P_C], 0x200
|
||||
mov word [opcode], 0
|
||||
mov word [I], 0
|
||||
mov word [S_P], 0
|
||||
|
||||
;DEBUGF DBG_INFO, "ESP = %x\n", esp
|
||||
stdcall _memset, memory, 0, MEM_SIZE
|
||||
stdcall _memset, V, 0, 16
|
||||
stdcall _memset, gfx, 0, GFX_SIZE
|
||||
stdcall _memset, stackmem, 0, 2*STACK_SIZE ; 2 = sizeof(dw)
|
||||
stdcall _memset, key, 0, KEY_SIZE
|
||||
;DEBUGF DBG_INFO, "ESP = %x\n", esp
|
||||
|
||||
mcall 66, 1 ; set scancode keyboard mode
|
||||
|
||||
xor ecx, ecx
|
||||
@@:
|
||||
cmp ecx, 80
|
||||
jge @f
|
||||
mov al, byte [chip8_fontset + ecx]
|
||||
mov byte [memory + FONTSET_ADDRESS + ecx], al
|
||||
inc ecx
|
||||
jmp @b
|
||||
@@:
|
||||
mov byte [chip8_draw_flag], 1
|
||||
mov byte [delay_timer], 0
|
||||
mov byte [sound_timer], 0
|
||||
stdcall _getseed
|
||||
stdcall _srand, eax
|
||||
|
||||
stdcall _rand
|
||||
DEBUGF DBG_INFO, "rand() = %u\n", eax
|
||||
;stdcall _rand
|
||||
;DEBUGF DBG_INFO, "rand() = %u\n", eax
|
||||
;stdcall _rand
|
||||
;DEBUGF DBG_INFO, "rand() = %u\n", eax
|
||||
;stdcall _rand
|
||||
;DEBUGF DBG_INFO, "rand() = %u\n", eax
|
||||
;stdcall _rand
|
||||
;DEBUGF DBG_INFO, "rand() = %u\n", eax
|
||||
|
||||
;mov word [opcode], 0xBFAF
|
||||
;movzx eax, word [opcode]
|
||||
;mov eax, 0xABCDEF92
|
||||
;stdcall unknown_opcode, eax
|
||||
;DEBUGF DBG_INFO, "testprint\n"
|
||||
pop ecx eax
|
||||
ret
|
||||
endp
|
||||
|
||||
|
||||
; load game from file to memory
|
||||
align 4
|
||||
proc chip8_loadgame stdcall, struct_ptr: dword
|
||||
; in: struct_ptr - pointer to structure for sysfn70
|
||||
; out: ZF = 1 file loaded successfully
|
||||
; ZF = 0 error
|
||||
; destroys: only flags
|
||||
push eax ebx
|
||||
|
||||
mov eax, 70
|
||||
mov ebx, [struct_ptr]
|
||||
int 0x40
|
||||
|
||||
cmp eax, 0
|
||||
je @f
|
||||
cmp eax, 6
|
||||
je @f
|
||||
jmp .load_fail
|
||||
@@:
|
||||
mov eax, 1
|
||||
jmp .ret
|
||||
|
||||
.load_fail:
|
||||
xor eax, eax
|
||||
.ret:
|
||||
test eax, eax
|
||||
pop ebx eax
|
||||
ret
|
||||
endp
|
||||
|
||||
|
||||
; emulate one cycle
|
||||
align 4
|
||||
proc chip8_emulatecycle stdcall
|
||||
; destroys: ?
|
||||
locals
|
||||
x db ?
|
||||
y db ?
|
||||
n db ?
|
||||
kk db ?
|
||||
nnn dw ?
|
||||
endl
|
||||
; fetch:
|
||||
movzx ecx, word [P_C]
|
||||
movzx ax, byte [memory + ecx]
|
||||
shl ax, 8
|
||||
movzx bx, byte [memory + 1 + ecx]
|
||||
or ax, bx
|
||||
mov word [opcode], ax
|
||||
; DEBUGF DBG_INFO, "opcode = 0x%x, ax = 0x%x\n", [opcode]:4, ax
|
||||
|
||||
shr ax, 8
|
||||
and ax, 0x000F
|
||||
mov byte [x], al
|
||||
|
||||
mov ax, word [opcode]
|
||||
shr ax, 4
|
||||
and ax, 0x000F
|
||||
mov byte [y], al
|
||||
|
||||
mov ax, word [opcode]
|
||||
and ax, 0x000F
|
||||
mov byte [n], al
|
||||
|
||||
mov ax, word [opcode]
|
||||
and ax, 0x00FF
|
||||
mov byte [kk], al
|
||||
|
||||
mov ax, word [opcode]
|
||||
and ax, 0x0FFF
|
||||
mov word [nnn], ax
|
||||
|
||||
; DEBUGF DBG_INFO, "P_C: 0x%x Op: 0x%x\n", [P_C], [opcode]:4 ; was word word
|
||||
; TODO test this and watch values of x, y, n, kk, nnn
|
||||
|
||||
; decode & execute
|
||||
; sw1
|
||||
mov ax, word [opcode]
|
||||
and ax, 0xF000
|
||||
|
||||
cmp ax, 0x0000
|
||||
je .sw1_case_0000
|
||||
|
||||
cmp ax, 0x1000
|
||||
je .sw1_case_1000
|
||||
|
||||
cmp ax, 0x2000
|
||||
je .sw1_case_2000
|
||||
|
||||
cmp ax, 0x3000
|
||||
je .sw1_case_3000
|
||||
|
||||
cmp ax, 0x4000
|
||||
je .sw1_case_4000
|
||||
|
||||
cmp ax, 0x5000
|
||||
je .sw1_case_5000
|
||||
|
||||
cmp ax, 0x6000
|
||||
je .sw1_case_6000
|
||||
|
||||
cmp ax, 0x7000
|
||||
je .sw1_case_7000
|
||||
|
||||
cmp ax, 0x8000
|
||||
je .sw1_case_8000
|
||||
|
||||
cmp ax, 0x9000
|
||||
je .sw1_case_9000
|
||||
|
||||
cmp ax, 0xA000
|
||||
je .sw1_case_A000
|
||||
|
||||
cmp ax, 0xB000
|
||||
je .sw1_case_B000
|
||||
|
||||
cmp ax, 0xC000
|
||||
je .sw1_case_C000
|
||||
|
||||
cmp ax, 0xD000
|
||||
je .sw1_case_D000
|
||||
|
||||
cmp ax, 0xE000
|
||||
je .sw1_case_E000
|
||||
|
||||
cmp ax, 0xF000
|
||||
je .sw1_case_F000
|
||||
|
||||
jmp .sw1_default
|
||||
|
||||
.sw1_case_0000:
|
||||
; sw2
|
||||
cmp byte [kk], 0xE0
|
||||
je .sw2_case_E0
|
||||
|
||||
cmp byte [kk], 0xEE
|
||||
je .sw2_case_EE
|
||||
|
||||
jmp .sw2_default
|
||||
|
||||
.sw2_case_E0: ; clear the screen
|
||||
stdcall _memset, gfx, 0, GFX_SIZE
|
||||
mov byte [chip8_draw_flag], 1
|
||||
add word [P_C], 2
|
||||
jmp .sw2_end
|
||||
|
||||
.sw2_case_EE: ; TODO check!!; ret
|
||||
dec word [S_P]
|
||||
movzx ecx, word [S_P]
|
||||
mov ax, word [stackmem + ecx*2]
|
||||
mov word [P_C], ax
|
||||
jmp .sw2_end
|
||||
|
||||
.sw2_default:
|
||||
movzx eax, word [opcode]
|
||||
stdcall unknown_opcode, eax
|
||||
.sw2_end:
|
||||
jmp .sw1_end
|
||||
|
||||
.sw1_case_1000: ; TODO check; 1nnn: jump to address nnn
|
||||
mov ax, word [nnn]
|
||||
mov word [P_C], ax
|
||||
jmp .sw1_end
|
||||
|
||||
.sw1_case_2000: ; TODO check; 2nnn: call address nnn
|
||||
mov ax, word [P_C]
|
||||
add ax, 2
|
||||
movzx ecx, word [S_P]
|
||||
mov word [stackmem + ecx*2], ax
|
||||
inc word [S_P]
|
||||
mov ax, word [nnn]
|
||||
mov word [P_C], ax
|
||||
jmp .sw1_end
|
||||
|
||||
.sw1_case_3000: ; 3xkk: skip next instr if V[x] = kk
|
||||
movzx ecx, byte [x]
|
||||
mov al, byte [V + ecx]
|
||||
mov bl, byte [kk]
|
||||
mov cx, 2
|
||||
cmp al, bl
|
||||
jne @f
|
||||
mov cx, 4
|
||||
@@:
|
||||
add word [P_C], cx
|
||||
jmp .sw1_end
|
||||
|
||||
.sw1_case_4000: ; 4xkk: skip next instr if V[x] != kk
|
||||
movzx ecx, byte [x]
|
||||
mov al, byte [V + ecx]
|
||||
mov bl, byte [kk]
|
||||
mov cx, 2
|
||||
cmp al, bl
|
||||
je @f
|
||||
mov cx, 4
|
||||
@@:
|
||||
add word [P_C], cx
|
||||
jmp .sw1_end
|
||||
|
||||
.sw1_case_5000: ; 5xy0: skip next instr if V[x] == V[y]
|
||||
movzx ecx, byte [x]
|
||||
mov al, byte [V + ecx]
|
||||
movzx ecx, byte [y]
|
||||
mov bl, byte [V + ecx]
|
||||
mov cx, 2
|
||||
cmp al, bl
|
||||
jne @f
|
||||
mov cx, 4
|
||||
@@:
|
||||
add word [P_C], cx
|
||||
jmp .sw1_end
|
||||
|
||||
.sw1_case_6000: ; 6xkk: set V[x] = kk
|
||||
movzx ecx, byte [x]
|
||||
mov bl, byte [kk]
|
||||
mov byte [V + ecx], bl
|
||||
add word [P_C], 2
|
||||
jmp .sw1_end
|
||||
|
||||
.sw1_case_7000: ; 7xkk: set V[x] = V[x] + kk
|
||||
movzx ecx, byte [x]
|
||||
mov bl, byte [kk]
|
||||
add byte [V + ecx], bl
|
||||
add word [P_C], 2
|
||||
jmp .sw1_end
|
||||
|
||||
.sw1_case_8000: ; 8xyn: Arithmetic stuff
|
||||
; sw3
|
||||
cmp byte [n], 0x0
|
||||
je .sw3_case_0
|
||||
|
||||
cmp byte [n], 0x1
|
||||
je .sw3_case_1
|
||||
|
||||
cmp byte [n], 0x2
|
||||
je .sw3_case_2
|
||||
|
||||
cmp byte [n], 0x3
|
||||
je .sw3_case_3
|
||||
|
||||
cmp byte [n], 0x4
|
||||
je .sw3_case_4
|
||||
|
||||
cmp byte [n], 0x5
|
||||
je .sw3_case_5
|
||||
|
||||
cmp byte [n], 0x6
|
||||
je .sw3_case_6
|
||||
|
||||
cmp byte [n], 0x7
|
||||
je .sw3_case_7
|
||||
|
||||
cmp byte [n], 0xE
|
||||
je .sw3_case_E
|
||||
|
||||
jmp .sw3_default
|
||||
|
||||
.sw3_case_0: ; V[x] = V[y]
|
||||
movzx ecx, byte [x]
|
||||
movzx edx, byte [y]
|
||||
mov al, byte [V + edx]
|
||||
mov byte [V + ecx], al
|
||||
jmp .sw3_end
|
||||
|
||||
.sw3_case_1: ; V[x] = V[x] | V[y]
|
||||
movzx ecx, byte [x]
|
||||
movzx edx, byte [y]
|
||||
mov al, byte [V + ecx]
|
||||
or al, byte [V + edx]
|
||||
mov byte [V + ecx], al
|
||||
jmp .sw3_end
|
||||
|
||||
.sw3_case_2: ; V[x] = V[x] & V[y]
|
||||
movzx ecx, byte [x]
|
||||
movzx edx, byte [y]
|
||||
mov al, byte [V + ecx]
|
||||
and al, byte [V + edx]
|
||||
mov byte [V + ecx], al
|
||||
jmp .sw3_end
|
||||
|
||||
.sw3_case_3: ; V[x] = V[x] ^ V[y]
|
||||
movzx ecx, byte [x]
|
||||
movzx edx, byte [y]
|
||||
mov al, byte [V + ecx]
|
||||
xor al, byte [V + edx]
|
||||
mov byte [V + ecx], al
|
||||
jmp .sw3_end
|
||||
|
||||
.sw3_case_4: ; V[x] = V[x] + V[y]; if carry, move 1 to V[0xF]
|
||||
movzx ecx, byte [x]
|
||||
movzx edx, byte [y]
|
||||
movzx ax, byte [V + ecx]
|
||||
movzx bx, byte [V + edx]
|
||||
add ax, bx
|
||||
mov byte [V + ecx], al
|
||||
|
||||
xor cl, cl
|
||||
cmp ax, 255
|
||||
jbe @f
|
||||
inc cl
|
||||
@@:
|
||||
mov byte [V + 0xF], cl
|
||||
jmp .sw3_end
|
||||
|
||||
.sw3_case_5: ;TODO check; V[x] = V[x] - V[y]; if no borrow, move 1 to V[0xF]
|
||||
movzx ecx, byte [x]
|
||||
movzx edx, byte [y]
|
||||
mov al, byte [V + ecx]
|
||||
mov bl, byte [V + edx]
|
||||
sub al, bl
|
||||
mov byte [V + ecx], al
|
||||
|
||||
xor cl, cl
|
||||
cmp al, bl
|
||||
jbe @f
|
||||
inc cl
|
||||
@@:
|
||||
mov byte [V + 0xF], cl
|
||||
jmp .sw3_end
|
||||
|
||||
.sw3_case_6: ; TODO check; V[x] = V[x] SHR 1 ; V[0xF] = least-significant bit of V[x] before shift
|
||||
movzx ecx, byte [x]
|
||||
mov al, byte [V + ecx]
|
||||
and al, 0x01
|
||||
mov byte [V + 0xF], al
|
||||
shr byte [V + ecx], 1
|
||||
jmp .sw3_end
|
||||
|
||||
.sw3_case_7: ; TODO check; V[x] = V[y] - V[x]; if no borrow, move 1 to V[0xF]
|
||||
movzx ecx, byte [y]
|
||||
movzx edx, byte [x]
|
||||
mov al, byte [V + ecx]
|
||||
mov bl, byte [V + edx]
|
||||
sub al, bl
|
||||
mov byte [V + ecx], al
|
||||
|
||||
xor cl, cl
|
||||
cmp al, bl
|
||||
jbe @f
|
||||
inc cl
|
||||
@@:
|
||||
mov byte [V + 0xF], cl
|
||||
jmp .sw3_end
|
||||
|
||||
.sw3_case_E: ; TODO check; V[0xF] = most-significant bit of V[x] before shift
|
||||
movzx ecx, byte [x]
|
||||
mov al, byte [V + ecx]
|
||||
shr al, 7
|
||||
and al, 0x01
|
||||
mov byte [V + 0xF], al
|
||||
shl byte [V + ecx], 1
|
||||
jmp .sw3_end
|
||||
|
||||
.sw3_default:
|
||||
movzx eax, word [opcode]
|
||||
stdcall unknown_opcode, eax
|
||||
|
||||
.sw3_end:
|
||||
add word [P_C], 2
|
||||
jmp .sw1_end
|
||||
|
||||
.sw1_case_9000: ; TODO check; 9xy0: skip instruction if V[x] != V[y]
|
||||
movzx ecx, byte [x]
|
||||
mov al, byte [V + ecx]
|
||||
movzx ecx, byte [y]
|
||||
mov bl, byte [V + ecx]
|
||||
mov cx, 2
|
||||
cmp al, bl
|
||||
je @f
|
||||
mov cx, 4
|
||||
@@:
|
||||
add word [P_C], cx
|
||||
jmp .sw1_end
|
||||
|
||||
.sw1_case_A000: ; Annn: set I to address nnn
|
||||
mov ax, word [nnn]
|
||||
mov word [I], ax
|
||||
add word [P_C], 2
|
||||
jmp .sw1_end
|
||||
|
||||
.sw1_case_B000: ; Bnnn: jump to location nnn + V[0]
|
||||
mov ax, word [nnn]
|
||||
movzx bx, byte [V]
|
||||
add ax, bx
|
||||
mov word [P_C], ax
|
||||
jmp .sw1_end
|
||||
|
||||
.sw1_case_C000: ; TODO check; Cxkk: V[x] = random byte AND kk
|
||||
stdcall _rand
|
||||
and al, byte [kk]
|
||||
movzx ecx, byte [x]
|
||||
mov byte [V + ecx], al
|
||||
add word [P_C], 2
|
||||
jmp .sw1_end
|
||||
|
||||
.sw1_case_D000: ; TODO check; Dxyn: Display an n-byte sprite starting at memory location I at (Vx, Vy) on the screen, VF = collision
|
||||
movzx ecx, byte [x]
|
||||
movzx eax, byte [V + ecx]
|
||||
movzx ecx, byte [y]
|
||||
movzx ebx, byte [V + ecx]
|
||||
movzx ecx, byte [n]
|
||||
stdcall chip8_draw_sprite, eax, ebx, ecx
|
||||
mov byte [chip8_draw_flag], 1
|
||||
add word [P_C], 2
|
||||
jmp .sw1_end
|
||||
|
||||
.sw1_case_E000: ; TODO check; key-pressed events
|
||||
cmp byte [kk], 0x9E
|
||||
je .sw5_case_9E
|
||||
|
||||
cmp byte [kk], 0xA1
|
||||
je .sw5_case_A1
|
||||
|
||||
jmp .sw5_default
|
||||
|
||||
.sw5_case_9E: ; skip next instruction if key V[X] is pressed
|
||||
movzx ecx, byte [x]
|
||||
movzx edx, byte [V + ecx]
|
||||
mov bl, byte [key + edx]
|
||||
mov ax, 2
|
||||
cmp bl, 1
|
||||
jne .sw5_case_9E_endcheck
|
||||
mov ax, 4
|
||||
mov byte [key + edx], 0 ; release pressed key
|
||||
.sw5_case_9E_endcheck:
|
||||
add word [P_C], ax
|
||||
jmp .sw5_end
|
||||
|
||||
.sw5_case_A1: ; skip next instruction if key V[X] is NOT pressed
|
||||
movzx ecx, byte [x]
|
||||
movzx eax, byte [V + ecx]
|
||||
mov bl, byte [key + eax]
|
||||
mov ax, 4
|
||||
cmp bl, 1
|
||||
jne .sw5_case_A1_endcheck
|
||||
mov ax, 2
|
||||
.sw5_case_A1_endcheck:
|
||||
mov byte [key + edx], 0 ; release pressed key
|
||||
add word [P_C], ax
|
||||
jmp .sw5_end
|
||||
|
||||
.sw5_default:
|
||||
movzx eax, word [opcode]
|
||||
stdcall unknown_opcode, eax
|
||||
.sw5_end:
|
||||
jmp .sw1_end
|
||||
|
||||
.sw1_case_F000: ; misc
|
||||
cmp byte [kk], 0x07
|
||||
je .sw4_case_07
|
||||
|
||||
cmp byte [kk], 0x0A
|
||||
je .sw4_case_0A
|
||||
|
||||
cmp byte [kk], 0x15
|
||||
je .sw4_case_15
|
||||
|
||||
cmp byte [kk], 0x18
|
||||
je .sw4_case_18
|
||||
|
||||
cmp byte [kk], 0x1E
|
||||
je .sw4_case_1E
|
||||
|
||||
cmp byte [kk], 0x29
|
||||
je .sw4_case_29
|
||||
|
||||
cmp byte [kk], 0x33
|
||||
je .sw4_case_33
|
||||
|
||||
cmp byte [kk], 0x55
|
||||
je .sw4_case_55
|
||||
|
||||
cmp byte [kk], 0x65
|
||||
je .sw4_case_65
|
||||
|
||||
jmp .sw4_default
|
||||
|
||||
.sw4_case_07: ; TODO check; V[X] = delay timer
|
||||
mov al, byte [delay_timer]
|
||||
movzx ecx, byte [x]
|
||||
mov byte [V + ecx], al
|
||||
add word [P_C], 2
|
||||
jmp .sw4_end
|
||||
|
||||
.sw4_case_0A: ; TODO check; wait for key instruction
|
||||
;.sw4_case_0A_loop:
|
||||
;mcall 2
|
||||
;stdcall keyboard_update, eax
|
||||
xor ecx, ecx
|
||||
.sw4_case_0A_loop2:
|
||||
cmp ecx, KEY_SIZE
|
||||
jae .sw4_case_0A_loop_end ;
|
||||
|
||||
cmp byte [key + ecx], 1
|
||||
jne .sw4_case_0A_loop2_endcheck
|
||||
|
||||
movzx edx, byte [x]
|
||||
mov byte [V + edx], cl
|
||||
mov byte [key + ecx], 0 ; release pressed key
|
||||
;jmp .sw4_case_0A_loop_end
|
||||
add word [P_C], 2
|
||||
jmp .sw4_end
|
||||
|
||||
.sw4_case_0A_loop2_endcheck:
|
||||
inc ecx
|
||||
jmp .sw4_case_0A_loop2
|
||||
|
||||
;jmp .sw4_case_0A_loop
|
||||
.sw4_case_0A_loop_end:
|
||||
;add word [P_C], 2
|
||||
jmp .sw4_end
|
||||
|
||||
.sw4_case_15: ; TODO check; delay_timer = V[X]
|
||||
movzx ecx, byte [x]
|
||||
mov al, byte [V + ecx]
|
||||
mov byte [delay_timer], al
|
||||
add word [P_C], 2
|
||||
jmp .sw4_end
|
||||
|
||||
.sw4_case_18: ; TODO check; sound_timer = V[X]
|
||||
movzx ecx, byte [x]
|
||||
mov al, byte [V + ecx]
|
||||
mov byte [sound_timer], al
|
||||
add word [P_C], 2
|
||||
jmp .sw4_end
|
||||
|
||||
.sw4_case_1E: ; I = I + V[X]
|
||||
; V[0xF] = (I + V[x] > 0xfff) ? 1 : 0; (TODO?? (no this line in other chip8 emulators))
|
||||
movzx ecx, byte [x]
|
||||
movzx ax, byte [V + ecx]
|
||||
add word [I], ax
|
||||
add word [P_C], 2
|
||||
jmp .sw4_end
|
||||
|
||||
.sw4_case_29: ; TODO check; I = location of font for character V[X]
|
||||
movzx ecx, byte [x]
|
||||
movzx ax, byte [V + ecx]
|
||||
mov bx, FONTSET_BYTES_PER_CHAR
|
||||
mul bx
|
||||
mov word [I], ax
|
||||
add word [P_C], 2
|
||||
jmp .sw4_end
|
||||
|
||||
.sw4_case_33: ; TODO check; Store BCD for V[X] starting at address I
|
||||
movzx ecx, byte [x]
|
||||
movzx ebx, byte [V + ecx]
|
||||
|
||||
stdcall mod_div, ebx, 1000, 100
|
||||
movzx ecx, word [I]
|
||||
mov byte [memory + ecx], al
|
||||
|
||||
stdcall mod_div, ebx, 100, 10
|
||||
mov byte [memory + ecx + 1], al
|
||||
|
||||
stdcall mod_div, ebx, 10, 1
|
||||
mov byte [memory + ecx + 2], al
|
||||
|
||||
add word [P_C], 2
|
||||
jmp .sw4_end
|
||||
|
||||
.sw4_case_55: ; TODO check; Copy sprite from registers 0 to X into memory at address I
|
||||
movzx edx, word [I]
|
||||
xor ecx, ecx
|
||||
.for_sw4_1:
|
||||
movzx eax, byte [x]
|
||||
cmp ecx, eax
|
||||
ja .for_sw4_1_end
|
||||
|
||||
mov al, byte [V + ecx]
|
||||
mov byte [memory + ecx + edx], al
|
||||
|
||||
inc ecx
|
||||
jmp .for_sw4_1
|
||||
.for_sw4_1_end:
|
||||
movzx ax, byte [x]
|
||||
inc ax
|
||||
add word [I], ax
|
||||
|
||||
add word [P_C], 2
|
||||
jmp .sw4_end
|
||||
|
||||
.sw4_case_65: ; TODO check; Copy sprite from memory at address X into registers 0 to I
|
||||
movzx edx, word [I]
|
||||
xor ecx, ecx
|
||||
.for_sw4_2:
|
||||
movzx eax, byte [x]
|
||||
cmp ecx, eax
|
||||
ja .for_sw4_2_end
|
||||
|
||||
mov al, byte [memory + ecx + edx]
|
||||
mov byte [V + ecx], al
|
||||
|
||||
inc ecx
|
||||
jmp .for_sw4_2
|
||||
.for_sw4_2_end:
|
||||
movzx ax, byte [x]
|
||||
inc ax
|
||||
add word [I], ax
|
||||
|
||||
add word [P_C], 2
|
||||
jmp .sw4_end
|
||||
|
||||
.sw4_default:
|
||||
movzx eax, word [opcode]
|
||||
stdcall unknown_opcode, eax
|
||||
.sw4_end:
|
||||
jmp .sw1_end
|
||||
|
||||
.sw1_default:
|
||||
movzx eax, word [opcode]
|
||||
stdcall unknown_opcode, eax
|
||||
|
||||
.sw1_end:
|
||||
ret
|
||||
endp
|
||||
|
||||
|
||||
; tick the timers
|
||||
align 4
|
||||
proc chip8_tick stdcall
|
||||
; destroys: flags
|
||||
cmp byte [delay_timer], 0
|
||||
jz @f
|
||||
dec byte [delay_timer]
|
||||
@@:
|
||||
cmp byte [sound_timer], 0
|
||||
jz .ret
|
||||
dec byte [sound_timer]
|
||||
cmp byte [sound_timer], 0
|
||||
jnz @f
|
||||
DEBUGF DBG_INFO, "BEEP!\n"
|
||||
@@:
|
||||
.ret:
|
||||
ret
|
||||
endp
|
||||
|
||||
|
||||
; print unknown opcode error & exit
|
||||
align 4
|
||||
proc unknown_opcode stdcall, op:word
|
||||
DEBUGF DBG_ERR, "Error: unknown opcode 0x%x\n", [op]:4
|
||||
mov eax, -1
|
||||
int 0x40
|
||||
ret
|
||||
endp
|
||||
|
||||
; draw sprite from memory to gfx; TODO check;
|
||||
; if collision then V[0xF] = 1
|
||||
align 4
|
||||
proc chip8_draw_sprite stdcall, col: dword, row: dword, n: dword
|
||||
locals
|
||||
byte_index dd ?
|
||||
bit_index dd ?
|
||||
pixelp dd ?
|
||||
temp dd ?
|
||||
_byte db ?
|
||||
_bit db ?
|
||||
endl
|
||||
|
||||
DEBUGF DBG_INFO, "draw_sprite x = %u, y = %u, n = %u\n", [col], [row], [n]
|
||||
|
||||
movzx eax, word [I]
|
||||
mov ebx, dword [memory + eax]
|
||||
mov ecx, dword [memory + eax + 4]
|
||||
DEBUGF DBG_INFO, "I = %x, at I: %x, at I + 4: %x\n", eax, ebx, ecx
|
||||
|
||||
mov byte [V + 0xF], 0
|
||||
mov dword [byte_index], 0
|
||||
.for1:
|
||||
movzx eax, byte [n]
|
||||
cmp dword [byte_index], eax
|
||||
jae .for1_end
|
||||
|
||||
movzx ecx, word [I]
|
||||
add ecx, dword [byte_index]
|
||||
mov al, byte [memory + ecx]
|
||||
mov byte [_byte], al
|
||||
mov dword [bit_index], 0
|
||||
.for2:
|
||||
cmp dword [bit_index], 8
|
||||
jae .for2_end
|
||||
|
||||
mov ecx, dword [bit_index]
|
||||
mov al, byte [_byte]
|
||||
shr al, cl
|
||||
and al, 1
|
||||
mov byte [_bit], al
|
||||
|
||||
mov eax, dword [row]
|
||||
add eax, dword [byte_index]
|
||||
imul eax, GFX_COLS
|
||||
add eax, dword [col]
|
||||
add eax, 7
|
||||
sub eax, dword [bit_index]
|
||||
add eax, gfx
|
||||
mov dword [pixelp], eax
|
||||
|
||||
; DEBUGF DBG_INFO, "gfx = %x, pixelp = %x\n", gfx, edx
|
||||
|
||||
cmp byte [_bit], 1
|
||||
jne .if2_end
|
||||
|
||||
mov eax, dword [pixelp]
|
||||
cmp byte [eax], 1
|
||||
jne .if2_end
|
||||
|
||||
mov byte [V + 0xF], 1
|
||||
.if2_end:
|
||||
|
||||
mov ebx, dword [pixelp]
|
||||
mov al, byte [ebx]
|
||||
xor al, byte [_bit]
|
||||
mov byte [ebx], al
|
||||
|
||||
inc dword [bit_index]
|
||||
jmp .for2
|
||||
.for2_end:
|
||||
|
||||
inc dword [byte_index]
|
||||
jmp .for1
|
||||
.for1_end:
|
||||
|
||||
ret
|
||||
endp
|
65
programs/emulator/chip8/gui.inc
Normal file
65
programs/emulator/chip8/gui.inc
Normal file
@ -0,0 +1,65 @@
|
||||
; draw main window
|
||||
align 4
|
||||
proc draw_main_window stdcall
|
||||
mcall 12, 1 ; notify about draw beginning
|
||||
mcall 48, 3, sys_colors, sizeof.system_colors
|
||||
|
||||
mov edx, [sys_colors.work] ; background color
|
||||
or edx, 0x74000000 ; window type
|
||||
; DEBUGF DBG_INFO, "mainwindow w, h = %u, %u", GFX_COLS*GFX_PIX_SIZE + 8, GFX_ROWS*GFX_PIX_SIZE + 28
|
||||
mcall 0, <50, GFX_COLS*GFX_PIX_SIZE + 8>, <50, GFX_ROWS*GFX_PIX_SIZE + 28>, , , main_window_title ;
|
||||
|
||||
stdcall draw_screen
|
||||
|
||||
mcall 12, 2 ; notify about draw ending
|
||||
ret
|
||||
endp
|
||||
|
||||
; draw screen
|
||||
align 4
|
||||
proc draw_screen stdcall
|
||||
pushad
|
||||
locals
|
||||
row_ind dd ?
|
||||
col_ind dd ?
|
||||
color dd ?
|
||||
endl
|
||||
|
||||
xor esi, esi
|
||||
.loop1:
|
||||
cmp esi, GFX_SIZE
|
||||
jae .loop1_end
|
||||
xor edx, edx
|
||||
mov eax, esi
|
||||
mov ecx, GFX_COLS
|
||||
div ecx ; eax = row index, edx = col index
|
||||
mov dword [row_ind], eax
|
||||
mov dword [col_ind], edx
|
||||
mov dword [color], 0x80FFFFFF ; white
|
||||
cmp byte [esi + gfx], 0 ; check if cell is 0 or not 0
|
||||
jne @f
|
||||
mov dword [color], 0x80000000 ; black
|
||||
@@:
|
||||
mov ebx, dword [col_ind]
|
||||
imul ebx, GFX_PIX_SIZE
|
||||
;add ebx, WINDOW_BORDER
|
||||
shl ebx, 16
|
||||
add ebx, GFX_PIX_SIZE
|
||||
|
||||
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
|
||||
mov edx, dword [color]
|
||||
int 0x40
|
||||
|
||||
inc esi
|
||||
jmp .loop1
|
||||
|
||||
.loop1_end:
|
||||
popad
|
||||
ret
|
||||
endp
|
12
programs/emulator/chip8/readme.txt
Normal file
12
programs/emulator/chip8/readme.txt
Normal file
@ -0,0 +1,12 @@
|
||||
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.chip8
|
||||
|
||||
P.S. ROMs from https://github.com/dmatlack/chip8/tree/master/roms
|
BIN
programs/emulator/chip8/roms/chip8.ch8
Normal file
BIN
programs/emulator/chip8/roms/chip8.ch8
Normal file
Binary file not shown.
BIN
programs/emulator/chip8/roms/clock.ch8
Normal file
BIN
programs/emulator/chip8/roms/clock.ch8
Normal file
Binary file not shown.
BIN
programs/emulator/chip8/roms/ibm.ch8
Normal file
BIN
programs/emulator/chip8/roms/ibm.ch8
Normal file
Binary file not shown.
BIN
programs/emulator/chip8/roms/invaders1.ch8
Normal file
BIN
programs/emulator/chip8/roms/invaders1.ch8
Normal file
Binary file not shown.
BIN
programs/emulator/chip8/roms/keytest.ch8
Normal file
BIN
programs/emulator/chip8/roms/keytest.ch8
Normal file
Binary file not shown.
BIN
programs/emulator/chip8/roms/life.ch8
Normal file
BIN
programs/emulator/chip8/roms/life.ch8
Normal file
Binary file not shown.
BIN
programs/emulator/chip8/roms/maze_alt.ch8
Normal file
BIN
programs/emulator/chip8/roms/maze_alt.ch8
Normal file
Binary file not shown.
BIN
programs/emulator/chip8/roms/pong1.ch8
Normal file
BIN
programs/emulator/chip8/roms/pong1.ch8
Normal file
Binary file not shown.
BIN
programs/emulator/chip8/roms/pong2.ch8
Normal file
BIN
programs/emulator/chip8/roms/pong2.ch8
Normal file
Binary file not shown.
BIN
programs/emulator/chip8/roms/pong3.ch8
Normal file
BIN
programs/emulator/chip8/roms/pong3.ch8
Normal file
Binary file not shown.
BIN
programs/emulator/chip8/roms/rnd.ch8
Normal file
BIN
programs/emulator/chip8/roms/rnd.ch8
Normal file
Binary file not shown.
BIN
programs/emulator/chip8/roms/sqrt.ch8
Normal file
BIN
programs/emulator/chip8/roms/sqrt.ch8
Normal file
Binary file not shown.
BIN
programs/emulator/chip8/roms/test_opcode.ch8
Normal file
BIN
programs/emulator/chip8/roms/test_opcode.ch8
Normal file
Binary file not shown.
BIN
programs/emulator/chip8/roms/tetris1.ch8
Normal file
BIN
programs/emulator/chip8/roms/tetris1.ch8
Normal file
Binary file not shown.
112
programs/emulator/chip8/utils.inc
Normal file
112
programs/emulator/chip8/utils.inc
Normal file
@ -0,0 +1,112 @@
|
||||
; note: proc that defines without stdcall, call using "call"
|
||||
; note: by stdcall convention callee is responsible for cleaning up the stack,
|
||||
; arguments are pushed onto the stack in right-to-left order
|
||||
align 4
|
||||
proc _memset stdcall, dest:dword, val:byte, cnt:dword ; doesnt clobber any registers
|
||||
;DEBUGF DBG_INFO, "memset(%x, %u, %u)\n", [dest], [val], [cnt]
|
||||
push eax ecx edi
|
||||
mov edi, dword [dest]
|
||||
mov al, byte [val]
|
||||
mov ecx, dword [cnt]
|
||||
rep stosb
|
||||
pop edi ecx eax
|
||||
ret
|
||||
endp
|
||||
|
||||
align 4
|
||||
proc _srand stdcall, seed:dword
|
||||
push eax
|
||||
;DEBUGF DBG_INFO, "_srand: next_rand = %u\n", [next_rand]
|
||||
mov eax, dword [seed]
|
||||
mov dword [next_rand], eax
|
||||
pop eax
|
||||
ret
|
||||
endp
|
||||
|
||||
align 4
|
||||
proc _rand stdcall
|
||||
push ebx edx
|
||||
;DEBUGF DBG_INFO, "_rand: next_rand = %u\n", [next_rand]
|
||||
mov eax, dword [next_rand]
|
||||
mov ebx, 214013
|
||||
mul ebx
|
||||
add eax, 2531011
|
||||
mov dword [next_rand], eax
|
||||
shr eax, 16
|
||||
and eax, 0x7fff
|
||||
pop edx ebx
|
||||
ret
|
||||
endp
|
||||
|
||||
align 4
|
||||
proc _getseed stdcall
|
||||
push edx
|
||||
rdtsc
|
||||
xor eax, edx
|
||||
pop edx
|
||||
ret
|
||||
endp
|
||||
|
||||
; calculate (num % num_mod) / num_div
|
||||
align 4
|
||||
proc mod_div stdcall, num: dword, num_mod: dword, num_div:dword ; TODO check
|
||||
; in: num - number
|
||||
; num_mod - first divisor
|
||||
; num_div - second divisor
|
||||
; out: eax - the result
|
||||
; destroys: mb flags
|
||||
push ecx edx
|
||||
xor edx, edx
|
||||
mov eax, dword [num]
|
||||
mov ecx, dword [num_mod]
|
||||
div ecx
|
||||
|
||||
mov eax, edx
|
||||
xor edx, edx
|
||||
mov ecx, dword [num_div]
|
||||
div ecx
|
||||
pop edx ecx
|
||||
ret
|
||||
endp
|
||||
|
||||
; update key map; TODO impl;
|
||||
align 4
|
||||
proc keyboard_update stdcall, _code: dword
|
||||
push eax ebx ecx edx
|
||||
mov eax, dword [_code]
|
||||
|
||||
mov edx, eax
|
||||
and edx, 0xF000
|
||||
|
||||
mov ebx, eax
|
||||
and ebx, 0x0F00
|
||||
shr ebx, 8
|
||||
|
||||
xor ecx, ecx
|
||||
cmp edx, 0x6000
|
||||
jne .if1_end
|
||||
mov ecx, 0x9
|
||||
.if1_end:
|
||||
add ebx, ecx
|
||||
; DEBUGF DBG_INFO, "keynum %x\n", ebx
|
||||
cmp ebx, KEY_SIZE
|
||||
jae .ret
|
||||
DEBUGF DBG_INFO, "keynum %x\n", ebx
|
||||
mov byte [key + ebx], 1
|
||||
|
||||
.ret:
|
||||
pop edx ecx ebx eax
|
||||
ret
|
||||
endp
|
||||
|
||||
; ; get seconds count
|
||||
; align 4
|
||||
; proc get_clock stdcall
|
||||
; ; out: eax - time from system start in 10^-2 secs
|
||||
; push ebx
|
||||
; mov eax, 26
|
||||
; mov ebx, 9
|
||||
; int 0x40
|
||||
; pop ebx
|
||||
; ret
|
||||
; endp
|
Loading…
Reference in New Issue
Block a user