Keyboard direct read from port 60h

This commit is contained in:
shadlyd15 2022-05-08 04:28:09 +02:00
parent ac81c1c17c
commit 6a1464ce1c
14 changed files with 79 additions and 130 deletions

View File

@ -40,6 +40,8 @@ OVMF_DIR = ../OVMF
CC = gcc CC = gcc
OBJCOPY = objcopy OBJCOPY = objcopy
BUILDDIR = bin
%.efi: %.so %.efi: %.so
$(OBJCOPY) -j .text -j .sdata -j .data -j .dynamic -j .dynsym -j .rel \ $(OBJCOPY) -j .text -j .sdata -j .data -j .dynamic -j .dynsym -j .rel \
-j .rela -j .reloc -S --target=$(FORMAT) $*.so $@ -j .rela -j .reloc -S --target=$(FORMAT) $*.so $@

Binary file not shown.

View File

@ -175,8 +175,7 @@ void graphics_clear_framebuffer(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop){
} }
} }
EFI_STATUS EFI_STATUS graphics_draw_bitmap( EFI_GRAPHICS_OUTPUT_PROTOCOL *gop,
graphics_draw_bitmap( EFI_GRAPHICS_OUTPUT_PROTOCOL *gop,
int x_offset, int x_offset,
int y_offset, int y_offset,
EFI_HANDLE *bmp_buffer){ EFI_HANDLE *bmp_buffer){

View File

@ -5,30 +5,40 @@
#include "kernel.h" #include "kernel.h"
#include "keyboard.h" #include "keyboard.h"
EFI_STATUS keyboard_poll(){ static char key_state[128],key_pressed[128];
if(!kernel.keyboard_event_handler) return EFI_INVALID_PARAMETER;
EFI_INPUT_KEY efi_input_key; static inline UINT8 inportb(UINT16 port) {
EFI_STATUS rc; UINT8 r;
while(1){ asm("inb %1, %0" : "=a" (r) : "dN" (port));
rc = uefi_call_wrapper(ST->ConIn->ReadKeyStroke, 2, ST->ConIn, &efi_input_key); return r;
if(rc == EFI_SUCCESS){
if(efi_input_key.UnicodeChar){
kernel.keyboard_event_handler(efi_input_key.UnicodeChar);
} else{
kernel.keyboard_event_handler(efi_input_key.ScanCode);
}
}
else {
return rc;
}
}
return rc;
} }
EFI_STATUS keyboard_init(void (*handler)(UINT32 key)){ EFI_STATUS keyboard_init(void (*handler)(UINT32 key)){
if(!handler) return EFI_INVALID_PARAMETER; if(!handler) return EFI_INVALID_PARAMETER;
kernel.keyboard_event_handler = handler; kernel.keyboard_event_handler = handler;
memset(key_state, 0x00, 128);
memset(key_pressed, 0x00, 128);
return EFI_SUCCESS; return EFI_SUCCESS;
} }
bool get_key(int scancode) {
bool res;
res = key_state[scancode] | key_pressed[scancode];
key_pressed[scancode]=0;
return res;
}
void keyboard_poll() {
UINT8 scancode = (UINT8) inportb(0x60);
if (scancode & 0x80){
scancode &= 0x7f;
if(key_state[scancode] == 1){
kernel.keyboard_event_handler(scancode);
}
key_state[scancode]=0;
}
else {
key_state[scancode]=1;
key_pressed[scancode]=1;
}
}

View File

@ -4,7 +4,8 @@
#include <efi.h> #include <efi.h>
#include <stdbool.h> #include <stdbool.h>
EFI_STATUS keyboard_poll(); bool get_key(int scancode);
void keyboard_poll();
EFI_STATUS keyboard_init(void (*handler)(UINT32 key)); EFI_STATUS keyboard_init(void (*handler)(UINT32 key));
#endif #endif

View File

@ -1,14 +1,14 @@
#define NES_FPS 60 #define NES_FPS 60
#define NES_SCREEN_WIDTH 256 #define NES_SCREEN_WIDTH 256
#define NES_SCREEN_HEIGHT 240 #define NES_SCREEN_HEIGHT 240
#define NES_SCREEN_ZOOM 3 #define NES_SCREEN_ZOOM 2
#define KEY_A 0x6b // k #define KEY_A 37 // k
#define KEY_B 0x6a // j #define KEY_B 36 // j
#define KEY_SELECT 0x75 // u #define KEY_SELECT 22 // u
#define KEY_START 0x69 // i #define KEY_START 23 // i
#define KEY_UP 0x77 // w #define KEY_UP 17 // w
#define KEY_DOWN 0x73 // s #define KEY_DOWN 31 // s
#define KEY_LEFT 0x61 // a #define KEY_LEFT 30 // a
#define KEY_RIGHT 0x64 // d #define KEY_RIGHT 32 // d
#define KEY_REBOOT 0x72 // r #define KEY_REBOOT 19 // r

View File

@ -3,7 +3,7 @@
#include "../ui/adafruit_gfx.h" #include "../ui/adafruit_gfx.h"
#include <string.h> #include <string.h>
UINT32 _nes_screen_buffer_prev[(NES_SCREEN_WIDTH) * (NES_SCREEN_HEIGHT) + 1]; // UINT32 _nes_screen_buffer_prev[(NES_SCREEN_WIDTH) * (NES_SCREEN_HEIGHT) + 1];
UINT32 _nes_screen_buffer_current[(NES_SCREEN_WIDTH) * (NES_SCREEN_HEIGHT) + 1]; UINT32 _nes_screen_buffer_current[(NES_SCREEN_WIDTH) * (NES_SCREEN_HEIGHT) + 1];
@ -21,13 +21,13 @@ void nes_set_bg(int colour){
void nes_gfx_swap(){ void nes_gfx_swap(){
for (int i = 0; i < NES_SCREEN_WIDTH*NES_SCREEN_HEIGHT; ++i){ for (int i = 0; i < NES_SCREEN_WIDTH*NES_SCREEN_HEIGHT; ++i){
if((_nes_screen_buffer_current[i] != _nes_screen_buffer_prev[i]) ){ // if((_nes_screen_buffer_current[i] != _nes_screen_buffer_prev[i]) ){
int x_offset = (kernel.graphics->Mode->Info->HorizontalResolution - NES_SCREEN_WIDTH*NES_SCREEN_ZOOM)/2 +1; int x_offset = (kernel.graphics->Mode->Info->HorizontalResolution - NES_SCREEN_WIDTH*NES_SCREEN_ZOOM)/2 +1;
int y_offset = (kernel.graphics->Mode->Info->VerticalResolution - NES_SCREEN_HEIGHT*NES_SCREEN_ZOOM)/2; int y_offset = (kernel.graphics->Mode->Info->VerticalResolution - NES_SCREEN_HEIGHT*NES_SCREEN_ZOOM)/2;
_nes_screen_buffer_prev[i] = _nes_screen_buffer_current[i]; // _nes_screen_buffer_prev[i] = _nes_screen_buffer_current[i];
fillRect( x_offset + (i%NES_SCREEN_WIDTH)*NES_SCREEN_ZOOM, fillRect( x_offset + (i%NES_SCREEN_WIDTH)*NES_SCREEN_ZOOM,
y_offset + (i/NES_SCREEN_WIDTH)*NES_SCREEN_ZOOM, y_offset + (i/NES_SCREEN_WIDTH)*NES_SCREEN_ZOOM,
NES_SCREEN_ZOOM, NES_SCREEN_ZOOM, _nes_screen_buffer_current[i]); NES_SCREEN_ZOOM, NES_SCREEN_ZOOM, _nes_screen_buffer_current[i]);
} // }
} }
} }

View File

@ -4,70 +4,28 @@
#include "../emulator/key.h" #include "../emulator/key.h"
#include "../driver/keyboard.h" #include "../driver/keyboard.h"
int hal_nes_get_key(uint16_t key){
bool _key_state[10]; switch (key)
{
void hal_nes_key_clear(){ case 0: // On / Off
memset(_key_state, 0x00, sizeof(_key_state)); return 1;
} case 1: // A
return get_key(37);//K
void hal_nes_ctrl_key_clear(){ case 2: // B
_key_state[NES_KEY_UP] = false; return get_key(36);;//J
_key_state[NES_KEY_LEFT] = false; case 3: // SELECT
_key_state[NES_KEY_DOWN] = false; return get_key(22);//U
_key_state[NES_KEY_RIGHT] = false; case 4: // START
_key_state[NES_KEY_SELECT] = false; return get_key(23);//I
_key_state[NES_KEY_START] = false; case 5: // UP
// _key_state[NES_KEY_B] = false; // Otherwise Mario will not jump long return get_key(17);//W
_key_state[NES_KEY_A] = false; case 6: // DOWN
_key_state[NES_KEY_REBOOT] = false; return get_key(31);//S
} case 7: // LEFT
return get_key(30);//A
void hal_nes_set_key(uint32_t key){ case 8: // RIGHT
hal_nes_key_clear(); return get_key(32);//D
switch(key){
case KEY_UP:
_key_state[NES_KEY_UP] = true;
break;
case KEY_LEFT:
_key_state[NES_KEY_LEFT] = true;
break;
case KEY_DOWN:
_key_state[NES_KEY_DOWN] = true;
break;
case KEY_RIGHT:
_key_state[NES_KEY_RIGHT] = true;
break;
case KEY_SELECT:
_key_state[NES_KEY_SELECT] = true;
break;
case KEY_START:
_key_state[NES_KEY_START] = true;
break;
case KEY_B:
_key_state[NES_KEY_B] = true;
break;
case KEY_A:
_key_state[NES_KEY_A] = true;
break;
case KEY_REBOOT:
_key_state[NES_KEY_REBOOT] = true;
break;
default: default:
break; return 1;
} }
}
bool hal_nes_get_key(uint16_t key){
if(!key) return true; // Power default on
return _key_state[key];
} }

View File

@ -6,22 +6,6 @@
#include "nes.h" #include "nes.h"
typedef enum nes_key_t { int hal_nes_get_key(uint16_t key);
NES_KEY_POWER,
NES_KEY_A,
NES_KEY_B,
NES_KEY_SELECT,
NES_KEY_START,
NES_KEY_UP,
NES_KEY_DOWN,
NES_KEY_LEFT,
NES_KEY_RIGHT,
NES_KEY_REBOOT
} nes_key_t;
void hal_nes_key_clear();
void hal_nes_set_key(uint32_t key);
bool hal_nes_get_key(uint16_t key);
void hal_nes_ctrl_key_clear();
#endif #endif

View File

@ -55,11 +55,9 @@ efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *systab){
list_file_browser(); list_file_browser();
keyboard_init(ui_key_handler); keyboard_init(ui_key_handler);
#if 1
unsigned long last_frame = 0; unsigned long last_frame = 0;
while(1){ while(1){
rc = keyboard_poll(); keyboard_poll();
const unsigned long now = (unsigned long)timer_ticks(); const unsigned long now = (unsigned long)timer_ticks();
if ((now - last_frame) > TICK_PER_SECOND/NES_FPS){ if ((now - last_frame) > TICK_PER_SECOND/NES_FPS){
last_frame = now; last_frame = now;
@ -70,8 +68,6 @@ efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *systab){
} }
} }
#endif // #if 1
Print(L"EFI EXIT : %r\n", rc); Print(L"EFI EXIT : %r\n", rc);
return EFI_SUCCESS; return EFI_SUCCESS;
} }

Binary file not shown.

View File

@ -163,12 +163,11 @@ void render_splash_screen(){
} }
void ui_key_handler(uint32_t key){ void ui_key_handler(uint32_t key){
if (g_ui_state == UI_STATE_MENU){ if(g_ui_state == UI_STATE_MENU){
render_menu(key); render_menu(key);
} }
else if (g_ui_state == UI_STATE_PLAY){ else if(g_ui_state == UI_STATE_PLAY){
hal_nes_set_key(key); if(key == KEY_REBOOT){
if (key == 'r'){
g_ui_state = UI_STATE_SPLASH; g_ui_state = UI_STATE_SPLASH;
} }
} }

Binary file not shown.

View File

@ -1,9 +1,8 @@
# NesUEFI - A bootable NES Emulator running on UEFI # NesUEFI - A bootable NES Emulator running on UEFI
![alt text](/splash.bmp "splash") ![alt text](/splash.bmp "splash")
**NesUEFI** is a **NES Emulator running without an operating system** directly on **Unified Extensible Firmware Interface (UEFI).** Simply place **NesUEFI** and nes roms in a pendrive and play. **NesUEFI file browser** will show the available roms. The core drivers (Graphics, File System, Keyboard, Timer) are written in c using **GNU-EFI** and the emulator part is a port of [LiteNES](https://github.com/NJU-ProjectN/LiteNES). Adafruit GFX Graphics Library is ported for GNU-EFI ecosystem in C for high level graphics operations and text rendering. **NesUEFI** is a **NES Emulator running without an operating system** directly on **Unified Extensible Firmware Interface (UEFI).** Simply place **NesUEFI** and nes roms in a pendrive and play. **NesUEFI file browser** will show the available roms. The core drivers (Graphics, File System, Timer) are written in c using **GNU-EFI** and the emulator part is a port of [LiteNES](https://github.com/NJU-ProjectN/LiteNES). Adafruit GFX Graphics Library is ported for GNU-EFI ecosystem in C for high level graphics operations and text rendering.
# Compile NesUEFI # Compile NesUEFI
## Requirements ## Requirements
@ -68,7 +67,8 @@ Technically NesUEFI should not mess with your system. But you should at least kn
- Copy **bootx64.efi** or **bootia32.efi** to boot folder. - Copy **bootx64.efi** or **bootia32.efi** to boot folder.
- For **64 bit** application the pendrive should look like this : **/efi/boot/bootx64.efi** - For **64 bit** application the pendrive should look like this : **/efi/boot/bootx64.efi**
- For **32 bit** application the pendrive should look like this : **/efi/boot/bootia32.efi** - For **32 bit** application the pendrive should look like this : **/efi/boot/bootia32.efi**
- Simply place your roms in the pendrive. **NesUEFI file browser** will show the available roms. - Copy **splash.bmp** on the root folder of the pendrive
- Copy your .nes roms in the pendrive.
# Demo on Real Hardware # Demo on Real Hardware
Video Coming Soon Video Coming Soon
@ -87,8 +87,8 @@ Video Coming Soon
## Known Issues ## Known Issues
- Mappers are not implemented yet. - Mappers are not implemented yet.
- It does not support Audio emulation yet. - It does not support Audio emulation yet.
- EFI only have a simple text input protocol. So it only recognizes input character but not keystroke. So key press and release events are emulated by holding down a key until a new key is pressed. Otherwise we can not emulate multi key press events.
- Only single player is supported. - Only single player is supported.
- NesUEFI only supports PS/2 keyboard. Most of the laptop keyboards should support it.
## Tested Games ## Tested Games
Below games are currently tested on real hardware. But NesUEFI is not only limited to these games. It should technically run all the classic roms that use mapper 0. [Here](https://nesdir.github.io/mapper0.html) is a list of mapper 0 games. Below games are currently tested on real hardware. But NesUEFI is not only limited to these games. It should technically run all the classic roms that use mapper 0. [Here](https://nesdir.github.io/mapper0.html) is a list of mapper 0 games.