1 /***************************************************************************
3 * ZXEmuT -- ZX Spectrum Emulator with Tcl scripting
5 * Copyright (C) 2012-2022 Ketmar Dark <ketmar@ketmar.no-ip.org>
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, version 3 of the License ONLY.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 **************************************************************************/
20 #define MV_FAST_RECODE
22 #include "../libzymosis/zymosis.h"
23 #include "libvideo/video.h"
25 #include "emucommon.h"
31 // ////////////////////////////////////////////////////////////////////////// //
33 static const uint8_t cp1251to866
[256] = {
34 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
35 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,
36 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,
37 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
38 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,
39 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f,
40 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,
41 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,
42 0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,
43 0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf,
44 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,
45 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
46 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
47 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
48 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff,
49 0xa8,0xb8,0xaa,0xba,0xaf,0xbf,0xa1,0xa2,0xb0,0x00,0xb7,0x00,0xb9,0xa4,0x00,0xa0,
54 static const uint16_t charMap1251
[128] = {
55 0x0402,0x0403,0x201A,0x0453,0x201E,0x2026,0x2020,0x2021,0x20AC,0x2030,0x0409,0x2039,0x040A,0x040C,0x040B,0x040F,
56 0x0452,0x2018,0x2019,0x201C,0x201D,0x2022,0x2013,0x2014,0x003F,0x2122,0x0459,0x203A,0x045A,0x045C,0x045B,0x045F,
57 0x00A0,0x040E,0x045E,0x0408,0x00A4,0x0490,0x00A6,0x00A7,0x0401,0x00A9,0x0404,0x00AB,0x00AC,0x00AD,0x00AE,0x0407,
58 0x00B0,0x00B1,0x0406,0x0456,0x0491,0x00B5,0x00B6,0x00B7,0x0451,0x2116,0x0454,0x00BB,0x0458,0x0405,0x0455,0x0457,
59 0x0410,0x0411,0x0412,0x0413,0x0414,0x0415,0x0416,0x0417,0x0418,0x0419,0x041A,0x041B,0x041C,0x041D,0x041E,0x041F,
60 0x0420,0x0421,0x0422,0x0423,0x0424,0x0425,0x0426,0x0427,0x0428,0x0429,0x042A,0x042B,0x042C,0x042D,0x042E,0x042F,
61 0x0430,0x0431,0x0432,0x0433,0x0434,0x0435,0x0436,0x0437,0x0438,0x0439,0x043A,0x043B,0x043C,0x043D,0x043E,0x043F,
62 0x0440,0x0441,0x0442,0x0443,0x0444,0x0445,0x0446,0x0447,0x0448,0x0449,0x044A,0x044B,0x044C,0x044D,0x044E,0x044F,
65 static const uint16_t charMap866
[128] = {
66 0x0410,0x0411,0x0412,0x0413,0x0414,0x0415,0x0416,0x0417,0x0418,0x0419,0x041A,0x041B,0x041C,0x041D,0x041E,0x041F,
67 0x0420,0x0421,0x0422,0x0423,0x0424,0x0425,0x0426,0x0427,0x0428,0x0429,0x042A,0x042B,0x042C,0x042D,0x042E,0x042F,
68 0x0430,0x0431,0x0432,0x0433,0x0434,0x0435,0x0436,0x0437,0x0438,0x0439,0x043A,0x043B,0x043C,0x043D,0x043E,0x043F,
69 0x2591,0x2592,0x2593,0x2502,0x2524,0x2561,0x2562,0x2556,0x2555,0x2563,0x2551,0x2557,0x255D,0x255C,0x255B,0x2510,
70 0x2514,0x2534,0x252C,0x251C,0x2500,0x253C,0x255E,0x255F,0x255A,0x2554,0x2569,0x2566,0x2560,0x2550,0x256C,0x2567,
71 0x2568,0x2564,0x2565,0x2559,0x2558,0x2552,0x2553,0x256B,0x256A,0x2518,0x250C,0x2588,0x2584,0x258C,0x2590,0x2580,
72 0x0440,0x0441,0x0442,0x0443,0x0444,0x0445,0x0446,0x0447,0x0448,0x0449,0x044A,0x044B,0x044C,0x044D,0x044E,0x044F,
73 0x0401,0x0451,0x0404,0x0454,0x0407,0x0457,0x040E,0x045E,0x00B0,0x2219,0x00B7,0x221A,0x2116,0x00A4,0x25A0,0x00A0,
77 static uint8_t table1251to866
[65536];
78 static int tableRCInited
= 0;
81 //==========================================================================
85 //==========================================================================
86 static void initTableRC (void) {
88 memset(table1251to866
, '.', sizeof(table1251to866
));
89 for (uint16_t f
= 0; f
< 128; ++f
) table1251to866
[f
] = (uint8_t)f
;
90 for (uint16_t f
= 0; f
< 128; ++f
) {
91 const uint16_t code
= charMap1251
[f
];
92 for (uint16_t c
= 0; c
< 128; ++c
) {
93 if (charMap866
[c
] == code
) {
94 table1251to866
[f
+128U] = (uint8_t)(c
+128U);
102 // ////////////////////////////////////////////////////////////////////////// //
103 int memviewActive
= 0;
104 uint8_t mv_pagemap
[256];
107 uint32_t mv_staddr
= 0x5B00;
108 int mv_encoding
= MV_ENC_7BIT
;
109 int mv_viewmode
= MV_MODE_HEX
;
110 int mv_textwidth
= 64;
111 uint8_t mv_textcolor
= 7; // paper is ignored
113 #define BOOKMARK_NONE (~((uint32_t)0))
115 static uint32_t bookmarks
[10];
117 static int inaddrpos
= -1;
118 static int mmeditpos
= 0;
119 static int mmeditactive
= 0;
121 static vt_simple_menu
*current_menu
= NULL
;
122 static void (*menu_sel_cb
) (uint32_t sel
) = NULL
;
123 static vt_simple_menu wkmenu
;
125 static int evtCtrlKeyDown
= 0;
126 static int evtAltKeyDown
= 0;
127 static int evtShiftKeyDown
= 0;
130 //==========================================================================
134 //==========================================================================
135 static inline uint16_t recodeByte (uint16_t b
) {
136 if (mv_encoding
== MV_ENC_1251
) {
137 #ifdef MV_FAST_RECODE
140 if (!tableRCInited
) initTableRC();
141 b
= table1251to866
[b
];
144 if (mv_encoding
== MV_ENC_7BIT
) b
&= 0x7f;
145 if (b
< 32 || b
== 127) b
= '.'|0x8000;
146 else if (b
== 32 && mv_viewmode
== MV_MODE_HEX
) b
= '.'|0x4000;
151 //==========================================================================
155 //==========================================================================
156 static __attribute__((always_inline
)) inline int isAddrEditActive (void) {
157 return (inaddrpos
>= 0);
161 //==========================================================================
165 //==========================================================================
166 static __attribute__((always_inline
)) inline int isMMEditActive (void) {
171 //==========================================================================
175 //==========================================================================
176 static __attribute__((always_inline
)) inline uint8_t getByte (uint32_t addr
) {
179 z80
.mem_read(&z80
, addr
, ZYM_MEMIO_OTHER
) :
180 zxMemoryBanks
[mv_pagemap
[((addr
>>14)-4)%(unsigned)zxMaxMemoryBank
]][addr
&0x3fffU
];
184 //==========================================================================
188 //==========================================================================
189 static void memviewResetMMap (int inorder
) {
190 for (uint32_t f
= 0; f
< 256; ++f
) mv_pagemap
[f
] = f
;
198 //==========================================================================
202 //==========================================================================
203 void memviewInit (void) {
205 for (unsigned f
= 0; f
< 10; ++f
) bookmarks
[f
] = BOOKMARK_NONE
;
209 //==========================================================================
213 //==========================================================================
214 void memviewSetActive (int st
) {
215 memviewActive
= !!st
;
219 //==========================================================================
223 //==========================================================================
224 static __attribute__((unused
)) void drawAllChars (void) {
225 for (int y
= 0; y
< 16; ++y
) {
226 for (int x
= 0; x
< 16; ++x
) {
227 vt_writechar(x
, y
, y
*16+x
, 0x0f);
230 for (int x
= 0; x
< 16; ++x
) {
231 vt_writechar(x
, VID_TEXT_HEIGHT
-1, '*', (x
<<4)|(x
< 8 ? 15 : 0));
236 //==========================================================================
240 //==========================================================================
241 static void rescanPages (void) {
242 for (int f
= 0; f
< zxMaxMemoryBank
; ++f
) {
243 zxMemBanksDirty
[f
] = 0;
244 const uint8_t *mbb
= zxMemoryBanks
[f
];
245 for (uint32_t pos
= 0; pos
< 0x4000; ++pos
, ++mbb
) {
247 zxMemBanksDirty
[f
] = 1;
255 //==========================================================================
259 //==========================================================================
260 static void drawMMap (void) {
264 vt_draw_frame_ex(xofs
-2, yofs
-1, 3*8+3, 10, 0x50,
265 VID_FRAME_DOUBLE
|VID_FRAME_OVERWRITE
|VID_FRAME_FILL
|VID_FRAME_SHADOW
,
268 for (int y
= 0; y
< 8; ++y
) {
269 for (int x
= 0; x
< 8; ++x
) {
271 if (y
*8+x
== mmeditpos
/2) {
274 attr
= (zxMemBanksDirty
[mv_pagemap
[y
*8+x
]] ? 0x50 : 0x51);
276 vt_writef(xofs
+x
*3, yofs
+y
, attr
, "%02X", mv_pagemap
[y
*8+x
]);
280 const int cx
= mmeditpos
%16;
281 const int cy
= mmeditpos
/16;
282 vt_writeattr(xofs
+(cx
/2)*3+(cx
%2), yofs
+cy
, emuGetCursorColor(0xF0, 0x70));
286 //==========================================================================
290 //==========================================================================
291 static void writeAddrAt (int x
, int y
, uint32_t addr
) {
294 if (addr
<= 0xffffU
) {
295 snprintf(buf
, sizeof(buf
), ".. %04X", addr
);
296 pg
= zxMemoryBankNum
[addr
>>14];
298 pg
= ((addr
>>14)-4)%(unsigned)zxMaxMemoryBank
;
299 snprintf(buf
, sizeof(buf
), "%02X %04X", pg
, addr
&0x3fffU
);
303 for (unsigned f
= 0; f
< 10; ++f
) {
304 if (bookmarks
[f
] == addr
) {
309 vt_writestrcnt(x
, y
, buf
, 7, attr
);
310 if (!zxMemBanksDirty
[pg
]) vt_writeattrs(x
, y
, 2, 0x03|(attr
&0xf0));
314 //==========================================================================
318 //==========================================================================
319 static void drawHexView (void) {
321 const int mhgt
= VID_TEXT_HEIGHT
-2;
322 uint32_t addr
= mv_staddr
;
323 vt_draw_frame(1, 0, 78, mhgt
+2, 15, VID_FRAME_SINGLE
);
326 for (int dy
= 0; dy
< mhgt
; ++dy
) {
327 writeAddrAt(xofs
, dy
+yofs
, addr
);
329 for (int dx
= 0; dx
< 16; ++dx
) {
330 if (addr
<= 0xffffU
&& addr
+(unsigned)dx
> 0xffffU
) break;
331 uint8_t b
= getByte(addr
+(unsigned)dx
);
332 snprintf(buf
, sizeof(buf
), "%02X", b
);
333 vt_writestrz(xofs
+8+dx
*3+(dx
>= 8), dy
+yofs
, buf
, 7);
336 for (int dx
= 0; dx
< 16; ++dx
) {
337 if (addr
<= 0xffffU
&& addr
+(unsigned)dx
> 0xffffU
) break;
338 uint16_t b
= recodeByte(getByte(addr
+(unsigned)dx
));
339 vt_writechar(xofs
+8+16*3+2+dx
+(dx
>= 8), dy
+yofs
, (char)b
,
340 (b
<= 0xff ? mv_textcolor
: (b
&0x8000 ? 5 : mv_textcolor
)+(b
&0x4000 ? 0x10 : 0)));
348 //==========================================================================
352 //==========================================================================
353 static uint32_t goLineUp (uint32_t addr
) {
355 uint8_t b
= getByte(addr
-1U);
356 const int skiptsp
= (b
== 10 || b
== 13);
359 if (addr
&& getByte(addr
-1U) == 13) --addr
;
361 } else if (b
== 13) {
365 int zerostate
= -1; // <0:haven't seen; 0:non-zero seen; 1:only zero seen
366 // skip trailing spaces
368 while (addr
&& getByte(addr
-1U) == 32) {
373 const uint32_t orgaddr
= addr
;
374 int count
= mv_textwidth
;
375 while (addr
&& count
--) {
376 b
= getByte(addr
-1U);
377 if (b
== 13 || b
== 10) return addr
;
379 if (zerostate
== 0) return addr
; // seen non-zero
380 zerostate
= 1; // only zero seen
382 if (zerostate
== 1) return addr
;
383 zerostate
= 0; // seen non-zero
387 return (addr
? orgaddr
-mv_textwidth
: 0);
391 //==========================================================================
395 //==========================================================================
396 static uint32_t goLineDown (uint32_t addr
) {
397 const uint32_t orgaddr
= addr
;
398 int count
= mv_textwidth
;
399 int zerostate
= -1; // <0:haven't seen; 0:non-zero seen; 1:only zero seen
401 while (addr
&& count
--) {
403 if (b
== 13 || b
== 10) {
404 if (b
== 13 && getByte(addr
) == 10) ++addr
;
408 if (zerostate
== 0) return addr
-1; // seen non-zero
409 zerostate
= 1; // only zero seen
411 if (zerostate
== 1) return addr
-1;
412 zerostate
= 0; // seen non-zero
415 addr
= orgaddr
+mv_textwidth
;
416 // check for trailing spaces
417 while (getByte(addr
) == 32) ++addr
;
419 if (b
== 13) b
= getByte(++addr
);
425 //==========================================================================
429 //==========================================================================
430 static void drawTextView (void) {
433 uint32_t addr
= mv_staddr
;
434 vt_draw_frame(1, 0, 78, VID_TEXT_HEIGHT
, 15, VID_FRAME_SINGLE
);
435 for (int y
= 0; y
< VID_TEXT_HEIGHT
-2; ++y
) {
436 writeAddrAt(xofs
, y
+yofs
, addr
);
437 uint32_t eaddr
= goLineDown(addr
);
438 if (eaddr
> addr
&& getByte(eaddr
-1) == 10) --eaddr
;
439 if (eaddr
> addr
&& getByte(eaddr
-1) == 13) --eaddr
;
440 const uint32_t naddr
= eaddr
;
441 if (eaddr
-addr
> mv_textwidth
) eaddr
= addr
+mv_textwidth
;
442 int xxofs
= (MV_MAX_TEXT_WIDTH
-mv_textwidth
)/2;
443 const uint32_t len
= eaddr
-addr
;
444 for (uint32_t x
= 0; x
< len
; ++x
) {
445 uint16_t b
= recodeByte(getByte(addr
++));
446 vt_writechar(xofs
+8+xxofs
+x
, y
+yofs
, (char)b
,
447 (b
<= 0xff ? mv_textcolor
: (b
&0x8000 ? 5 : mv_textcolor
)+(b
&0x4000 ? 0x10 : 0)));
449 // check for trailing spaces
451 while (getByte(addr
) == 32) ++addr
;
452 if (getByte(addr
) == 13) ++addr
;
453 if (getByte(addr
) == 10) ++addr
;
455 vt_writef(7, 0, 0x05, "[wdt:%d]", mv_textwidth
);
459 //==========================================================================
463 //==========================================================================
464 void memviewDraw (void) {
465 //vt_cls(0xb0, 0x01);
468 if (mv_viewmode
== MV_MODE_HEX
) drawHexView(); else drawTextView();
470 switch (mv_encoding
) {
471 case MV_ENC_7BIT
: vt_writestrz(2+70, 0, "[7bit]", 4); break;
472 case MV_ENC_1251
: vt_writestrz(2+68, 0, "[cp1251]", 4); break;
473 case MV_ENC_866
: vt_writestrz(2+69, 0, "[cp866]", 4); break;
476 // draw physical page
479 if (mv_staddr
<= 0xffffU
) {
480 pg
= zxMemoryBankNum
[mv_staddr
>>14];
482 pg
= mv_pagemap
[((mv_staddr
>>14)-4)%(unsigned)zxMaxMemoryBank
];
484 uint8_t attr
= (zxMemBanksDirty
[pg
] ? 0x04 : 0x03);
485 vt_writef(2, 0, attr
, "[%02X]", pg
);
488 if (isAddrEditActive()) {
489 vt_writeattr(2+inaddrpos
+(inaddrpos
>= 2), 1, emuGetCursorColor(0xF0, 0x70));
490 } else if (isMMEditActive()) {
494 if (current_menu
) vt_smm_draw(current_menu
);
502 //==========================================================================
506 //==========================================================================
507 static void doLeft (void) {
508 if (isAddrEditActive()) {
509 if (inaddrpos
) --inaddrpos
;
512 if (isMMEditActive()) {
514 if (evtCtrlKeyDown
) {
515 mmeditpos
= (mmeditpos
&0xfe)-1;
516 if (mmeditpos
< 1) mmeditpos
= 1;
523 if (mv_staddr
) --mv_staddr
;
527 //==========================================================================
531 //==========================================================================
532 static void doRight (void) {
533 if (isAddrEditActive()) {
534 if (inaddrpos
< 5) ++inaddrpos
;
537 if (isMMEditActive()) {
538 if (evtCtrlKeyDown
) {
539 mmeditpos
= (mmeditpos
&0xfe)+3;
540 if (mmeditpos
>= 64*2) mmeditpos
= 64*2-1;
542 if (mmeditpos
< 64*2-1) ++mmeditpos
;
550 //==========================================================================
554 //==========================================================================
555 static void doUp (void) {
556 if (isAddrEditActive()) {
557 if (inaddrpos
>= 2) inaddrpos
= 0;
560 if (isMMEditActive()) {
561 if (mmeditpos
>= 8*2) mmeditpos
-= 8*2;
564 if (mv_viewmode
== MV_MODE_TEXT
) {
565 uint32_t nn
= goLineUp(mv_staddr
);
566 if (mv_staddr
> 0xffffU
&& nn
<= 0xffffU
) nn
= 0x010000U
;
570 if (mv_staddr
<= 0xffffU
) {
571 if (mv_staddr
< 16) mv_staddr
= 0; else mv_staddr
-= 16;
578 //==========================================================================
582 //==========================================================================
583 static void doDown (void) {
584 if (isAddrEditActive()) {
585 if (inaddrpos
< 2) inaddrpos
= 2;
588 if (isMMEditActive()) {
589 if (mmeditpos
+8*2 < 64*2) mmeditpos
+= 8*2;
592 if (mv_viewmode
== MV_MODE_TEXT
) {
593 mv_staddr
= goLineDown(mv_staddr
);
600 //==========================================================================
604 //==========================================================================
605 static void doPageUp (void) {
606 if (isAddrEditActive()) {
607 if (mv_staddr
> 0xffffU
) {
608 uint32_t pg
= (mv_staddr
>>14)-4;
610 mv_staddr
= (pg
+4)<<14;
614 if (isMMEditActive()) return;
615 if (mv_viewmode
== MV_MODE_TEXT
) {
616 for (int f
= 0; f
< VID_TEXT_HEIGHT
-3; ++f
) {
617 uint32_t nn
= goLineUp(mv_staddr
);
618 if (mv_staddr
> 0xffffU
&& nn
<= 0xffffU
) nn
= 0x010000U
;
623 if (mv_staddr
<= 0xffffU
) {
624 if (mv_staddr
< 16*(VID_TEXT_HEIGHT
-2)) mv_staddr
= 0; else mv_staddr
-= 16*(VID_TEXT_HEIGHT
-2);
626 mv_staddr
-= 16*(VID_TEXT_HEIGHT
-2);
631 //==========================================================================
635 //==========================================================================
636 static void doPageDown (void) {
637 if (isAddrEditActive()) {
638 if (mv_staddr
<= 0xffffU
) {
639 mv_staddr
= 0x010000U
;
641 uint32_t pg
= (mv_staddr
>>14)-4;
642 if (pg
+1 < (uint32_t)zxMaxMemoryBank
) mv_staddr
= (pg
+5)<<14;
646 if (isMMEditActive()) return;
647 if (mv_viewmode
== MV_MODE_TEXT
) {
648 for (int f
= 0; f
< VID_TEXT_HEIGHT
-3; ++f
) {
649 mv_staddr
= goLineDown(mv_staddr
);
653 if (mv_staddr
<= 0xffffU
) {
654 if (mv_staddr
+16*(VID_TEXT_HEIGHT
-2) > 0xffffU
) mv_staddr
= 0x10000U
-16; else mv_staddr
+= 16*(VID_TEXT_HEIGHT
-2);
656 mv_staddr
+= 16*(VID_TEXT_HEIGHT
-2);
661 //==========================================================================
665 //==========================================================================
666 static void menu_set_encoding (uint32_t sel
) {
667 mv_encoding
= (int)sel
;
671 //==========================================================================
673 // menu_set_text_width
675 //==========================================================================
676 static void menu_set_text_width (uint32_t sel
) {
677 const int wdts
[5] = {32, 42, 51, 64, MV_MAX_TEXT_WIDTH
};
678 mv_textwidth
= wdts
[sel
];
682 //==========================================================================
684 // menu_set_text_bright
686 //==========================================================================
687 static void menu_set_text_bright (uint32_t sel
) {
688 mv_textcolor
&= 0x07;
689 mv_textcolor
|= (sel
? 0x08 : 0x00);
693 //==========================================================================
695 // menu_set_text_color
697 //==========================================================================
698 static void menu_set_text_color (uint32_t sel
) {
699 mv_textcolor
= (mv_textcolor
&0x08)|(sel
+1);
703 //==========================================================================
705 // menu_set_view_mode
707 //==========================================================================
708 static void menu_set_view_mode (uint32_t sel
) {
709 mv_viewmode
= (int)sel
;
713 //==========================================================================
717 //==========================================================================
718 int memviewKeyEvent (SDL_KeyboardEvent
*key
) {
720 int mrs
= vt_smm_process_key(current_menu
, key
);
723 vt_smm_deinit(current_menu
);
726 case VID_SMM_NOTMINE
:
730 case VID_SMM_SELECTED
:
732 const uint32_t cy
= current_menu
->cursor_y
;
733 vt_smm_deinit(current_menu
);
737 vt_smm_deinit(current_menu
);
745 if (key
->type
!= SDL_KEYDOWN
) return 1;
747 evtCtrlKeyDown
= !!(key
->keysym
.mod
&KMOD_CTRL
);
748 evtAltKeyDown
= !!(key
->keysym
.mod
&KMOD_ALT
);
749 evtShiftKeyDown
= !!(key
->keysym
.mod
&KMOD_SHIFT
);
751 if (isAddrEditActive() && key
->keysym
.unicode
> 32 && key
->keysym
.unicode
< 127) {
752 int d
= digitInBase((char)key
->keysym
.unicode
, 16);
755 uint32_t pg
= (mv_staddr
> 0xffffU
? (mv_staddr
>>14)-4 : 0);
756 pg
&= (inaddrpos
? 0xf0U
: 0x0fU
);
757 pg
|= ((unsigned)d
)<<((1-inaddrpos
)*4);
758 if (pg
< zxMaxMemoryBank
) {
759 mv_staddr
= (mv_staddr
&0x3fffU
)|((pg
+4)<<14);
762 if (mv_staddr
> 0xffffU
&& inaddrpos
== 2 && d
> 3) return 1;
763 if (mv_staddr
> 0xffffU
) {
764 uint32_t pg
= (mv_staddr
>>14);
765 mv_staddr
&= ~(0x000fU
<<((5-inaddrpos
)*4));
766 mv_staddr
|= ((unsigned)d
)<<((5-inaddrpos
)*4);
769 mv_staddr
&= ~(0x000fU
<<((5-inaddrpos
)*4));
770 mv_staddr
|= ((unsigned)d
)<<((5-inaddrpos
)*4);
773 if (inaddrpos
< 5) ++inaddrpos
;
778 if (isMMEditActive() && key
->keysym
.unicode
> 32 && key
->keysym
.unicode
< 127) {
779 int d
= digitInBase((char)key
->keysym
.unicode
, 16);
781 const int mmindex
= mmeditpos
/2;
782 uint8_t v
= mv_pagemap
[mmindex
];
783 if (mmeditpos
%2 == 0) {
790 if (v
< zxMaxMemoryBank
) {
792 if (mv_pagemap
[mmindex
] != v
) {
794 while (swidx
< 64 && mv_pagemap
[swidx
] != v
) ++swidx
;
796 uint8_t vtmp
= mv_pagemap
[swidx
];
797 mv_pagemap
[swidx
] = mv_pagemap
[mmindex
];
798 mv_pagemap
[mmindex
] = vtmp
;
800 mv_pagemap
[mmindex
] = v
;
804 if (mmeditpos
>= 64*2) mmeditpos
= 64*2-1;
810 if (!isAddrEditActive() && !isMMEditActive() &&
811 key
->keysym
.sym
>= SDLK_0
&& key
->keysym
.sym
<= SDLK_9
)
813 int dig
= (int)(key
->keysym
.sym
-SDLK_0
);
814 if (evtShiftKeyDown
) {
815 if (mv_viewmode
== MV_MODE_TEXT
) {
817 const int twdta
[5] = {MV_MAX_TEXT_WIDTH
,32,42,51,64};
818 mv_textwidth
= twdta
[dig
];
821 } else if (evtCtrlKeyDown
) {
822 bookmarks
[dig
] = mv_staddr
;
823 } else if (evtAltKeyDown
) {
824 if (bookmarks
[dig
] != BOOKMARK_NONE
) mv_staddr
= bookmarks
[dig
];
829 switch (key
->keysym
.sym
) {
833 if (isAddrEditActive()) inaddrpos
= -1;
834 else if (isMMEditActive()) mmeditactive
= 0;
835 else memviewSetActive(0);
839 if (isMMEditActive()) {
840 // go to the selected physical page
841 mv_staddr
= (((mmeditpos
/2)+4)<<14);
847 case SDLK_DELETE
: case SDLK_KP_PERIOD
:
848 if (isAddrEditActive()) {
849 if (inaddrpos
< 2) mv_staddr
&= 0xffffU
;
850 } else if (isMMEditActive()) {
851 if (evtShiftKeyDown
) memviewResetMMap(0);
852 else if (evtCtrlKeyDown
) memviewResetMMap(1);
853 else if (evtAltKeyDown
) {
858 } else if (!evtShiftKeyDown
&& !evtCtrlKeyDown
&& !evtAltKeyDown
) {
859 const int mmindex
= mmeditpos
/2;
860 uint8_t v
= (uint8_t)mmindex
;
861 if (mv_pagemap
[mmindex
] != v
) {
863 while (swidx
< 64 && mv_pagemap
[swidx
] != v
) ++swidx
;
865 uint8_t vtmp
= mv_pagemap
[swidx
];
866 mv_pagemap
[swidx
] = mv_pagemap
[mmindex
];
867 mv_pagemap
[mmindex
] = vtmp
;
869 mv_pagemap
[mmindex
] = v
;
877 mv_viewmode
= !mv_viewmode
; // we have only two for now
880 case SDLK_LEFT
: case SDLK_KP4
: doLeft(); return 1;
881 case SDLK_RIGHT
: case SDLK_KP6
: doRight(); return 1;
882 case SDLK_UP
: case SDLK_KP8
: doUp(); return 1;
883 case SDLK_DOWN
: case SDLK_KP2
: doDown(); return 1;
884 case SDLK_PAGEUP
: case SDLK_KP9
: case SDLK_o
: doPageUp(); return 1;
885 case SDLK_PAGEDOWN
: case SDLK_KP3
: case SDLK_p
: doPageDown(); return 1;
886 case SDLK_BACKSPACE
: if (isAddrEditActive()) doLeft(); return 1;
889 if (isAddrEditActive()) return 1;
890 if (mv_viewmode
== MV_MODE_TEXT
) {
891 if (evtShiftKeyDown
) doPageUp(); else doPageDown();
895 case SDLK_HOME
: case SDLK_KP7
:
896 if (isAddrEditActive()) inaddrpos
= (inaddrpos
> 2 ? 2 : 0);
898 case SDLK_END
: case SDLK_KP1
:
899 if (isAddrEditActive()) inaddrpos
= (inaddrpos
< 2 ? 2 : 5);
903 if (!isAddrEditActive() && !isMMEditActive()) {
905 vt_smm_init(&wkmenu
, "Text brightness", (const char *[]){"off", "on", NULL
});
906 menu_sel_cb
= &menu_set_text_bright
;
907 wkmenu
.cursor_y
= (mv_textcolor
>= 0x08 ? 1 : 0);
908 current_menu
= &wkmenu
;
910 mv_textcolor
^= 0x08;
916 if (!isAddrEditActive() && !isMMEditActive()) {
918 vt_smm_init(&wkmenu
, "Text color", (const char *[]){
919 "blue", "red", "magenta", "green", "cyan", "yellow", "white",
921 menu_sel_cb
= &menu_set_text_color
;
922 wkmenu
.cursor_y
= (mv_textcolor
&0x07)-1;
923 current_menu
= &wkmenu
;
924 } else if (evtCtrlKeyDown
&& evtShiftKeyDown
) {
925 for (unsigned f
= 0; f
< 10; ++f
) bookmarks
[f
] = BOOKMARK_NONE
;
927 mv_textcolor
= ((mv_textcolor
+1)&0x07)|(mv_textcolor
&0x08);
928 if (!mv_textcolor
) mv_textcolor
= 1;
929 else if (mv_textcolor
== 8) mv_textcolor
= 9;
935 if (!isMMEditActive() && !isAddrEditActive()) {
937 vt_smm_init(&wkmenu
, "Encoding", (const char *[]){"7 bit", "CP 866", "CP 1251", NULL
});
938 menu_sel_cb
= &menu_set_encoding
;
939 wkmenu
.cursor_y
= (uint32_t)mv_encoding
;
940 current_menu
= &wkmenu
;
948 if (!isAddrEditActive() && !isMMEditActive()) inaddrpos
= 2;
952 if (!isAddrEditActive() && !isMMEditActive()) {
954 vt_smm_init(&wkmenu
, "View mode", (const char *[]){"hex", "text", NULL
});
955 menu_sel_cb
= &menu_set_view_mode
;
956 wkmenu
.cursor_y
= (uint32_t)mv_viewmode
;
957 current_menu
= &wkmenu
;
963 if (isMMEditActive() && evtCtrlKeyDown
) {
969 if (!isAddrEditActive() && !isMMEditActive()) {
970 if (evtAltKeyDown
&& mv_viewmode
== MV_MODE_TEXT
) {
971 vt_smm_init(&wkmenu
, "Text width", (const char *[]){"32", "42", "51", "64", "max", NULL
});
972 menu_sel_cb
= &menu_set_text_width
;
973 if (mv_textwidth
<= 32) wkmenu
.cursor_y
= 0;
974 else if (mv_textwidth
<= 42) wkmenu
.cursor_y
= 1;
975 else if (mv_textwidth
<= 51) wkmenu
.cursor_y
= 2;
976 else if (mv_textwidth
<= 64) wkmenu
.cursor_y
= 3;
977 else wkmenu
.cursor_y
= 4;
978 current_menu
= &wkmenu
;
984 if (isAddrEditActive()) return 1;
985 if (!isMMEditActive()) mmeditactive
= 1;
989 if (!isAddrEditActive() && !isMMEditActive()) {
1002 if (!isAddrEditActive() && !isMMEditActive()) {
1003 if (evtAltKeyDown
) {
1004 int v
= ((optPaused
&PAUSE_PERMANENT_MASK
) == 0);
1005 emuSetPaused(v
? PAUSE_PERMANENT_SET
: PAUSE_PERMANENT_RESET
);
1011 /*if ((key->keysym.mod&KMOD_ALT) != 0)*/ {
1012 if (isAddrEditActive()) {
1013 vt_smm_init_textview(&wkmenu
, "Small help (MM)",
1015 "dunno, cursor keys. pgup/pgdn moves by pages.",
1016 "del on page number clears page index.",
1019 } else if (isMMEditActive()) {
1020 vt_smm_init_textview(&wkmenu
, "Small help (AE)",
1022 "\x01""C-Del", " restore pages in order",
1023 "\x01""S-Del", " restore pages in 502 order",
1024 "\x01""M-Del", " restore pages in 201 order",
1025 "\x01""Del", " make current page ordered",
1026 "\x01""Enter", " go to the selected page",
1027 "\x01""C-R", " analyze pages, mark pages filled with zeroes as unused",
1031 vt_smm_init_textview(&wkmenu
, "Small help",
1033 "\x01""M-F1", " toggle pause",
1034 "\x01""M-F9", " toggle maxspeed",
1035 "\x01""F6", " switch view mode",
1036 //"\x01""F8", " switch encoding",
1037 "\x01""G", " input address",
1038 "\x01""C", " cycle text colors",
1039 "\x01""B", " toggle text brightness",
1040 "\x01""0-4", " set text width",
1041 "\x01""M-E", " select encoding",
1042 "\x01""M-W", " select text width",
1043 "\x01""M-M", " select view mode",
1044 "\x01""S-<digit>", " maximum text width (in text mode)",
1045 "\x01""C-<digit>", " set bookmark",
1046 "\x01""M-<digit>", " go to bookmark",
1047 "\x01""C-S-C", " clear bookmarks",
1052 current_menu
= &wkmenu
;