From 8521e5afe90635cd5e08fd95d466187c6ef8b051 Mon Sep 17 00:00:00 2001 From: sorgelig Date: Sat, 29 Jul 2017 01:57:22 +0800 Subject: [PATCH 01/17] Support for bidirectional PS/2 protocol. --- user_io.c | 104 +++++++++++++++++++++++++++++++++++++++++++++++++++--- user_io.h | 3 +- 2 files changed, 101 insertions(+), 6 deletions(-) diff --git a/user_io.c b/user_io.c index 80b36a4..bb679c6 100644 --- a/user_io.c +++ b/user_io.c @@ -456,17 +456,36 @@ uint16_t user_io_sd_get_status(uint32_t *lba) } // read 8 bit keyboard LEDs status from FPGA -uint8_t user_io_kbdled_get_status(void) +uint16_t user_io_kbdled_get_status(void) { - uint8_t c; + uint16_t c; spi_uio_cmd_cont(UIO_GET_KBD_LED); - c = spi_in(); + c = spi_w(0); DisableIO(); return c; } +uint8_t user_io_ps2_ctl(uint8_t *kbd_ctl, uint8_t *mouse_ctl) +{ + uint16_t c; + uint8_t res = 0; + + spi_uio_cmd_cont(UIO_PS2_CTL); + + c = spi_w(0); + if (kbd_ctl) *kbd_ctl = (uint8_t)c; + res |= ((c >> 8) & 1); + + c = spi_w(0); + if (mouse_ctl) *mouse_ctl = (uint8_t)c; + res |= ((c >> 7) & 2); + + DisableIO(); + return res; +} + // read 32 bit ethernet status word from FPGA uint32_t user_io_eth_get_status(void) { @@ -749,6 +768,12 @@ void __inline diskled_on() diskled_is_on = 1; } +void kbd_reply(char code) +{ + printf("kbd_reply = 0x%02X\n", code); + spi_uio_cmd8(UIO_KEYBOARD, code); +} + void user_io_poll() { if ((core_type != CORE_TYPE_MINIMIG2) && @@ -845,10 +870,10 @@ void user_io_poll() if (core_type == CORE_TYPE_8BIT) { + /* unsigned char c = 1, f, p = 0; // check for serial data to be sent - // check for incoming serial data. this is directly forwarded to the // arm rs232 and mixes with debug output. spi_uio_cmd_cont(UIO_SIO_IN); @@ -869,6 +894,7 @@ void user_io_poll() iprintf("\033[0m"); } DisableIO(); + */ // sd card emulation { @@ -1141,10 +1167,78 @@ void user_io_poll() if (core_type == CORE_TYPE_ARCHIE) archie_poll(); + static uint8_t use_ps2ctl = 0; + static uint8_t leds = 0; + if(use_ps2ctl) + { + static uint8_t kbd_cmd = 0; + static uint8_t kbd_byte = 0; + + leds |= (KBD_LED_FLAG_STATUS | KBD_LED_CAPS_CONTROL); + + uint8_t kbd_ctl, mouse_ctl; + uint8_t ps2ctl = user_io_ps2_ctl(&kbd_ctl, &mouse_ctl); + + if (ps2ctl & 1) + { + printf("kbd_ctl = 0x%02X\n", kbd_ctl); + if (!kbd_byte) + { + kbd_cmd = kbd_ctl; + switch (kbd_cmd) + { + case 0xff: + kbd_reply(0xFA); + kbd_reply(0xAA); + break; + + case 0xf4: + case 0xf5: + case 0xfa: + kbd_reply(0xFA); + break; + + case 0xed: + kbd_reply(0xFA); + kbd_byte++; + break; + + default: + kbd_reply(0xFE); + break; + } + } + else + { + switch (kbd_cmd) + { + case 0xed: + kbd_reply(0xFA); + kbd_byte = 0; + + if (kbd_ctl & 4) leds |= KBD_LED_CAPS_STATUS; + else leds &= ~KBD_LED_CAPS_STATUS; + + break; + + default: + kbd_byte = 0; + break; + } + } + } + } + if (CheckTimer(led_timer)) { led_timer = GetTimer(LED_FREQ); - uint8_t leds = user_io_kbdled_get_status(); + if (!use_ps2ctl) + { + uint16_t s = user_io_kbdled_get_status(); + if(s & 0x100) use_ps2ctl = 1; + if (!use_ps2ctl) leds = (uint8_t)s; + } + if ((leds & KBD_LED_FLAG_MASK) != KBD_LED_FLAG_STATUS) leds = 0; if ((keyboard_leds & KBD_LED_CAPS_MASK) != (leds & KBD_LED_CAPS_MASK)) diff --git a/user_io.h b/user_io.h index 8c3e400..27fc306 100644 --- a/user_io.h +++ b/user_io.h @@ -53,6 +53,7 @@ #define UIO_SET_STATUS2 0x1e // 32bit status #define UIO_GET_KBD_LED 0x1f // keyboard LEDs control #define UIO_SET_VIDEO 0x20 // set HDMI video mode 0: 1280x720p60(TV), 1: 1280x1024p60(PC), 2-255: reserved +#define UIO_PS2_CTL 0x21 // get PS2 control from supported cores // codes as used by 8bit (atari 800, zx81) via SS2 #define UIO_GET_STATUS 0x50 @@ -192,5 +193,5 @@ void user_io_set_index(unsigned char index); unsigned char user_io_ext_idx(char *, char*); void user_io_check_reset(unsigned short modifiers, char useKeys); - + #endif // USER_IO_H From d8990cf316ac9ea98928bc846298db8660c80d69 Mon Sep 17 00:00:00 2001 From: sorgelig Date: Mon, 31 Jul 2017 08:07:08 +0800 Subject: [PATCH 02/17] Initial support for ao486. --- MiSTer.vcxproj | 2 + MiSTer.vcxproj.filters | 6 + spi.c | 8 + spi.h | 1 + user_io.c | 71 +++- user_io.h | 6 + x86.c | 773 +++++++++++++++++++++++++++++++++++++++++ x86.h | 8 + 8 files changed, 863 insertions(+), 12 deletions(-) create mode 100644 x86.c create mode 100644 x86.h diff --git a/MiSTer.vcxproj b/MiSTer.vcxproj index 61ec713..64edaeb 100644 --- a/MiSTer.vcxproj +++ b/MiSTer.vcxproj @@ -57,6 +57,7 @@ + @@ -86,6 +87,7 @@ + diff --git a/MiSTer.vcxproj.filters b/MiSTer.vcxproj.filters index f2d1745..17969eb 100644 --- a/MiSTer.vcxproj.filters +++ b/MiSTer.vcxproj.filters @@ -65,6 +65,9 @@ Source Files + + Source Files + @@ -148,6 +151,9 @@ Header Files + + Header Files + diff --git a/spi.c b/spi.c index d2e831a..ed2d166 100644 --- a/spi.c +++ b/spi.c @@ -132,6 +132,14 @@ void spi32(uint32_t parm) spi8(parm >> 0); } +uint32_t spi32w(uint32_t parm) +{ + uint32_t res; + res = spi_w(parm); + res |= (spi_w(parm>>16))<<16; + return res; +} + // little endian: lsb first void spi32le(uint32_t parm) { diff --git a/spi.h b/spi.h index 35414a7..26ff901 100644 --- a/spi.h +++ b/spi.h @@ -29,6 +29,7 @@ void spi24(uint32_t parm); void spi32(uint32_t parm); void spi32le(uint32_t parm); void spi_n(uint8_t value, uint16_t cnt); +uint32_t spi32w(uint32_t parm); /* block transfer functions */ void spi_block_read(uint8_t *addr, int wide); diff --git a/user_io.c b/user_io.c index bb679c6..5db3419 100644 --- a/user_io.c +++ b/user_io.c @@ -20,6 +20,7 @@ #include "file_io.h" #include "config.h" #include "menu.h" +#include "x86.h" #define BREAK 0x8000 @@ -133,9 +134,17 @@ char is_menu_core() return (is_menu_type == 1); } +static int is_x86_type = 0; +char is_x86_core() +{ + if (!is_x86_type) is_x86_type = strcasecmp(core_name, "AO486") ? 2 : 1; + return (is_x86_type == 1); +} + static void user_io_read_core_name() { is_menu_type = 0; + is_x86_type = 0; core_name[0] = 0; if (user_io_is_8bit_with_config_string()) @@ -276,21 +285,46 @@ void user_io_detect_core_type() user_io_8bit_set_status(status, 0xffffffff); } - // check if there's a .rom present - sprintf(mainpath, "%s/boot.rom", user_io_get_core_name()); - if (!user_io_file_tx(mainpath, 0)) + // check for multipart rom + sprintf(mainpath, "%s/boot0.rom", user_io_get_core_name()); + if (user_io_file_tx(mainpath, 0)) { - strcpy(name + strlen(name) - 3, "ROM"); - user_io_file_tx(name, 0); + sprintf(mainpath, "%s/boot1.rom", user_io_get_core_name()); + if (user_io_file_tx(mainpath, 0x40)) + { + sprintf(mainpath, "%s/boot2.rom", user_io_get_core_name()); + if (user_io_file_tx(mainpath, 0x80)) + { + sprintf(mainpath, "%s/boot3.rom", user_io_get_core_name()); + user_io_file_tx(mainpath, 0xC0); + } + } + } + else + { + // legacy style of rom + sprintf(mainpath, "%s/boot.rom", user_io_get_core_name()); + if (!user_io_file_tx(mainpath, 0)) + { + strcpy(name + strlen(name) - 3, "ROM"); + user_io_file_tx(name, 0); + } } - // check if there's a .vhd present - sprintf(mainpath, "%s/boot.vhd", user_io_get_core_name()); - user_io_set_index(0); - if (!user_io_file_mount(0, mainpath)) + if (is_x86_core()) { - strcpy(name + strlen(name) - 3, "VHD"); - user_io_file_mount(0, name); + x86_init(); + } + else + { + // check if there's a .vhd present + sprintf(mainpath, "%s/boot.vhd", user_io_get_core_name()); + user_io_set_index(0); + if (!user_io_file_mount(0, mainpath)) + { + strcpy(name + strlen(name) - 3, "VHD"); + user_io_file_mount(0, name); + } } } @@ -613,6 +647,14 @@ int user_io_file_tx(char* name, unsigned char index) /* transmit the entire file using one transfer */ iprintf("Selected file %s with %lu bytes to send for index %d.%d\n", name, bytes2send, index&0x3F, index>>6); + if (is_x86_core()) + { + printf("using DMA transfer mode\n"); + x86_send(&f, index); + FileClose(&f); + return 1; + } + // set index byte (0=bios rom, 1-n=OSD entry index) user_io_set_index(index); @@ -654,7 +696,7 @@ int user_io_file_tx(char* name, unsigned char index) spi8(0x00); DisableFpga(); - iprintf("\n"); + printf("\n"); return 1; } @@ -897,6 +939,11 @@ void user_io_poll() */ // sd card emulation + if (is_x86_core()) + { + x86_poll(); + } + else { static char buffer[4][512]; static uint64_t buffer_lba[4] = { -1,-1,-1,-1 }; diff --git a/user_io.h b/user_io.h index 27fc306..ef38875 100644 --- a/user_io.h +++ b/user_io.h @@ -64,6 +64,11 @@ #define UIO_FILE_INDEX 0x55 #define UIO_FILE_INFO 0x56 +// ao486 direct memory access +#define UIO_DMA_WRITE 0x61 +#define UIO_DMA_READ 0x62 +#define UIO_DMA_SDIO 0x63 + #define JOY_RIGHT 0x01 #define JOY_LEFT 0x02 #define JOY_DOWN 0x04 @@ -168,6 +173,7 @@ int user_io_file_mount(int num, char *name); char *user_io_get_core_name(); char *user_io_get_core_name_ex(); char is_menu_core(); +char is_x86_core(); emu_mode_t user_io_get_kbdemu(); diff --git a/x86.c b/x86.c new file mode 100644 index 0000000..625b37a --- /dev/null +++ b/x86.c @@ -0,0 +1,773 @@ +/* + * Copyright (c) 2014, Aleksander Osman + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include + +#include "spi.h" +#include "user_io.h" +#include "file_io.h" + +#define ALT_CPU_CPU_FREQ 30000000u + +#define FLOPPY_BASE 0x8800 +#define HDD_BASE 0x8840 +#define PC_BUS_BASE 0x88a0 +#define PIO_OUTPUT_BASE 0x8860 +#define SOUND_BASE 0x9000 +#define PIT_BASE 0x8880 +#define RTC_BASE 0x8c00 +#define SD_BASE 0x0A00 + +static uint8_t dma_sdio(int status) +{ + uint8_t res; + EnableFpga(); + spi8(UIO_DMA_SDIO); + res = spi_w((uint16_t)status); + DisableFpga(); + return res; +} + +static uint32_t dma_get(uint32_t address) +{ + EnableFpga(); + spi8(UIO_DMA_READ); + spi32w(address); + uint32_t res = spi32w(0); + DisableFpga(); + return res; +} + +static void dma_set(uint32_t address, uint32_t data) +{ + EnableFpga(); + spi8(UIO_DMA_WRITE); + spi32w(address); + spi32w(data); + DisableFpga(); +} + +static void dma_sendbuf(uint32_t address, uint32_t length, uint32_t *data) +{ + EnableFpga(); + spi8(UIO_DMA_WRITE); + spi32w(address); + while (length--) spi32w(*data++); + DisableFpga(); +} + +static void dma_rcvbuf(uint32_t address, uint32_t length, uint32_t *data) +{ + EnableFpga(); + spi8(UIO_DMA_READ); + spi32w(address); + while (length--) *data++ = spi32w(0); + DisableFpga(); +} + +int x86_send(fileTYPE *f, uint8_t index) +{ + static uint32_t buf[128]; + + FileSeekLBA(f, 0); + + EnableFpga(); + spi8(UIO_DMA_WRITE); + spi32w( index ? 0x80C0000 : 0x80F0000 ); + + unsigned long bytes2send = f->size; + + while (bytes2send) + { + printf("."); + + uint16_t chunk = (bytes2send>512) ? 512 : bytes2send; + bytes2send -= chunk; + + FileReadSec(f, buf); + + chunk = (chunk + 3) >> 2; + uint32_t* p = buf; + while(chunk--) spi32w(*p++); + } + DisableFpga(); + + printf("\n"); + return 1; +} + +static void crc32(uint8_t *ptr, uint32_t *crc_output) +{ + static uint8_t crc[32]; + + //do nothing + if(ptr != NULL && crc_output != NULL) return; + + //initialize + if(ptr == NULL && crc_output == NULL) + { + for(int i=0; i<32; i++) crc[i] = 1; + return; + } + + //output + if(ptr == NULL && crc_output != NULL) + { + *crc_output = 0; + for(int i=0; i<32; i++) + { + (*crc_output) |= crc[i] << (31-i); + } + (*crc_output) = ~(*crc_output); + return; + } + + uint8_t in[8]; + for(int j=0; j<8; j++) in[j] = ((*ptr) >> j) & 1; + + uint8_t new_crc[32]; + + new_crc[31] = in[2] ^ crc[23] ^ crc[29]; + new_crc[30] = in[0] ^ in[3] ^ crc[22] ^ crc[28] ^ crc[31]; + new_crc[29] = in[0] ^ in[1] ^ in[4] ^ crc[21] ^ crc[27] ^ crc[30] ^ crc[31]; + new_crc[28] = in[1] ^ in[2] ^ in[5] ^ crc[20] ^ crc[26] ^ crc[29] ^ crc[30]; + new_crc[27] = in[0] ^ in[2] ^ in[3] ^ in[6] ^ crc[19] ^ crc[25] ^ crc[28] ^ crc[29] ^ crc[31]; + new_crc[26] = in[1] ^ in[3] ^ in[4] ^ in[7] ^ crc[18] ^ crc[24] ^ crc[27] ^ crc[28] ^ crc[30]; + new_crc[25] = in[4] ^ in[5] ^ crc[17] ^ crc[26] ^ crc[27]; + new_crc[24] = in[0] ^ in[5] ^ in[6] ^ crc[16] ^ crc[25] ^ crc[26] ^ crc[31]; + new_crc[23] = in[1] ^ in[6] ^ in[7] ^ crc[15] ^ crc[24] ^ crc[25] ^ crc[30]; + new_crc[22] = in[7] ^ crc[14] ^ crc[24]; + new_crc[21] = in[2] ^ crc[13] ^ crc[29]; + new_crc[20] = in[3] ^ crc[12] ^ crc[28]; + new_crc[19] = in[0] ^ in[4] ^ crc[11] ^ crc[27] ^ crc[31]; + new_crc[18] = in[0] ^ in[1] ^ in[5] ^ crc[10] ^ crc[26] ^ crc[30] ^ crc[31]; + new_crc[17] = in[1] ^ in[2] ^ in[6] ^ crc[9] ^ crc[25] ^ crc[29] ^ crc[30]; + new_crc[16] = in[2] ^ in[3] ^ in[7] ^ crc[8] ^ crc[24] ^ crc[28] ^ crc[29]; + new_crc[15] = in[0] ^ in[2] ^ in[3] ^ in[4] ^ crc[7] ^ crc[27] ^ crc[28] ^ crc[29] ^ crc[31]; + new_crc[14] = in[0] ^ in[1] ^ in[3] ^ in[4] ^ in[5] ^ crc[6] ^ crc[26] ^ crc[27] ^ crc[28] ^ crc[30] ^ crc[31]; + new_crc[13] = in[0] ^ in[1] ^ in[2] ^ in[4] ^ in[5] ^ in[6] ^ crc[5] ^ crc[25] ^ crc[26] ^ crc[27] ^ crc[29] ^ crc[30] ^ crc[31]; + new_crc[12] = in[1] ^ in[2] ^ in[3] ^ in[5] ^ in[6] ^ in[7] ^ crc[4] ^ crc[24] ^ crc[25] ^ crc[26] ^ crc[28] ^ crc[29] ^ crc[30]; + new_crc[11] = in[3] ^ in[4] ^ in[6] ^ in[7] ^ crc[3] ^ crc[24] ^ crc[25] ^ crc[27] ^ crc[28]; + new_crc[10] = in[2] ^ in[4] ^ in[5] ^ in[7] ^ crc[2] ^ crc[24] ^ crc[26] ^ crc[27] ^ crc[29]; + new_crc[9] = in[2] ^ in[3] ^ in[5] ^ in[6] ^ crc[1] ^ crc[25] ^ crc[26] ^ crc[28] ^ crc[29]; + new_crc[8] = in[3] ^ in[4] ^ in[6] ^ in[7] ^ crc[0] ^ crc[24] ^ crc[25] ^ crc[27] ^ crc[28]; + new_crc[7] = in[0] ^ in[2] ^ in[4] ^ in[5] ^ in[7] ^ crc[24] ^ crc[26] ^ crc[27] ^ crc[29] ^ crc[31]; + new_crc[6] = in[0] ^ in[1] ^ in[2] ^ in[3] ^ in[5] ^ in[6] ^ crc[25] ^ crc[26] ^ crc[28] ^ crc[29] ^ crc[30] ^ crc[31]; + new_crc[5] = in[0] ^ in[1] ^ in[2] ^ in[3] ^ in[4] ^ in[6] ^ in[7] ^ crc[24] ^ crc[25] ^ crc[27] ^ crc[28] ^ crc[29] ^ crc[30] ^ crc[31]; + new_crc[4] = in[1] ^ in[3] ^ in[4] ^ in[5] ^ in[7] ^ crc[24] ^ crc[26] ^ crc[27] ^ crc[28] ^ crc[30]; + new_crc[3] = in[0] ^ in[4] ^ in[5] ^ in[6] ^ crc[25] ^ crc[26] ^ crc[27] ^ crc[31]; + new_crc[2] = in[0] ^ in[1] ^ in[5] ^ in[6] ^ in[7] ^ crc[24] ^ crc[25] ^ crc[26] ^ crc[30] ^ crc[31]; + new_crc[1] = in[0] ^ in[1] ^ in[6] ^ in[7] ^ crc[24] ^ crc[25] ^ crc[30] ^ crc[31]; + new_crc[0] = in[1] ^ in[7] ^ crc[24] ^ crc[30]; + + memcpy(crc, new_crc, sizeof(crc)); +} + +struct entry_t +{ + uint8_t type; + uint8_t name[15]; + + union args_t { + struct bios_t { + uint32_t sector; + uint32_t size_in_bytes; + uint32_t destination; + uint32_t crc32; + } bios; + struct hdd_t { + uint32_t sector; + uint32_t cyliders; + uint32_t heads; + uint32_t spt; + } hdd; + struct floppy_t { + uint32_t sector; + } floppy; + struct end_of_list_t { + uint32_t crc32; + } end_of_list; + } args; +} __attribute__((packed)); + +#define ENTRIES_COUNT 128 +static struct entry_t entries[ENTRIES_COUNT]; + +#define TYPE_BIOS 1 +#define TYPE_VGABIOS 2 +#define TYPE_HDD 3 +#define TYPE_FD_1_44M 16 +#define TYPE_CRC32 127 + +#define ENTRY_ABORT -500 + +static int floppy_index = -1; +static int hdd_index = -1; + +static bool floppy_is_160k = false; +static bool floppy_is_180k = false; +static bool floppy_is_320k = false; +static bool floppy_is_360k = false; +static bool floppy_is_720k = false; +static bool floppy_is_1_2m = false; +static bool floppy_is_1_44m= true; +static bool floppy_is_2_88m= false; + +static bool floppy_writeprotect = true; + +#define IOWR(base, reg, value) dma_set(base+(reg<<2), value) + +static void set_floppy(int index) +{ + floppy_index = index; + floppy_writeprotect = true; + + int floppy_sd_base = (index >= 0) ? entries[floppy_index].args.floppy.sector : 0; + + int floppy_media = + (floppy_index < 0)? 0x20 : + (floppy_is_160k)? 0x00 : + (floppy_is_180k)? 0x00 : + (floppy_is_320k)? 0x00 : + (floppy_is_360k)? 0x00 : + (floppy_is_720k)? 0xC0 : + (floppy_is_1_2m)? 0x00 : + (floppy_is_1_44m)? 0x80 : + (floppy_is_2_88m)? 0x40 : + 0x20; + + IOWR(FLOPPY_BASE, 0x0, floppy_index >= 0 ? 1 : 0); + IOWR(FLOPPY_BASE, 0x1, floppy_writeprotect? 1 : 0); + IOWR(FLOPPY_BASE, 0x6, floppy_sd_base); + IOWR(FLOPPY_BASE, 0xC, floppy_media); +} + +static fileTYPE sd_image = { 0 }; + +static int img_mount(char *name) +{ + int writable = FileCanWrite(name); + int ret = FileOpenEx(&sd_image, name, writable ? (O_RDWR | O_SYNC) : O_RDONLY); + if (!ret) + { + sd_image.size = 0; + printf("Failed to open file %s\n", name); + return 0; + } + + printf("Mount %s as %s\n", name, writable ? "read-write" : "read-only"); + return 1; +} + +static int img_read(uint32_t lba, void *buf, uint32_t len) +{ + if (!FileSeekLBA(&sd_image, lba)) return 0; + return FileReadAdv(&sd_image, buf, len); +} + +static int img_write(uint32_t lba, void *buf, uint32_t len) +{ + if (!FileSeekLBA(&sd_image, lba)) return 0; + return FileWriteAdv(&sd_image, buf, len); +} + +void x86_init() +{ + IOWR(PC_BUS_BASE, 0, 0x00FFF0EA); + IOWR(PC_BUS_BASE, 1, 0x000000F0); + + //resets output + IOWR(PIO_OUTPUT_BASE, 0, 0x01); + + if (!img_mount("ao486.vhd")) + { + return; + } + + if (!img_read(0, entries, sizeof(entries))) + { + return; + } + + //check crc32 + bool crc_ok = false; + for(int i=0; i= 0? 1 : 0); + IOWR(FLOPPY_BASE, 0x1, floppy_writeprotect? 1 : 0); + IOWR(FLOPPY_BASE, 0x2, floppy_cylinders); + IOWR(FLOPPY_BASE, 0x3, floppy_spt); + IOWR(FLOPPY_BASE, 0x4, floppy_total_sectors); + IOWR(FLOPPY_BASE, 0x5, floppy_heads); + IOWR(FLOPPY_BASE, 0x6, floppy_sd_base); + IOWR(FLOPPY_BASE, 0x7, (int)(floppy_wait_cycles / (1000000000.0 / ALT_CPU_CPU_FREQ))); + IOWR(FLOPPY_BASE, 0x8, (int)(1000000.0 / (1000000000.0 / ALT_CPU_CPU_FREQ))); + IOWR(FLOPPY_BASE, 0x9, (int)(1666666.0 / (1000000000.0 / ALT_CPU_CPU_FREQ))); + IOWR(FLOPPY_BASE, 0xA, (int)(2000000.0 / (1000000000.0 / ALT_CPU_CPU_FREQ))); + IOWR(FLOPPY_BASE, 0xB, (int)(500000.0 / (1000000000.0 / ALT_CPU_CPU_FREQ))); + IOWR(FLOPPY_BASE, 0xC, floppy_media); + + //-------------------------------------------------------------------------- hdd + + hdd_index = 2; + unsigned int hd_cylinders = entries[hdd_index].args.hdd.cyliders; //1-1024; 10 bits; implemented 16 bits + unsigned int hd_heads = entries[hdd_index].args.hdd.heads; //1-16; 4 bits; at least 9 heads for cmos 0x20 + unsigned int hd_spt = entries[hdd_index].args.hdd.spt; //1-255; 8 bits; + + int hdd_sd_base = entries[hdd_index].args.hdd.sector; + + unsigned int hd_total_sectors = hd_cylinders * hd_heads * hd_spt; + + /* + 0x00.[31:0]: identify write + 0x01.[16:0]: media cylinders + 0x02.[4:0]: media heads + 0x03.[8:0]: media spt + 0x04.[13:0]: media sectors per cylinder = spt * heads + 0x05.[31:0]: media sectors total + 0x06.[31:0]: media sd base + */ + + uint32_t identify[256] = + { + 0x0040, //word 0 + (hd_cylinders > 16383)? 16383 : hd_cylinders, //word 1 + 0x0000, //word 2 reserved + hd_heads, //word 3 + (uint16_t)(512 * hd_spt), //word 4 + 512, //word 5 + hd_spt, //word 6 + 0x0000, //word 7 vendor specific + 0x0000, //word 8 vendor specific + 0x0000, //word 9 vendor specific + ('A' << 8) | 'O', //word 10 + ('H' << 8) | 'D', //word 11 + ('0' << 8) | '0', //word 12 + ('0' << 8) | '0', //word 13 + ('0' << 8) | ' ', //word 14 + (' ' << 8) | ' ', //word 15 + (' ' << 8) | ' ', //word 16 + (' ' << 8) | ' ', //word 17 + (' ' << 8) | ' ', //word 18 + (' ' << 8) | ' ', //word 19 + 3, //word 20 buffer type + 512, //word 21 cache size + 4, //word 22 number of ecc bytes + 0,0,0,0, //words 23..26 firmware revision + ('A' << 8) | 'O', //words 27..46 model number + (' ' << 8) | 'H', + ('a' << 8) | 'r', + ('d' << 8) | 'd', + ('r' << 8) | 'i', + ('v' << 8) | 'e', + (' ' << 8) | ' ', + (' ' << 8) | ' ', + (' ' << 8) | ' ', + (' ' << 8) | ' ', + (' ' << 8) | ' ', + (' ' << 8) | ' ', + (' ' << 8) | ' ', + (' ' << 8) | ' ', + (' ' << 8) | ' ', + (' ' << 8) | ' ', + (' ' << 8) | ' ', + (' ' << 8) | ' ', + (' ' << 8) | ' ', + (' ' << 8) | ' ', + 16, //word 47 max multiple sectors + 1, //word 48 dword io + 1<<9, //word 49 lba supported + 0x0000, //word 50 reserved + 0x0200, //word 51 pio timing + 0x0200, //word 52 pio timing + 0x0007, //word 53 valid fields + (hd_cylinders > 16383)? 16383 : hd_cylinders, //word 54 + hd_heads, //word 55 + hd_spt, //word 56 + hd_total_sectors & 0xFFFF, //word 57 + hd_total_sectors >> 16, //word 58 + 0x0000, //word 59 multiple sectors + hd_total_sectors & 0xFFFF, //word 60 + hd_total_sectors >> 16, //word 61 + 0x0000, //word 62 single word dma modes + 0x0000, //word 63 multiple word dma modes + 0x0000, //word 64 pio modes + 120,120,120,120, //word 65..68 + 0,0,0,0,0,0,0,0,0,0,0, //word 69..79 + 0x007E, //word 80 ata modes + 0x0000, //word 81 minor version number + 1<<14, //word 82 supported commands + (1<<14) | (1<<13) | (1<<12) | (1<<10), //word 83 + 1<<14, //word 84 + 1<<14, //word 85 + (1<<14) | (1<<13) | (1<<12) | (1<<10), //word 86 + 1<<14, //word 87 + 0x0000, //word 88 + 0,0,0,0, //word 89..92 + 1 | (1<<14) | 0x2000, //word 93 + 0,0,0,0,0,0, //word 94..99 + hd_total_sectors & 0xFFFF, //word 100 + hd_total_sectors >> 16, //word 101 + 0, //word 102 + 0, //word 103 + + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,//word 104..127 + + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, //word 128..255 + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + }; + + for(int i=0; i<128; i++) IOWR(HDD_BASE, 0, ((unsigned int)identify[2*i+1] << 16) | (unsigned int)identify[2*i+0]); + + IOWR(HDD_BASE, 1, hd_cylinders); + IOWR(HDD_BASE, 2, hd_heads); + IOWR(HDD_BASE, 3, hd_spt); + IOWR(HDD_BASE, 4, hd_spt * hd_heads); + IOWR(HDD_BASE, 5, hd_spt * hd_heads * hd_cylinders); + IOWR(HDD_BASE, 6, hdd_sd_base); + + printf("HDD:\n hd_cylinders %d\n hd_heads %d\n hd_spt %d\n hdd_sd_base %d\n\n", hd_cylinders, hd_heads, hd_spt, hdd_sd_base); + + //-------------------------------------------------------------------------- rtc + + bool boot_from_floppy = true; + + /* + 128.[26:0]: cycles in second + 129.[12:0]: cycles in 122.07031 us + */ + + IOWR(RTC_BASE, 128, (int)(1000000000.0 / (1000000000.0 / ALT_CPU_CPU_FREQ))); + IOWR(RTC_BASE, 129, (int)(122070.0 / (1000000000.0 / ALT_CPU_CPU_FREQ))); + + unsigned char fdd_type = (floppy_is_2_88m)? 0x50 : (floppy_is_1_44m)? 0x40 : (floppy_is_720k)? 0x30 : (floppy_is_1_2m)? 0x20 : 0x10; + + bool translate_none = hd_cylinders <= 1024 && hd_heads <= 16 && hd_spt <= 63; + bool translate_large= !translate_none && (hd_cylinders * hd_heads) <= 131072; + bool translate_lba = !translate_none && !translate_large; + + unsigned char translate_byte = (translate_large)? 1 : (translate_lba)? 2 : 0; + + //rtc contents 0-127 + unsigned int cmos[128] = { + 0x00, //0x00: SEC BCD + 0x00, //0x01: ALARM SEC BCD + 0x00, //0x02: MIN BCD + 0x00, //0x03: ALARM MIN BCD + 0x12, //0x04: HOUR BCD 24h + 0x12, //0x05: ALARM HOUR BCD 24h + 0x01, //0x06: DAY OF WEEK Sunday=1 + 0x03, //0x07: DAY OF MONTH BCD from 1 + 0x11, //0x08: MONTH BCD from 1 + 0x13, //0x09: YEAR BCD + 0x26, //0x0A: REG A + 0x02, //0x0B: REG B + 0x00, //0x0C: REG C + 0x80, //0x0D: REG D + 0x00, //0x0E: REG E - POST status + 0x00, //0x0F: REG F - shutdown status + + fdd_type, //0x10: floppy drive type; 0-none, 1-360K, 2-1.2M, 3-720K, 4-1.44M, 5-2.88M + 0x00, //0x11: configuration bits; not used + 0xF0, //0x12: hard disk types; 0-none, 1:E-type, F-type 16+ + 0x00, //0x13: advanced configuration bits; not used + 0x0D, //0x14: equipment bits + 0x80, //0x15: base memory in 1k LSB + 0x02, //0x16: base memory in 1k MSB + 0x00, //0x17: memory size above 1m in 1k LSB + 0xFC, //0x18: memory size above 1m in 1k MSB + 0x2F, //0x19: extended hd types 1/2; type 47d + 0x00, //0x1A: extended hd types 2/2 + + hd_cylinders & 0xFF, //0x1B: hd 0 configuration 1/9; cylinders low + (hd_cylinders >> 8) & 0xFF, //0x1C: hd 0 configuration 2/9; cylinders high + hd_heads, //0x1D: hd 0 configuration 3/9; heads + 0xFF, //0x1E: hd 0 configuration 4/9; write pre-comp low + 0xFF, //0x1F: hd 0 configuration 5/9; write pre-comp high + 0xC8, //0x20: hd 0 configuration 6/9; retries/bad map/heads>8 + hd_cylinders & 0xFF, //0x21: hd 0 configuration 7/9; landing zone low + (hd_cylinders >> 8) & 0xFF, //0x22: hd 0 configuration 8/9; landing zone high + hd_spt, //0x23: hd 0 configuration 9/9; sectors/track + + 0x00, //0x24: hd 1 configuration 1/9 + 0x00, //0x25: hd 1 configuration 2/9 + 0x00, //0x26: hd 1 configuration 3/9 + 0x00, //0x27: hd 1 configuration 4/9 + 0x00, //0x28: hd 1 configuration 5/9 + 0x00, //0x29: hd 1 configuration 6/9 + 0x00, //0x2A: hd 1 configuration 7/9 + 0x00, //0x2B: hd 1 configuration 8/9 + 0x00, //0x2C: hd 1 configuration 9/9 + + (boot_from_floppy)? 0x20u : 0x00u, //0x2D: boot sequence + + 0x00, //0x2E: checksum MSB + 0x00, //0x2F: checksum LSB + + 0x00, //0x30: memory size above 1m in 1k LSB + 0xFC, //0x31: memory size above 1m in 1k MSB + + 0x20, //0x32: IBM century + 0x00, //0x33: ? + + 0x00, //0x34: memory size above 16m in 64k LSB + 0x07, //0x35: memory size above 16m in 64k MSB; 128 MB + + 0x00, //0x36: ? + 0x20, //0x37: IBM PS/2 century + + 0x00, //0x38: eltorito boot sequence; not used + translate_byte, //0x39: ata translation policy 1/2 + 0x00, //0x3A: ata translation policy 2/2 + + 0x00, //0x3B: ? + 0x00, //0x3C: ? + + 0x00, //0x3D: eltorito boot sequence; not used + + 0x00, //0x3E: ? + 0x00, //0x3F: ? + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + + //count checksum + unsigned short sum = 0; + for(int i=0x10; i<=0x2D; i++) sum += cmos[i]; + + cmos[0x2E] = sum >> 8; + cmos[0x2F] = sum & 0xFF; + + for(unsigned int i=0; i> 2, (uint32_t*)&sd_params); + printf("Read: 0x%08x, 0x%08x, %d\n", sd_params.addr, sd_params.lba, sd_params.bl_cnt); + + if (sd_image.size) + { + if (sd_params.bl_cnt>0 && sd_params.bl_cnt<=4) + { + if (img_read(sd_params.lba, secbuf, sd_params.bl_cnt * 512)) + { + dma_sendbuf(sd_params.addr, sd_params.bl_cnt * 128, secbuf); + res = 1; + } + } + else + { + printf("Error: Block count %d is out of range 1..4.\n", sd_params.bl_cnt); + } + } + else + { + printf("Error: image is not ready.\n"); + } + + dma_sdio(res ? 1 : 2); + } + else if (sd_req == 2) + { + dma_rcvbuf(SD_BASE + (4 << 2), sizeof(sd_params) >> 2, (uint32_t*)&sd_params); + printf("Write: 0x%08x, 0x%08x, %d\n", sd_params.addr, sd_params.lba, sd_params.bl_cnt); + + if (sd_image.size) + { + if (sd_params.bl_cnt>0 && sd_params.bl_cnt <= 4) + { + if (sd_image.mode & O_RDWR) + { + dma_rcvbuf(sd_params.addr, sd_params.bl_cnt * 128, secbuf); + if (img_write(sd_params.lba, secbuf, sd_params.bl_cnt * 512)) + { + res = 1; + } + } + else + { + printf("Error: image is read-only.\n"); + } + } + else + { + printf("Error: Block count %d is out of range 1..4.\n", sd_params.bl_cnt); + } + } + else + { + printf("Error: image is not ready.\n"); + } + + dma_sdio(res ? 1 : 2); + } +} diff --git a/x86.h b/x86.h new file mode 100644 index 0000000..1ccdaec --- /dev/null +++ b/x86.h @@ -0,0 +1,8 @@ +#ifndef X86_H +#define X86_H + +void x86_init(); +void x86_poll(); +int x86_send(fileTYPE *f, uint8_t index); + +#endif From 383fb380629e500b1182055cf759a91130498c40 Mon Sep 17 00:00:00 2001 From: sorgelig Date: Tue, 1 Aug 2017 05:45:42 +0800 Subject: [PATCH 03/17] ao486: temporary workaround for kbd, system clock is 90mhz. --- input.c | 2 +- main.c | 2 -- user_io.c | 2 +- x86.c | 2 +- 4 files changed, 3 insertions(+), 5 deletions(-) diff --git a/input.c b/input.c index c0aebb9..e1d7ad1 100644 --- a/input.c +++ b/input.c @@ -728,7 +728,7 @@ static void input_cb(struct input_event *ev, int dev) static char keys[6] = { 0,0,0,0,0,0 }; // repeat events won't be processed - if (ev->type == EV_KEY && ev->value > 1) return; + if (ev->type == EV_KEY && (ev->value > 1 && !is_x86_core())) return; int map_skip = (ev->type == EV_KEY && ev->code == 57 && mapping_dev >= 0 && mapping_type==1); int cancel = (ev->type == EV_KEY && ev->code == 1); diff --git a/main.c b/main.c index 756edfe..f63020c 100644 --- a/main.c +++ b/main.c @@ -86,8 +86,6 @@ void core_init() int main(int argc, char *argv[]) { - uint8_t mmc_ok = 0; - fpga_io_init(); fpga_gpo_write(0); diff --git a/user_io.c b/user_io.c index 5db3419..dbe7bf2 100644 --- a/user_io.c +++ b/user_io.c @@ -1672,7 +1672,7 @@ void user_io_kbd(uint16_t key, int press) } else { - send_keycode(code); + send_keycode((press == 2) ? code & ~EXT : code); } } } diff --git a/x86.c b/x86.c index 625b37a..3f60ec5 100644 --- a/x86.c +++ b/x86.c @@ -35,7 +35,7 @@ #include "user_io.h" #include "file_io.h" -#define ALT_CPU_CPU_FREQ 30000000u +#define ALT_CPU_CPU_FREQ 90000000u #define FLOPPY_BASE 0x8800 #define HDD_BASE 0x8840 From 61541d48da15b6fd920138a971637e0fa89e80cf Mon Sep 17 00:00:00 2001 From: sorgelig Date: Tue, 1 Aug 2017 20:51:48 +0800 Subject: [PATCH 04/17] ao486: more keyboard tweaks. --- input.c | 353 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 350 insertions(+), 3 deletions(-) diff --git a/input.c b/input.c index e1d7ad1..e02202f 100644 --- a/input.c +++ b/input.c @@ -310,6 +310,272 @@ static int ev2usb[] = NONE //255 ??? }; +#define OSD 0x0100 // to be used by OSD, not the core itself +#define OSD_OPEN 0x0200 // OSD key not forwarded to core, but queued in arm controller +#define CAPS_LOCK_TOGGLE 0x0400 // caps lock toggle behaviour +#define NUM_LOCK_TOGGLE 0x0800 +#define EXT 0x1000 + +static int ev2ps2[] = +{ + NONE, //0 KEY_RESERVED + 0x76, //1 KEY_ESC + 0x16, //2 KEY_1 + 0x1e, //3 KEY_2 + 0x26, //4 KEY_3 + 0x25, //5 KEY_4 + 0x2e, //6 KEY_5 + 0x36, //7 KEY_6 + 0x3d, //8 KEY_7 + 0x3e, //9 KEY_8 + 0x46, //10 KEY_9 + 0x45, //11 KEY_0 + 0x4e, //12 KEY_MINUS + 0x55, //13 KEY_EQUAL + 0x66, //14 KEY_BACKSPACE + 0x0d, //15 KEY_TAB + 0x15, //16 KEY_Q + 0x1d, //17 KEY_W + 0x24, //18 KEY_E + 0x2d, //19 KEY_R + 0x2c, //20 KEY_T + 0x35, //21 KEY_Y + 0x3c, //22 KEY_U + 0x43, //23 KEY_I + 0x44, //24 KEY_O + 0x4d, //25 KEY_P + 0x54, //26 KEY_LEFTBRACE + 0x5b, //27 KEY_RIGHTBRACE + 0x5a, //28 KEY_ENTER + 0x14, //29 KEY_LEFTCTRL + 0x1c, //30 KEY_A + 0x1b, //31 KEY_S + 0x23, //32 KEY_D + 0x2b, //33 KEY_F + 0x34, //34 KEY_G + 0x33, //35 KEY_H + 0x3b, //36 KEY_J + 0x42, //37 KEY_K + 0x4b, //38 KEY_L + 0x4c, //39 KEY_SEMICOLON + 0x52, //40 KEY_APOSTROPHE + 0x0e, //41 KEY_GRAVE + 0x12, //42 KEY_LEFTSHIFT + 0x5d, //43 KEY_BACKSLASH + 0x1a, //44 KEY_Z + 0x22, //45 KEY_X + 0x21, //46 KEY_C + 0x2a, //47 KEY_V + 0x32, //48 KEY_B + 0x31, //49 KEY_N + 0x3a, //50 KEY_M + 0x41, //51 KEY_COMMA + 0x49, //52 KEY_DOT + 0x4a, //53 KEY_SLASH + 0x59, //54 KEY_RIGHTSHIFT + 0x7c, //55 KEY_KPASTERISK + 0x11, //56 KEY_LEFTALT + 0x29, //57 KEY_SPACE + 0x58, //58 KEY_CAPSLOCK + 0x05, //59 KEY_F1 + 0x06, //60 KEY_F2 + 0x04, //61 KEY_F3 + 0x0c, //62 KEY_F4 + 0x03, //63 KEY_F5 + 0x0b, //64 KEY_F6 + 0x83, //65 KEY_F7 + 0x0a, //66 KEY_F8 + 0x01, //67 KEY_F9 + 0x09, //68 KEY_F10 + 0x77, //69 KEY_NUMLOCK + 0x7E, //70 KEY_SCROLLLOCK + 0x6c, //71 KEY_KP7 + 0x75, //72 KEY_KP8 + 0x7d, //73 KEY_KP9 + 0x7b, //74 KEY_KPMINUS + 0x6b, //75 KEY_KP4 + 0x73, //76 KEY_KP5 + 0x74, //77 KEY_KP6 + 0x79, //78 KEY_KPPLUS + 0x69, //79 KEY_KP1 + 0x72, //80 KEY_KP2 + 0x7a, //81 KEY_KP3 + 0x70, //82 KEY_KP0 + 0x71, //83 KEY_KPDOT + NONE, //84 ??? + NONE, //85 KEY_ZENKAKU + NONE, //86 KEY_102ND + 0x78, //87 KEY_F11 + NONE, //88 KEY_F12 + NONE, //89 KEY_RO + NONE, //90 KEY_KATAKANA + NONE, //91 KEY_HIRAGANA + NONE, //92 KEY_HENKAN + NONE, //93 KEY_KATAKANA + NONE, //94 KEY_MUHENKAN + NONE, //95 KEY_KPJPCOMMA + EXT | 0x5a, //96 KEY_KPENTER + EXT | 0x14, //97 KEY_RIGHTCTRL + EXT | 0x4a, //98 KEY_KPSLASH + NONE, //99 KEY_SYSRQ + EXT | 0x11, //100 KEY_RIGHTALT + NONE, //101 KEY_LINEFEED + EXT | 0x6c, //102 KEY_HOME + EXT | 0x75, //103 KEY_UP + EXT | 0x7d, //104 KEY_PAGEUP + EXT | 0x6b, //105 KEY_LEFT + EXT | 0x74, //106 KEY_RIGHT + EXT | 0x69, //107 KEY_END + EXT | 0x72, //108 KEY_DOWN + EXT | 0x7d, //109 KEY_PAGEDOWN + EXT | 0x70, //110 KEY_INSERT + EXT | 0x71, //111 KEY_DELETE + NONE, //112 KEY_MACRO + NONE, //113 KEY_MUTE + NONE, //114 KEY_VOLUMEDOWN + NONE, //115 KEY_VOLUMEUP + NONE, //116 KEY_POWER + NONE, //117 KEY_KPEQUAL + NONE, //118 KEY_KPPLUSMINUS + 0xE1, //119 KEY_PAUSE + NONE, //120 KEY_SCALE + NONE, //121 KEY_KPCOMMA + NONE, //122 KEY_HANGEUL + NONE, //123 KEY_HANJA + NONE, //124 KEY_YEN + EXT | 0x1f, //125 KEY_LEFTMETA + EXT | 0x27, //126 KEY_RIGHTMETA + NONE, //127 KEY_COMPOSE + NONE, //128 KEY_STOP + NONE, //129 KEY_AGAIN + NONE, //130 KEY_PROPS + NONE, //131 KEY_UNDO + NONE, //132 KEY_FRONT + NONE, //133 KEY_COPY + NONE, //134 KEY_OPEN + NONE, //135 KEY_PASTE + NONE, //136 KEY_FIND + NONE, //137 KEY_CUT + NONE, //138 KEY_HELP + NONE, //139 KEY_MENU + NONE, //140 KEY_CALC + NONE, //141 KEY_SETUP + NONE, //142 KEY_SLEEP + NONE, //143 KEY_WAKEUP + NONE, //144 KEY_FILE + NONE, //145 KEY_SENDFILE + NONE, //146 KEY_DELETEFILE + NONE, //147 KEY_XFER + NONE, //148 KEY_PROG1 + NONE, //149 KEY_PROG2 + NONE, //150 KEY_WWW + NONE, //151 KEY_MSDOS + NONE, //152 KEY_SCREENLOCK + NONE, //153 KEY_DIRECTION + NONE, //154 KEY_CYCLEWINDOWS + NONE, //155 KEY_MAIL + NONE, //156 KEY_BOOKMARKS + NONE, //157 KEY_COMPUTER + NONE, //158 KEY_BACK + NONE, //159 KEY_FORWARD + NONE, //160 KEY_CLOSECD + NONE, //161 KEY_EJECTCD + NONE, //162 KEY_EJECTCLOSECD + NONE, //163 KEY_NEXTSONG + NONE, //164 KEY_PLAYPAUSE + NONE, //165 KEY_PREVIOUSSONG + NONE, //166 KEY_STOPCD + NONE, //167 KEY_RECORD + NONE, //168 KEY_REWIND + NONE, //169 KEY_PHONE + NONE, //170 KEY_ISO + NONE, //171 KEY_CONFIG + NONE, //172 KEY_HOMEPAGE + NONE, //173 KEY_REFRESH + NONE, //174 KEY_EXIT + NONE, //175 KEY_MOVE + NONE, //176 KEY_EDIT + NONE, //177 KEY_SCROLLUP + NONE, //178 KEY_SCROLLDOWN + NONE, //179 KEY_KPLEFTPAREN + NONE, //180 KEY_KPRIGHTPAREN + NONE, //181 KEY_NEW + NONE, //182 KEY_REDO + NONE, //183 KEY_F13 + NONE, //184 KEY_F14 + NONE, //185 KEY_F15 + NONE, //186 KEY_F16 + NONE, //187 KEY_F17 + NONE, //188 KEY_F18 + NONE, //189 KEY_F19 + NONE, //190 KEY_F20 + NONE, //191 KEY_F21 + NONE, //192 KEY_F22 + NONE, //193 KEY_F23 + NONE, //194 KEY_F24 + NONE, //195 ??? + NONE, //196 ??? + NONE, //197 ??? + NONE, //198 ??? + NONE, //199 ??? + NONE, //200 KEY_PLAYCD + NONE, //201 KEY_PAUSECD + NONE, //202 KEY_PROG3 + NONE, //203 KEY_PROG4 + NONE, //204 KEY_DASHBOARD + NONE, //205 KEY_SUSPEND + NONE, //206 KEY_CLOSE + NONE, //207 KEY_PLAY + NONE, //208 KEY_FASTFORWARD + NONE, //209 KEY_BASSBOOST + 0xE2, //210 KEY_PRINT + NONE, //211 KEY_HP + NONE, //212 KEY_CAMERA + NONE, //213 KEY_SOUND + NONE, //214 KEY_QUESTION + NONE, //215 KEY_EMAIL + NONE, //216 KEY_CHAT + NONE, //217 KEY_SEARCH + NONE, //218 KEY_CONNECT + NONE, //219 KEY_FINANCE + NONE, //220 KEY_SPORT + NONE, //221 KEY_SHOP + NONE, //222 KEY_ALTERASE + NONE, //223 KEY_CANCEL + NONE, //224 KEY_BRIGHT_DOWN + NONE, //225 KEY_BRIGHT_UP + NONE, //226 KEY_MEDIA + NONE, //227 KEY_SWITCHVIDEO + NONE, //228 KEY_DILLUMTOGGLE + NONE, //229 KEY_DILLUMDOWN + NONE, //230 KEY_DILLUMUP + NONE, //231 KEY_SEND + NONE, //232 KEY_REPLY + NONE, //233 KEY_FORWARDMAIL + NONE, //234 KEY_SAVE + NONE, //235 KEY_DOCUMENTS + NONE, //236 KEY_BATTERY + NONE, //237 KEY_BLUETOOTH + NONE, //238 KEY_WLAN + NONE, //239 KEY_UWB + NONE, //240 KEY_UNKNOWN + NONE, //241 KEY_VIDEO_NEXT + NONE, //242 KEY_VIDEO_PREV + NONE, //243 KEY_BRIGHT_CYCLE + NONE, //244 KEY_BRIGHT_AUTO + NONE, //245 KEY_DISPLAY_OFF + NONE, //246 KEY_WWAN + NONE, //247 KEY_RFKILL + NONE, //248 KEY_MICMUTE + NONE, //249 ??? + NONE, //250 ??? + NONE, //251 ??? + NONE, //252 ??? + NONE, //253 ??? + NONE, //254 ??? + NONE //255 ??? +}; + int mfd = -1; int mwd = -1; @@ -721,6 +987,86 @@ static void joy_analog(int num, int axis, int offset) } } +static int input_cb_x86(struct input_event *ev, int dev) +{ + if(user_io_osd_is_visible() || ev->type != EV_KEY || !is_x86_core() || ev->code>255) return 0; + + int code = ev2ps2[ev->code]; + if (code == NONE) return 0; + + //pause + if ((code & 0xff) == 0xE1) + { + // pause does not have a break code + if (ev->value != 1) + { + // Pause key sends E11477E1F014E077 + static const unsigned char c[] = { 0xe1, 0x14, 0x77, 0xe1, 0xf0, 0x14, 0xf0, 0x77, 0x00 }; + const unsigned char *p = c; + + spi_uio_cmd_cont(UIO_KEYBOARD); + + printf("PS2 PAUSE CODE: "); + while (*p) + { + printf("%x ", *p); + spi8(*p++); + } + printf("\n"); + + DisableIO(); + } + } + // print screen + else if ((code & 0xff) == 0xE2) + { + if (ev->value <= 1) + { + static const unsigned char c[2][8] = { + { 0xE0, 0xF0, 0x7C, 0xE0, 0xF0, 0x12, 0x00, 0x00 }, + { 0xE0, 0x12, 0xE0, 0x7C, 0x00, 0x00, 0x00, 0x00 } + }; + + const unsigned char *p = c[ev->value]; + + spi_uio_cmd_cont(UIO_KEYBOARD); + + printf("PS2 PRINT CODE: "); + while (*p) + { + printf("%x ", *p); + spi8(*p++); + } + printf("\n"); + + DisableIO(); + } + } + else + { + spi_uio_cmd_cont(UIO_KEYBOARD); + /* + iprintf("PS2 KBD "); + if (code & EXT) iprintf("e0 "); + if (code & BREAK) iprintf("f0 "); + iprintf("%x\n", code & 0xff); + */ + + // prepend extended code flag if required + if (code & EXT) spi8(0xe0); + + // prepend break code if required + if (!ev->value) spi8(0xf0); + + // send code itself + spi8(code & 0xff); + + DisableIO(); + } + + return 1; +} + static void input_cb(struct input_event *ev, int dev) { static int key_mapped = 0; @@ -728,7 +1074,7 @@ static void input_cb(struct input_event *ev, int dev) static char keys[6] = { 0,0,0,0,0,0 }; // repeat events won't be processed - if (ev->type == EV_KEY && (ev->value > 1 && !is_x86_core())) return; + if (ev->type == EV_KEY && ev->value > 1) return; int map_skip = (ev->type == EV_KEY && ev->code == 57 && mapping_dev >= 0 && mapping_type==1); int cancel = (ev->type == EV_KEY && ev->code == 1); @@ -1236,7 +1582,7 @@ int input_test(int getchar) { //keyboard, buttons case EV_KEY: - if(ev.value<=1) printf("Input event: type=EV_KEY, code=%d(0x%x), value=%d\n", ev.code, ev.code, ev.value); + printf("Input event: type=EV_KEY, code=%d(0x%x), value=%d\n", ev.code, ev.code, ev.value); break; //mouse @@ -1269,7 +1615,8 @@ int input_test(int getchar) } } - input_cb(&ev, i); + + if(!input_cb_x86(&ev, i)) input_cb(&ev, i); //sumulate digital directions from analog if (ev.type == EV_ABS && !(ev.code<=1 && mouse_emu && !user_io_osd_is_visible())) From 50f2b025972b815e17dcd09db217924caaf913c5 Mon Sep 17 00:00:00 2001 From: sorgelig Date: Wed, 2 Aug 2017 02:24:57 +0800 Subject: [PATCH 05/17] Keyboard code refactoring. --- MiSTer.vcxproj | 1 - MiSTer.vcxproj.filters | 3 - input.c | 862 +++++++++++++++++++++++++---------------- input.h | 28 ++ keycodes.h | 509 ------------------------ menu.c | 80 ++-- menu.h | 21 +- user_io.c | 312 ++++++--------- 8 files changed, 719 insertions(+), 1097 deletions(-) delete mode 100644 keycodes.h diff --git a/MiSTer.vcxproj b/MiSTer.vcxproj index 64edaeb..46bb6d8 100644 --- a/MiSTer.vcxproj +++ b/MiSTer.vcxproj @@ -79,7 +79,6 @@ - diff --git a/MiSTer.vcxproj.filters b/MiSTer.vcxproj.filters index 17969eb..a5a7241 100644 --- a/MiSTer.vcxproj.filters +++ b/MiSTer.vcxproj.filters @@ -124,9 +124,6 @@ Header Files - - Header Files - Header Files diff --git a/input.c b/input.c index e02202f..088e099 100644 --- a/input.c +++ b/input.c @@ -1,6 +1,5 @@ #include #include -#include #include #include #include @@ -18,129 +17,97 @@ #define NUMDEV 10 -typedef struct -{ - uint16_t vid, pid; - char led; - char last_l, last_r, last_u, last_d; - - char has_map; - uint32_t map[32]; - - char has_mmap; - uint32_t mmap[32]; - - char has_kbdmap; - uint8_t kbdmap[256]; -} devInput; - -static devInput input[NUMDEV] = {0}; -static int first_joystick = -1; - -#define FN 0x10000 - -#define LCTRL 0x0100 -#define LSHIFT 0x0200 -#define LALT 0x0400 -#define LGUI 0x0800 -#define RCTRL 0x1000 -#define RSHIFT 0x2000 -#define RALT 0x4000 -#define RGUI 0x8000 -#define MODMASK 0xFF00 -#define NONE 0 - -static int ev2usb[] = +static int ev2amiga[] = { NONE, //0 KEY_RESERVED - 0x29, //1 KEY_ESC - 0x1e, //2 KEY_1 - 0x1f, //3 KEY_2 - 0x20, //4 KEY_3 - 0x21, //5 KEY_4 - 0x22, //6 KEY_5 - 0x23, //7 KEY_6 - 0x24, //8 KEY_7 - 0x25, //9 KEY_8 - 0x26, //10 KEY_9 - 0x27, //11 KEY_0 - 0x2D, //12 KEY_MINUS - 0x2E, //13 KEY_EQUAL - 0x2A, //14 KEY_BACKSPACE - 0x2B, //15 KEY_TAB - 0x14, //16 KEY_Q - 0x1a, //17 KEY_W - 0x08, //18 KEY_E - 0x15, //19 KEY_R - 0x17, //20 KEY_T - 0x1c, //21 KEY_Y - 0x18, //22 KEY_U - 0x0c, //23 KEY_I - 0x12, //24 KEY_O - 0x13, //25 KEY_P - 0x2F, //26 KEY_LEFTBRACE - 0x30, //27 KEY_RIGHTBRACE - 0x28, //28 KEY_ENTER - LCTRL, //29 KEY_LEFTCTRL - 0x04, //30 KEY_A - 0x16, //31 KEY_S - 0x07, //32 KEY_D - 0x09, //33 KEY_F - 0x0a, //34 KEY_G - 0x0b, //35 KEY_H - 0x0d, //36 KEY_J - 0x0e, //37 KEY_K - 0x0f, //38 KEY_L - 0x33, //39 KEY_SEMICOLON - 0x34, //40 KEY_APOSTROPHE - 0x35, //41 KEY_GRAVE - LSHIFT, //42 KEY_LEFTSHIFT - 0x31, //43 KEY_BACKSLASH - 0x1d, //44 KEY_Z - 0x1b, //45 KEY_X - 0x06, //46 KEY_C - 0x19, //47 KEY_V - 0x05, //48 KEY_B - 0x11, //49 KEY_N - 0x10, //50 KEY_M - 0x36, //51 KEY_COMMA - 0x37, //52 KEY_DOT - 0x38, //53 KEY_SLASH - RSHIFT, //54 KEY_RIGHTSHIFT - 0x55, //55 KEY_KPASTERISK - LALT, //56 KEY_LEFTALT - 0x2C, //57 KEY_SPACE - 0x39, //58 KEY_CAPSLOCK - 0x3a, //59 KEY_F1 - 0x3b, //60 KEY_F2 - 0x3c, //61 KEY_F3 - 0x3d, //62 KEY_F4 - 0x3e, //63 KEY_F5 - 0x3f, //64 KEY_F6 - 0x40, //65 KEY_F7 - 0x41, //66 KEY_F8 - 0x42, //67 KEY_F9 - 0x43, //68 KEY_F10 - 0x53, //69 KEY_NUMLOCK - 0x47, //70 KEY_SCROLLLOCK - 0x5F, //71 KEY_KP7 - 0x60, //72 KEY_KP8 - 0x61, //73 KEY_KP9 - 0x56, //74 KEY_KPMINUS - 0x5C, //75 KEY_KP4 - 0x5D, //76 KEY_KP5 - 0x5E, //77 KEY_KP6 - 0x57, //78 KEY_KPPLUS - 0x59, //79 KEY_KP1 - 0x5A, //80 KEY_KP2 - 0x5B, //81 KEY_KP3 - 0x62, //82 KEY_KP0 - 0x63, //83 KEY_KPDOT + 0x45, //1 KEY_ESC + 0x01, //2 KEY_1 + 0x02, //3 KEY_2 + 0x03, //4 KEY_3 + 0x04, //5 KEY_4 + 0x05, //6 KEY_5 + 0x06, //7 KEY_6 + 0x07, //8 KEY_7 + 0x08, //9 KEY_8 + 0x09, //10 KEY_9 + 0x0a, //11 KEY_0 + 0x0b, //12 KEY_MINUS + 0x0c, //13 KEY_EQUAL + 0x41, //14 KEY_BACKSPACE + 0x42, //15 KEY_TAB + 0x10, //16 KEY_Q + 0x11, //17 KEY_W + 0x12, //18 KEY_E + 0x13, //19 KEY_R + 0x14, //20 KEY_T + 0x15, //21 KEY_Y + 0x16, //22 KEY_U + 0x17, //23 KEY_I + 0x18, //24 KEY_O + 0x19, //25 KEY_P + 0x1a, //26 KEY_LEFTBRACE + 0x1b, //27 KEY_RIGHTBRACE + 0x44, //28 KEY_ENTER + 0x63, //29 KEY_LEFTCTRL + 0x20, //30 KEY_A + 0x21, //31 KEY_S + 0x22, //32 KEY_D + 0x23, //33 KEY_F + 0x24, //34 KEY_G + 0x25, //35 KEY_H + 0x26, //36 KEY_J + 0x27, //37 KEY_K + 0x28, //38 KEY_L + 0x29, //39 KEY_SEMICOLON + 0x2a, //40 KEY_APOSTROPHE + 0x00, //41 KEY_GRAVE + 0x60, //42 KEY_LEFTSHIFT + 0x0d, //43 KEY_BACKSLASH + 0x31, //44 KEY_Z + 0x32, //45 KEY_X + 0x33, //46 KEY_C + 0x34, //47 KEY_V + 0x35, //48 KEY_B + 0x36, //49 KEY_N + 0x37, //50 KEY_M + 0x38, //51 KEY_COMMA + 0x39, //52 KEY_DOT + 0x3a, //53 KEY_SLASH + 0x61, //54 KEY_RIGHTSHIFT + 0x5d, //55 KEY_KPASTERISK + 0x64, //56 KEY_LEFTALT + 0x40, //57 KEY_SPACE + 0x62 | CAPS_TOGGLE, //58 KEY_CAPSLOCK + 0x50, //59 KEY_F1 + 0x51, //60 KEY_F2 + 0x52, //61 KEY_F3 + 0x53, //62 KEY_F4 + 0x54, //63 KEY_F5 + 0x55, //64 KEY_F6 + 0x56, //65 KEY_F7 + 0x57, //66 KEY_F8 + 0x58, //67 KEY_F9 + 0x59, //68 KEY_F10 + NONE, //69 KEY_NUMLOCK + NONE, //70 KEY_SCROLLLOCK + 0x3d, //71 KEY_KP7 + 0x3e, //72 KEY_KP8 + 0x3f, //73 KEY_KP9 + 0x4a, //74 KEY_KPMINUS + 0x2d, //75 KEY_KP4 + 0x2e, //76 KEY_KP5 + 0x2f, //77 KEY_KP6 + 0x5e, //78 KEY_KPPLUS + 0x1d, //79 KEY_KP1 + 0x1e, //80 KEY_KP2 + 0x1f, //81 KEY_KP3 + 0x0f, //82 KEY_KP0 + 0x3c, //83 KEY_KPDOT NONE, //84 ??? NONE, //85 KEY_ZENKAKU - FN, //86 KEY_102ND - 0x44, //87 KEY_F11 - 0x45, //88 KEY_F12 + NONE, //86 KEY_102ND + 0x5f, //87 KEY_F11 + NONE, //88 KEY_F12 NONE, //89 KEY_RO NONE, //90 KEY_KATAKANA NONE, //91 KEY_HIRAGANA @@ -148,38 +115,38 @@ static int ev2usb[] = NONE, //93 KEY_KATAKANA NONE, //94 KEY_MUHENKAN NONE, //95 KEY_KPJPCOMMA - 0x28, //96 KEY_KPENTER - RCTRL, //97 KEY_RIGHTCTRL - 0x54, //98 KEY_KPSLASH + 0x43, //96 KEY_KPENTER + 0x63, //97 KEY_RIGHTCTRL + 0x5c, //98 KEY_KPSLASH NONE, //99 KEY_SYSRQ - RALT, //100 KEY_RIGHTALT + 0x65, //100 KEY_RIGHTALT NONE, //101 KEY_LINEFEED - 0x4A, //102 KEY_HOME - 0x52, //103 KEY_UP - 0x4B, //104 KEY_PAGEUP - 0x50, //105 KEY_LEFT - 0x4F, //106 KEY_RIGHT - 0x4D, //107 KEY_END - 0x51, //108 KEY_DOWN - 0x4E, //109 KEY_PAGEDOWN - 0x49, //110 KEY_INSERT - 0x4C, //111 KEY_DELETE + 0x6a, //102 KEY_HOME + 0x4c, //103 KEY_UP + NONE, //104 KEY_PAGEUP + 0x4f, //105 KEY_LEFT + 0x4e, //106 KEY_RIGHT + NONE, //107 KEY_END + 0x4d, //108 KEY_DOWN + NONE, //109 KEY_PAGEDOWN + 0x0d, //110 KEY_INSERT + 0x46, //111 KEY_DELETE NONE, //112 KEY_MACRO NONE, //113 KEY_MUTE NONE, //114 KEY_VOLUMEDOWN NONE, //115 KEY_VOLUMEUP NONE, //116 KEY_POWER - 0x67, //117 KEY_KPEQUAL + NONE, //117 KEY_KPEQUAL NONE, //118 KEY_KPPLUSMINUS - 0x48, //119 KEY_PAUSE + NONE, //119 KEY_PAUSE NONE, //120 KEY_SCALE NONE, //121 KEY_KPCOMMA NONE, //122 KEY_HANGEUL NONE, //123 KEY_HANJA NONE, //124 KEY_YEN - LGUI, //125 KEY_LEFTMETA - RGUI, //126 KEY_RIGHTMETA - 0x65, //127 KEY_COMPOSE + 0x66, //125 KEY_LEFTMETA + 0x67, //126 KEY_RIGHTMETA + NONE, //127 KEY_COMPOSE NONE, //128 KEY_STOP NONE, //129 KEY_AGAIN NONE, //130 KEY_PROPS @@ -235,10 +202,10 @@ static int ev2usb[] = NONE, //180 KEY_KPRIGHTPAREN NONE, //181 KEY_NEW NONE, //182 KEY_REDO - NONE, //183 KEY_F13 - NONE, //184 KEY_F14 + 0x5a, //183 KEY_F13 + 0x5b, //184 KEY_F14 NONE, //185 KEY_F15 - NONE, //186 KEY_F16 + 0x5f, //186 KEY_F16 NONE, //187 KEY_F17 NONE, //188 KEY_F18 NONE, //189 KEY_F19 @@ -246,7 +213,7 @@ static int ev2usb[] = NONE, //191 KEY_F21 NONE, //192 KEY_F22 NONE, //193 KEY_F23 - RCTRL, //194 KEY_F24 + 0x63, //194 KEY_F24 NONE, //195 ??? NONE, //196 ??? NONE, //197 ??? @@ -262,7 +229,7 @@ static int ev2usb[] = NONE, //207 KEY_PLAY NONE, //208 KEY_FASTFORWARD NONE, //209 KEY_BASSBOOST - 0x46, //210 KEY_PRINT + NONE, //210 KEY_PRINT NONE, //211 KEY_HP NONE, //212 KEY_CAMERA NONE, //213 KEY_SOUND @@ -310,13 +277,8 @@ static int ev2usb[] = NONE //255 ??? }; -#define OSD 0x0100 // to be used by OSD, not the core itself -#define OSD_OPEN 0x0200 // OSD key not forwarded to core, but queued in arm controller -#define CAPS_LOCK_TOGGLE 0x0400 // caps lock toggle behaviour -#define NUM_LOCK_TOGGLE 0x0800 -#define EXT 0x1000 -static int ev2ps2[] = +static const int ev2ps2[] = { NONE, //0 KEY_RESERVED 0x76, //1 KEY_ESC @@ -347,7 +309,7 @@ static int ev2ps2[] = 0x54, //26 KEY_LEFTBRACE 0x5b, //27 KEY_RIGHTBRACE 0x5a, //28 KEY_ENTER - 0x14, //29 KEY_LEFTCTRL + LCTRL | 0x14, //29 KEY_LEFTCTRL 0x1c, //30 KEY_A 0x1b, //31 KEY_S 0x23, //32 KEY_D @@ -360,7 +322,7 @@ static int ev2ps2[] = 0x4c, //39 KEY_SEMICOLON 0x52, //40 KEY_APOSTROPHE 0x0e, //41 KEY_GRAVE - 0x12, //42 KEY_LEFTSHIFT + LSHIFT | 0x12, //42 KEY_LEFTSHIFT 0x5d, //43 KEY_BACKSLASH 0x1a, //44 KEY_Z 0x22, //45 KEY_X @@ -372,9 +334,9 @@ static int ev2ps2[] = 0x41, //51 KEY_COMMA 0x49, //52 KEY_DOT 0x4a, //53 KEY_SLASH - 0x59, //54 KEY_RIGHTSHIFT + RSHIFT | 0x59, //54 KEY_RIGHTSHIFT 0x7c, //55 KEY_KPASTERISK - 0x11, //56 KEY_LEFTALT + LALT | 0x11, //56 KEY_LEFTALT 0x29, //57 KEY_SPACE 0x58, //58 KEY_CAPSLOCK 0x05, //59 KEY_F1 @@ -387,8 +349,8 @@ static int ev2ps2[] = 0x0a, //66 KEY_F8 0x01, //67 KEY_F9 0x09, //68 KEY_F10 - 0x77, //69 KEY_NUMLOCK - 0x7E, //70 KEY_SCROLLLOCK + EMU_SWITCH_2 | 0x77, //69 KEY_NUMLOCK + EMU_SWITCH_1 | 0x7E, //70 KEY_SCROLLLOCK 0x6c, //71 KEY_KP7 0x75, //72 KEY_KP8 0x7d, //73 KEY_KP9 @@ -406,7 +368,7 @@ static int ev2ps2[] = NONE, //85 KEY_ZENKAKU NONE, //86 KEY_102ND 0x78, //87 KEY_F11 - NONE, //88 KEY_F12 + OSD_OPEN, //88 KEY_F12 NONE, //89 KEY_RO NONE, //90 KEY_KATAKANA NONE, //91 KEY_HIRAGANA @@ -415,10 +377,10 @@ static int ev2ps2[] = NONE, //94 KEY_MUHENKAN NONE, //95 KEY_KPJPCOMMA EXT | 0x5a, //96 KEY_KPENTER - EXT | 0x14, //97 KEY_RIGHTCTRL + RCTRL | EXT | 0x14, //97 KEY_RIGHTCTRL EXT | 0x4a, //98 KEY_KPSLASH NONE, //99 KEY_SYSRQ - EXT | 0x11, //100 KEY_RIGHTALT + RALT | EXT | 0x11, //100 KEY_RIGHTALT NONE, //101 KEY_LINEFEED EXT | 0x6c, //102 KEY_HOME EXT | 0x75, //103 KEY_UP @@ -443,8 +405,8 @@ static int ev2ps2[] = NONE, //122 KEY_HANGEUL NONE, //123 KEY_HANJA NONE, //124 KEY_YEN - EXT | 0x1f, //125 KEY_LEFTMETA - EXT | 0x27, //126 KEY_RIGHTMETA + LGUI | EXT | 0x1f, //125 KEY_LEFTMETA + RGUI | EXT | 0x27, //126 KEY_RIGHTMETA NONE, //127 KEY_COMPOSE NONE, //128 KEY_STOP NONE, //129 KEY_AGAIN @@ -505,14 +467,14 @@ static int ev2ps2[] = NONE, //184 KEY_F14 NONE, //185 KEY_F15 NONE, //186 KEY_F16 - NONE, //187 KEY_F17 - NONE, //188 KEY_F18 - NONE, //189 KEY_F19 - NONE, //190 KEY_F20 + EMU_SWITCH_1 | 1, //187 KEY_F17 + EMU_SWITCH_1 | 2, //188 KEY_F18 + EMU_SWITCH_1 | 3, //189 KEY_F19 + EMU_SWITCH_1 | 4, //190 KEY_F20 NONE, //191 KEY_F21 NONE, //192 KEY_F22 NONE, //193 KEY_F23 - NONE, //194 KEY_F24 + RCTRL | EXT | 0x14, //194 KEY_F24 NONE, //195 ??? NONE, //196 ??? NONE, //197 ??? @@ -576,6 +538,344 @@ static int ev2ps2[] = NONE //255 ??? }; +/* + +// unmapped atari keys: +// 0x63 KP ( +// 0x64 KP ) + +// keycode translation table for atari +const unsigned short usb2atari[] = { +MISS, // 00: NoEvent +MISS, // 01: Overrun Error +MISS, // 02: POST fail +MISS, // 03: ErrorUndefined +0x1e, // 04: a +0x30, // 05: b +0x2e, // 06: c +0x20, // 07: d +0x12, // 08: e +0x21, // 09: f +0x22, // 0a: g +0x23, // 0b: h +0x17, // 0c: i +0x24, // 0d: j +0x25, // 0e: k +0x26, // 0f: l +0x32, // 10: m +0x31, // 11: n +0x18, // 12: o +0x19, // 13: p +0x10, // 14: q +0x13, // 15: r +0x1f, // 16: s +0x14, // 17: t +0x16, // 18: u +0x2f, // 19: v +0x11, // 1a: w +0x2d, // 1b: x +0x15, // 1c: y +0x2c, // 1d: z +0x02, // 1e: 1 +0x03, // 1f: 2 +0x04, // 20: 3 +0x05, // 21: 4 +0x06, // 22: 5 +0x07, // 23: 6 +0x08, // 24: 7 +0x09, // 25: 8 +0x0a, // 26: 9 +0x0b, // 27: 0 +0x1c, // 28: Return +0x01, // 29: Escape +0x0e, // 2a: Backspace +0x0f, // 2b: Tab +0x39, // 2c: Space +0x0c, // 2d: - +0x0d, // 2e: = +0x1a, // 2f: [ +0x1b, // 30: ] +0x29, // 31: backslash, only on us keyboard +0x29, // 32: Europe 1, only on int. keyboard +0x27, // 33: ; +0x28, // 34: ' +0x2b, // 35: ` +0x33, // 36: , +0x34, // 37: . +0x35, // 38: / +0x3a | CAPS_LOCK_TOGGLE, // 39: Caps Lock +0x3b, // 3a: F1 +0x3c, // 3b: F2 +0x3d, // 3c: F3 +0x3e, // 3d: F4 +0x3f, // 3e: F5 +0x40, // 3f: F6 +0x41, // 40: F7 +0x42, // 41: F8 +0x43, // 42: F9 +0x44, // 43: F10 +MISS, // 44: F11 +OSD_OPEN, // 45: F12 +MISS, // 46: Print Screen +NUM_LOCK_TOGGLE, // 47: Scroll Lock +MISS, // 48: Pause +0x52, // 49: Insert +0x47, // 4a: Home +0x62, // 4b: Page Up +0x53, // 4c: Delete +MISS, // 4d: End +0x61, // 4e: Page Down +0x4d, // 4f: Right Arrow +0x4b, // 50: Left Arrow +0x50, // 51: Down Arrow +0x48, // 52: Up Arrow +NUM_LOCK_TOGGLE, // 53: Num Lock +0x65, // 54: KP / +0x66, // 55: KP * +0x4a, // 56: KP - +0x4e, // 57: KP + +0x72, // 58: KP Enter +0x6d, // 59: KP 1 +0x6e, // 5a: KP 2 +0x6f, // 5b: KP 3 +0x6a, // 5c: KP 4 +0x6b, // 5d: KP 5 +0x6c, // 5e: KP 6 +0x67, // 5f: KP 7 +0x68, // 60: KP 8 +0x69, // 61: KP 9 +0x70, // 62: KP 0 +0x71, // 63: KP . +0x60, // 64: Europe 2 +OSD_OPEN, // 65: App +MISS, // 66: Power +MISS, // 67: KP = +MISS, // 68: F13 +MISS, // 69: F14 +MISS, // 6a: F15 +0x52, // 6b: insert (for keyrah) +NUM_LOCK_TOGGLE | 1, // 6c: F17 +NUM_LOCK_TOGGLE | 2, // 6d: F18 +NUM_LOCK_TOGGLE | 3, // 6e: F19 +NUM_LOCK_TOGGLE | 4 // 6f: F20 +}; +*/ + +/* + +// Archimedes unmapped keys +// Missing sterling +// Missing kp_hash +// Missing button_1 +// Missing button_2 +// Missing button_3 +// Missing button_4 +// Missing button_5 + +// keycode translation table +const unsigned short usb2archie[] = { +MISS, // 00: NoEvent +MISS, // 01: Overrun Error +MISS, // 02: POST fail +MISS, // 03: ErrorUndefined +0x3c, // 04: a +0x52, // 05: b +0x50, // 06: c +0x3e, // 07: d +0x29, // 08: e +0x3f, // 09: f +0x40, // 0a: g +0x41, // 0b: h +0x2e, // 0c: i +0x42, // 0d: j +0x43, // 0e: k +0x44, // 0f: l +0x54, // 10: m +0x53, // 11: n +0x2f, // 12: o +0x30, // 13: p +0x27, // 14: q +0x2a, // 15: r +0x3d, // 16: s +0x2b, // 17: t +0x2d, // 18: u +0x51, // 19: v +0x28, // 1a: w +0x4f, // 1b: x +0x2c, // 1c: y +0x4e, // 1d: z +0x11, // 1e: 1 +0x12, // 1f: 2 +0x13, // 20: 3 +0x14, // 21: 4 +0x15, // 22: 5 +0x16, // 23: 6 +0x17, // 24: 7 +0x18, // 25: 8 +0x19, // 26: 9 +0x1a, // 27: 0 +0x47, // 28: Return +0x00, // 29: Escape +0x1e, // 2a: Backspace +0x26, // 2b: Tab +0x5f, // 2c: Space +0x1b, // 2d: - +0x1c, // 2e: = +0x31, // 2f: [ +0x32, // 30: ] +0x33, // 31: backslash (only on us keyboards) +0x33, // 32: Europe 1 (only on international kbds) +0x45, // 33: ; +0x46, // 34: ' +0x10, // 35: ` +0x55, // 36: , +0x56, // 37: . +0x57, // 38: / +0x5d, // 39: Caps Lock +0x01, // 3a: F1 +0x02, // 3b: F2 +0x03, // 3c: F3 +0x04, // 3d: F4 +0x05, // 3e: F5 +0x06, // 3f: F6 +0x07, // 40: F7 +0x08, // 41: F8 +0x09, // 42: F9 +0x0a, // 43: F10 +0x0b, // 44: F11 +0x0c, // 45: F12 - Used heavily by the archie... OSD moved to printscreen. +// 0x0d, // 46: Print Screen +OSD_OPEN, // 46: Print Screen +0x0e, // 47: Scroll Lock +0x0f, // 48: Pause +0x1f, // 49: Insert +0x20, // 4a: Home +0x21, // 4b: Page Up +0x34, // 4c: Delete +0x35, // 4d: End +0x36, // 4e: Page Down +0x64, // 4f: Right Arrow +0x62, // 50: Left Arrow +0x63, // 51: Down Arrow +0x59, // 52: Up Arrow +0x22, // 53: Num Lock +0x23, // 54: KP / +0x24, // 55: KP * +0x3a, // 56: KP - +0x4b, // 57: KP + +0x67, // 58: KP Enter +0x5a, // 59: KP 1 +0x5b, // 5a: KP 2 +0x5c, // 5b: KP 3 +0x48, // 5c: KP 4 +0x49, // 5d: KP 5 +0x4a, // 5e: KP 6 +0x37, // 5f: KP 7 +0x38, // 60: KP 8 +0x39, // 61: KP 9 +0x65, // 62: KP 0 +0x66, // 63: KP decimal +MISS, // 64: Europe 2 +0x72, // 65: App (maps to middle mouse button) +MISS, // 66: Power +MISS, // 67: KP = +MISS, // 68: F13 +MISS, // 69: F14 +MISS, // 6a: F15 +0x1f, // 6b: insert (for keyrah) +MISS, // 6c: F17 +MISS, // 6d: F18 +MISS, // 6e: F19 +MISS, // 6f: F20 +}; +*/ + +/* +unsigned short modifier_keycode(unsigned char index) +{ +// usb modifer bits: +//0 1 2 3 4 5 6 7 +//LCTRL LSHIFT LALT LGUI RCTRL RSHIFT RALT RGUI + +if (core_type == CORE_TYPE_MINIMIG2) +{ +static const unsigned short amiga_modifier[] = { 0x63, 0x60, 0x64, 0x66, 0x63, 0x61, 0x65, 0x67 }; +return amiga_modifier[index]; +} + +if (core_type == CORE_TYPE_MIST) +{ +static const unsigned short atari_modifier[] = { 0x1d, 0x2a, 0x38, MISS, 0x1d, 0x36, 0x38, MISS }; +return atari_modifier[index]; +} + +if (core_type == CORE_TYPE_8BIT) +{ +static const unsigned short ps2_modifier[] = { 0x14, 0x12, 0x11, EXT | 0x1f, EXT | 0x14, 0x59, EXT | 0x11, EXT | 0x27 }; +return ps2_modifier[index]; +} + +if (core_type == CORE_TYPE_ARCHIE) +{ +static const unsigned short archie_modifier[] = { 0x36, 0x4c, 0x5e, MISS, 0x61, 0x58, 0x60, MISS }; +return archie_modifier[index]; +} + +return MISS; +} +*/ + + +uint32_t get_ps2_code(uint16_t key) +{ + if (key > 255) return NONE; + return ev2ps2[key]; +} + +uint32_t get_amiga_code(uint16_t key) +{ + if (key > 255) return NONE; + return ev2amiga[key]; +} + +uint32_t get_atari_code(uint16_t key) +{ + if (key > 255) return NONE; + return 0; // ev2atari[key]; +} + +uint32_t get_archie_code(uint16_t key) +{ + if (key > 255) return NONE; + return 0; // ev2archie[key]; +} + +static uint32_t modifier = 0; + +uint32_t get_key_mod() +{ + return modifier & MODMASK; +} + +typedef struct +{ + uint16_t vid, pid; + char led; + char last_l, last_r, last_u, last_d; + + char has_map; + uint32_t map[32]; + + char has_mmap; + uint32_t mmap[32]; + + char has_kbdmap; + uint8_t kbdmap[256]; +} devInput; + +static devInput input[NUMDEV] = { 0 }; +static int first_joystick = -1; + int mfd = -1; int mwd = -1; @@ -789,51 +1089,51 @@ uint16_t get_map_pid() static char kr_fn_table[] = { - 0x54, 0x48, // pause/break - 0x55, 0x46, // prnscr - 0x50, 0x4a, // home - 0x4f, 0x4d, // end - 0x52, 0x4b, // pgup - 0x51, 0x4e, // pgdown - 0x3a, 0x44, // f11 - 0x3b, 0x45, // f12 + KEY_KPSLASH, KEY_PAUSE, + KEY_KPASTERISK, KEY_PRINT, + KEY_LEFT, KEY_HOME, + KEY_RIGHT, KEY_END, + KEY_UP, KEY_PAGEUP, + KEY_DOWN, KEY_PAGEDOWN, + KEY_F1, KEY_F11, + KEY_F2, KEY_F12, - 0x3c, 0x6c, // EMU_MOUSE - 0x3d, 0x6d, // EMU_JOY0 - 0x3e, 0x6e, // EMU_JOY1 - 0x3f, 0x6f, // EMU_NONE + KEY_F3, KEY_F17, // EMU_MOUSE + KEY_F4, KEY_F18, // EMU_JOY0 + KEY_F5, KEY_F19, // EMU_JOY1 + KEY_F6, KEY_F20, // EMU_NONE - //Emulate keypad for A600 - 0x1E, 0x59, //KP1 - 0x1F, 0x5A, //KP2 - 0x20, 0x5B, //KP3 - 0x21, 0x5C, //KP4 - 0x22, 0x5D, //KP5 - 0x23, 0x5E, //KP6 - 0x24, 0x5F, //KP7 - 0x25, 0x60, //KP8 - 0x26, 0x61, //KP9 - 0x27, 0x62, //KP0 - 0x2D, 0x56, //KP- - 0x2E, 0x57, //KP+ - 0x31, 0x55, //KP* - 0x2F, 0x68, //KP( - 0x30, 0x69, //KP) - 0x37, 0x63, //KP. - 0x28, 0x58 //KP Enter + //Emulate keypad for A600 + KEY_1, KEY_KP1, + KEY_2, KEY_KP2, + KEY_3, KEY_KP3, + KEY_4, KEY_KP4, + KEY_5, KEY_KP5, + KEY_6, KEY_KP6, + KEY_7, KEY_KP7, + KEY_8, KEY_KP8, + KEY_9, KEY_KP9, + KEY_0, KEY_KP0, + KEY_MINUS, KEY_KPMINUS, + KEY_EQUAL, KEY_KPPLUS, + KEY_BACKSLASH, KEY_KPASTERISK, + KEY_LEFTBRACE, KEY_F13, //KP( + KEY_RIGHTBRACE, KEY_F14, //KP) + KEY_DOT, KEY_KPDOT, + KEY_ENTER, KEY_KPENTER }; static int keyrah_trans(int key, int press) { static int fn = 0; - if (key == 0x53) return 0x68; - if (key == 0x47) return 0x69; - if (key == 0x49) return 0x6b; // workaround! + if (key == KEY_NUMLOCK) return KEY_F13; // numlock -> f13 + if (key == KEY_SCROLLLOCK) return KEY_F14; // scrlock -> f14 + if (key == KEY_INSERT) return KEY_F16; // insert -> f16. workaround! - if (key == FN) + if (key == KEY_102ND) { - if (!press && fn == 1) menu_key_set(KEY_AMI_MENU); + if (!press && fn == 1) menu_key_set(KEY_F12); fn = press ? 1 : 0; return 0; } @@ -987,95 +1287,12 @@ static void joy_analog(int num, int axis, int offset) } } -static int input_cb_x86(struct input_event *ev, int dev) -{ - if(user_io_osd_is_visible() || ev->type != EV_KEY || !is_x86_core() || ev->code>255) return 0; - - int code = ev2ps2[ev->code]; - if (code == NONE) return 0; - - //pause - if ((code & 0xff) == 0xE1) - { - // pause does not have a break code - if (ev->value != 1) - { - // Pause key sends E11477E1F014E077 - static const unsigned char c[] = { 0xe1, 0x14, 0x77, 0xe1, 0xf0, 0x14, 0xf0, 0x77, 0x00 }; - const unsigned char *p = c; - - spi_uio_cmd_cont(UIO_KEYBOARD); - - printf("PS2 PAUSE CODE: "); - while (*p) - { - printf("%x ", *p); - spi8(*p++); - } - printf("\n"); - - DisableIO(); - } - } - // print screen - else if ((code & 0xff) == 0xE2) - { - if (ev->value <= 1) - { - static const unsigned char c[2][8] = { - { 0xE0, 0xF0, 0x7C, 0xE0, 0xF0, 0x12, 0x00, 0x00 }, - { 0xE0, 0x12, 0xE0, 0x7C, 0x00, 0x00, 0x00, 0x00 } - }; - - const unsigned char *p = c[ev->value]; - - spi_uio_cmd_cont(UIO_KEYBOARD); - - printf("PS2 PRINT CODE: "); - while (*p) - { - printf("%x ", *p); - spi8(*p++); - } - printf("\n"); - - DisableIO(); - } - } - else - { - spi_uio_cmd_cont(UIO_KEYBOARD); - /* - iprintf("PS2 KBD "); - if (code & EXT) iprintf("e0 "); - if (code & BREAK) iprintf("f0 "); - iprintf("%x\n", code & 0xff); - */ - - // prepend extended code flag if required - if (code & EXT) spi8(0xe0); - - // prepend break code if required - if (!ev->value) spi8(0xf0); - - // send code itself - spi8(code & 0xff); - - DisableIO(); - } - - return 1; -} - static void input_cb(struct input_event *ev, int dev) { static int key_mapped = 0; static uint8_t modifiers = 0; static char keys[6] = { 0,0,0,0,0,0 }; - // repeat events won't be processed - if (ev->type == EV_KEY && ev->value > 1) return; - int map_skip = (ev->type == EV_KEY && ev->code == 57 && mapping_dev >= 0 && mapping_type==1); int cancel = (ev->type == EV_KEY && ev->code == 1); int enter = (ev->type == EV_KEY && ev->code == 28); @@ -1086,9 +1303,12 @@ static void input_cb(struct input_event *ev, int dev) case EV_KEY: if (ev->code >= 272 && ev->code <= 279) { - unsigned char mask = 1 << (ev->code - 272); - mouse_btn = (ev->value) ? mouse_btn | mask : mouse_btn & ~mask; - user_io_mouse(mouse_btn, 0, 0); + if (ev->value <= 1) + { + unsigned char mask = 1 << (ev->code - 272); + mouse_btn = (ev->value) ? mouse_btn | mask : mouse_btn & ~mask; + user_io_mouse(mouse_btn, 0, 0); + } return; } break; @@ -1148,7 +1368,7 @@ static void input_cb(struct input_event *ev, int dev) { if (mapping_type == 2) { - if (ev->value && ev->code < 256) + if (ev->value == 1 && ev->code < 256) { if(mapping_dev < 0) { @@ -1175,7 +1395,7 @@ static void input_cb(struct input_event *ev, int dev) if (mapping_dev == dev && mapping_button < mapping_count) { - if (ev->value) + if (ev->value == 1) { if (!mapping_button) memset(input[dev].map, 0, sizeof(input[dev].map)); @@ -1188,7 +1408,7 @@ static void input_cb(struct input_event *ev, int dev) key_mapped = 1; } } - else + else if(ev->value == 0) { if (key_mapped) mapping_button++; key_mapped = 0; @@ -1250,7 +1470,7 @@ static void input_cb(struct input_event *ev, int dev) { if (ev->code == input[dev].map[i]) { - joy_digital((first_joystick == dev) ? 0 : 1, 1 << i, ev->value, i); + if(ev->value <= 1) joy_digital((first_joystick == dev) ? 0 : 1, 1 << i, ev->value, i); return; } } @@ -1261,7 +1481,7 @@ static void input_cb(struct input_event *ev, int dev) { if (ev->code == input[dev].map[i]) { - joy_digital((first_joystick == dev) ? 0 : 1, 1 << i, ev->value, i); + if (ev->value <= 1) joy_digital((first_joystick == dev) ? 0 : 1, 1 << i, ev->value, i); return; } } @@ -1270,7 +1490,7 @@ static void input_cb(struct input_event *ev, int dev) { if (ev->code == input[dev].mmap[i]) { - joy_digital((first_joystick == dev) ? 0 : 1, 1 << (i - 8), ev->value, i - 8); + if (ev->value <= 1) joy_digital((first_joystick == dev) ? 0 : 1, 1 << (i - 8), ev->value, i - 8); return; } } @@ -1278,11 +1498,11 @@ static void input_cb(struct input_event *ev, int dev) if (ev->code == input[dev].map[17]) { - joy_digital((first_joystick == dev) ? 0 : 1, 0, ev->value, 17); + if (ev->value <= 1) joy_digital((first_joystick == dev) ? 0 : 1, 0, ev->value, 17); return; } - if (ev->code == input[dev].mmap[15]) + if (ev->code == input[dev].mmap[15] && (ev->value <= 1)) { mouse_emu = ev->value ? mouse_emu | 1 : mouse_emu & ~1; printf("mouse_emu = %d\n", mouse_emu); @@ -1312,7 +1532,7 @@ static void input_cb(struct input_event *ev, int dev) { if (ev->code == input[dev].map[i]) { - joy_digital((user_io_get_kbdemu() == EMU_JOY0) ? 0 : 1, 1 << i, ev->value, i); + if (ev->value <= 1) joy_digital((user_io_get_kbdemu() == EMU_JOY0) ? 0 : 1, 1 << i, ev->value, i); return; } } @@ -1320,7 +1540,7 @@ static void input_cb(struct input_event *ev, int dev) if (ev->code == input[dev].map[16]) { - joy_digital((user_io_get_kbdemu() == EMU_JOY0) ? 0 : 1, 0, ev->value, 16); + if (ev->value <= 1) joy_digital((user_io_get_kbdemu() == EMU_JOY0) ? 0 : 1, 0, ev->value, 16); return; } } @@ -1363,14 +1583,14 @@ static void input_cb(struct input_event *ev, int dev) if (ev->code == input[dev].mmap[15]) { - mouse_sniper = ev->value; + if (ev->value <= 1) mouse_sniper = ev->value; return; } } if (ev->code == input[dev].map[16]) { - if (ev->value) + if (ev->value == 1) { kbd_mouse_emu = !kbd_mouse_emu; printf("kbd_mouse_emu = %d\n", kbd_mouse_emu); @@ -1394,34 +1614,27 @@ static void input_cb(struct input_event *ev, int dev) input[dev].has_kbdmap = 1; } - int key = input[dev].kbdmap[ev->code] ? input[dev].kbdmap[ev->code] : ev->code; - key = (key < (sizeof(ev2usb) / sizeof(ev2usb[0]))) ? ev2usb[key] : NONE; - if(key != NONE) - { - static uint16_t mod = 0; + static uint16_t mod = 0; - //Keyrah v2: USB\VID_18D8&PID_0002\A600/A1200_MULTIMEDIA_EXTENSION_VERSION - int keyrah = (mist_cfg.keyrah_mode && (((((uint32_t)input[dev].vid) << 16) | input[dev].pid) == mist_cfg.keyrah_mode)); + // replace MENU key by RGUI to allow using Right Amiga on reduced keyboards + // (it also disables the use of Menu for OSD) + uint16_t code = ev->code; + if (mist_cfg.key_menu_as_rgui && code == 139) code = 126; - if (keyrah) key = keyrah_trans(key, ev->value); - if (key & 0xffff) - { - unsigned short reset_m = mod >> 8; - if (key == 0x4c) reset_m |= 0x100; - user_io_check_reset(reset_m, (keyrah && !mist_cfg.reset_combo) ? 1 : mist_cfg.reset_combo); + //Keyrah v2: USB\VID_18D8&PID_0002\A600/A1200_MULTIMEDIA_EXTENSION_VERSION + int keyrah = (mist_cfg.keyrah_mode && (((((uint32_t)input[dev].vid) << 16) | input[dev].pid) == mist_cfg.keyrah_mode)); + if (keyrah) code = keyrah_trans(code, ev->value); - if (key & MODMASK) - { - if (ev->value) mod |= key; - else mod &= ~key; - } - key = (mod & MODMASK) | (key & ~MODMASK); + uint32_t ps2code = get_ps2_code(code); + if (ev->value) modifier |= ps2code; + else modifier &= ~ps2code; - menu_mod_set(mod >> 8); - user_io_kbd((uint16_t)key, ev->value); - } - return; - } + uint16_t reset_m = (modifier & MODMASK) >> 8; + if (code == 111) reset_m |= 0x100; + user_io_check_reset(reset_m, (keyrah && !mist_cfg.reset_combo) ? 1 : mist_cfg.reset_combo); + + user_io_kbd(code, ev->value); + return; } break; @@ -1615,8 +1828,7 @@ int input_test(int getchar) } } - - if(!input_cb_x86(&ev, i)) input_cb(&ev, i); + input_cb(&ev, i); //sumulate digital directions from analog if (ev.type == EV_ABS && !(ev.code<=1 && mouse_emu && !user_io_osd_is_visible())) diff --git a/input.h b/input.h index c73bdaa..77061f6 100644 --- a/input.h +++ b/input.h @@ -2,11 +2,33 @@ #ifndef EVINPUT_H #define EVINPUT_H +#include + #define HID_LED_NUM_LOCK 1 #define HID_LED_CAPS_LOCK 2 #define HID_LED_SCROLL_LOCK 4 #define HID_LED_MASK 7 +#define NONE 0xFF +#define LCTRL 0x000100 +#define LSHIFT 0x000200 +#define LALT 0x000400 +#define LGUI 0x000800 +#define RCTRL 0x001000 +#define RSHIFT 0x002000 +#define RALT 0x004000 +#define RGUI 0x008000 +#define MODMASK 0x00FF00 + +#define OSD 0x010000 // to be used by OSD, not the core itself +#define OSD_OPEN 0x020000 // OSD key not forwarded to core, but queued in arm controller +#define CAPS_TOGGLE 0x040000 // caps lock toggle behaviour +#define EXT 0x080000 +#define EMU_SWITCH_1 0x100000 +#define EMU_SWITCH_2 0x200000 + +#define UPSTROKE 0x400000 + void set_kbdled(int mask, int state); int get_kbdled(int mask); int toggle_kbdled(int mask); @@ -22,4 +44,10 @@ void finish_map_setting(int dismiss); uint16_t get_map_vid(); uint16_t get_map_pid(); +uint32_t get_key_mod(); +uint32_t get_ps2_code(uint16_t key); +uint32_t get_amiga_code(uint16_t key); +uint32_t get_atari_code(uint16_t key); +uint32_t get_archie_code(uint16_t key); + #endif diff --git a/keycodes.h b/keycodes.h deleted file mode 100644 index e41f558..0000000 --- a/keycodes.h +++ /dev/null @@ -1,509 +0,0 @@ -// http://wiki.amigaos.net/index.php/Keymap_Library -// http://www.win.tue.nl/~aeb/linux/kbd/scancodes-14.html - -#include "osd.h" - -#ifndef KEYCODES_H -#define KEYCODES_H - -#define MISS 0xff -#define KEYCODE_MAX (0x6f) - -// The original minimig had the keyboard connected to the FPGA. Thus all key events (even for OSD) -// came from the FPGA core. The MIST has the keyboard attached to the arm controller. To be compatible -// with the minimig core all keys (incl. OSD!) are forwarded to the FPGA and the OSD keys are returned. -// These keys are tagged with the "OSD" flag -// The atari/mist core does not forwards keys through the FPGA but queues them inside the arm controller. -// Keys flagged with "OSD_OPEN" are used to open the OSD in non-minimig. They can have a keycode which -// will be sent into the core - -#define OSD 0x0100 // to be used by OSD, not the core itself -#define OSD_OPEN 0x0200 // OSD key not forwarded to core, but queued in arm controller -#define CAPS_LOCK_TOGGLE 0x0400 // caps lock toggle behaviour -#define NUM_LOCK_TOGGLE 0x0800 -#define EXT 0x1000 // extended PS/2 keycode - -// amiga unmapped: -// 0x5a KP-( (mapped on Keyrah) -// 0x5b KP-) (mapped on Keyrah) -// codes >= 0x69 are for OSD only and are not sent to the amiga itself - -// keycode translation table -const unsigned short usb2ami[] = { - MISS, // 00: NoEvent - MISS, // 01: Overrun Error - MISS, // 02: POST fail - MISS, // 03: ErrorUndefined - 0x20, // 04: a - 0x35, // 05: b - 0x33, // 06: c - 0x22, // 07: d - 0x12, // 08: e - 0x23, // 09: f - 0x24, // 0a: g - 0x25, // 0b: h - 0x17, // 0c: i - 0x26, // 0d: j - 0x27, // 0e: k - 0x28, // 0f: l - 0x37, // 10: m - 0x36, // 11: n - 0x18, // 12: o - 0x19, // 13: p - 0x10, // 14: q - 0x13, // 15: r - 0x21, // 16: s - 0x14, // 17: t - 0x16, // 18: u - 0x34, // 19: v - 0x11, // 1a: w - 0x32, // 1b: x - 0x15, // 1c: y - 0x31, // 1d: z - 0x01, // 1e: 1 - 0x02, // 1f: 2 - 0x03, // 20: 3 - 0x04, // 21: 4 - 0x05, // 22: 5 - 0x06, // 23: 6 - 0x07, // 24: 7 - 0x08, // 25: 8 - 0x09, // 26: 9 - 0x0a, // 27: 0 - 0x44, // 28: Return - 0x45, // 29: Escape - 0x41, // 2a: Backspace - 0x42, // 2b: Tab - 0x40, // 2c: Space - 0x0b, // 2d: - - 0x0c, // 2e: = - 0x1a, // 2f: [ - 0x1b, // 30: ] - 0x0d, // 31: backslash (only on us keyboards) - 0x2b, // 32: Europe 1 (only on international keyboards) - 0x29, // 33: ; - 0x2a, // 34: ' - 0x00, // 35: ` - 0x38, // 36: , - 0x39, // 37: . - 0x3a, // 38: / - 0x62 | CAPS_LOCK_TOGGLE, // 39: Caps Lock - 0x50, // 3a: F1 - 0x51, // 3b: F2 - 0x52, // 3c: F3 - 0x53, // 3d: F4 - 0x54, // 3e: F5 - 0x55, // 3f: F6 - 0x56, // 40: F7 - 0x57, // 41: F8 - 0x58, // 42: F9 - 0x59, // 43: F10 - 0x5f, // 44: F11 - OSD_OPEN, // 45: F12 (OSD) - 0x6e | OSD, // 46: Print Screen (OSD) - NUM_LOCK_TOGGLE, // 47: Scroll Lock (OSD) - 0x6f | OSD, // 48: Pause - 0x0d, // 49: backslash to avoid panic in Germany ;) - 0x6a, // 4a: Home - 0x6c | OSD, // 4b: Page Up (OSD) - 0x46, // 4c: Delete - MISS, // 4d: End - 0x6d | OSD, // 4e: Page Down (OSD) - 0x4e, // 4f: Right Arrow - 0x4f, // 50: Left Arrow - 0x4d, // 51: Down Arrow - 0x4c, // 52: Up Arrow - NUM_LOCK_TOGGLE, // 53: Num Lock - 0x5c, // 54: KP / - 0x5d, // 55: KP * - 0x4a, // 56: KP - - 0x5e, // 57: KP + - 0x43, // 58: KP Enter - 0x1d, // 59: KP 1 - 0x1e, // 5a: KP 2 - 0x1f, // 5b: KP 3 - 0x2d, // 5c: KP 4 - 0x2e, // 5d: KP 5 - 0x2f, // 5e: KP 6 - 0x3d, // 5f: KP 7 - 0x3e, // 60: KP 8 - 0x3f, // 61: KP 9 - 0x0f, // 62: KP 0 - 0x3c, // 63: KP . - 0x30, // 64: Europe 2 - 0x69 | OSD, // 65: App - MISS, // 66: Power - MISS, // 67: KP = - 0x5a, // 68: KP ( - 0x5b, // 69: KP ) - MISS, // 6a: F15 - 0x5f, // 6b: help (for keyrah) - NUM_LOCK_TOGGLE | 1, // 6c: F17 - NUM_LOCK_TOGGLE | 2, // 6d: F18 - NUM_LOCK_TOGGLE | 3, // 6e: F19 - NUM_LOCK_TOGGLE | 4 // 6f: F20 -}; - -// unmapped atari keys: -// 0x63 KP ( -// 0x64 KP ) - -// keycode translation table for atari -const unsigned short usb2atari[] = { - MISS, // 00: NoEvent - MISS, // 01: Overrun Error - MISS, // 02: POST fail - MISS, // 03: ErrorUndefined - 0x1e, // 04: a - 0x30, // 05: b - 0x2e, // 06: c - 0x20, // 07: d - 0x12, // 08: e - 0x21, // 09: f - 0x22, // 0a: g - 0x23, // 0b: h - 0x17, // 0c: i - 0x24, // 0d: j - 0x25, // 0e: k - 0x26, // 0f: l - 0x32, // 10: m - 0x31, // 11: n - 0x18, // 12: o - 0x19, // 13: p - 0x10, // 14: q - 0x13, // 15: r - 0x1f, // 16: s - 0x14, // 17: t - 0x16, // 18: u - 0x2f, // 19: v - 0x11, // 1a: w - 0x2d, // 1b: x - 0x15, // 1c: y - 0x2c, // 1d: z - 0x02, // 1e: 1 - 0x03, // 1f: 2 - 0x04, // 20: 3 - 0x05, // 21: 4 - 0x06, // 22: 5 - 0x07, // 23: 6 - 0x08, // 24: 7 - 0x09, // 25: 8 - 0x0a, // 26: 9 - 0x0b, // 27: 0 - 0x1c, // 28: Return - 0x01, // 29: Escape - 0x0e, // 2a: Backspace - 0x0f, // 2b: Tab - 0x39, // 2c: Space - 0x0c, // 2d: - - 0x0d, // 2e: = - 0x1a, // 2f: [ - 0x1b, // 30: ] - 0x29, // 31: backslash, only on us keyboard - 0x29, // 32: Europe 1, only on int. keyboard - 0x27, // 33: ; - 0x28, // 34: ' - 0x2b, // 35: ` - 0x33, // 36: , - 0x34, // 37: . - 0x35, // 38: / - 0x3a | CAPS_LOCK_TOGGLE, // 39: Caps Lock - 0x3b, // 3a: F1 - 0x3c, // 3b: F2 - 0x3d, // 3c: F3 - 0x3e, // 3d: F4 - 0x3f, // 3e: F5 - 0x40, // 3f: F6 - 0x41, // 40: F7 - 0x42, // 41: F8 - 0x43, // 42: F9 - 0x44, // 43: F10 - MISS, // 44: F11 - OSD_OPEN, // 45: F12 - MISS, // 46: Print Screen - NUM_LOCK_TOGGLE, // 47: Scroll Lock - MISS, // 48: Pause - 0x52, // 49: Insert - 0x47, // 4a: Home - 0x62, // 4b: Page Up - 0x53, // 4c: Delete - MISS, // 4d: End - 0x61, // 4e: Page Down - 0x4d, // 4f: Right Arrow - 0x4b, // 50: Left Arrow - 0x50, // 51: Down Arrow - 0x48, // 52: Up Arrow - NUM_LOCK_TOGGLE, // 53: Num Lock - 0x65, // 54: KP / - 0x66, // 55: KP * - 0x4a, // 56: KP - - 0x4e, // 57: KP + - 0x72, // 58: KP Enter - 0x6d, // 59: KP 1 - 0x6e, // 5a: KP 2 - 0x6f, // 5b: KP 3 - 0x6a, // 5c: KP 4 - 0x6b, // 5d: KP 5 - 0x6c, // 5e: KP 6 - 0x67, // 5f: KP 7 - 0x68, // 60: KP 8 - 0x69, // 61: KP 9 - 0x70, // 62: KP 0 - 0x71, // 63: KP . - 0x60, // 64: Europe 2 - OSD_OPEN, // 65: App - MISS, // 66: Power - MISS, // 67: KP = - MISS, // 68: F13 - MISS, // 69: F14 - MISS, // 6a: F15 - 0x52, // 6b: insert (for keyrah) - NUM_LOCK_TOGGLE | 1, // 6c: F17 - NUM_LOCK_TOGGLE | 2, // 6d: F18 - NUM_LOCK_TOGGLE | 3, // 6e: F19 - NUM_LOCK_TOGGLE | 4 // 6f: F20 -}; - -// keycode translation table for ps2 emulation -const unsigned short usb2ps2[] = { - MISS, // 00: NoEvent - MISS, // 01: Overrun Error - MISS, // 02: POST fail - MISS, // 03: ErrorUndefined - 0x1c, // 04: a - 0x32, // 05: b - 0x21, // 06: c - 0x23, // 07: d - 0x24, // 08: e - 0x2b, // 09: f - 0x34, // 0a: g - 0x33, // 0b: h - 0x43, // 0c: i - 0x3b, // 0d: j - 0x42, // 0e: k - 0x4b, // 0f: l - 0x3a, // 10: m - 0x31, // 11: n - 0x44, // 12: o - 0x4d, // 13: p - 0x15, // 14: q - 0x2d, // 15: r - 0x1b, // 16: s - 0x2c, // 17: t - 0x3c, // 18: u - 0x2a, // 19: v - 0x1d, // 1a: w - 0x22, // 1b: x - 0x35, // 1c: y - 0x1a, // 1d: z - 0x16, // 1e: 1 - 0x1e, // 1f: 2 - 0x26, // 20: 3 - 0x25, // 21: 4 - 0x2e, // 22: 5 - 0x36, // 23: 6 - 0x3d, // 24: 7 - 0x3e, // 25: 8 - 0x46, // 26: 9 - 0x45, // 27: 0 - 0x5a, // 28: Return - 0x76, // 29: Escape - 0x66, // 2a: Backspace - 0x0d, // 2b: Tab - 0x29, // 2c: Space - 0x4e, // 2d: - - 0x55, // 2e: = - 0x54, // 2f: [ - 0x5b, // 30: ] - 0x5d, // 31: backslash - 0x5d, // 32: Europe 1 - 0x4c, // 33: ; - 0x52, // 34: ' - 0x0e, // 35: ` - 0x41, // 36: , - 0x49, // 37: . - 0x4a, // 38: / - 0x58, // 39: Caps Lock - 0x05, // 3a: F1 - 0x06, // 3b: F2 - 0x04, // 3c: F3 - 0x0c, // 3d: F4 - 0x03, // 3e: F5 - 0x0b, // 3f: F6 - 0x83, // 40: F7 - 0x0a, // 41: F8 - 0x01, // 42: F9 - 0x09, // 43: F10 - 0x78, // 44: F11 - OSD_OPEN | 0x07, // 45: F12 (OSD) - EXT | 0x7c, // 46: Print Screen - NUM_LOCK_TOGGLE, // 47: Scroll Lock - 0x77, // 48: Pause (special key handled inside user_io) - EXT | 0x70, // 49: Insert - EXT | 0x6c, // 4a: Home - EXT | 0x7d, // 4b: Page Up - EXT | 0x71, // 4c: Delete - EXT | 0x69, // 4d: End - EXT | 0x7a, // 4e: Page Down - EXT | 0x74, // 4f: Right Arrow - EXT | 0x6b, // 50: Left Arrow - EXT | 0x72, // 51: Down Arrow - EXT | 0x75, // 52: Up Arrow - NUM_LOCK_TOGGLE, // 53: Num Lock - EXT | 0x4a, // 54: KP / - 0x7c, // 55: KP * - 0x7b, // 56: KP - - 0x79, // 57: KP + - EXT | 0x5a, // 58: KP Enter - 0x69, // 59: KP 1 - 0x72, // 5a: KP 2 - 0x7a, // 5b: KP 3 - 0x6b, // 5c: KP 4 - 0x73, // 5d: KP 5 - 0x74, // 5e: KP 6 - 0x6c, // 5f: KP 7 - 0x75, // 60: KP 8 - 0x7d, // 61: KP 9 - 0x70, // 62: KP 0 - 0x71, // 63: KP . - 0x61, // 64: Europe 2 - OSD_OPEN | EXT | 0x2f, // 65: App - EXT | 0x37, // 66: Power - 0x0f, // 67: KP = - 0x77, // 68: Num Lock - 0x7e, // 69: Scroll Lock - 0x18, // 6a: F15 - EXT | 0x70, // 6b: insert (for keyrah) - NUM_LOCK_TOGGLE | 1, // 6c: F17 - NUM_LOCK_TOGGLE | 2, // 6d: F18 - NUM_LOCK_TOGGLE | 3, // 6e: F19 - NUM_LOCK_TOGGLE | 4 // 6f: F20 -}; - -// Archimedes unmapped keys -// Missing sterling -// Missing kp_hash -// Missing button_1 -// Missing button_2 -// Missing button_3 -// Missing button_4 -// Missing button_5 - -// keycode translation table -const unsigned short usb2archie[] = { - MISS, // 00: NoEvent - MISS, // 01: Overrun Error - MISS, // 02: POST fail - MISS, // 03: ErrorUndefined - 0x3c, // 04: a - 0x52, // 05: b - 0x50, // 06: c - 0x3e, // 07: d - 0x29, // 08: e - 0x3f, // 09: f - 0x40, // 0a: g - 0x41, // 0b: h - 0x2e, // 0c: i - 0x42, // 0d: j - 0x43, // 0e: k - 0x44, // 0f: l - 0x54, // 10: m - 0x53, // 11: n - 0x2f, // 12: o - 0x30, // 13: p - 0x27, // 14: q - 0x2a, // 15: r - 0x3d, // 16: s - 0x2b, // 17: t - 0x2d, // 18: u - 0x51, // 19: v - 0x28, // 1a: w - 0x4f, // 1b: x - 0x2c, // 1c: y - 0x4e, // 1d: z - 0x11, // 1e: 1 - 0x12, // 1f: 2 - 0x13, // 20: 3 - 0x14, // 21: 4 - 0x15, // 22: 5 - 0x16, // 23: 6 - 0x17, // 24: 7 - 0x18, // 25: 8 - 0x19, // 26: 9 - 0x1a, // 27: 0 - 0x47, // 28: Return - 0x00, // 29: Escape - 0x1e, // 2a: Backspace - 0x26, // 2b: Tab - 0x5f, // 2c: Space - 0x1b, // 2d: - - 0x1c, // 2e: = - 0x31, // 2f: [ - 0x32, // 30: ] - 0x33, // 31: backslash (only on us keyboards) - 0x33, // 32: Europe 1 (only on international kbds) - 0x45, // 33: ; - 0x46, // 34: ' - 0x10, // 35: ` - 0x55, // 36: , - 0x56, // 37: . - 0x57, // 38: / - 0x5d, // 39: Caps Lock - 0x01, // 3a: F1 - 0x02, // 3b: F2 - 0x03, // 3c: F3 - 0x04, // 3d: F4 - 0x05, // 3e: F5 - 0x06, // 3f: F6 - 0x07, // 40: F7 - 0x08, // 41: F8 - 0x09, // 42: F9 - 0x0a, // 43: F10 - 0x0b, // 44: F11 - 0x0c, // 45: F12 - Used heavily by the archie... OSD moved to printscreen. - // 0x0d, // 46: Print Screen - OSD_OPEN, // 46: Print Screen - 0x0e, // 47: Scroll Lock - 0x0f, // 48: Pause - 0x1f, // 49: Insert - 0x20, // 4a: Home - 0x21, // 4b: Page Up - 0x34, // 4c: Delete - 0x35, // 4d: End - 0x36, // 4e: Page Down - 0x64, // 4f: Right Arrow - 0x62, // 50: Left Arrow - 0x63, // 51: Down Arrow - 0x59, // 52: Up Arrow - 0x22, // 53: Num Lock - 0x23, // 54: KP / - 0x24, // 55: KP * - 0x3a, // 56: KP - - 0x4b, // 57: KP + - 0x67, // 58: KP Enter - 0x5a, // 59: KP 1 - 0x5b, // 5a: KP 2 - 0x5c, // 5b: KP 3 - 0x48, // 5c: KP 4 - 0x49, // 5d: KP 5 - 0x4a, // 5e: KP 6 - 0x37, // 5f: KP 7 - 0x38, // 60: KP 8 - 0x39, // 61: KP 9 - 0x65, // 62: KP 0 - 0x66, // 63: KP decimal - MISS, // 64: Europe 2 - 0x72, // 65: App (maps to middle mouse button) - MISS, // 66: Power - MISS, // 67: KP = - MISS, // 68: F13 - MISS, // 69: F14 - MISS, // 6a: F15 - 0x1f, // 6b: insert (for keyrah) - MISS, // 6c: F17 - MISS, // 6d: F18 - MISS, // 6e: F19 - MISS, // 6f: F20 -}; - -#endif diff --git a/menu.c b/menu.c index f742bdc..18bec9a 100644 --- a/menu.c +++ b/menu.c @@ -415,52 +415,42 @@ const uint8_t keycode_table[128] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -static uint8_t GetASCIIKey(unsigned char keycode) +static uint8_t GetASCIIKey(uint32_t keycode) { - if (keycode & KEY_AMI_UPSTROKE) + if (keycode & UPSTROKE) return 0; - return keycode_table[keycode & 0x7F]; + return keycode_table[get_amiga_code(keycode & 0xFFFF) & 0x7F]; } /* the Atari core handles OSD keys competely inside the core */ -static unsigned char menu_key = 0; -static unsigned char menu_mod = 0; +static uint32_t menu_key = 0; -void menu_key_set(unsigned char c) +void menu_key_set(uint32_t c) { - //iprintf("OSD enqueue: %x\n", c); + //printf("OSD enqueue: %x\n", c); menu_key = c; } -void menu_mod_set(uint8_t m) -{ - menu_mod = m; -} - // get key status -static uint8_t menu_key_get(void) +static uint32_t menu_key_get(void) { - static unsigned char c2; + static uint32_t c2; static unsigned long delay; static unsigned long repeat; static unsigned char repeat2; - unsigned char c1, c; + uint32_t c1, c; c1 = menu_key; - - // OsdKeyGet permanently returns the last key event. - - // generate normal "key-pressed" event c = 0; if (c1 != c2) c = c1; c2 = c1; // inject a fake "MENU_KEY" if no menu is visible and the menu key is loaded - if (!user_io_osd_is_visible() && is_menu_core()) c = KEY_AMI_MENU; + if (!user_io_osd_is_visible() && is_menu_core()) c = KEY_F12; // generate repeat "key-pressed" events - if ((c1 & KEY_AMI_UPSTROKE) || (!c1)) + if ((c1 & UPSTROKE) || (!c1)) { repeat = GetTimer(REPEATDELAY); } @@ -475,10 +465,9 @@ static uint8_t menu_key_get(void) { static unsigned char last_but = 0; unsigned char but = user_io_menu_button(); - if (!but && last_but) c = KEY_AMI_MENU; + if (!but && last_but) c = KEY_F12; last_but = but; } - return(c); } @@ -486,7 +475,7 @@ void HandleUI(void) { char *p; char s[40]; - unsigned char i, c, m, up, down, select, menu, right, left, plus, minus; + unsigned char i, m, up, down, select, menu, right, left, plus, minus; uint8_t mod; unsigned long len; static hardfileTYPE t_hardfile[2]; // temporary copy of former hardfile configuration @@ -502,7 +491,7 @@ void HandleUI(void) char usb_id[64]; // get user control codes - c = menu_key_get(); + uint32_t c = menu_key_get(); // decode and set events menu = false; @@ -516,9 +505,9 @@ void HandleUI(void) switch (c) { - case KEY_AMI_MENU: + case KEY_F12: menu = true; - menu_key_set(KEY_AMI_MENU | KEY_AMI_UPSTROKE); + menu_key_set(KEY_F12 | UPSTROKE); break; // Within the menu the esc key acts as the menu key. problem: @@ -526,35 +515,35 @@ void HandleUI(void) // break code for the ESC key when the key is released will // reach the core which never saw the make code. Simple solution: // react on break code instead of make code - case KEY_AMI_ESC | KEY_AMI_UPSTROKE: + case KEY_ESC | UPSTROKE: if (menustate != MENU_NONE2) menu = true; break; - case KEY_AMI_ENTER: - case KEY_AMI_SPACE: + case KEY_ENTER: + case KEY_SPACE: select = true; break; - case KEY_AMI_UP: + case KEY_UP: up = true; break; - case KEY_AMI_DOWN: + case KEY_DOWN: down = true; break; - case KEY_AMI_LEFT: + case KEY_LEFT: left = true; break; - case KEY_AMI_RIGHT: + case KEY_RIGHT: right = true; break; - case KEY_AMI_KPPLUS: - case 0x0c: // =/+ + case KEY_KPPLUS: + case KEY_EQUAL: // =/+ plus = true; break; - case KEY_AMI_KPMINUS: - case 0x0b: // -/_ + case KEY_KPMINUS: + case KEY_MINUS: // -/_ minus = true; break; - +/* case 0x01: // 1: 1280x720 mode if (user_io_osd_is_visible) mist_cfg.video_mode = 0; break; @@ -562,6 +551,7 @@ void HandleUI(void) case 0x02: // 2: 1280x1024 mode if (user_io_osd_is_visible) mist_cfg.video_mode = 1; break; +*/ } if (menu || select || up || down || left || right) @@ -633,7 +623,7 @@ void HandleUI(void) case MENU_NONE2: if (menu) { - if (menu_mod & 0x44) //Alt+Menu + if (get_key_mod() & (LALT|RALT)) //Alt+Menu { OsdSetSize(16); SelectFile("RBF", 0, MENU_FIRMWARE_CORE_FILE_SELECTED, MENU_NONE1, 0); @@ -1832,7 +1822,7 @@ void HandleUI(void) else if (menusub == 11) menustate = MENU_NONE1; } - else if (c == KEY_AMI_BACK) // eject all floppies + else if (c == KEY_BACKSPACE) // eject all floppies { for (i = 0; i <= drives; i++) df[i].status = 0; @@ -1934,25 +1924,25 @@ void HandleUI(void) ScrollLongName(); // scrolls file name if longer than display line - if (c == KEY_AMI_HOME) + if (c == KEY_HOME) { ScanDirectory(SelectedPath, SCAN_INIT, fs_pFileExt, fs_Options); menustate = MENU_FILE_SELECT1; } - if (c == KEY_AMI_BACK) + if (c == KEY_BACKSPACE) { changeDir(".."); menustate = MENU_FILE_SELECT1; } - if ((c == KEY_AMI_PGUP) || (c == KEY_AMI_LEFT)) + if ((c == KEY_PAGEUP) || (c == KEY_LEFT)) { ScanDirectory(SelectedPath, SCAN_PREV_PAGE, fs_pFileExt, fs_Options); menustate = MENU_FILE_SELECT1; } - if ((c == KEY_AMI_PGDN) || (c == KEY_AMI_RIGHT)) + if ((c == KEY_PAGEDOWN) || (c == KEY_RIGHT)) { ScanDirectory(SelectedPath, SCAN_NEXT_PAGE, fs_pFileExt, fs_Options); menustate = MENU_FILE_SELECT1; diff --git a/menu.h b/menu.h index 0493542..0f2e36b 100644 --- a/menu.h +++ b/menu.h @@ -3,23 +3,6 @@ #include "fdd.h" // for adfTYPE definition -#define KEY_AMI_UPSTROKE 0x80 -#define KEY_AMI_MENU 0x69 -#define KEY_AMI_PGUP 0x6C -#define KEY_AMI_PGDN 0x6D -#define KEY_AMI_HOME 0x6A -#define KEY_AMI_ESC 0x45 -#define KEY_AMI_KPENTER 0x43 -#define KEY_AMI_ENTER 0x44 -#define KEY_AMI_BACK 0x41 -#define KEY_AMI_SPACE 0x40 -#define KEY_AMI_UP 0x4C -#define KEY_AMI_DOWN 0x4D -#define KEY_AMI_LEFT 0x4F -#define KEY_AMI_RIGHT 0x4E -#define KEY_AMI_KPPLUS 0x5E -#define KEY_AMI_KPMINUS 0x4A - // UI strings, used by boot messages extern const char *config_filter_msg[]; extern const char *config_memory_chip_msg[]; @@ -40,7 +23,7 @@ void ShowSplash(); void HideSplash(); void EjectAllFloppies(); -void menu_key_set(unsigned char c); -void menu_mod_set(uint8_t m); +void menu_key_set(uint32_t c); +void menu_mod_set(uint32_t m); #endif diff --git a/user_io.c b/user_io.c index dbe7bf2..70b76f3 100644 --- a/user_io.c +++ b/user_io.c @@ -10,7 +10,6 @@ #include "user_io.h" #include "archie.h" #include "debug.h" -#include "keycodes.h" #include "ikbd.h" #include "spi.h" #include "mist_cfg.h" @@ -334,28 +333,6 @@ void user_io_detect_core_type() } } -unsigned short usb2amiga(unsigned char k) -{ - // replace MENU key by RGUI to allow using Right Amiga on reduced keyboards - // (it also disables the use of Menu for OSD) - if (mist_cfg.key_menu_as_rgui && k == 0x65) - { - return 0x67; - } - return usb2ami[k]; -} - -unsigned short usb2ps2code(unsigned char k) -{ - // replace MENU key by RGUI e.g. to allow using RGUI on reduced keyboards without physical key - // (it also disables the use of Menu for OSD) - if (mist_cfg.key_menu_as_rgui && k == 0x65) - { - return EXT | 0x27; - } - return usb2ps2[k]; -} - void user_io_analog_joystick(unsigned char joystick, char valueX, char valueY) { if (core_type == CORE_TYPE_8BIT) @@ -816,6 +793,8 @@ void kbd_reply(char code) spi_uio_cmd8(UIO_KEYBOARD, code); } +static uint8_t use_ps2ctl = 0; + void user_io_poll() { if ((core_type != CORE_TYPE_MINIMIG2) && @@ -1214,7 +1193,6 @@ void user_io_poll() if (core_type == CORE_TYPE_ARCHIE) archie_poll(); - static uint8_t use_ps2ctl = 0; static uint8_t leds = 0; if(use_ps2ctl) { @@ -1316,12 +1294,36 @@ char user_io_user_button() return((!user_io_menu_button() && (fpga_get_buttons() & BUTTON_USR)) ? 1 : 0); } -static void send_keycode(unsigned short code) +static void send_keycode(unsigned short key, int press) { if (core_type == CORE_TYPE_MINIMIG2) { - // amiga has "break" marker in msb - if (code & BREAK) code = (code & 0xff) | 0x80; + if (press > 1) return; + + uint32_t code = get_amiga_code(key); + if (code == NONE) return; + + if (code & CAPS_TOGGLE) + { + if (press = 1) + { + // send alternating make and break codes for caps lock + if(caps_lock_toggle) code |= 0x80; + caps_lock_toggle = !caps_lock_toggle; + set_kbd_led(HID_LED_CAPS_LOCK, caps_lock_toggle); + } + else + { + return; + } + } + else + { + // amiga has "break" marker in msb + if (!press) code |= 0x80; + } + + code &= 0xff; // send immediately if possible if (CheckTimer(kbd_timer) && (kbd_fifo_w == kbd_fifo_r)) @@ -1332,63 +1334,103 @@ static void send_keycode(unsigned short code) { kbd_fifo_enqueue(code); } + return; } if (core_type == CORE_TYPE_MIST) { + if (press > 1) return; + + uint32_t code = get_atari_code(key); + if (code == NONE) return; + // atari has "break" marker in msb - if (code & BREAK) code = (code & 0xff) | 0x80; + if (!press) code = (code & 0xff) | 0x80; ikbd_keyboard(code); + return; } if (core_type == CORE_TYPE_8BIT) { - // send ps2 keycodes for those cores that prefer ps2 - spi_uio_cmd_cont(UIO_KEYBOARD); + uint32_t code = get_ps2_code(key); + if (code == NONE) return; - // "pause" has a complex code - if ((code & 0xff) == 0x77) + //pause + if ((code & 0xff) == 0xE1) { // pause does not have a break code - if (!(code & BREAK)) + if (press != 1) { // Pause key sends E11477E1F014E077 - static const unsigned char c[] = { - 0xe1, 0x14, 0x77, 0xe1, 0xf0, 0x14, 0xf0, 0x77, 0x00 }; + static const unsigned char c[] = { 0xe1, 0x14, 0x77, 0xe1, 0xf0, 0x14, 0xf0, 0x77, 0x00 }; const unsigned char *p = c; - iprintf("PS2 KBD "); + spi_uio_cmd_cont(UIO_KEYBOARD); + + printf("PS2 PAUSE CODE: "); while (*p) { - iprintf("%x ", *p); + printf("%x ", *p); spi8(*p++); } - iprintf("\n"); + printf("\n"); + + DisableIO(); + } + } + // print screen + else if ((code & 0xff) == 0xE2) + { + if (press <= 1) + { + static const unsigned char c[2][8] = { + { 0xE0, 0xF0, 0x7C, 0xE0, 0xF0, 0x12, 0x00, 0x00 }, + { 0xE0, 0x12, 0xE0, 0x7C, 0x00, 0x00, 0x00, 0x00 } + }; + + const unsigned char *p = c[press]; + + spi_uio_cmd_cont(UIO_KEYBOARD); + + printf("PS2 PRINT CODE: "); + while (*p) + { + printf("%x ", *p); + spi8(*p++); + } + printf("\n"); + + DisableIO(); } } else { - /* - iprintf("PS2 KBD "); - if (code & EXT) iprintf("e0 "); - if (code & BREAK) iprintf("f0 "); - iprintf("%x\n", code & 0xff); - */ + if (press > 1 && !use_ps2ctl) return; + + spi_uio_cmd_cont(UIO_KEYBOARD); // prepend extended code flag if required if (code & EXT) spi8(0xe0); // prepend break code if required - if (code & BREAK) spi8(0xf0); + if (!press) spi8(0xf0); // send code itself spi8(code & 0xff); - } - DisableIO(); + DisableIO(); + } } - if (core_type == CORE_TYPE_ARCHIE) archie_kbd(code); + if (core_type == CORE_TYPE_ARCHIE) + { + if (press > 1) return; + + uint32_t code = get_archie_code(key); + if (code == NONE) return; + + archie_kbd(code); + } } void user_io_mouse(unsigned char b, int16_t x, int16_t y) @@ -1423,19 +1465,6 @@ LCTRL LSHIFT LALT LGUI RCTRL RSHIFT RALT RGUI #define EMU_BTN3 (2+(keyrah*4)) // left alt #define EMU_BTN4 (3+(keyrah*4)) // left gui (usually windows key) -unsigned short keycode(unsigned char in) -{ - if (core_type == CORE_TYPE_MINIMIG2) return usb2amiga(in); - - // atari st and the 8 bit core (currently only used for atari 800) - // use the same key codes - if (core_type == CORE_TYPE_MIST) return usb2atari[in]; - if (core_type == CORE_TYPE_ARCHIE) return usb2archie[in]; - if (core_type == CORE_TYPE_8BIT) return usb2ps2code(in); - - return MISS; -} - extern configTYPE config; void user_io_check_reset(unsigned short modifiers, char useKeys) @@ -1473,58 +1502,19 @@ void user_io_check_reset(unsigned short modifiers, char useKeys) } } -unsigned short modifier_keycode(unsigned char index) -{ - /* usb modifer bits: - 0 1 2 3 4 5 6 7 - LCTRL LSHIFT LALT LGUI RCTRL RSHIFT RALT RGUI - */ - - if (core_type == CORE_TYPE_MINIMIG2) - { - static const unsigned short amiga_modifier[] = { 0x63, 0x60, 0x64, 0x66, 0x63, 0x61, 0x65, 0x67 }; - return amiga_modifier[index]; - } - - if (core_type == CORE_TYPE_MIST) - { - static const unsigned short atari_modifier[] = { 0x1d, 0x2a, 0x38, MISS, 0x1d, 0x36, 0x38, MISS }; - return atari_modifier[index]; - } - - if (core_type == CORE_TYPE_8BIT) - { - static const unsigned short ps2_modifier[] = { 0x14, 0x12, 0x11, EXT | 0x1f, EXT | 0x14, 0x59, EXT | 0x11, EXT | 0x27 }; - return ps2_modifier[index]; - } - - if (core_type == CORE_TYPE_ARCHIE) - { - static const unsigned short archie_modifier[] = { 0x36, 0x4c, 0x5e, MISS, 0x61, 0x58, 0x60, MISS }; - return archie_modifier[index]; - } - - return MISS; -} - void user_io_osd_key_enable(char on) { iprintf("OSD is now %s\n", on ? "visible" : "invisible"); osd_is_visible = on; } -static char key_used_by_osd(unsigned short s) +static char key_used_by_osd(uint32_t s) { // this key is only used to open the OSD and has no keycode - if ((s & OSD_OPEN) && !(s & 0xff)) return true; + if (s & OSD_OPEN) return 1; // no keys are suppressed if the OSD is inactive - if (!osd_is_visible) return false; - - // in atari mode eat all keys if the OSD is online, - // else none as it's up to the core to forward keys - // to the OSD - return((core_type == CORE_TYPE_MIST) || (core_type == CORE_TYPE_ARCHIE) || (core_type == CORE_TYPE_8BIT)); + return osd_is_visible; } void user_io_kbd(uint16_t key, int press) @@ -1534,105 +1524,37 @@ void user_io_kbd(uint16_t key, int press) (core_type == CORE_TYPE_ARCHIE) || (core_type == CORE_TYPE_8BIT)) { - uint8_t m = key >> 8; - uint8_t k = key & 0xFF; - - static unsigned char modifier = 0; - - // handle modifier keys - if (m != modifier) + if (key) { - for (int i = 0; i<8; i++) - { - uint16_t code = modifier_keycode(i); - - // Do we have a downstroke on a modifier key? - if ((m & (1 << i)) && !(modifier & (1 << i))) - { - if (code != MISS) - { - if (is_menu_core()) printf("keycode(make)%s for core: %d(0x%X)\n", (code & EXT) ? "(ext)" : "", code & 255, code & 255); - if(!osd_is_visible) send_keycode(code); - } - } - - if (!(m & (1 << i)) && (modifier & (1 << i))) - { - if (code != MISS) - { - if (is_menu_core()) printf("keycode(break)%s for core: %d(0x%X)\n", (code & EXT) ? "(ext)" : "", code & 255, code & 255); - if (!osd_is_visible) send_keycode(BREAK | code); - } - } - } - - modifier = m; - } - - // check if there are keys in the pressed list which aren't - // reported anymore - if (k) - { - uint16_t code = keycode(k); + uint32_t code = get_ps2_code(key); if (!press) { - if (is_menu_core()) printf("keycode(break)%s for core: %d(0x%X)\n", (code & EXT) ? "(ext)" : "", code & 255, code & 255); + if (is_menu_core()) printf("PS2 code(break)%s for core: %d(0x%X)\n", (code & EXT) ? "(ext)" : "", code & 255, code & 255); - if (code != MISS) + if (code & OSD_OPEN) menu_key_set(UPSTROKE | KEY_F12); + else if (osd_is_visible) menu_key_set(UPSTROKE | key); + else { - if (code & OSD_OPEN) - { - menu_key_set(KEY_AMI_UPSTROKE | KEY_AMI_MENU); - } - else - { - // special OSD key handled internally - if (osd_is_visible) menu_key_set(KEY_AMI_UPSTROKE | usb2amiga(k)); - } - - if (!key_used_by_osd(code) && !(code & CAPS_LOCK_TOGGLE) && !(code & NUM_LOCK_TOGGLE)) - { - send_keycode(BREAK | code); - } + send_keycode(key, press); } } else { - if (is_menu_core()) printf("keycode(make)%s for core: %d(0x%X)\n", (code & EXT) ? "(ext)" : "", code & 255, code & 255); + if (is_menu_core()) printf("PS2 code(make)%s for core: %d(0x%X)\n", (code & EXT) ? "(ext)" : "", code & 255, code & 255); - if ((k <= KEYCODE_MAX) && code != MISS) + if (code & OSD_OPEN) { - // If OSD is visible, then all keys are sent into the OSD - // using Amiga key codes since the OSD itself uses Amiga key codes - // for historical reasons. If the OSD is invisble then only - // those keys marked for OSD in the core specific table are - // sent for OSD handling. - if (code & OSD_OPEN) + if (press == 1) menu_key_set(KEY_F12); + } + else if (osd_is_visible) + { + if (press == 1) menu_key_set(key); + } + else + { + if ((code & EMU_SWITCH_1) || ((code & EMU_SWITCH_2) && !use_ps2ctl)) { - menu_key_set(KEY_AMI_MENU); - } - else - { - // special OSD key handled internally - if (osd_is_visible) - { - menu_key_set(usb2amiga(k)); - } - } - - // no further processing of any key that is currently - // redirected to the OSD - if (!key_used_by_osd(code)) - { - if (code & CAPS_LOCK_TOGGLE) - { - // send alternating make and break codes for caps lock - send_keycode((code & 0xff) | (caps_lock_toggle ? BREAK : 0)); - caps_lock_toggle = !caps_lock_toggle; - - set_kbd_led(HID_LED_CAPS_LOCK, caps_lock_toggle); - } - else if (code & NUM_LOCK_TOGGLE) + if (press == 1) { // num lock has four states indicated by leds: // all off: normal @@ -1640,7 +1562,7 @@ void user_io_kbd(uint16_t key, int press) // num lock on, scroll lock off: joy0 emu // num lock off, scroll lock on: joy1 emu - switch (code ^ NUM_LOCK_TOGGLE) + switch (code & 0xff) { case 1: if (!joy_force) emu_mode = EMU_MOUSE; @@ -1670,10 +1592,10 @@ void user_io_kbd(uint16_t key, int press) if (emu_mode == EMU_MOUSE || emu_mode == EMU_JOY1) set_kbd_led(HID_LED_SCROLL_LOCK, true); else set_kbd_led(HID_LED_SCROLL_LOCK, false); } - else - { - send_keycode((press == 2) ? code & ~EXT : code); - } + } + else + { + send_keycode(key, press); } } } From ec2403d5ed09ac74c1e1f55d467519af76f0c3a8 Mon Sep 17 00:00:00 2001 From: sorgelig Date: Wed, 2 Aug 2017 05:52:13 +0800 Subject: [PATCH 06/17] ao486: load hdd and fdd from dedicated files. --- main.c | 1 + x86.c | 214 +++++++++++++++------------------------------------------ 2 files changed, 57 insertions(+), 158 deletions(-) diff --git a/main.c b/main.c index f63020c..d07ade9 100644 --- a/main.c +++ b/main.c @@ -87,6 +87,7 @@ void core_init() int main(int argc, char *argv[]) { fpga_io_init(); + fpga_core_reset(1); fpga_gpo_write(0); DISKLED_OFF; diff --git a/x86.c b/x86.c index 3f60ec5..7b2f232 100644 --- a/x86.c +++ b/x86.c @@ -191,47 +191,6 @@ static void crc32(uint8_t *ptr, uint32_t *crc_output) memcpy(crc, new_crc, sizeof(crc)); } -struct entry_t -{ - uint8_t type; - uint8_t name[15]; - - union args_t { - struct bios_t { - uint32_t sector; - uint32_t size_in_bytes; - uint32_t destination; - uint32_t crc32; - } bios; - struct hdd_t { - uint32_t sector; - uint32_t cyliders; - uint32_t heads; - uint32_t spt; - } hdd; - struct floppy_t { - uint32_t sector; - } floppy; - struct end_of_list_t { - uint32_t crc32; - } end_of_list; - } args; -} __attribute__((packed)); - -#define ENTRIES_COUNT 128 -static struct entry_t entries[ENTRIES_COUNT]; - -#define TYPE_BIOS 1 -#define TYPE_VGABIOS 2 -#define TYPE_HDD 3 -#define TYPE_FD_1_44M 16 -#define TYPE_CRC32 127 - -#define ENTRY_ABORT -500 - -static int floppy_index = -1; -static int hdd_index = -1; - static bool floppy_is_160k = false; static bool floppy_is_180k = false; static bool floppy_is_320k = false; @@ -241,44 +200,24 @@ static bool floppy_is_1_2m = false; static bool floppy_is_1_44m= true; static bool floppy_is_2_88m= false; -static bool floppy_writeprotect = true; +static fileTYPE fdd_image = { 0 }; +static fileTYPE hdd_image = { 0 }; -#define IOWR(base, reg, value) dma_set(base+(reg<<2), value) +#define IMG_TYPE_FDD 0x800 +#define IMG_TYPE_HDD 0x000 -static void set_floppy(int index) +static __inline fileTYPE *get_image(uint32_t type) { - floppy_index = index; - floppy_writeprotect = true; - - int floppy_sd_base = (index >= 0) ? entries[floppy_index].args.floppy.sector : 0; - - int floppy_media = - (floppy_index < 0)? 0x20 : - (floppy_is_160k)? 0x00 : - (floppy_is_180k)? 0x00 : - (floppy_is_320k)? 0x00 : - (floppy_is_360k)? 0x00 : - (floppy_is_720k)? 0xC0 : - (floppy_is_1_2m)? 0x00 : - (floppy_is_1_44m)? 0x80 : - (floppy_is_2_88m)? 0x40 : - 0x20; - - IOWR(FLOPPY_BASE, 0x0, floppy_index >= 0 ? 1 : 0); - IOWR(FLOPPY_BASE, 0x1, floppy_writeprotect? 1 : 0); - IOWR(FLOPPY_BASE, 0x6, floppy_sd_base); - IOWR(FLOPPY_BASE, 0xC, floppy_media); + return (type == IMG_TYPE_FDD) ? &fdd_image : &hdd_image; } -static fileTYPE sd_image = { 0 }; - -static int img_mount(char *name) +static int img_mount(uint32_t type, char *name) { int writable = FileCanWrite(name); - int ret = FileOpenEx(&sd_image, name, writable ? (O_RDWR | O_SYNC) : O_RDONLY); + int ret = FileOpenEx(get_image(type), name, writable ? (O_RDWR | O_SYNC) : O_RDONLY); if (!ret) { - sd_image.size = 0; + get_image(type)->size = 0; printf("Failed to open file %s\n", name); return 0; } @@ -287,66 +226,25 @@ static int img_mount(char *name) return 1; } -static int img_read(uint32_t lba, void *buf, uint32_t len) +static int img_read(uint32_t type, uint32_t lba, void *buf, uint32_t len) { - if (!FileSeekLBA(&sd_image, lba)) return 0; - return FileReadAdv(&sd_image, buf, len); + if (!FileSeekLBA(get_image(type), lba)) return 0; + return FileReadAdv(get_image(type), buf, len); } -static int img_write(uint32_t lba, void *buf, uint32_t len) +static int img_write(uint32_t type, uint32_t lba, void *buf, uint32_t len) { - if (!FileSeekLBA(&sd_image, lba)) return 0; - return FileWriteAdv(&sd_image, buf, len); + if (!FileSeekLBA(get_image(type), lba)) return 0; + return FileWriteAdv(get_image(type), buf, len); } +#define IOWR(base, reg, value) dma_set(base+(reg<<2), value) + void x86_init() { IOWR(PC_BUS_BASE, 0, 0x00FFF0EA); IOWR(PC_BUS_BASE, 1, 0x000000F0); - //resets output - IOWR(PIO_OUTPUT_BASE, 0, 0x01); - - if (!img_mount("ao486.vhd")) - { - return; - } - - if (!img_read(0, entries, sizeof(entries))) - { - return; - } - - //check crc32 - bool crc_ok = false; - for(int i=0; i= 0? 1 : 0); - IOWR(FLOPPY_BASE, 0x1, floppy_writeprotect? 1 : 0); + IOWR(FLOPPY_BASE, 0x0, floppy? 1 : 0); + IOWR(FLOPPY_BASE, 0x1, (floppy && (get_image(IMG_TYPE_FDD)->mode & O_RDWR)) ? 0 : 1); IOWR(FLOPPY_BASE, 0x2, floppy_cylinders); IOWR(FLOPPY_BASE, 0x3, floppy_spt); IOWR(FLOPPY_BASE, 0x4, floppy_total_sectors); IOWR(FLOPPY_BASE, 0x5, floppy_heads); - IOWR(FLOPPY_BASE, 0x6, floppy_sd_base); + IOWR(FLOPPY_BASE, 0x6, 0); // base LBA IOWR(FLOPPY_BASE, 0x7, (int)(floppy_wait_cycles / (1000000000.0 / ALT_CPU_CPU_FREQ))); IOWR(FLOPPY_BASE, 0x8, (int)(1000000.0 / (1000000000.0 / ALT_CPU_CPU_FREQ))); IOWR(FLOPPY_BASE, 0x9, (int)(1666666.0 / (1000000000.0 / ALT_CPU_CPU_FREQ))); @@ -446,14 +344,21 @@ void x86_init() //-------------------------------------------------------------------------- hdd - hdd_index = 2; - unsigned int hd_cylinders = entries[hdd_index].args.hdd.cyliders; //1-1024; 10 bits; implemented 16 bits - unsigned int hd_heads = entries[hdd_index].args.hdd.heads; //1-16; 4 bits; at least 9 heads for cmos 0x20 - unsigned int hd_spt = entries[hdd_index].args.hdd.spt; //1-255; 8 bits; + unsigned int hd_cylinders = 0; + unsigned int hd_heads = 0; + unsigned int hd_spt = 0; + unsigned int hd_total_sectors = 0; + unsigned int hdd_sd_base = 0; - int hdd_sd_base = entries[hdd_index].args.hdd.sector; + int hdd = img_mount(IMG_TYPE_HDD, "ao486/hdd.vhd"); + if (hdd) + { + hd_cylinders = 1024; + hd_heads = 16; + hd_spt = 63; - unsigned int hd_total_sectors = hd_cylinders * hd_heads * hd_spt; + hd_total_sectors = get_image(IMG_TYPE_HDD)->size / 512; + } /* 0x00.[31:0]: identify write @@ -560,20 +465,20 @@ void x86_init() 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; - for(int i=0; i<128; i++) IOWR(HDD_BASE, 0, ((unsigned int)identify[2*i+1] << 16) | (unsigned int)identify[2*i+0]); + for(int i=0; i<128; i++) IOWR(HDD_BASE, 0, hdd ? ((unsigned int)identify[2*i+1] << 16) | (unsigned int)identify[2*i+0] : 0); IOWR(HDD_BASE, 1, hd_cylinders); IOWR(HDD_BASE, 2, hd_heads); IOWR(HDD_BASE, 3, hd_spt); IOWR(HDD_BASE, 4, hd_spt * hd_heads); IOWR(HDD_BASE, 5, hd_spt * hd_heads * hd_cylinders); - IOWR(HDD_BASE, 6, hdd_sd_base); + IOWR(HDD_BASE, 6, 0); // base LBA - printf("HDD:\n hd_cylinders %d\n hd_heads %d\n hd_spt %d\n hdd_sd_base %d\n\n", hd_cylinders, hd_heads, hd_spt, hdd_sd_base); + printf("HDD:\n hd_cylinders %d\n hd_heads %d\n hd_spt %d\n hd_total_sectors %d\n\n", hd_cylinders, hd_heads, hd_spt, hd_total_sectors); //-------------------------------------------------------------------------- rtc - bool boot_from_floppy = true; + bool boot_from_floppy = floppy; /* 128.[26:0]: cycles in second @@ -589,7 +494,7 @@ void x86_init() bool translate_large= !translate_none && (hd_cylinders * hd_heads) <= 131072; bool translate_lba = !translate_none && !translate_large; - unsigned char translate_byte = (translate_large)? 1 : (translate_lba)? 2 : 0; + unsigned char translate_byte = 1; //(translate_large) ? 1 : (translate_lba) ? 2 : 0; //rtc contents 0-127 unsigned int cmos[128] = { @@ -622,15 +527,15 @@ void x86_init() 0x2F, //0x19: extended hd types 1/2; type 47d 0x00, //0x1A: extended hd types 2/2 - hd_cylinders & 0xFF, //0x1B: hd 0 configuration 1/9; cylinders low - (hd_cylinders >> 8) & 0xFF, //0x1C: hd 0 configuration 2/9; cylinders high - hd_heads, //0x1D: hd 0 configuration 3/9; heads - 0xFF, //0x1E: hd 0 configuration 4/9; write pre-comp low - 0xFF, //0x1F: hd 0 configuration 5/9; write pre-comp high - 0xC8, //0x20: hd 0 configuration 6/9; retries/bad map/heads>8 - hd_cylinders & 0xFF, //0x21: hd 0 configuration 7/9; landing zone low - (hd_cylinders >> 8) & 0xFF, //0x22: hd 0 configuration 8/9; landing zone high - hd_spt, //0x23: hd 0 configuration 9/9; sectors/track + hdd ? hd_cylinders & 0xFF : 0, //0x1B: hd 0 configuration 1/9; cylinders low + hdd ? (hd_cylinders >> 8) & 0xFF : 0, //0x1C: hd 0 configuration 2/9; cylinders high + hdd ? hd_heads : 0, //0x1D: hd 0 configuration 3/9; heads + hdd ? 0xFF : 0, //0x1E: hd 0 configuration 4/9; write pre-comp low + hdd ? 0xFF : 0, //0x1F: hd 0 configuration 5/9; write pre-comp high + hdd ? 0xC8 : 0, //0x20: hd 0 configuration 6/9; retries/bad map/heads>8 + hdd ? hd_cylinders & 0xFF : 0, //0x21: hd 0 configuration 7/9; landing zone low + hdd ? (hd_cylinders >> 8) & 0xFF : 0, //0x22: hd 0 configuration 8/9; landing zone high + hdd ? hd_spt : 0, //0x23: hd 0 configuration 9/9; sectors/track 0x00, //0x24: hd 1 configuration 1/9 0x00, //0x25: hd 1 configuration 2/9 @@ -685,13 +590,6 @@ void x86_init() cmos[0x2F] = sum & 0xFF; for(unsigned int i=0; i> 2, (uint32_t*)&sd_params); - printf("Read: 0x%08x, 0x%08x, %d\n", sd_params.addr, sd_params.lba, sd_params.bl_cnt); + //printf("Read: 0x%08x, 0x%08x, %d\n", sd_params.addr, sd_params.lba, sd_params.bl_cnt); - if (sd_image.size) + if (get_image(sd_params.addr)->size) { if (sd_params.bl_cnt>0 && sd_params.bl_cnt<=4) { - if (img_read(sd_params.lba, secbuf, sd_params.bl_cnt * 512)) + if (img_read(sd_params.addr, sd_params.lba, secbuf, sd_params.bl_cnt * 512)) { dma_sendbuf(sd_params.addr, sd_params.bl_cnt * 128, secbuf); res = 1; @@ -739,16 +637,16 @@ void x86_poll() else if (sd_req == 2) { dma_rcvbuf(SD_BASE + (4 << 2), sizeof(sd_params) >> 2, (uint32_t*)&sd_params); - printf("Write: 0x%08x, 0x%08x, %d\n", sd_params.addr, sd_params.lba, sd_params.bl_cnt); + //printf("Write: 0x%08x, 0x%08x, %d\n", sd_params.addr, sd_params.lba, sd_params.bl_cnt); - if (sd_image.size) + if (get_image(sd_params.addr)->size) { if (sd_params.bl_cnt>0 && sd_params.bl_cnt <= 4) { - if (sd_image.mode & O_RDWR) + if (get_image(sd_params.addr)->mode & O_RDWR) { dma_rcvbuf(sd_params.addr, sd_params.bl_cnt * 128, secbuf); - if (img_write(sd_params.lba, secbuf, sd_params.bl_cnt * 512)) + if (img_write(sd_params.addr, sd_params.lba, secbuf, sd_params.bl_cnt * 512)) { res = 1; } From 8ad256acc010c3e30ed6d7d1c2e4814f361b0a8e Mon Sep 17 00:00:00 2001 From: sorgelig Date: Wed, 2 Aug 2017 20:09:24 +0800 Subject: [PATCH 07/17] Fix directory navigation. --- file_io.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/file_io.c b/file_io.c index f2631a3..4f52d7b 100644 --- a/file_io.c +++ b/file_io.c @@ -478,7 +478,7 @@ int de_cmp(const void *e1, const void *e2) const struct dirent *de2 = e2; if ((de1->d_type == DT_DIR) && !strcmp(de1->d_name, "..")) return -1; - if ((de2->d_type == DT_DIR) && !strcmp(de1->d_name, "..")) return 1; + if ((de2->d_type == DT_DIR) && !strcmp(de2->d_name, "..")) return 1; if ((de1->d_type == DT_DIR) && (de2->d_type == DT_REG)) return -1; if ((de1->d_type == DT_REG) && (de2->d_type == DT_DIR)) return 1; @@ -723,7 +723,7 @@ int ScanDirectory(char* path, int mode, char *extension, int options) if (found >= 0) { iSelectedEntry = found; - if (iSelectedEntry + (OsdGetSize() / 2) - 1 >= nDirEntries) iFirstEntry = nDirEntries - OsdGetSize(); + if (iSelectedEntry + (OsdGetSize() / 2) >= nDirEntries) iFirstEntry = nDirEntries - OsdGetSize(); else iFirstEntry = iSelectedEntry - (OsdGetSize()/2) + 1; if (iFirstEntry < 0) iFirstEntry = 0; } From 1bed61c56395bce437dcf212339f88ed014373d8 Mon Sep 17 00:00:00 2001 From: sorgelig Date: Wed, 2 Aug 2017 22:24:55 +0800 Subject: [PATCH 08/17] OSD tweaks for ao486. --- file_io.h | 3 +- main.c | 1 - menu.c | 62 ++++++++++++---- menu.h | 2 + user_io.c | 26 +++++-- x86.c | 207 +++++++++++++++++++++++++++++++++++------------------- x86.h | 6 ++ 7 files changed, 214 insertions(+), 93 deletions(-) diff --git a/file_io.h b/file_io.h index 6020fd2..3949f99 100644 --- a/file_io.h +++ b/file_io.h @@ -29,7 +29,8 @@ extern int iFirstEntry; #define SCAN_SET_ITEM 3 // find exact item // options flags -#define SCAN_DIR 1 // include subdirectories +#define SCAN_DIR 1 // include subdirectories +#define SCAN_UMOUNT 2 // include subdirectories void FindStorage(); int getStorage(int from_setting); diff --git a/main.c b/main.c index d07ade9..f63020c 100644 --- a/main.c +++ b/main.c @@ -87,7 +87,6 @@ void core_init() int main(int argc, char *argv[]) { fpga_io_init(); - fpga_core_reset(1); fpga_gpo_write(0); DISKLED_OFF; diff --git a/menu.c b/menu.c index 18bec9a..421a42d 100644 --- a/menu.c +++ b/menu.c @@ -46,6 +46,7 @@ along with this program. If not, see . #include #include "mist_cfg.h" #include "input.h" +#include "x86.h" /*menu states*/ enum MENU @@ -269,7 +270,7 @@ static void SelectFile(char* pFileExt, unsigned char Options, unsigned char Menu iprintf("%s - %s\n", pFileExt, fs_pFileExt); AdjustDirectory(SelectedPath); - if (strncmp(pFileExt, fs_pFileExt, 12) != 0) // check desired file extension + if (strncmp(pFileExt, fs_pFileExt, 12) != 0 || !strlen(SelectedPath)) // check desired file extension { // if different from the current one go to the root directory and init entry buffer SelectedPath[0] = 0; @@ -808,7 +809,11 @@ void HandleUI(void) } // check for 'O'ption strings - if (p && (p[0] == 'O')) { + if (p && (p[0] == 'O')) + { + //option handled by ARM + if (p[1] == 'X') p++; + unsigned long x = getStatus(p, status); // get currently active option @@ -945,15 +950,26 @@ void HandleUI(void) static char ext[13]; substrcpy(ext, p, 1); while (strlen(ext) < 3) strcat(ext, " "); - SelectFile(ext, SCAN_DIR, + SelectFile(ext, SCAN_DIR | ((p[0] == 'S') ? SCAN_UMOUNT : 0), (p[0] == 'F') ? MENU_8BIT_MAIN_FILE_SELECTED : MENU_8BIT_MAIN_IMAGE_SELECTED, MENU_8BIT_MAIN1, 1); } else if (p[0] == 'O') { + int byarm = 0; + if (p[1] == 'X') + { + byarm = 1; + p++; + } + unsigned long status = user_io_8bit_set_status(0, 0); // 0,0 gets status unsigned long x = getStatus(p, status) + 1; + if (byarm && is_x86_core()) + { + if (p[1] == '2') x86_set_fdd_boot(!(x&1)); + } // check if next value available substrcpy(s, p, 2 + x); if (!strlen(s)) x = 0; @@ -966,12 +982,20 @@ void HandleUI(void) { // determine which status bit is affected unsigned long mask = 1 << getIdx(p); - unsigned long status = user_io_8bit_set_status(0, 0); + if (mask == 1 && is_x86_core()) + { + x86_init(); + menustate = MENU_NONE1; + } + else + { + unsigned long status = user_io_8bit_set_status(0, 0); - user_io_8bit_set_status(status ^ mask, mask); - user_io_8bit_set_status(status, mask); + user_io_8bit_set_status(status ^ mask, mask); + user_io_8bit_set_status(status, mask); + menustate = MENU_8BIT_MAIN1; + } - menustate = MENU_8BIT_MAIN1; } } } @@ -990,9 +1014,16 @@ void HandleUI(void) case MENU_8BIT_MAIN_IMAGE_SELECTED: iprintf("Image selected: %s\n", SelectedPath); - user_io_set_index(user_io_ext_idx(SelectedPath, fs_pFileExt) << 6 | (menusub + 1)); - user_io_file_mount(drive_num, SelectedPath); - menustate = MENU_NONE1; + if (is_x86_core()) + { + x86_set_image(drive_num, SelectedPath); + } + else + { + user_io_set_index(user_io_ext_idx(SelectedPath, fs_pFileExt) << 6 | (menusub + 1)); + user_io_file_mount(drive_num, SelectedPath); + } + menustate = SelectedPath[0] ? MENU_NONE1 : MENU_8BIT_MAIN1; break; case MENU_8BIT_SYSTEM1: @@ -1069,6 +1100,7 @@ void HandleUI(void) unsigned long status = user_io_8bit_set_status(0, 0); iprintf("Saving config to %s\n", filename); FileSaveConfig(filename, &status, 4); + if (is_x86_core()) x86_config_save(); menustate = MENU_8BIT_MAIN1; menusub = 0; } @@ -1932,8 +1964,14 @@ void HandleUI(void) if (c == KEY_BACKSPACE) { - changeDir(".."); - menustate = MENU_FILE_SELECT1; + if (fs_Options & SCAN_UMOUNT) + { + for (int i = 0; i < OsdGetSize() - 1; i++) OsdWrite(i, "", 0, 0); + OsdWrite(OsdGetSize() / 2, " Unmounting the image", 0, 0); + usleep(1500000); + SelectedPath[0] = 0; + menustate = fs_MenuSelect; + } } if ((c == KEY_PAGEUP) || (c == KEY_LEFT)) diff --git a/menu.h b/menu.h index 0f2e36b..82ccf09 100644 --- a/menu.h +++ b/menu.h @@ -23,6 +23,8 @@ void ShowSplash(); void HideSplash(); void EjectAllFloppies(); +unsigned long getStatus(char *opt, unsigned long status); + void menu_key_set(uint32_t c); void menu_mod_set(uint32_t m); diff --git a/user_io.c b/user_io.c index 70b76f3..7ec6518 100644 --- a/user_io.c +++ b/user_io.c @@ -180,12 +180,6 @@ static int joy_force = 0; static void parse_config() { - // check if core has a config string - core_type_8bit_with_config_string = (user_io_8bit_get_string(0) != NULL); - - // set core name. This currently only sets a name for the 8 bit cores - user_io_read_core_name(); - joy_force = 0; if (core_type_8bit_with_config_string) { @@ -202,6 +196,19 @@ static void parse_config() input_notify_mode(); set_kbd_led(HID_LED_NUM_LOCK, true); } + + if (p[0] == 'O' && p[1] == 'X') + { + unsigned long status = user_io_8bit_set_status(0, 0); + printf("found OX option: %s, 0x%08X\n", p, status); + + unsigned long x = getStatus(p+1, status); + + if (is_x86_core()) + { + if (p[2] == '2') x86_set_fdd_boot(!(x&1)); + } + } } i++; } while (p); @@ -266,8 +273,11 @@ void user_io_detect_core_type() // forward SD card config to core in case it uses the local // SD card implementation user_io_sd_set_config(); + // check if core has a config string + core_type_8bit_with_config_string = (user_io_8bit_get_string(0) != NULL); - parse_config(); + // set core name. This currently only sets a name for the 8 bit cores + user_io_read_core_name(); // send a reset user_io_8bit_set_status(UIO_STATUS_RESET, UIO_STATUS_RESET); @@ -283,6 +293,7 @@ void user_io_detect_core_type() iprintf("Found config\n"); user_io_8bit_set_status(status, 0xffffffff); } + parse_config(); // check for multipart rom sprintf(mainpath, "%s/boot0.rom", user_io_get_core_name()); @@ -312,6 +323,7 @@ void user_io_detect_core_type() if (is_x86_core()) { + x86_config_load(); x86_init(); } else diff --git a/x86.c b/x86.c index 7b2f232..e3ba0ef 100644 --- a/x86.c +++ b/x86.c @@ -34,6 +34,7 @@ #include "spi.h" #include "user_io.h" #include "file_io.h" +#include "fpga_io.h" #define ALT_CPU_CPU_FREQ 90000000u @@ -46,6 +47,17 @@ #define RTC_BASE 0x8c00 #define SD_BASE 0x0A00 +#define CFG_VER 1 + +typedef struct +{ + uint32_t ver; + char fdd_name[1024]; + char hdd_name[1024]; +} x86_config; + +static x86_config config; + static uint8_t dma_sdio(int status) { uint8_t res; @@ -202,6 +214,7 @@ static bool floppy_is_2_88m= false; static fileTYPE fdd_image = { 0 }; static fileTYPE hdd_image = { 0 }; +static bool boot_from_floppy = 1; #define IMG_TYPE_FDD 0x800 #define IMG_TYPE_HDD 0x000 @@ -213,6 +226,8 @@ static __inline fileTYPE *get_image(uint32_t type) static int img_mount(uint32_t type, char *name) { + FileClose(get_image(type)); + int writable = FileCanWrite(name); int ret = FileOpenEx(get_image(type), name, writable ? (O_RDWR | O_SYNC) : O_RDONLY); if (!ret) @@ -240,8 +255,88 @@ static int img_write(uint32_t type, uint32_t lba, void *buf, uint32_t len) #define IOWR(base, reg, value) dma_set(base+(reg<<2), value) +static int fdd_set(char* filename) +{ + int floppy = img_mount(IMG_TYPE_FDD, filename); + + /* + 0x00.[0]: media present + 0x01.[0]: media writeprotect + 0x02.[7:0]: media cylinders + 0x03.[7:0]: media sectors per track + 0x04.[31:0]: media total sector count + 0x05.[1:0]: media heads + 0x06.[31:0]: media sd base + 0x07.[15:0]: media wait cycles: 200000 us / spt + 0x08.[15:0]: media wait rate 0: 1000 us + 0x09.[15:0]: media wait rate 1: 1666 us + 0x0A.[15:0]: media wait rate 2: 2000 us + 0x0B.[15:0]: media wait rate 3: 500 us + 0x0C.[7:0]: media type: 8'h20 none; 8'h00 old; 8'hC0 720k; 8'h80 1_44M; 8'h40 2_88M + */ + + int floppy_cylinders = (floppy_is_2_88m || floppy_is_1_44m || floppy_is_1_2m || floppy_is_720k) ? 80 : 40; + int floppy_spt = + (floppy_is_160k) ? 8 : + (floppy_is_180k) ? 9 : + (floppy_is_320k) ? 8 : + (floppy_is_360k) ? 9 : + (floppy_is_720k) ? 9 : + (floppy_is_1_2m) ? 15 : + (floppy_is_1_44m) ? 18 : + (floppy_is_2_88m) ? 36 : + 0; + int floppy_total_sectors = + (floppy_is_160k) ? 320 : + (floppy_is_180k) ? 360 : + (floppy_is_320k) ? 640 : + (floppy_is_360k) ? 720 : + (floppy_is_720k) ? 1440 : + (floppy_is_1_2m) ? 2400 : + (floppy_is_1_44m) ? 2880 : + (floppy_is_2_88m) ? 5760 : + 0; + int floppy_heads = (floppy_is_160k || floppy_is_180k) ? 1 : 2; + + int floppy_wait_cycles = 200000000 / floppy_spt; + + int floppy_media = + (!floppy) ? 0x20 : + (floppy_is_160k) ? 0x00 : + (floppy_is_180k) ? 0x00 : + (floppy_is_320k) ? 0x00 : + (floppy_is_360k) ? 0x00 : + (floppy_is_720k) ? 0xC0 : + (floppy_is_1_2m) ? 0x00 : + (floppy_is_1_44m) ? 0x80 : + (floppy_is_2_88m) ? 0x40 : + 0x20; + + IOWR(FLOPPY_BASE, 0x0, floppy ? 1 : 0); + IOWR(FLOPPY_BASE, 0x1, (floppy && (get_image(IMG_TYPE_FDD)->mode & O_RDWR)) ? 0 : 1); + IOWR(FLOPPY_BASE, 0x2, floppy_cylinders); + IOWR(FLOPPY_BASE, 0x3, floppy_spt); + IOWR(FLOPPY_BASE, 0x4, floppy_total_sectors); + IOWR(FLOPPY_BASE, 0x5, floppy_heads); + IOWR(FLOPPY_BASE, 0x6, 0); // base LBA + IOWR(FLOPPY_BASE, 0x7, (int)(floppy_wait_cycles / (1000000000.0 / ALT_CPU_CPU_FREQ))); + IOWR(FLOPPY_BASE, 0x8, (int)(1000000.0 / (1000000000.0 / ALT_CPU_CPU_FREQ))); + IOWR(FLOPPY_BASE, 0x9, (int)(1666666.0 / (1000000000.0 / ALT_CPU_CPU_FREQ))); + IOWR(FLOPPY_BASE, 0xA, (int)(2000000.0 / (1000000000.0 / ALT_CPU_CPU_FREQ))); + IOWR(FLOPPY_BASE, 0xB, (int)(500000.0 / (1000000000.0 / ALT_CPU_CPU_FREQ))); + IOWR(FLOPPY_BASE, 0xC, floppy_media); + + return floppy; +} + void x86_init() { + user_io_8bit_set_status(UIO_STATUS_RESET, UIO_STATUS_RESET); + fpga_core_reset(1); + usleep(10000); + fpga_gpo_write(0); + spi_uio_cmd(0); + IOWR(PC_BUS_BASE, 0, 0x00FFF0EA); IOWR(PC_BUS_BASE, 1, 0x000000F0); @@ -273,75 +368,8 @@ void x86_init() //-------------------------------------------------------------------------- floppy - int floppy = img_mount(IMG_TYPE_FDD, "ao486/floppy.img"); - - /* - 0x00.[0]: media present - 0x01.[0]: media writeprotect - 0x02.[7:0]: media cylinders - 0x03.[7:0]: media sectors per track - 0x04.[31:0]: media total sector count - 0x05.[1:0]: media heads - 0x06.[31:0]: media sd base - 0x07.[15:0]: media wait cycles: 200000 us / spt - 0x08.[15:0]: media wait rate 0: 1000 us - 0x09.[15:0]: media wait rate 1: 1666 us - 0x0A.[15:0]: media wait rate 2: 2000 us - 0x0B.[15:0]: media wait rate 3: 500 us - 0x0C.[7:0]: media type: 8'h20 none; 8'h00 old; 8'hC0 720k; 8'h80 1_44M; 8'h40 2_88M - */ - - int floppy_cylinders = (floppy_is_2_88m || floppy_is_1_44m || floppy_is_1_2m || floppy_is_720k)? 80 : 40; - int floppy_spt = - (floppy_is_160k)? 8 : - (floppy_is_180k)? 9 : - (floppy_is_320k)? 8 : - (floppy_is_360k)? 9 : - (floppy_is_720k)? 9 : - (floppy_is_1_2m)? 15 : - (floppy_is_1_44m)? 18 : - (floppy_is_2_88m)? 36 : - 0; - int floppy_total_sectors = - (floppy_is_160k)? 320 : - (floppy_is_180k)? 360 : - (floppy_is_320k)? 640 : - (floppy_is_360k)? 720 : - (floppy_is_720k)? 1440 : - (floppy_is_1_2m)? 2400 : - (floppy_is_1_44m)? 2880 : - (floppy_is_2_88m)? 5760 : - 0; - int floppy_heads = (floppy_is_160k || floppy_is_180k)? 1 : 2; - - int floppy_wait_cycles = 200000000 / floppy_spt; - - int floppy_media = - (!floppy)? 0x20 : - (floppy_is_160k)? 0x00 : - (floppy_is_180k)? 0x00 : - (floppy_is_320k)? 0x00 : - (floppy_is_360k)? 0x00 : - (floppy_is_720k)? 0xC0 : - (floppy_is_1_2m)? 0x00 : - (floppy_is_1_44m)? 0x80 : - (floppy_is_2_88m)? 0x40 : - 0x20; - - IOWR(FLOPPY_BASE, 0x0, floppy? 1 : 0); - IOWR(FLOPPY_BASE, 0x1, (floppy && (get_image(IMG_TYPE_FDD)->mode & O_RDWR)) ? 0 : 1); - IOWR(FLOPPY_BASE, 0x2, floppy_cylinders); - IOWR(FLOPPY_BASE, 0x3, floppy_spt); - IOWR(FLOPPY_BASE, 0x4, floppy_total_sectors); - IOWR(FLOPPY_BASE, 0x5, floppy_heads); - IOWR(FLOPPY_BASE, 0x6, 0); // base LBA - IOWR(FLOPPY_BASE, 0x7, (int)(floppy_wait_cycles / (1000000000.0 / ALT_CPU_CPU_FREQ))); - IOWR(FLOPPY_BASE, 0x8, (int)(1000000.0 / (1000000000.0 / ALT_CPU_CPU_FREQ))); - IOWR(FLOPPY_BASE, 0x9, (int)(1666666.0 / (1000000000.0 / ALT_CPU_CPU_FREQ))); - IOWR(FLOPPY_BASE, 0xA, (int)(2000000.0 / (1000000000.0 / ALT_CPU_CPU_FREQ))); - IOWR(FLOPPY_BASE, 0xB, (int)(500000.0 / (1000000000.0 / ALT_CPU_CPU_FREQ))); - IOWR(FLOPPY_BASE, 0xC, floppy_media); - + int floppy = fdd_set(config.fdd_name); + //-------------------------------------------------------------------------- hdd unsigned int hd_cylinders = 0; @@ -350,7 +378,7 @@ void x86_init() unsigned int hd_total_sectors = 0; unsigned int hdd_sd_base = 0; - int hdd = img_mount(IMG_TYPE_HDD, "ao486/hdd.vhd"); + int hdd = img_mount(IMG_TYPE_HDD, config.hdd_name); if (hdd) { hd_cylinders = 1024; @@ -478,8 +506,6 @@ void x86_init() //-------------------------------------------------------------------------- rtc - bool boot_from_floppy = floppy; - /* 128.[26:0]: cycles in second 129.[12:0]: cycles in 122.07031 us @@ -590,6 +616,8 @@ void x86_init() cmos[0x2F] = sum & 0xFF; for(unsigned int i=0; i Date: Thu, 3 Aug 2017 02:41:10 +0800 Subject: [PATCH 09/17] Fix PageDn button. --- input.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/input.c b/input.c index 088e099..aaff9c8 100644 --- a/input.c +++ b/input.c @@ -389,7 +389,7 @@ static const int ev2ps2[] = EXT | 0x74, //106 KEY_RIGHT EXT | 0x69, //107 KEY_END EXT | 0x72, //108 KEY_DOWN - EXT | 0x7d, //109 KEY_PAGEDOWN + EXT | 0x7a, //109 KEY_PAGEDOWN EXT | 0x70, //110 KEY_INSERT EXT | 0x71, //111 KEY_DELETE NONE, //112 KEY_MACRO From d50d5b365ae7352ec6db4307e04cb1c0b2647033 Mon Sep 17 00:00:00 2001 From: sorgelig Date: Thu, 3 Aug 2017 02:41:43 +0800 Subject: [PATCH 10/17] ao486: mouse support. --- user_io.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 72 insertions(+), 10 deletions(-) diff --git a/user_io.c b/user_io.c index 7ec6518..4ff2145 100644 --- a/user_io.c +++ b/user_io.c @@ -805,6 +805,12 @@ void kbd_reply(char code) spi_uio_cmd8(UIO_KEYBOARD, code); } +void mouse_reply(char code) +{ + printf("mouse_reply = 0x%02X\n", code); + spi_uio_cmd8(UIO_MOUSE, code); +} + static uint8_t use_ps2ctl = 0; void user_io_poll() @@ -1208,9 +1214,6 @@ void user_io_poll() static uint8_t leds = 0; if(use_ps2ctl) { - static uint8_t kbd_cmd = 0; - static uint8_t kbd_byte = 0; - leds |= (KBD_LED_FLAG_STATUS | KBD_LED_CAPS_CONTROL); uint8_t kbd_ctl, mouse_ctl; @@ -1218,11 +1221,14 @@ void user_io_poll() if (ps2ctl & 1) { + static uint8_t cmd = 0; + static uint8_t byte = 0; + printf("kbd_ctl = 0x%02X\n", kbd_ctl); - if (!kbd_byte) + if (!byte) { - kbd_cmd = kbd_ctl; - switch (kbd_cmd) + cmd = kbd_ctl; + switch (cmd) { case 0xff: kbd_reply(0xFA); @@ -1237,7 +1243,7 @@ void user_io_poll() case 0xed: kbd_reply(0xFA); - kbd_byte++; + byte++; break; default: @@ -1247,11 +1253,11 @@ void user_io_poll() } else { - switch (kbd_cmd) + switch (cmd) { case 0xed: kbd_reply(0xFA); - kbd_byte = 0; + byte = 0; if (kbd_ctl & 4) leds |= KBD_LED_CAPS_STATUS; else leds &= ~KBD_LED_CAPS_STATUS; @@ -1259,7 +1265,63 @@ void user_io_poll() break; default: - kbd_byte = 0; + byte = 0; + break; + } + } + } + + if (ps2ctl & 2) + { + static uint8_t cmd = 0; + static uint8_t byte = 0; + + printf("mouse_ctl = 0x%02X\n", mouse_ctl); + if (!byte) + { + cmd = mouse_ctl; + switch (cmd) + { + case 0xe8: + case 0xf3: + mouse_reply(0xFA); + byte++; + break; + + case 0xf2: + mouse_reply(0xFA); + mouse_reply(0x00); + break; + + case 0xe6: + case 0xf4: + case 0xf5: + mouse_reply(0xFA); + break; + + case 0xff: + mouse_reply(0xFA); + mouse_reply(0xAA); + mouse_reply(0x00); + break; + + default: + //mouse_reply(0xFE); + break; + } + } + else + { + switch (cmd) + { + case 0xf3: + case 0xe8: + mouse_reply(0xFA); + byte = 0; + break; + + default: + byte = 0; break; } } From 93b4932185767a1aca02193b2598b9332574da28 Mon Sep 17 00:00:00 2001 From: sorgelig Date: Thu, 3 Aug 2017 03:57:56 +0800 Subject: [PATCH 11/17] Block the mouse while OSD is active. --- user_io.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/user_io.c b/user_io.c index 4ff2145..879173a 100644 --- a/user_io.c +++ b/user_io.c @@ -1509,6 +1509,8 @@ static void send_keycode(unsigned short key, int press) void user_io_mouse(unsigned char b, int16_t x, int16_t y) { + if (osd_is_visible) return; + // send mouse data as minimig expects it if (core_type == CORE_TYPE_MINIMIG2) { From e38fabf9077243ca78dca773a3e25631751fccec Mon Sep 17 00:00:00 2001 From: sorgelig Date: Thu, 3 Aug 2017 22:11:44 +0800 Subject: [PATCH 12/17] ao486: remove unneeded reset. --- x86.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/x86.c b/x86.c index e3ba0ef..cd3a15e 100644 --- a/x86.c +++ b/x86.c @@ -332,10 +332,6 @@ static int fdd_set(char* filename) void x86_init() { user_io_8bit_set_status(UIO_STATUS_RESET, UIO_STATUS_RESET); - fpga_core_reset(1); - usleep(10000); - fpga_gpo_write(0); - spi_uio_cmd(0); IOWR(PC_BUS_BASE, 0, 0x00FFF0EA); IOWR(PC_BUS_BASE, 1, 0x000000F0); From ffd3889420a34227b3867d5e126566bd52e1d53d Mon Sep 17 00:00:00 2001 From: sorgelig Date: Thu, 3 Aug 2017 22:19:00 +0800 Subject: [PATCH 13/17] Release 20170803. --- releases/MiSTer_20170803 | Bin 0 -> 106444 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 releases/MiSTer_20170803 diff --git a/releases/MiSTer_20170803 b/releases/MiSTer_20170803 new file mode 100644 index 0000000000000000000000000000000000000000..9e3ec1dc8d3e4aaea64082cde43325afe4e47399 GIT binary patch literal 106444 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 literal 0 HcmV?d00001 From 40c59c81b787e430cbc173f48fcff7d1bd70ca7d Mon Sep 17 00:00:00 2001 From: sorgelig Date: Sat, 5 Aug 2017 03:07:17 +0800 Subject: [PATCH 14/17] ao486: FDD size detection, tweaks in startup and reset code. --- user_io.c | 61 ++++++++++------------ x86.c | 149 ++++++++++++++++++++++++++++++++++++------------------ x86.h | 1 - 3 files changed, 127 insertions(+), 84 deletions(-) diff --git a/user_io.c b/user_io.c index 879173a..83bd357 100644 --- a/user_io.c +++ b/user_io.c @@ -295,32 +295,6 @@ void user_io_detect_core_type() } parse_config(); - // check for multipart rom - sprintf(mainpath, "%s/boot0.rom", user_io_get_core_name()); - if (user_io_file_tx(mainpath, 0)) - { - sprintf(mainpath, "%s/boot1.rom", user_io_get_core_name()); - if (user_io_file_tx(mainpath, 0x40)) - { - sprintf(mainpath, "%s/boot2.rom", user_io_get_core_name()); - if (user_io_file_tx(mainpath, 0x80)) - { - sprintf(mainpath, "%s/boot3.rom", user_io_get_core_name()); - user_io_file_tx(mainpath, 0xC0); - } - } - } - else - { - // legacy style of rom - sprintf(mainpath, "%s/boot.rom", user_io_get_core_name()); - if (!user_io_file_tx(mainpath, 0)) - { - strcpy(name + strlen(name) - 3, "ROM"); - user_io_file_tx(name, 0); - } - } - if (is_x86_core()) { x86_config_load(); @@ -328,6 +302,32 @@ void user_io_detect_core_type() } else { + // check for multipart rom + sprintf(mainpath, "%s/boot0.rom", user_io_get_core_name()); + if (user_io_file_tx(mainpath, 0)) + { + sprintf(mainpath, "%s/boot1.rom", user_io_get_core_name()); + if (user_io_file_tx(mainpath, 0x40)) + { + sprintf(mainpath, "%s/boot2.rom", user_io_get_core_name()); + if (user_io_file_tx(mainpath, 0x80)) + { + sprintf(mainpath, "%s/boot3.rom", user_io_get_core_name()); + user_io_file_tx(mainpath, 0xC0); + } + } + } + else + { + // legacy style of rom + sprintf(mainpath, "%s/boot.rom", user_io_get_core_name()); + if (!user_io_file_tx(mainpath, 0)) + { + strcpy(name + strlen(name) - 3, "ROM"); + user_io_file_tx(name, 0); + } + } + // check if there's a .vhd present sprintf(mainpath, "%s/boot.vhd", user_io_get_core_name()); user_io_set_index(0); @@ -636,14 +636,6 @@ int user_io_file_tx(char* name, unsigned char index) /* transmit the entire file using one transfer */ iprintf("Selected file %s with %lu bytes to send for index %d.%d\n", name, bytes2send, index&0x3F, index>>6); - if (is_x86_core()) - { - printf("using DMA transfer mode\n"); - x86_send(&f, index); - FileClose(&f); - return 1; - } - // set index byte (0=bios rom, 1-n=OSD entry index) user_io_set_index(index); @@ -781,6 +773,7 @@ void user_io_send_buttons(char force) key_map = map; spi_uio_cmd8(UIO_BUT_SW, map); printf("sending keymap: %X\n", map); + if ((key_map & BUTTON2) && is_x86_core) x86_init(); } if (old_video_mode != mist_cfg.video_mode) diff --git a/x86.c b/x86.c index cd3a15e..271571e 100644 --- a/x86.c +++ b/x86.c @@ -105,36 +105,39 @@ static void dma_rcvbuf(uint32_t address, uint32_t length, uint32_t *data) DisableFpga(); } -int x86_send(fileTYPE *f, uint8_t index) -{ - static uint32_t buf[128]; - - FileSeekLBA(f, 0); - - EnableFpga(); - spi8(UIO_DMA_WRITE); - spi32w( index ? 0x80C0000 : 0x80F0000 ); - - unsigned long bytes2send = f->size; - - while (bytes2send) - { - printf("."); - - uint16_t chunk = (bytes2send>512) ? 512 : bytes2send; - bytes2send -= chunk; - - FileReadSec(f, buf); - - chunk = (chunk + 3) >> 2; - uint32_t* p = buf; - while(chunk--) spi32w(*p++); - } - DisableFpga(); - - printf("\n"); - return 1; -} +static int load_bios(char* name, uint8_t index) +{ + fileTYPE f = { 0 }; + static uint32_t buf[128]; + + if (!FileOpen(&f, name)) return 0; + + unsigned long bytes2send = f.size; + printf("BIOS %s, %lu bytes.\n", name, bytes2send); + + EnableFpga(); + spi8(UIO_DMA_WRITE); + spi32w( index ? 0x80C0000 : 0x80F0000 ); + + while (bytes2send) + { + printf("."); + + uint16_t chunk = (bytes2send>512) ? 512 : bytes2send; + bytes2send -= chunk; + + FileReadSec(&f, buf); + + chunk = (chunk + 3) >> 2; + uint32_t* p = buf; + while(chunk--) spi32w(*p++); + } + DisableFpga(); + FileClose(&f); + + printf("\n"); + return 1; +} static void crc32(uint8_t *ptr, uint32_t *crc_output) { @@ -209,9 +212,12 @@ static bool floppy_is_320k = false; static bool floppy_is_360k = false; static bool floppy_is_720k = false; static bool floppy_is_1_2m = false; -static bool floppy_is_1_44m= true; +static bool floppy_is_1_44m= false; +static bool floppy_is_1_68m= false; static bool floppy_is_2_88m= false; +#define CMOS_FDD_TYPE ((floppy_is_2_88m) ? 0x50 : (floppy_is_1_44m || floppy_is_1_68m) ? 0x40 : (floppy_is_720k) ? 0x30 : (floppy_is_1_2m) ? 0x20 : 0x10) + static fileTYPE fdd_image = { 0 }; static fileTYPE hdd_image = { 0 }; static bool boot_from_floppy = 1; @@ -255,9 +261,58 @@ static int img_write(uint32_t type, uint32_t lba, void *buf, uint32_t len) #define IOWR(base, reg, value) dma_set(base+(reg<<2), value) +static uint32_t cmos[128]; + +void cmos_set(int addr, uint8_t val) +{ + if (addr >= sizeof(cmos)) return; + + cmos[addr] = val; + return; + + uint16_t sum = 0; + for (int i = 0x10; i <= 0x2D; i++) sum += cmos[i]; + + cmos[0x2E] = sum >> 8; + cmos[0x2F] = sum & 0xFF; + + IOWR(RTC_BASE, addr, cmos[addr]); + + IOWR(RTC_BASE, 0x2E, cmos[0x2E]); + IOWR(RTC_BASE, 0x2F, cmos[0x2F]); +} + static int fdd_set(char* filename) { + floppy_is_160k = false; + floppy_is_180k = false; + floppy_is_320k = false; + floppy_is_360k = false; + floppy_is_720k = false; + floppy_is_1_2m = false; + floppy_is_1_44m = false; + floppy_is_1_68m = false; + floppy_is_2_88m = false; + int floppy = img_mount(IMG_TYPE_FDD, filename); + uint32_t size = get_image(IMG_TYPE_FDD)->size/512; + if (floppy && size) + { + if (size >= 5760) floppy_is_2_88m = true; + else if (size >= 3360) floppy_is_1_68m = true; + else if (size >= 2880) floppy_is_1_44m = true; + else if (size >= 2400) floppy_is_1_2m = true; + else if (size >= 1440) floppy_is_720k = true; + else if (size >= 720) floppy_is_360k = true; + else if (size >= 640) floppy_is_320k = true; + else if (size >= 360) floppy_is_180k = true; + else floppy_is_160k = true; + } + else + { + floppy = 0; + floppy_is_1_44m = true; + } /* 0x00.[0]: media present @@ -275,7 +330,6 @@ static int fdd_set(char* filename) 0x0C.[7:0]: media type: 8'h20 none; 8'h00 old; 8'hC0 720k; 8'h80 1_44M; 8'h40 2_88M */ - int floppy_cylinders = (floppy_is_2_88m || floppy_is_1_44m || floppy_is_1_2m || floppy_is_720k) ? 80 : 40; int floppy_spt = (floppy_is_160k) ? 8 : (floppy_is_180k) ? 9 : @@ -284,21 +338,14 @@ static int fdd_set(char* filename) (floppy_is_720k) ? 9 : (floppy_is_1_2m) ? 15 : (floppy_is_1_44m) ? 18 : + (floppy_is_1_68m) ? 21 : (floppy_is_2_88m) ? 36 : 0; - int floppy_total_sectors = - (floppy_is_160k) ? 320 : - (floppy_is_180k) ? 360 : - (floppy_is_320k) ? 640 : - (floppy_is_360k) ? 720 : - (floppy_is_720k) ? 1440 : - (floppy_is_1_2m) ? 2400 : - (floppy_is_1_44m) ? 2880 : - (floppy_is_2_88m) ? 5760 : - 0; - int floppy_heads = (floppy_is_160k || floppy_is_180k) ? 1 : 2; - int floppy_wait_cycles = 200000000 / floppy_spt; + int floppy_cylinders = (floppy_is_2_88m || floppy_is_1_68m || floppy_is_1_44m || floppy_is_1_2m || floppy_is_720k) ? 80 : 40; + int floppy_heads = (floppy_is_160k || floppy_is_180k) ? 1 : 2; + int floppy_total_sectors = floppy_spt * floppy_heads * floppy_cylinders; + int floppy_wait_cycles = 200000000 / floppy_spt; int floppy_media = (!floppy) ? 0x20 : @@ -326,6 +373,7 @@ static int fdd_set(char* filename) IOWR(FLOPPY_BASE, 0xB, (int)(500000.0 / (1000000000.0 / ALT_CPU_CPU_FREQ))); IOWR(FLOPPY_BASE, 0xC, floppy_media); + //cmos_set(0x10, CMOS_FDD_TYPE); return floppy; } @@ -333,6 +381,9 @@ void x86_init() { user_io_8bit_set_status(UIO_STATUS_RESET, UIO_STATUS_RESET); + load_bios("ao486/boot0.rom", 0); + load_bios("ao486/boot1.rom", 1); + IOWR(PC_BUS_BASE, 0, 0x00FFF0EA); IOWR(PC_BUS_BASE, 1, 0x000000F0); @@ -364,7 +415,7 @@ void x86_init() //-------------------------------------------------------------------------- floppy - int floppy = fdd_set(config.fdd_name); + fdd_set(config.fdd_name); //-------------------------------------------------------------------------- hdd @@ -510,8 +561,6 @@ void x86_init() IOWR(RTC_BASE, 128, (int)(1000000000.0 / (1000000000.0 / ALT_CPU_CPU_FREQ))); IOWR(RTC_BASE, 129, (int)(122070.0 / (1000000000.0 / ALT_CPU_CPU_FREQ))); - unsigned char fdd_type = (floppy_is_2_88m)? 0x50 : (floppy_is_1_44m)? 0x40 : (floppy_is_720k)? 0x30 : (floppy_is_1_2m)? 0x20 : 0x10; - bool translate_none = hd_cylinders <= 1024 && hd_heads <= 16 && hd_spt <= 63; bool translate_large= !translate_none && (hd_cylinders * hd_heads) <= 131072; bool translate_lba = !translate_none && !translate_large; @@ -519,7 +568,7 @@ void x86_init() unsigned char translate_byte = 1; //(translate_large) ? 1 : (translate_lba) ? 2 : 0; //rtc contents 0-127 - unsigned int cmos[128] = { + uint32_t tmp[128] = { 0x00, //0x00: SEC BCD 0x00, //0x01: ALARM SEC BCD 0x00, //0x02: MIN BCD @@ -537,7 +586,7 @@ void x86_init() 0x00, //0x0E: REG E - POST status 0x00, //0x0F: REG F - shutdown status - fdd_type, //0x10: floppy drive type; 0-none, 1-360K, 2-1.2M, 3-720K, 4-1.44M, 5-2.88M + CMOS_FDD_TYPE, //0x10: floppy drive type; 0-none, 1-360K, 2-1.2M, 3-720K, 4-1.44M, 5-2.88M 0x00, //0x11: configuration bits; not used 0xF0, //0x12: hard disk types; 0-none, 1:E-type, F-type 16+ 0x00, //0x13: advanced configuration bits; not used @@ -604,6 +653,8 @@ void x86_init() 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + memcpy(cmos, tmp, sizeof(cmos)); + //count checksum unsigned short sum = 0; for(int i=0x10; i<=0x2D; i++) sum += cmos[i]; diff --git a/x86.h b/x86.h index 065da01..8bb15f7 100644 --- a/x86.h +++ b/x86.h @@ -3,7 +3,6 @@ void x86_init(); void x86_poll(); -int x86_send(fileTYPE *f, uint8_t index); void x86_set_image(int num, char *filename); From fddc6b0e24feefca51e40ae85b87bd93870855ad Mon Sep 17 00:00:00 2001 From: sorgelig Date: Sat, 5 Aug 2017 04:19:49 +0800 Subject: [PATCH 15/17] Release 20170805. --- releases/MiSTer_20170805 | Bin 0 -> 107124 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 releases/MiSTer_20170805 diff --git a/releases/MiSTer_20170805 b/releases/MiSTer_20170805 new file mode 100644 index 0000000000000000000000000000000000000000..4695002b8637fc8bf29f0b9963b7c47649a40be6 GIT binary patch literal 107124 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 G@4o@21}$d* literal 0 HcmV?d00001 From dd613edc8eb31f8cb10c006eac21cf7e3005e908 Mon Sep 17 00:00:00 2001 From: sorgelig Date: Sun, 6 Aug 2017 19:55:06 +0800 Subject: [PATCH 16/17] ao486: set the real time (internet is required). --- user_io.c | 9 ++++++++- x86.c | 23 ++++++++++++++++------- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/user_io.c b/user_io.c index 83bd357..ea64742 100644 --- a/user_io.c +++ b/user_io.c @@ -1292,6 +1292,13 @@ void user_io_poll() mouse_reply(0xFA); break; + case 0xe9: + mouse_reply(0xFA); + mouse_reply(0x00); + mouse_reply(0x00); + mouse_reply(0x00); + break; + case 0xff: mouse_reply(0xFA); mouse_reply(0xAA); @@ -1299,7 +1306,7 @@ void user_io_poll() break; default: - //mouse_reply(0xFE); + mouse_reply(0xFE); break; } } diff --git a/x86.c b/x86.c index 271571e..89d447e 100644 --- a/x86.c +++ b/x86.c @@ -30,6 +30,7 @@ #include #include #include +#include #include "spi.h" #include "user_io.h" @@ -377,6 +378,11 @@ static int fdd_set(char* filename) return floppy; } +static uint8_t bin2bcd(unsigned val) +{ + return ((val / 10) << 4) + (val % 10); +} + void x86_init() { user_io_8bit_set_status(UIO_STATUS_RESET, UIO_STATUS_RESET); @@ -567,18 +573,21 @@ void x86_init() unsigned char translate_byte = 1; //(translate_large) ? 1 : (translate_lba) ? 2 : 0; + time_t t = time(NULL); + struct tm tm = *localtime(&t); + //rtc contents 0-127 uint32_t tmp[128] = { - 0x00, //0x00: SEC BCD + bin2bcd(tm.tm_sec), //0x00: SEC BCD 0x00, //0x01: ALARM SEC BCD - 0x00, //0x02: MIN BCD + bin2bcd(tm.tm_min), //0x02: MIN BCD 0x00, //0x03: ALARM MIN BCD - 0x12, //0x04: HOUR BCD 24h + bin2bcd(tm.tm_hour), //0x04: HOUR BCD 24h 0x12, //0x05: ALARM HOUR BCD 24h - 0x01, //0x06: DAY OF WEEK Sunday=1 - 0x03, //0x07: DAY OF MONTH BCD from 1 - 0x11, //0x08: MONTH BCD from 1 - 0x13, //0x09: YEAR BCD + tm.tm_wday+1, //0x06: DAY OF WEEK Sunday=1 + bin2bcd(tm.tm_mday), //0x07: DAY OF MONTH BCD from 1 + bin2bcd(tm.tm_mon+1), //0x08: MONTH BCD from 1 + bin2bcd((tm.tm_year<117) ? 17 : tm.tm_year-100), //0x09: YEAR BCD 0x26, //0x0A: REG A 0x02, //0x0B: REG B 0x00, //0x0C: REG C From 423d401c16b60a31165368278b299c89d39cddaa Mon Sep 17 00:00:00 2001 From: sorgelig Date: Mon, 7 Aug 2017 03:17:39 +0800 Subject: [PATCH 17/17] Release 20170806. --- releases/MiSTer_20170806 | Bin 0 -> 110540 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 releases/MiSTer_20170806 diff --git a/releases/MiSTer_20170806 b/releases/MiSTer_20170806 new file mode 100644 index 0000000000000000000000000000000000000000..5bc747908bc8aa8acb36179b3fa6bbf9d00a8258 GIT binary patch literal 110540 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 NwG7@LLQe$me*j=gC(!@^ literal 0 HcmV?d00001