Merge branch 'master' of https://github.com/MiSTer-devel/Main_MiSTer
This commit is contained in:
@@ -57,6 +57,7 @@
|
||||
<ClCompile Include="spi.c" />
|
||||
<ClCompile Include="tos.c" />
|
||||
<ClCompile Include="user_io.c" />
|
||||
<ClCompile Include="x86.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="archie.h" />
|
||||
@@ -78,7 +79,6 @@
|
||||
<ClInclude Include="ikbd.h" />
|
||||
<ClInclude Include="ini_parser.h" />
|
||||
<ClInclude Include="input.h" />
|
||||
<ClInclude Include="keycodes.h" />
|
||||
<ClInclude Include="logo.h" />
|
||||
<ClInclude Include="menu.h" />
|
||||
<ClInclude Include="mist_cfg.h" />
|
||||
@@ -86,6 +86,7 @@
|
||||
<ClInclude Include="spi.h" />
|
||||
<ClInclude Include="tos.h" />
|
||||
<ClInclude Include="user_io.h" />
|
||||
<ClInclude Include="x86.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="build.sh" />
|
||||
|
||||
@@ -65,6 +65,9 @@
|
||||
<ClCompile Include="file_io.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="x86.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="archie.h">
|
||||
@@ -121,9 +124,6 @@
|
||||
<ClInclude Include="input.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="keycodes.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="logo.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
@@ -148,6 +148,9 @@
|
||||
<ClInclude Include="file_io.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="x86.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="build.sh" />
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
28
input.h
28
input.h
@@ -2,11 +2,33 @@
|
||||
#ifndef EVINPUT_H
|
||||
#define EVINPUT_H
|
||||
|
||||
#include <linux/input.h>
|
||||
|
||||
#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
|
||||
|
||||
509
keycodes.h
509
keycodes.h
@@ -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
|
||||
2
main.c
2
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);
|
||||
|
||||
|
||||
142
menu.c
142
menu.c
@@ -46,6 +46,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include <stdbool.h>
|
||||
#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;
|
||||
|
||||
@@ -415,52 +416,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 +466,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 +476,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 +492,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 +506,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 +516,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 +552,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 +624,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);
|
||||
@@ -818,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
|
||||
@@ -955,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;
|
||||
@@ -976,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1000,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:
|
||||
@@ -1079,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;
|
||||
}
|
||||
@@ -1832,7 +1854,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 +1956,31 @@ 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 (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_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;
|
||||
|
||||
23
menu.h
23
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,9 @@ void ShowSplash();
|
||||
void HideSplash();
|
||||
void EjectAllFloppies();
|
||||
|
||||
void menu_key_set(unsigned char c);
|
||||
void menu_mod_set(uint8_t m);
|
||||
unsigned long getStatus(char *opt, unsigned long status);
|
||||
|
||||
void menu_key_set(uint32_t c);
|
||||
void menu_mod_set(uint32_t m);
|
||||
|
||||
#endif
|
||||
|
||||
BIN
releases/MiSTer_20170803
Normal file
BIN
releases/MiSTer_20170803
Normal file
Binary file not shown.
BIN
releases/MiSTer_20170805
Normal file
BIN
releases/MiSTer_20170805
Normal file
Binary file not shown.
BIN
releases/MiSTer_20170806
Normal file
BIN
releases/MiSTer_20170806
Normal file
Binary file not shown.
8
spi.c
8
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)
|
||||
{
|
||||
|
||||
1
spi.h
1
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);
|
||||
|
||||
577
user_io.c
577
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"
|
||||
@@ -20,6 +19,7 @@
|
||||
#include "file_io.h"
|
||||
#include "config.h"
|
||||
#include "menu.h"
|
||||
#include "x86.h"
|
||||
|
||||
#define BREAK 0x8000
|
||||
|
||||
@@ -133,9 +133,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())
|
||||
@@ -172,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)
|
||||
{
|
||||
@@ -194,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);
|
||||
@@ -258,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);
|
||||
@@ -275,22 +293,49 @@ void user_io_detect_core_type()
|
||||
iprintf("Found config\n");
|
||||
user_io_8bit_set_status(status, 0xffffffff);
|
||||
}
|
||||
parse_config();
|
||||
|
||||
// check if there's a <core>.rom present
|
||||
sprintf(mainpath, "%s/boot.rom", user_io_get_core_name());
|
||||
if (!user_io_file_tx(mainpath, 0))
|
||||
if (is_x86_core())
|
||||
{
|
||||
strcpy(name + strlen(name) - 3, "ROM");
|
||||
user_io_file_tx(name, 0);
|
||||
x86_config_load();
|
||||
x86_init();
|
||||
}
|
||||
|
||||
// check if there's a <core>.vhd present
|
||||
sprintf(mainpath, "%s/boot.vhd", user_io_get_core_name());
|
||||
user_io_set_index(0);
|
||||
if (!user_io_file_mount(0, mainpath))
|
||||
else
|
||||
{
|
||||
strcpy(name + strlen(name) - 3, "VHD");
|
||||
user_io_file_mount(0, name);
|
||||
// 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 <core>.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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -300,28 +345,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)
|
||||
@@ -456,17 +479,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)
|
||||
{
|
||||
@@ -635,7 +677,7 @@ int user_io_file_tx(char* name, unsigned char index)
|
||||
spi8(0x00);
|
||||
DisableFpga();
|
||||
|
||||
iprintf("\n");
|
||||
printf("\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -731,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)
|
||||
@@ -749,6 +792,20 @@ 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 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()
|
||||
{
|
||||
if ((core_type != CORE_TYPE_MINIMIG2) &&
|
||||
@@ -845,10 +902,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,8 +926,14 @@ void user_io_poll()
|
||||
iprintf("\033[0m");
|
||||
}
|
||||
DisableIO();
|
||||
*/
|
||||
|
||||
// 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 };
|
||||
@@ -1141,10 +1204,140 @@ void user_io_poll()
|
||||
|
||||
if (core_type == CORE_TYPE_ARCHIE) archie_poll();
|
||||
|
||||
static uint8_t leds = 0;
|
||||
if(use_ps2ctl)
|
||||
{
|
||||
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)
|
||||
{
|
||||
static uint8_t cmd = 0;
|
||||
static uint8_t byte = 0;
|
||||
|
||||
printf("kbd_ctl = 0x%02X\n", kbd_ctl);
|
||||
if (!byte)
|
||||
{
|
||||
cmd = kbd_ctl;
|
||||
switch (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);
|
||||
byte++;
|
||||
break;
|
||||
|
||||
default:
|
||||
kbd_reply(0xFE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (cmd)
|
||||
{
|
||||
case 0xed:
|
||||
kbd_reply(0xFA);
|
||||
byte = 0;
|
||||
|
||||
if (kbd_ctl & 4) leds |= KBD_LED_CAPS_STATUS;
|
||||
else leds &= ~KBD_LED_CAPS_STATUS;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
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 0xe9:
|
||||
mouse_reply(0xFA);
|
||||
mouse_reply(0x00);
|
||||
mouse_reply(0x00);
|
||||
mouse_reply(0x00);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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))
|
||||
@@ -1175,12 +1368,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))
|
||||
@@ -1191,67 +1408,109 @@ 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)
|
||||
{
|
||||
if (osd_is_visible) return;
|
||||
|
||||
// send mouse data as minimig expects it
|
||||
if (core_type == CORE_TYPE_MINIMIG2)
|
||||
{
|
||||
@@ -1282,19 +1541,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)
|
||||
@@ -1332,58 +1578,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)
|
||||
@@ -1393,105 +1600,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
|
||||
@@ -1499,7 +1638,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;
|
||||
@@ -1529,10 +1668,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(code);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
send_keycode(key, press);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -63,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
|
||||
@@ -167,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();
|
||||
|
||||
@@ -192,5 +199,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
|
||||
|
||||
790
x86.c
Normal file
790
x86.c
Normal file
@@ -0,0 +1,790 @@
|
||||
/*
|
||||
* 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "spi.h"
|
||||
#include "user_io.h"
|
||||
#include "file_io.h"
|
||||
#include "fpga_io.h"
|
||||
|
||||
#define ALT_CPU_CPU_FREQ 90000000u
|
||||
|
||||
#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
|
||||
|
||||
#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;
|
||||
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();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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));
|
||||
}
|
||||
|
||||
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= 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;
|
||||
|
||||
#define IMG_TYPE_FDD 0x800
|
||||
#define IMG_TYPE_HDD 0x000
|
||||
|
||||
static __inline fileTYPE *get_image(uint32_t type)
|
||||
{
|
||||
return (type == IMG_TYPE_FDD) ? &fdd_image : &hdd_image;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
get_image(type)->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 type, uint32_t lba, void *buf, uint32_t len)
|
||||
{
|
||||
if (!FileSeekLBA(get_image(type), lba)) return 0;
|
||||
return FileReadAdv(get_image(type), buf, len);
|
||||
}
|
||||
|
||||
static int img_write(uint32_t type, uint32_t lba, void *buf, uint32_t 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)
|
||||
|
||||
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
|
||||
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_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_1_68m) ? 21 :
|
||||
(floppy_is_2_88m) ? 36 :
|
||||
0;
|
||||
|
||||
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 :
|
||||
(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);
|
||||
|
||||
//cmos_set(0x10, CMOS_FDD_TYPE);
|
||||
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);
|
||||
|
||||
load_bios("ao486/boot0.rom", 0);
|
||||
load_bios("ao486/boot1.rom", 1);
|
||||
|
||||
IOWR(PC_BUS_BASE, 0, 0x00FFF0EA);
|
||||
IOWR(PC_BUS_BASE, 1, 0x000000F0);
|
||||
|
||||
//-------------------------------------------------------------------------- sound
|
||||
/*
|
||||
0-255.[15:0]: cycles in period
|
||||
256.[12:0]: cycles in 80us
|
||||
257.[9:0]: cycles in 1 sample: 96000 Hz
|
||||
*/
|
||||
|
||||
double cycle_in_ns = (1000000000.0 / ALT_CPU_CPU_FREQ); //33.333333;
|
||||
for(int i=0; i<256; i++)
|
||||
{
|
||||
double f = 1000000.0 / (256.0-i);
|
||||
|
||||
double cycles_in_period = 1000000000.0 / (f * cycle_in_ns);
|
||||
IOWR(SOUND_BASE, i, (int)cycles_in_period);
|
||||
}
|
||||
|
||||
IOWR(SOUND_BASE, 256, (int)(80000.0 / (1000000000.0 / ALT_CPU_CPU_FREQ)));
|
||||
IOWR(SOUND_BASE, 257, (int)((1000000000.0/96000.0) / (1000000000.0 / ALT_CPU_CPU_FREQ)));
|
||||
|
||||
//-------------------------------------------------------------------------- pit
|
||||
/*
|
||||
0.[7:0]: cycles in sysclock 1193181 Hz
|
||||
*/
|
||||
|
||||
IOWR(PIT_BASE, 0, (int)((1000000000.0/1193181.0) / (1000000000.0 / ALT_CPU_CPU_FREQ)));
|
||||
|
||||
//-------------------------------------------------------------------------- floppy
|
||||
|
||||
fdd_set(config.fdd_name);
|
||||
|
||||
//-------------------------------------------------------------------------- hdd
|
||||
|
||||
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 = img_mount(IMG_TYPE_HDD, config.hdd_name);
|
||||
if (hdd)
|
||||
{
|
||||
hd_cylinders = 1024;
|
||||
hd_heads = 16;
|
||||
hd_spt = 63;
|
||||
|
||||
hd_total_sectors = get_image(IMG_TYPE_HDD)->size / 512;
|
||||
}
|
||||
|
||||
/*
|
||||
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, 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, 0); // base LBA
|
||||
|
||||
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
|
||||
|
||||
/*
|
||||
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)));
|
||||
|
||||
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 = 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] = {
|
||||
bin2bcd(tm.tm_sec), //0x00: SEC BCD
|
||||
0x00, //0x01: ALARM SEC BCD
|
||||
bin2bcd(tm.tm_min), //0x02: MIN BCD
|
||||
0x00, //0x03: ALARM MIN BCD
|
||||
bin2bcd(tm.tm_hour), //0x04: HOUR BCD 24h
|
||||
0x12, //0x05: ALARM HOUR BCD 24h
|
||||
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
|
||||
0x80, //0x0D: REG D
|
||||
0x00, //0x0E: REG E - POST status
|
||||
0x00, //0x0F: REG F - shutdown status
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
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
|
||||
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
|
||||
};
|
||||
|
||||
memcpy(cmos, tmp, sizeof(cmos));
|
||||
|
||||
//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<sizeof(cmos)/sizeof(unsigned int); i++) IOWR(RTC_BASE, i, cmos[i]);
|
||||
|
||||
user_io_8bit_set_status(0, UIO_STATUS_RESET);
|
||||
}
|
||||
|
||||
struct sd_param_t
|
||||
{
|
||||
uint32_t addr;
|
||||
uint32_t lba;
|
||||
uint32_t bl_cnt;
|
||||
};
|
||||
|
||||
static struct sd_param_t sd_params = { 0 };
|
||||
|
||||
void x86_poll()
|
||||
{
|
||||
int res = 0;
|
||||
static uint32_t secbuf[128 * 4];
|
||||
|
||||
char sd_req = dma_sdio(0);
|
||||
if (sd_req == 1)
|
||||
{
|
||||
dma_rcvbuf(SD_BASE + (4 << 2), sizeof(sd_params) >> 2, (uint32_t*)&sd_params);
|
||||
//printf("Read: 0x%08x, 0x%08x, %d\n", sd_params.addr, sd_params.lba, sd_params.bl_cnt);
|
||||
|
||||
if (get_image(sd_params.addr)->size)
|
||||
{
|
||||
if (sd_params.bl_cnt>0 && sd_params.bl_cnt<=4)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
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 (get_image(sd_params.addr)->size)
|
||||
{
|
||||
if (sd_params.bl_cnt>0 && sd_params.bl_cnt <= 4)
|
||||
{
|
||||
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.addr, 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);
|
||||
}
|
||||
}
|
||||
|
||||
void x86_set_image(int num, char *filename)
|
||||
{
|
||||
if (num == 2)
|
||||
{
|
||||
strcpy(config.hdd_name, filename);
|
||||
}
|
||||
|
||||
if (num == 0)
|
||||
{
|
||||
strcpy(config.fdd_name, filename);
|
||||
fdd_set(filename);
|
||||
}
|
||||
}
|
||||
|
||||
void x86_config_save()
|
||||
{
|
||||
config.ver = CFG_VER;
|
||||
FileSaveConfig("ao486sys.cfg", &config, sizeof(config));
|
||||
}
|
||||
|
||||
void x86_config_load()
|
||||
{
|
||||
static x86_config tmp;
|
||||
memset(&config, 0, sizeof(config));
|
||||
if (FileLoadConfig("ao486sys.cfg", &tmp, sizeof(tmp)) && (tmp.ver == CFG_VER))
|
||||
{
|
||||
memcpy(&config, &tmp, sizeof(config));
|
||||
}
|
||||
}
|
||||
|
||||
void x86_set_fdd_boot(uint32_t boot)
|
||||
{
|
||||
boot_from_floppy = (boot != 0);
|
||||
}
|
||||
Reference in New Issue
Block a user