Page 1 of 1

Problem with ts_vmod()

Posted: Sun Feb 11, 2018 3:19 pm
by Stefan123
I have a problem with ts_vmod() in zxn.h. When I use the following line, I can verify in the ZEsarUX debugger that the 0xFF port is to 0x06 but not 0x3E as you would have expected:

Code: Select all

ts_vmod(IO_TVM_HIRES_WHITE);
However, the following workaround works as expected:

Code: Select all

z80_outp(0xFF, IO_TVM_HIRES_WHITE);

Posted: Mon Feb 12, 2018 6:06 am
by alvin
Stefan123 wrote:I have a problem with ts_vmod() in zxn.h. When I use the following line, I can verify in the ZEsarUX debugger that the 0xFF port is to 0x06 but not 0x3E as you would have expected:

Code: Select all

ts_vmod(IO_TVM_HIRES_WHITE);
ts_vmod is intended to take a paper colour in its argument:

ts_vmod(TVM_HIRES | PAPER_WHITE);

Code: Select all

// timex video mode

#define TVM_SPECTRUM   __IO_TVM_DFILE_1       // 256x192 pix, 32x24 attr
#define TVM_HICOLOR    __IO_TVM_HICOLOR       // 256x192 pix, 32x192 attr
#define TVM_HIRES      __IO_TVM_HIRES         // 512x192 pix or with paper colour

extern void ts_vmod(unsigned char mode) __preserves_regs(b,c,d,e,iyl,iyh);
extern void ts_vmod_fastcall(unsigned char mode) __preserves_regs(b,c,d,e,iyl,iyh) __z88dk_fastcall;
#define ts_vmod(a) ts_vmod_fastcall(a)
The reason is port 0xff specifies colour in bits 3..5 which is the same location as paper colours in attribute bytes so it's possible to use the already existing macros PAPER_*. ts_vmod will invert bits 3..5 to turn the paper colour into an ink colour before mixing that with the bits in port 0xff that have to be preserved.

Code: Select all

asm_ts_vmod:

   ; change video mode
   ;
   ; enter : l = mode
   ;
   ; uses  : af, l
   
   ld a,l
   xor $38
   and $3f
   ld l,a
   
   in a,($ff)
   and $c0
   or l
   out ($ff),a
   
   ret

Posted: Mon Feb 12, 2018 6:09 am
by alvin
It saves the definition of yet another set of colour macros. Setting ts_vmod is not going to be a timing sensitive thing in most applications and if it is, you'd most likely want to avoid the function call anyway and set port 0xff directly with "IO_FF = ...;"

Posted: Mon Feb 12, 2018 5:44 pm
by Stefan123
I thought the IO_TVM_HIRES_BLACK, IO_TVM_HIRES_BLUE, ..., IO_TVM_HIRES_WHITE macros in zxn.h were supposed to be used as arguments to ts_vmod().

Posted: Tue Feb 13, 2018 12:30 am
by alvin
Stefan123 wrote:I thought the IO_TVM_HIRES_BLACK, IO_TVM_HIRES_BLUE, ..., IO_TVM_HIRES_WHITE macros in zxn.h were supposed to be used as arguments to ts_vmod().
I forgot those were there. Anything with IO in front has to do with io ports:

https://github.com/z88dk/z88dk/blob/mas ... zxn.h#L118
https://github.com/z88dk/z88dk/blob/mas ... zxn.h#L191

Each io port is given two names: IO_{PORT_NUM} and IO_{TEXT_NAME} so foe port 0xff they are:

Code: Select all

__sfr __at 0xff IO_FF;
__sfr __at __IO_TIMEX_VIDEO_MODE IO_TIMEX_VIDEO_MODE;
And then defined bits for the port are given names IO_{PORT_NAME_INITIAL}_BITNAME

Code: Select all

// 0xff, IO_TIMEX_VIDEO_MODE

