Enumerate CGA CRTC registers and modes and implement that into the code

This commit is contained in:
starfrost013
2025-06-09 14:12:13 +01:00
parent 79c408b286
commit b639bf1853
2 changed files with 107 additions and 64 deletions

View File

@@ -15,11 +15,47 @@
* *
* Copyright 2008-2018 Sarah Walker. * Copyright 2008-2018 Sarah Walker.
* Copyright 2016-2018 Miran Grca. * Copyright 2016-2018 Miran Grca.
* Copyright 2025 starfrost (refactoring)
*/ */
#ifndef VIDEO_CGA_H #ifndef VIDEO_CGA_H
#define VIDEO_CGA_H #define VIDEO_CGA_H
// Mode flags for the CGA.
// Set by writing to 3D8
typedef enum cga_mode_flags_e
{
CGA_MODE_FLAG_HIGHRES = 1 << 0, // 80-column text mode
CGA_MODE_FLAG_GRAPHICS = 1 << 1, // Graphics mode
CGA_MODE_FLAG_BW = 1 << 2, // Black and white
CGA_MODE_FLAG_VIDEO_ENABLE = 1 << 3, // 0 = no video (as if the video was 0)
CGA_MODE_FLAG_HIGHRES_GRAPHICS = 1 << 4, // 640*200 mode. Corrupts the
CGA_MODE_FLAG_BLINK = 1 << 5, // If this is set, bit 5 of textmode characters blinks. Otherwise it is a high-intensity bg mode.
} cga_mode_flags;
// Motorola MC6845 CRTC registers
typedef enum cga_crtc_registers_e
{
CGA_CRTC_HTOTAL = 0x0, // Horizontal total (total number of characters incl. hsync)
CGA_CRTC_HDISP = 0x1, // Horizontal display
CGA_CRTC_HSYNC_POS = 0x2, // Horizontal position of horizontal ysnc
CGA_CRTC_HSYNC_WIDTH = 0x3, // Width of horizontal sync
CGA_CRTC_VTOTAL = 0x4, // Vertical total (total number of scanlines incl. vsync)
CGA_CRTC_VTOTAL_ADJUST = 0x5, // Vertical total adjust value
CGA_CRTC_VDISP = 0x6, // Vertical display (total number of displayed scanline)
CGA_CRTC_VSYNC = 0x7, // Vertical sync scanline number
CGA_CRTC_INTERLACE = 0x8, // If set, interlacing mode is enabled
CGA_CRTC_MAX_SCANLINE_ADDR = 0x9,
CGA_CRTC_CURSOR_START = 0xA,
CGA_CRTC_CURSOR_END = 0xB,
CGA_CRTC_START_ADDR_HIGH = 0xC,
CGA_CRTC_START_ADDR_LOW = 0xD,
CGA_CRTC_CURSOR_ADDR_HIGH = 0xE,
CGA_CRTC_CURSOR_ADDR_LOW = 0xF,
CGA_CRTC_LIGHT_PEN_ADDR_HIGH = 0x10,
CGA_CRTC_LIGHT_PEN_ADDR_LOW = 0x11,
} cga_crtc_registers;
typedef struct cga_t { typedef struct cga_t {
mem_mapping_t mapping; mem_mapping_t mapping;

View File

@@ -16,7 +16,7 @@
* *
* Copyright 2008-2019 Sarah Walker. * Copyright 2008-2019 Sarah Walker.
* Copyright 2016-2019 Miran Grca. * Copyright 2016-2019 Miran Grca.
* Copyright 2023 W. M. Martinez * Copyright 2023 W. M. Martine
*/ */
#include <stdio.h> #include <stdio.h>
#include <stdint.h> #include <stdint.h>
@@ -73,10 +73,10 @@ void cga_recalctimings(cga_t *cga);
static void static void
cga_update_latch(cga_t *cga) cga_update_latch(cga_t *cga)
{ {
uint32_t lp_latch = cga->displine * cga->crtc[1]; uint32_t lp_latch = cga->displine * cga->crtc[CGA_CRTC_HDISP];
cga->crtc[0x10] = (lp_latch >> 8) & 0x3f; cga->crtc[0x10] = (lp_latch >> 8) & 0x3f;
cga->crtc[0x11] = lp_latch & 0xff; cga->crtc[CGA_CRTC_LIGHT_PEN_ADDR_LOW] = lp_latch & 0xff;
} }
void void
@@ -96,6 +96,8 @@ cga_out(uint16_t addr, uint8_t val, void *priv)
old = cga->crtc[cga->crtcreg]; old = cga->crtc[cga->crtcreg];
cga->crtc[cga->crtcreg] = val & crtcmask[cga->crtcreg]; cga->crtc[cga->crtcreg] = val & crtcmask[cga->crtcreg];
if (old != val) { if (old != val) {
// Update the timings if we are writing any invalid CRTC register or a valid CRTC register
// except the CURSOR and LIGHT PEN registers
if ((cga->crtcreg < 0xe) || (cga->crtcreg > 0x11)) { if ((cga->crtcreg < 0xe) || (cga->crtcreg > 0x11)) {
cga->fullchange = changeframecount; cga->fullchange = changeframecount;
cga_recalctimings(cga); cga_recalctimings(cga);
@@ -235,12 +237,12 @@ cga_recalctimings(cga_t *cga)
double _dispontime; double _dispontime;
double _dispofftime; double _dispofftime;
if (cga->cgamode & 1) { if (cga->cgamode & CGA_MODE_FLAG_HIGHRES) {
disptime = (double) (cga->crtc[0] + 1); disptime = (double) (cga->crtc[CGA_CRTC_HTOTAL] + 1);
_dispontime = (double) cga->crtc[1]; _dispontime = (double) cga->crtc[CGA_CRTC_HDISP];
} else { } else {
disptime = (double) ((cga->crtc[0] + 1) << 1); disptime = (double) ((cga->crtc[CGA_CRTC_HTOTAL] + 1) << 1);
_dispontime = (double) (cga->crtc[1] << 1); _dispontime = (double) (cga->crtc[CGA_CRTC_HDISP] << 1);
} }
_dispofftime = disptime - _dispontime; _dispofftime = disptime - _dispontime;
_dispontime = _dispontime * CGACONST; _dispontime = _dispontime * CGACONST;
@@ -252,7 +254,7 @@ cga_recalctimings(cga_t *cga)
static void static void
cga_render(cga_t *cga, int line) cga_render(cga_t *cga, int line)
{ {
uint16_t ca = (cga->crtc[15] | (cga->crtc[14] << 8)) & 0x3fff; uint16_t ca = (cga->crtc[CGA_CRTC_CURSOR_ADDR_LOW] | (cga->crtc[CGA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x3fff;
int drawcursor; int drawcursor;
int x; int x;
int c; int c;
@@ -262,33 +264,35 @@ cga_render(cga_t *cga, int line)
int cols[4]; int cols[4];
int col; int col;
if ((cga->cgamode & 0x12) == 0x12) { int32_t highres_graphics_flag = (CGA_MODE_FLAG_HIGHRES_GRAPHICS | CGA_MODE_FLAG_GRAPHICS);
if ((cga->cgamode & highres_graphics_flag == highres_graphics_flag)) {
for (c = 0; c < 8; ++c) { for (c = 0; c < 8; ++c) {
buffer32->line[line][c] = 0; buffer32->line[line][c] = 0;
if (cga->cgamode & 1) if (cga->cgamode & CGA_MODE_FLAG_HIGHRES)
buffer32->line[line][c + (cga->crtc[1] << 3) + 8] = 0; buffer32->line[line][c + (cga->crtc[CGA_CRTC_HDISP] << 3) + 8] = 0;
else else
buffer32->line[line][c + (cga->crtc[1] << 4) + 8] = 0; buffer32->line[line][c + (cga->crtc[CGA_CRTC_HDISP] << 4) + 8] = 0;
} }
} else { } else {
for (c = 0; c < 8; ++c) { for (c = 0; c < 8; ++c) {
buffer32->line[line][c] = (cga->cgacol & 15) + 16; buffer32->line[line][c] = (cga->cgacol & 15) + 16;
if (cga->cgamode & 1) if (cga->cgamode & CGA_MODE_FLAG_HIGHRES)
buffer32->line[line][c + (cga->crtc[1] << 3) + 8] = (cga->cgacol & 15) + 16; buffer32->line[line][c + (cga->crtc[CGA_CRTC_HDISP] << 3) + 8] = (cga->cgacol & 15) + 16;
else else
buffer32->line[line][c + (cga->crtc[1] << 4) + 8] = (cga->cgacol & 15) + 16; buffer32->line[line][c + (cga->crtc[CGA_CRTC_HDISP] << 4) + 8] = (cga->cgacol & 15) + 16;
} }
} }
if (cga->cgamode & 1) { if (cga->cgamode & CGA_MODE_FLAG_HIGHRES) {
for (x = 0; x < cga->crtc[1]; x++) { for (x = 0; x < cga->crtc[CGA_CRTC_HDISP]; x++) {
if (cga->cgamode & 8) { if (cga->cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) {
chr = cga->charbuffer[x << 1]; chr = cga->charbuffer[x << 1];
attr = cga->charbuffer[(x << 1) + 1]; attr = cga->charbuffer[(x << 1) + 1];
} else } else
chr = attr = 0; chr = attr = 0;
drawcursor = ((cga->ma == ca) && cga->con && cga->cursoron); drawcursor = ((cga->ma == ca) && cga->con && cga->cursoron);
cols[1] = (attr & 15) + 16; cols[1] = (attr & 15) + 16;
if (cga->cgamode & 0x20) { if (cga->cgamode & CGA_MODE_FLAG_BLINK) {
cols[0] = ((attr >> 4) & 7) + 16; cols[0] = ((attr >> 4) & 7) + 16;
if ((cga->cgablink & 8) && (attr & 0x80) && !cga->drawcursor) if ((cga->cgablink & 8) && (attr & 0x80) && !cga->drawcursor)
cols[1] = cols[0]; cols[1] = cols[0];
@@ -308,15 +312,15 @@ cga_render(cga_t *cga, int line)
cga->ma++; cga->ma++;
} }
} else if (!(cga->cgamode & 2)) { } else if (!(cga->cgamode & 2)) {
for (x = 0; x < cga->crtc[1]; x++) { for (x = 0; x < cga->crtc[CGA_CRTC_HDISP]; x++) {
if (cga->cgamode & 8) { if (cga->cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) {
chr = cga->vram[(cga->ma << 1) & 0x3fff]; chr = cga->vram[(cga->ma << 1) & 0x3fff];
attr = cga->vram[((cga->ma << 1) + 1) & 0x3fff]; attr = cga->vram[((cga->ma << 1) + 1) & 0x3fff];
} else } else
chr = attr = 0; chr = attr = 0;
drawcursor = ((cga->ma == ca) && cga->con && cga->cursoron); drawcursor = ((cga->ma == ca) && cga->con && cga->cursoron);
cols[1] = (attr & 15) + 16; cols[1] = (attr & 15) + 16;
if (cga->cgamode & 0x20) { if (cga->cgamode & CGA_MODE_FLAG_BLINK) {
cols[0] = ((attr >> 4) & 7) + 16; cols[0] = ((attr >> 4) & 7) + 16;
if ((cga->cgablink & 8) && (attr & 0x80)) if ((cga->cgablink & 8) && (attr & 0x80))
cols[1] = cols[0]; cols[1] = cols[0];
@@ -337,10 +341,10 @@ cga_render(cga_t *cga, int line)
} }
} }
} }
} else if (!(cga->cgamode & 16)) { } else if (!(cga->cgamode & CGA_MODE_FLAG_HIGHRES_GRAPHICS)) {
cols[0] = (cga->cgacol & 15) | 16; cols[0] = (cga->cgacol & 15) | 16;
col = (cga->cgacol & 16) ? 24 : 16; col = (cga->cgacol & 16) ? 24 : 16;
if (cga->cgamode & 4) { if (cga->cgamode & CGA_MODE_FLAG_BW) {
cols[1] = col | 3; /* Cyan */ cols[1] = col | 3; /* Cyan */
cols[2] = col | 4; /* Red */ cols[2] = col | 4; /* Red */
cols[3] = col | 7; /* White */ cols[3] = col | 7; /* White */
@@ -353,8 +357,8 @@ cga_render(cga_t *cga, int line)
cols[2] = col | 4; /* Red */ cols[2] = col | 4; /* Red */
cols[3] = col | 6; /* Yellow */ cols[3] = col | 6; /* Yellow */
} }
for (x = 0; x < cga->crtc[1]; x++) { for (x = 0; x < cga->crtc[CGA_CRTC_HDISP]; x++) {
if (cga->cgamode & 8) if (cga->cgamode & CGA_MODE_FLAG_VIDEO_ENABLE)
dat = (cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000)] << 8) | dat = (cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000)] << 8) |
cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000) + 1]; cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000) + 1];
else else
@@ -370,8 +374,8 @@ cga_render(cga_t *cga, int line)
} else { } else {
cols[0] = 0; cols[0] = 0;
cols[1] = (cga->cgacol & 15) + 16; cols[1] = (cga->cgacol & 15) + 16;
for (x = 0; x < cga->crtc[1]; x++) { for (x = 0; x < cga->crtc[CGA_CRTC_HDISP]; x++) {
if (cga->cgamode & 8) if (cga->cgamode & CGA_MODE_FLAG_VIDEO_ENABLE)
dat = (cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000)] << 8) | dat = (cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000)] << 8) |
cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000) + 1]; cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000) + 1];
else else
@@ -388,12 +392,14 @@ cga_render(cga_t *cga, int line)
static void static void
cga_render_blank(cga_t *cga, int line) cga_render_blank(cga_t *cga, int line)
{ {
int col = ((cga->cgamode & 0x12) == 0x12) ? 0 : (cga->cgacol & 15) + 16; int32_t highres_graphics_flag = (CGA_MODE_FLAG_HIGHRES_GRAPHICS | CGA_MODE_FLAG_GRAPHICS);
if (cga->cgamode & 1) int col = ((cga->cgamode & highres_graphics_flag) == highres_graphics_flag) ? 0 : (cga->cgacol & 15) + 16;
hline(buffer32, 0, line, (cga->crtc[1] << 3) + 16, col);
if (cga->cgamode & CGA_MODE_FLAG_HIGHRES)
hline(buffer32, 0, line, (cga->crtc[CGA_CRTC_HDISP] << 3) + 16, col);
else else
hline(buffer32, 0, line, (cga->crtc[1] << 4) + 16, col); hline(buffer32, 0, line, (cga->crtc[CGA_CRTC_HDISP] << 4) + 16, col);
} }
static void static void
@@ -401,14 +407,15 @@ cga_render_process(cga_t *cga, int line)
{ {
int x; int x;
uint8_t border; uint8_t border;
int32_t highres_graphics_flag = (CGA_MODE_FLAG_HIGHRES_GRAPHICS | CGA_MODE_FLAG_GRAPHICS);
if (cga->cgamode & 1) if (cga->cgamode & CGA_MODE_FLAG_HIGHRES)
x = (cga->crtc[1] << 3) + 16; x = (cga->crtc[CGA_CRTC_HDISP] << 3) + 16;
else else
x = (cga->crtc[1] << 4) + 16; x = (cga->crtc[CGA_CRTC_HDISP] << 4) + 16;
if (cga->composite) { if (cga->composite) {
border = ((cga->cgamode & 0x12) == 0x12) ? 0 : (cga->cgacol & 15); border = ((cga->cgamode & highres_graphics_flag) == highres_graphics_flag) ? 0 : (cga->cgacol & 15);
Composite_Process(cga->cgamode, border, x >> 2, buffer32->line[line]); Composite_Process(cga->cgamode, border, x >> 2, buffer32->line[line]);
} else } else
@@ -524,7 +531,7 @@ cga_poll(void *priv)
cga->cgastat |= 1; cga->cgastat |= 1;
cga->linepos = 1; cga->linepos = 1;
oldsc = cga->sc; oldsc = cga->sc;
if ((cga->crtc[8] & 3) == 3) if ((cga->crtc[CGA_CRTC_INTERLACE] & 3) == 3)
cga->sc = ((cga->sc << 1) + cga->oddeven) & 7; cga->sc = ((cga->sc << 1) + cga->oddeven) & 7;
if (cga->cgadispon) { if (cga->cgadispon) {
if (cga->displine < cga->firstline) { if (cga->displine < cga->firstline) {
@@ -573,7 +580,7 @@ cga_poll(void *priv)
} }
cga->sc = oldsc; cga->sc = oldsc;
if (cga->vc == cga->crtc[7] && !cga->sc) if (cga->vc == cga->crtc[CGA_CRTC_VSYNC] && !cga->sc)
cga->cgastat |= 8; cga->cgastat |= 8;
cga->displine++; cga->displine++;
if (cga->displine >= 360) if (cga->displine >= 360)
@@ -586,12 +593,12 @@ cga_poll(void *priv)
if (!cga->vsynctime) if (!cga->vsynctime)
cga->cgastat &= ~8; cga->cgastat &= ~8;
} }
if (cga->sc == (cga->crtc[11] & 31) || ((cga->crtc[8] & 3) == 3 && if (cga->sc == (cga->crtc[CGA_CRTC_CURSOR_END] & 31) || ((cga->crtc[CGA_CRTC_INTERLACE] & 3) == 3 &&
cga->sc == ((cga->crtc[11] & 31) >> 1))) { cga->sc == ((cga->crtc[CGA_CRTC_CURSOR_END] & 31) >> 1))) {
cga->con = 0; cga->con = 0;
cga->coff = 1; cga->coff = 1;
} }
if ((cga->crtc[8] & 3) == 3 && cga->sc == (cga->crtc[9] >> 1)) if ((cga->crtc[CGA_CRTC_INTERLACE] & 3) == 3 && cga->sc == (cga->crtc[CGA_CRTC_MAX_SCANLINE_ADDR] >> 1))
cga->maback = cga->ma; cga->maback = cga->ma;
if (cga->vadj) { if (cga->vadj) {
cga->sc++; cga->sc++;
@@ -600,27 +607,27 @@ cga_poll(void *priv)
cga->vadj--; cga->vadj--;
if (!cga->vadj) { if (!cga->vadj) {
cga->cgadispon = 1; cga->cgadispon = 1;
cga->ma = cga->maback = (cga->crtc[13] | (cga->crtc[12] << 8)) & 0x3fff; cga->ma = cga->maback = (CGA_CRTC_START_ADDR_LOW | (CGA_CRTC_START_ADDR_HIGH << 8)) & 0x3fff;
cga->sc = 0; cga->sc = 0;
} }
} else if (cga->sc == cga->crtc[9]) { } else if (cga->sc == cga->crtc[CGA_CRTC_MAX_SCANLINE_ADDR]) {
cga->maback = cga->ma; cga->maback = cga->ma;
cga->sc = 0; cga->sc = 0;
oldvc = cga->vc; oldvc = cga->vc;
cga->vc++; cga->vc++;
cga->vc &= 127; cga->vc &= 127;
if (cga->vc == cga->crtc[6]) if (cga->vc == cga->crtc[CGA_CRTC_VDISP])
cga->cgadispon = 0; cga->cgadispon = 0;
if (oldvc == cga->crtc[4]) { if (oldvc == cga->crtc[CGA_CRTC_VTOTAL]) {
cga->vc = 0; cga->vc = 0;
cga->vadj = cga->crtc[5]; cga->vadj = cga->crtc[CGA_CRTC_VTOTAL_ADJUST];
if (!cga->vadj) { if (!cga->vadj) {
cga->cgadispon = 1; cga->cgadispon = 1;
cga->ma = cga->maback = (cga->crtc[13] | (cga->crtc[12] << 8)) & 0x3fff; cga->ma = cga->maback = (CGA_CRTC_START_ADDR_LOW | (CGA_CRTC_START_ADDR_HIGH << 8)) & 0x3fff;
} }
switch (cga->crtc[10] & 0x60) { switch (cga->crtc[CGA_CRTC_CURSOR_START] & 0x60) {
case 0x20: case 0x20:
cga->cursoron = 0; cga->cursoron = 0;
break; break;
@@ -633,15 +640,15 @@ cga_poll(void *priv)
} }
} }
if (cga->vc == cga->crtc[7]) { if (cga->vc == cga->crtc[CGA_CRTC_VSYNC]) {
cga->cgadispon = 0; cga->cgadispon = 0;
cga->displine = 0; cga->displine = 0;
cga->vsynctime = 16; cga->vsynctime = 16;
if (cga->crtc[7]) { if (cga->crtc[CGA_CRTC_VSYNC]) {
if (cga->cgamode & 1) if (cga->cgamode & CGA_MODE_FLAG_HIGHRES)
x = (cga->crtc[1] << 3) + 16; x = (cga->crtc[CGA_CRTC_HDISP] << 3) + 16;
else else
x = (cga->crtc[1] << 4) + 16; x = (cga->crtc[CGA_CRTC_HDISP] << 4) + 16;
cga->lastline++; cga->lastline++;
xs_temp = x; xs_temp = x;
@@ -657,7 +664,7 @@ cga_poll(void *priv)
if (!enable_overscan) if (!enable_overscan)
xs_temp -= 16; xs_temp -= 16;
if ((cga->cgamode & 8) && ((xs_temp != xsize) || if ((cga->cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) && ((xs_temp != xsize) ||
(ys_temp != ysize) || video_force_resize_get())) { (ys_temp != ysize) || video_force_resize_get())) {
xsize = xs_temp; xsize = xs_temp;
ysize = ys_temp; ysize = ys_temp;
@@ -691,15 +698,15 @@ cga_poll(void *priv)
video_res_x = xsize; video_res_x = xsize;
video_res_y = ysize; video_res_y = ysize;
if (cga->cgamode & 1) { if (cga->cgamode & CGA_MODE_FLAG_HIGHRES) {
video_res_x /= 8; video_res_x /= 8;
video_res_y /= cga->crtc[9] + 1; video_res_y /= cga->crtc[CGA_CRTC_MAX_SCANLINE_ADDR] + 1;
video_bpp = 0; video_bpp = 0;
} else if (!(cga->cgamode & 2)) { } else if (!(cga->cgamode & CGA_MODE_FLAG_GRAPHICS)) {
video_res_x /= 16; video_res_x /= 16;
video_res_y /= cga->crtc[9] + 1; video_res_y /= cga->crtc[CGA_CRTC_MAX_SCANLINE_ADDR] + 1;
video_bpp = 0; video_bpp = 0;
} else if (!(cga->cgamode & 16)) { } else if (!(cga->cgamode & CGA_MODE_FLAG_HIGHRES_GRAPHICS)) {
video_res_x /= 2; video_res_x /= 2;
video_bpp = 2; video_bpp = 2;
} else } else
@@ -717,11 +724,11 @@ cga_poll(void *priv)
} }
if (cga->cgadispon) if (cga->cgadispon)
cga->cgastat &= ~1; cga->cgastat &= ~1;
if (cga->sc == (cga->crtc[10] & 31) || ((cga->crtc[8] & 3) == 3 && if (cga->sc == (cga->crtc[CGA_CRTC_CURSOR_START] & 31) || ((cga->crtc[CGA_CRTC_INTERLACE] & 3) == 3 &&
cga->sc == ((cga->crtc[10] & 31) >> 1))) cga->sc == ((cga->crtc[CGA_CRTC_CURSOR_START] & 31) >> 1)))
cga->con = 1; cga->con = 1;
if (cga->cgadispon && (cga->cgamode & 1)) { if (cga->cgadispon && (cga->cgamode & CGA_MODE_FLAG_HIGHRES)) {
for (x = 0; x < (cga->crtc[1] << 1); x++) for (x = 0; x < (cga->crtc[CGA_CRTC_HDISP] << 1); x++)
cga->charbuffer[x] = cga->vram[((cga->ma << 1) + x) & 0x3fff]; cga->charbuffer[x] = cga->vram[((cga->ma << 1) + x) & 0x3fff];
} }
} }