diff --git a/.gitignore b/.gitignore index db12cb4..a95e7a4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ build/ .*.swp +venv diff --git a/common/main.c b/common/main.c index 78a1a82..87b31d6 100644 --- a/common/main.c +++ b/common/main.c @@ -100,12 +100,16 @@ inline void title_screen_update(minefield* mf) // TODO: platform dependent title screen, animations, music etc. draw_title_screen(mf); - uint8_t input = input_read(KEYBOARD); - if (input == MINE_INPUT_IGNORED) { - return; + uint8_t input = MINE_INPUT_IGNORED; + for (uint8_t source = 0; source <= JOY_4; ++source) { + input = input_read(source); + if (input != MINE_INPUT_IGNORED) + break; } - debug("\nkey code = ", input); + if (input == MINE_INPUT_IGNORED) + return; + debug("\nkey code = ", input); switch (input) { case MINE_INPUT_OPEN: case MINE_INPUT_OPEN_BLOCK: @@ -143,12 +147,16 @@ inline void game_over_update(minefield* mf) draw_minefield_contents(mf); #endif - uint8_t input = input_read(KEYBOARD); - if (input == MINE_INPUT_IGNORED) { - return; + uint8_t input = MINE_INPUT_IGNORED; + for (uint8_t source = 0; source <= JOY_4; ++source) { + input = input_read(source); + if (input != MINE_INPUT_IGNORED) + break; } - debug("\nkey code = ", input); + if (input == MINE_INPUT_IGNORED) + return; + debug("\nkey code = ", input); switch (input) { case MINE_INPUT_OPEN: case MINE_INPUT_OPEN_BLOCK: @@ -177,12 +185,16 @@ inline void gameplay_update(minefield* mf) update_counter(mf); #endif /* ENABLE_COUNTER */ - uint8_t input = input_read(KEYBOARD); - if (input == MINE_INPUT_IGNORED) { - return; + uint8_t input = MINE_INPUT_IGNORED; + for (uint8_t source = 0; source <= JOY_4; ++source) { + input = input_read(source); + if (input != MINE_INPUT_IGNORED) + break; } - debug("\nkey code = ", input); + if (input == MINE_INPUT_IGNORED) + return; + debug("\nkey code = ", input); update_gameplay_input(mf, input); } diff --git a/platforms/msx2/debugdevice.tcl b/platforms/msx2/debugdevice.tcl index a1a4cbc..c32c211 100644 --- a/platforms/msx2/debugdevice.tcl +++ b/platforms/msx2/debugdevice.tcl @@ -1,3 +1,25 @@ +proc test_joystick1 {} { + global keyjoystick1 + set keyjoystick1.triga 1 + set keyjoystick1.trigb 2 + set keyjoystick1.up W + set keyjoystick1.down S + set keyjoystick1.left A + set keyjoystick1.right D + plug joyporta keyjoystick1 +} + +proc test_joystick2 {} { + global keyjoystick1 + set keyjoystick1.triga 1 + set keyjoystick1.trigb 2 + set keyjoystick1.up W + set keyjoystick1.down S + set keyjoystick1.left A + set keyjoystick1.right D + plug joyportb keyjoystick1 +} + proc pause {{value 0}} { global use_pause if {$use_pause && $value == 0xff} { debug break } @@ -15,5 +37,6 @@ if { [info exists ::env(DEBUG)] } { debug set_watchpoint write_io {0x2e} {} {pause $::wp_last_value} } +# Click on the middle button to confine mouse pointer inside OpenMSX window. bind "mouse button2 down" toggle grabinput plug joyporta mouse diff --git a/platforms/msx2/input.c b/platforms/msx2/input.c index 911a55b..e2b3808 100644 --- a/platforms/msx2/input.c +++ b/platforms/msx2/input.c @@ -4,6 +4,9 @@ #include "common.h" +uint8_t source_mouse = 0xff; + + static uint8_t keyboard_read_row(uint8_t row) __z88dk_fastcall __naked { row; assert(row <= 10); @@ -50,12 +53,49 @@ static uint8_t keyboard_read() } +static joydata joy; + + +static uint8_t joystick_read(uint8_t source) +{ + uint8_t input = read_raw_joyport(source); + + if (!(input & (1 << 0))) { + return MINE_INPUT_UP; + } + if (!(input & (1 << 1))) { + return MINE_INPUT_DOWN; + } + if (!(input & (1 << 2))) { + return MINE_INPUT_LEFT; + } + if (!(input & (1 << 3))) { + return MINE_INPUT_RIGHT; + } + if (!(input & (1 << 4))) { + return MINE_INPUT_OPEN; + } + if (!(input & (1 << 5))) { + return MINE_INPUT_FLAG; + } + return MINE_INPUT_IGNORED; +} + + uint8_t input_read(uint8_t source) { + static uint8_t wait_joy[3] = {0}; + if (source == KEYBOARD) return keyboard_read(); - - /* not implemented yet */ + // distinguish mouse input from joystick input + else if (source < JOY_3 && source_mouse == 0xff) { + uint8_t* tick = &wait_joy[source]; + if ((*tick)++ >= 30) { + *tick = 0; + return joystick_read(source); + } + } return MINE_INPUT_IGNORED; } diff --git a/platforms/msx2/mouse.c b/platforms/msx2/mouse.c index 793d0de..ce1e357 100644 --- a/platforms/msx2/mouse.c +++ b/platforms/msx2/mouse.c @@ -7,8 +7,9 @@ #include "minefield.h" -/* mouse data */ -static struct mouse mouse; +joydata mouse; + +/* contextual mouse data */ static int x = 84; static int y = 33; static bool l_pressed = false; @@ -18,7 +19,7 @@ static bool ignored = false; void update_mouse(minefield* mf, uint8_t source) { - read_mouse(&mouse, source); + read_joyport(&mouse, source); x -= mouse.dx; if (x > 255) x = 255; diff --git a/platforms/msx2/mouselib.asm b/platforms/msx2/mouselib.asm index a915cd0..854f01b 100644 --- a/platforms/msx2/mouselib.asm +++ b/platforms/msx2/mouselib.asm @@ -1,7 +1,9 @@ ; int8_t search_mouse() ; void read_mouse(struct mouse* mouse, uint8_t source) __sdcccall(0) +; void read_raw_joyport(uint8_t source) __z88dk_fastcall -.globl read_mouse +.globl _search_mouse +.globl _read_joyport REGWTP = 0xA0 ; register write port VALWTP = 0xA1 ; value write port @@ -16,35 +18,36 @@ IO_REG2 = 15 _search_mouse:: ld de, #PORT1 ; DE = mouse on port 1 - ld b, #LONG_WAIT ; first delay is the longest + ld b, #LONG_WAIT ; first delay is longer call search_device0 cp #0xff jp z, port2 ; device not found? Searching on port 2 or a ; mouse signature? - ld a, #1 + ld l, #1 ret z ; signature found, return "1" for mouse port 1 - ld a, e + ld l, e ret ; return x offset port2: ld de, #PORT2 ; DE = mouse on port 2 call search_device cp #0xff + ld l, a ret z ; return -1: device not found or it's a joystick or a ; mouse signature? - ld a, #2 + ld l, #2 ret z ; signature found, return "2" for mouse port 2 - xor a - ret ; ignore input + ld l, #0 + ret ; ignore input (return "0") search_device: ld b, #SHORT_WAIT search_device0: - call get_mouse_data0 ; read bits 7-4 of the offset + call get_joy_data0 ; read bits 7-4 of the offset ld hl, #saved_tmp_data ld (hl), a ; save x offset 1/2 or #0xc0 ; clear bits b7/b6 ld c, a ; c <- byte1 - call get_mouse_data ; read bits 3-0 of the offset + call get_joy_data ; read bits 3-0 of the offset inc hl ld (hl), a ; save x offset 2/2 or #0xc0 @@ -62,9 +65,10 @@ search_device0: rlca or #0x3f and d ; a <- (byte1 << 2 | 0x3f) & (byte1 << 4 | 0x0f) & byte2 + ld l, a ret ; return device id fingerprint -_read_mouse:: +_read_joyport:: push ix ld ix, #2 add ix, sp @@ -75,10 +79,10 @@ _read_mouse:: ld de, #PORT1 ; DE = 01310h for mouse in port 1 (D = 00010011b, E = 00010000b) and #2 - jr z, read_mouse + jr z, read_cached_joyport ld de, #PORT2 ; DE = 06C20h for mouse in port 2 (D = 01101100b, E = 00100000b) -read_mouse: +read_cached_joyport: ld ix, #saved_tmp_data ld a, 0(ix) ; read previously stored x offset used in detection and #0xf @@ -93,14 +97,14 @@ read_mouse: ld (hl), a ; save to mouse data struct (1/4) inc hl - call get_mouse_data ; read bits 7-4 of the y offset + call get_joy_data ; read bits 7-4 of the y offset and #0xf rlca rlca rlca rlca ; adjust y offset's higher bits ld c, a ; save as temp data - call get_mouse_data ; read bits 3-0 of the y offset + call get_joy_data ; read bits 3-0 of the y offset ; can read mouse button bit 4 = left button / bit 5 = right button ld b, a and #0xf @@ -130,9 +134,25 @@ read_mouse: pop ix ret -get_mouse_data: +_read_raw_joyport:: + ld a, l ; a <- l (z88dk_fastcall) + ld de, #PORT1 ; DE = 01310h for mouse in port 1 (D = 00010011b, E = 00010000b) + and #2 + ld b, #LONG_WAIT ; first delay is longer + jr z, read_joyport + ld de, #PORT2 ; DE = 06C20h for mouse in port 2 (D = 01101100b, E = 00100000b) +read_joyport: + call get_joy_data0 ; read bits 7-4 of joystick + call get_joy_data ; read bits 5-0 of the joystick + and #0x3f + ld l, a ; z88dk_fastcall return register + ld b, #LONGER_WAIT + call wait + ret + +get_joy_data: ld b, #SHORT_WAIT -get_mouse_data0: +get_joy_data0: di ld a, #IO_REG2 out (#REGWTP), a ; read PSG register 15 for mouse @@ -171,6 +191,5 @@ wait_loop3: ; R800 extra wait 2/2 .area DATA saved_tmp_data: - .db 0xff - .db 0xff - + .db #0xff + .db #0xff diff --git a/platforms/msx2/msx2.h b/platforms/msx2/msx2.h index e6fe2b7..d2fe1dc 100644 --- a/platforms/msx2/msx2.h +++ b/platforms/msx2/msx2.h @@ -1,6 +1,7 @@ #ifndef MSX2_H #define MSX2_H +#include "game.h" #include /* __sdcccall function attribute on SDCC 4.1.12 and later */ @@ -87,18 +88,24 @@ void put_sprite_attr(struct sprite_attr *src, uint8_t index) SDCCCALL0; /* search for plugged mouse device */ int8_t search_mouse(); -/* structure for storing mouse data */ -struct mouse { +/* structure for storing mouse or joystick data */ +typedef struct { int8_t dx; int8_t dy; uint8_t l_button; /* 1 = OFF, 2 = ON */ uint8_t r_button; /* 1 = OFF, 2 = ON */ -}; +} joydata; + +void read_joyport(joydata* data, uint8_t source) SDCCCALL0; -void read_mouse(struct mouse* mouse, uint8_t source) SDCCCALL0; +uint8_t read_raw_joyport(uint8_t source) __z88dk_fastcall; void put_mouse(uint8_t x, uint8_t y); void hide_mouse(); +inline void update_mouse(minefield* mf, uint8_t source); + +inline void update_joystick(uint8_t source); + #endif /* MSX2_H */ diff --git a/platforms/msx2/video.c b/platforms/msx2/video.c index e6292a4..f6df3f9 100644 --- a/platforms/msx2/video.c +++ b/platforms/msx2/video.c @@ -215,19 +215,16 @@ void update_counter(minefield* mf) } -extern inline void update_mouse(minefield* mf, uint8_t source); - - void idle_update(minefield* mf) { + extern uint8_t source_mouse; static uint8_t ignore_input = 0; static uint8_t mouse1 = 0; static uint8_t mouse2 = 0; - static uint8_t source = 0xff; static uint8_t fifth = 0; switch (++fifth) { - case 4: { + case 3: { /* count how many times mouse is not found */ int8_t mouse = search_mouse(); switch (mouse) { @@ -236,19 +233,19 @@ void idle_update(minefield* mf) break; case 1: ignore_input = 0; - if (source == 0xff && mouse1 > IGNORE_MOUSE_THRESHOLD) { + if (source_mouse == 0xff && mouse1 > IGNORE_MOUSE_THRESHOLD) { debug_msg("mouse1 detected\n"); + source_mouse = 1; mouse2 = 0; - source = 1; } mouse1++; break; case 2: ignore_input = 0; - if (source == 0xff && mouse2 > IGNORE_MOUSE_THRESHOLD) { + if (source_mouse == 0xff && mouse2 > IGNORE_MOUSE_THRESHOLD) { debug_msg("mouse2 detected\n"); + source_mouse = 2; mouse1 = 0; - source = 2; } mouse2++; break; @@ -261,9 +258,9 @@ void idle_update(minefield* mf) fifth = 0; if (ignore_input > IGNORE_MOUSE_THRESHOLD) { hide_mouse(); - source = 0xff; - } else if (source != 0xff) { - update_mouse(mf, source); + source_mouse = 0xff; + } else if (source_mouse != 0xff) { + update_mouse(mf, source_mouse); } break; default: