mirror of
https://github.com/shadlyd15/NesUEFI
synced 2024-11-21 20:31:23 +03:00
Keyboard direct read from port 60h
This commit is contained in:
parent
ac81c1c17c
commit
6a1464ce1c
@ -40,6 +40,8 @@ OVMF_DIR = ../OVMF
|
||||
CC = gcc
|
||||
OBJCOPY = objcopy
|
||||
|
||||
BUILDDIR = bin
|
||||
|
||||
%.efi: %.so
|
||||
$(OBJCOPY) -j .text -j .sdata -j .data -j .dynamic -j .dynsym -j .rel \
|
||||
-j .rela -j .reloc -S --target=$(FORMAT) $*.so $@
|
||||
|
Binary file not shown.
@ -175,8 +175,7 @@ void graphics_clear_framebuffer(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop){
|
||||
}
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
graphics_draw_bitmap( EFI_GRAPHICS_OUTPUT_PROTOCOL *gop,
|
||||
EFI_STATUS graphics_draw_bitmap( EFI_GRAPHICS_OUTPUT_PROTOCOL *gop,
|
||||
int x_offset,
|
||||
int y_offset,
|
||||
EFI_HANDLE *bmp_buffer){
|
||||
|
@ -5,30 +5,40 @@
|
||||
#include "kernel.h"
|
||||
#include "keyboard.h"
|
||||
|
||||
EFI_STATUS keyboard_poll(){
|
||||
if(!kernel.keyboard_event_handler) return EFI_INVALID_PARAMETER;
|
||||
static char key_state[128],key_pressed[128];
|
||||
|
||||
EFI_INPUT_KEY efi_input_key;
|
||||
EFI_STATUS rc;
|
||||
while(1){
|
||||
rc = uefi_call_wrapper(ST->ConIn->ReadKeyStroke, 2, ST->ConIn, &efi_input_key);
|
||||
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;
|
||||
static inline UINT8 inportb(UINT16 port) {
|
||||
UINT8 r;
|
||||
asm("inb %1, %0" : "=a" (r) : "dN" (port));
|
||||
return r;
|
||||
}
|
||||
|
||||
EFI_STATUS keyboard_init(void (*handler)(UINT32 key)){
|
||||
if(!handler) return EFI_INVALID_PARAMETER;
|
||||
kernel.keyboard_event_handler = handler;
|
||||
memset(key_state, 0x00, 128);
|
||||
memset(key_pressed, 0x00, 128);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,8 @@
|
||||
#include <efi.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
EFI_STATUS keyboard_poll();
|
||||
bool get_key(int scancode);
|
||||
void keyboard_poll();
|
||||
EFI_STATUS keyboard_init(void (*handler)(UINT32 key));
|
||||
|
||||
#endif
|
@ -1,14 +1,14 @@
|
||||
#define NES_FPS 60
|
||||
#define NES_SCREEN_WIDTH 256
|
||||
#define NES_SCREEN_HEIGHT 240
|
||||
#define NES_SCREEN_ZOOM 3
|
||||
#define NES_SCREEN_ZOOM 2
|
||||
|
||||
#define KEY_A 0x6b // k
|
||||
#define KEY_B 0x6a // j
|
||||
#define KEY_SELECT 0x75 // u
|
||||
#define KEY_START 0x69 // i
|
||||
#define KEY_UP 0x77 // w
|
||||
#define KEY_DOWN 0x73 // s
|
||||
#define KEY_LEFT 0x61 // a
|
||||
#define KEY_RIGHT 0x64 // d
|
||||
#define KEY_REBOOT 0x72 // r
|
||||
#define KEY_A 37 // k
|
||||
#define KEY_B 36 // j
|
||||
#define KEY_SELECT 22 // u
|
||||
#define KEY_START 23 // i
|
||||
#define KEY_UP 17 // w
|
||||
#define KEY_DOWN 31 // s
|
||||
#define KEY_LEFT 30 // a
|
||||
#define KEY_RIGHT 32 // d
|
||||
#define KEY_REBOOT 19 // r
|
@ -3,7 +3,7 @@
|
||||
#include "../ui/adafruit_gfx.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];
|
||||
|
||||
|
||||
@ -21,13 +21,13 @@ void nes_set_bg(int colour){
|
||||
|
||||
void nes_gfx_swap(){
|
||||
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 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,
|
||||
y_offset + (i/NES_SCREEN_WIDTH)*NES_SCREEN_ZOOM,
|
||||
NES_SCREEN_ZOOM, NES_SCREEN_ZOOM, _nes_screen_buffer_current[i]);
|
||||
}
|
||||
// }
|
||||
}
|
||||
}
|
@ -4,70 +4,28 @@
|
||||
#include "../emulator/key.h"
|
||||
#include "../driver/keyboard.h"
|
||||
|
||||
|
||||
bool _key_state[10];
|
||||
|
||||
void hal_nes_key_clear(){
|
||||
memset(_key_state, 0x00, sizeof(_key_state));
|
||||
}
|
||||
|
||||
void hal_nes_ctrl_key_clear(){
|
||||
_key_state[NES_KEY_UP] = false;
|
||||
_key_state[NES_KEY_LEFT] = false;
|
||||
_key_state[NES_KEY_DOWN] = false;
|
||||
_key_state[NES_KEY_RIGHT] = false;
|
||||
_key_state[NES_KEY_SELECT] = false;
|
||||
_key_state[NES_KEY_START] = false;
|
||||
// _key_state[NES_KEY_B] = false; // Otherwise Mario will not jump long
|
||||
_key_state[NES_KEY_A] = false;
|
||||
_key_state[NES_KEY_REBOOT] = false;
|
||||
}
|
||||
|
||||
void hal_nes_set_key(uint32_t key){
|
||||
hal_nes_key_clear();
|
||||
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;
|
||||
|
||||
int hal_nes_get_key(uint16_t key){
|
||||
switch (key)
|
||||
{
|
||||
case 0: // On / Off
|
||||
return 1;
|
||||
case 1: // A
|
||||
return get_key(37);//K
|
||||
case 2: // B
|
||||
return get_key(36);;//J
|
||||
case 3: // SELECT
|
||||
return get_key(22);//U
|
||||
case 4: // START
|
||||
return get_key(23);//I
|
||||
case 5: // UP
|
||||
return get_key(17);//W
|
||||
case 6: // DOWN
|
||||
return get_key(31);//S
|
||||
case 7: // LEFT
|
||||
return get_key(30);//A
|
||||
case 8: // RIGHT
|
||||
return get_key(32);//D
|
||||
default:
|
||||
break;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
bool hal_nes_get_key(uint16_t key){
|
||||
if(!key) return true; // Power default on
|
||||
return _key_state[key];
|
||||
}
|
@ -6,22 +6,6 @@
|
||||
|
||||
#include "nes.h"
|
||||
|
||||
typedef enum nes_key_t {
|
||||
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();
|
||||
int hal_nes_get_key(uint16_t key);
|
||||
|
||||
#endif
|
@ -55,11 +55,9 @@ efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *systab){
|
||||
list_file_browser();
|
||||
keyboard_init(ui_key_handler);
|
||||
|
||||
#if 1
|
||||
|
||||
unsigned long last_frame = 0;
|
||||
while(1){
|
||||
rc = keyboard_poll();
|
||||
keyboard_poll();
|
||||
const unsigned long now = (unsigned long)timer_ticks();
|
||||
if ((now - last_frame) > TICK_PER_SECOND/NES_FPS){
|
||||
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);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
BIN
NesUEFI/main.efi
BIN
NesUEFI/main.efi
Binary file not shown.
@ -163,12 +163,11 @@ void render_splash_screen(){
|
||||
}
|
||||
|
||||
void ui_key_handler(uint32_t key){
|
||||
if (g_ui_state == UI_STATE_MENU){
|
||||
if(g_ui_state == UI_STATE_MENU){
|
||||
render_menu(key);
|
||||
}
|
||||
else if (g_ui_state == UI_STATE_PLAY){
|
||||
hal_nes_set_key(key);
|
||||
if (key == 'r'){
|
||||
else if(g_ui_state == UI_STATE_PLAY){
|
||||
if(key == KEY_REBOOT){
|
||||
g_ui_state = UI_STATE_SPLASH;
|
||||
}
|
||||
}
|
||||
|
Binary file not shown.
@ -1,9 +1,8 @@
|
||||
|
||||
# NesUEFI - A bootable NES Emulator running on UEFI
|
||||
|
||||
![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
|
||||
## 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.
|
||||
- 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**
|
||||
- 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
|
||||
Video Coming Soon
|
||||
@ -87,8 +87,8 @@ Video Coming Soon
|
||||
## Known Issues
|
||||
- Mappers are not implemented 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.
|
||||
- NesUEFI only supports PS/2 keyboard. Most of the laptop keyboards should support it.
|
||||
|
||||
## 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.
|
||||
|
Loading…
Reference in New Issue
Block a user