#define IO_TVM_DISABLE_ULA_INTERRUPT  __IO_TVM_DISABLE_ULA_INTERRUPT
#define IO_TVM_DFILE_1  __IO_TVM_DFILE_1
#define IO_TVM_DFILE_2  __IO_TVM_DFILE_2
#define IO_TVM_HICOLOR  __IO_TVM_HICOLOR
#define IO_TVM_HIRES  __IO_TVM_HIRES
#define IO_TVM_HIRES_BLACK  __IO_TVM_HIRES_BLACK
#define IO_TVM_HIRES_BLUE  __IO_TVM_HIRES_BLUE
#define IO_TVM_HIRES_RED  __IO_TVM_HIRES_RED
#define IO_TVM_HIRES_MAGENTA  __IO_TVM_HIRES_MAGENTA
#define IO_TVM_HIRES_GREEN  __IO_TVM_HIRES_GREEN
#define IO_TVM_HIRES_CYAN  __IO_TVM_HIRES_CYAN
#define IO_TVM_HIRES_YELLOW  __IO_TVM_HIRES_YELLOW
#define IO_TVM_HIRES_WHITE __IO_TVM_HIRES_WHITE
And the port initial in this case is "TVM" which also happens to be the initial for the function "ts_vmod()" so that its flag bits also have a TVM initial in their names:

Code: Select all

// timex video mode

#define TVM_SPECTRUM   __IO_TVM_DFILE_1       // 256x192 pix, 32x24 attr
#define TVM_HICOLOR    __IO_TVM_HICOLOR       // 256x192 pix, 32x192 attr
#define TVM_HIRES      __IO_TVM_HIRES         // 512x192 pix or with paper colour

extern void ts_vmod(unsigned char mode) __preserves_regs(b,c,d,e,iyl,iyh);
extern void ts_vmod_fastcall(unsigned char mode) __preserves_regs(b,c,d,e,iyl,iyh) __z88dk_fastcall;
#define ts_vmod(a) ts_vmod_fastcall(a)
So I can see the confusion. I'm not entirely sure if it's a good thing to name io ports rather than just sticking to port numbers in the name but it's used in the sms target for vdp address and data because that may help in the portability of libraries for TMS98xx chips.

Maybe this last set of constants should be renamed with initial TSVM to avoid confusion:

Code: Select all

// timex video mode

#define TSVM_SPECTRUM   __IO_TVM_DFILE_1       // 256x192 pix, 32x24 attr
#define TSVM_HICOLOR    __IO_TVM_HICOLOR       // 256x192 pix, 32x192 attr
#define TSVM_HIRES      __IO_TVM_HIRES         // 512x192 pix or with paper colour
Would that help?

Posted: Tue Feb 13, 2018 12:35 am
by alvin
Maybe we should have the bit names also available with port number in them:

Code: Select all

#define IO_FF_DISABLE_ULA_INTERRUPT  __IO_TVM_DISABLE_ULA_INTERRUPT
#define IO_FF_DFILE_1  __IO_TVM_DFILE_1
#define IO_FF_DFILE_2  __IO_TVM_DFILE_2
#define IO_FF_HICOLOR  __IO_TVM_HICOLOR
#define IO_FF_HIRES  __IO_TVM_HIRES
#define IO_FF_HIRES_BLACK  __IO_TVM_HIRES_BLACK
#define IO_FF_HIRES_BLUE  __IO_TVM_HIRES_BLUE
#define IO_FF_HIRES_RED  __IO_TVM_HIRES_RED
#define IO_FF_HIRES_MAGENTA  __IO_TVM_HIRES_MAGENTA
#define IO_FF_HIRES_GREEN  __IO_TVM_HIRES_GREEN
#define IO_FF_HIRES_CYAN  __IO_TVM_HIRES_CYAN
#define IO_FF_HIRES_YELLOW  __IO_TVM_HIRES_YELLOW
#define IO_FF_HIRES_WHITE __IO_TVM_HIRES_WHITE

Posted: Tue Feb 13, 2018 8:11 pm
by Stefan123
Naming is not easy... Maybe just adding comments above the IO_TVM_HIRES_BLACK macro group and TVM_HIRES macro group explaining their purpose would help? It would have helped me :)