Annotation of uae/src/svga.c, revision 1.1.1.2

1.1       root        1:  /* 
                      2:   * UAE - The Un*x Amiga Emulator
                      3:   * 
                      4:   * SVGAlib interface.
                      5:   * 
                      6:   * (c) 1995 Bernd Schmidt
                      7:   */
                      8: 
                      9: #include "sysconfig.h"
                     10: #include "sysdeps.h"
                     11: 
                     12: #include <assert.h>
                     13: #include <ctype.h>
                     14: #include <signal.h>
                     15: #include <vga.h>
                     16: #include <vgamouse.h>
                     17: #include <vgakeyboard.h>
                     18: 
                     19: #include "config.h"
                     20: #include "options.h"
                     21: #include "memory.h"
                     22: #include "custom.h"
1.1.1.2 ! root       23: #include "readcpu.h"
1.1       root       24: #include "newcpu.h"
                     25: #include "keyboard.h"
                     26: #include "xwin.h"
                     27: #include "keybuf.h"
                     28: #include "gui.h"
                     29: 
                     30: #define SCODE_CURSORBLOCKUP    103     /* Cursor key block. */
                     31: #define SCODE_CURSORBLOCKLEFT 105
                     32: #define SCODE_CURSORBLOCKRIGHT 106
                     33: #define SCODE_CURSORBLOCKDOWN 108
                     34: 
                     35: #define SCODE_INSERT 110
                     36: #define SCODE_HOME 102
                     37: #define SCODE_PGUP 104
                     38: #define SCODE_DELETE 111
                     39: #define SCODE_END 107
                     40: #define SCODE_PGDN 109
                     41: 
                     42: #define SCODE_KEYPAD0  82
                     43: #define SCODE_KEYPAD1  79
                     44: #define SCODE_KEYPAD2  80
                     45: #define SCODE_KEYPAD3  81
                     46: #define SCODE_KEYPAD4  75
                     47: #define SCODE_KEYPAD5  76
                     48: #define SCODE_KEYPAD6  77
                     49: #define SCODE_KEYPAD7  71
                     50: #define SCODE_KEYPAD8  72
                     51: #define SCODE_KEYPAD9  73
                     52: #define SCODE_KEYPADENTER      96
                     53: #define SCODE_KEYPADPLUS       78
                     54: #define SCODE_KEYPADMINUS      74
                     55: 
                     56: #define SCODE_Q                16
                     57: #define SCODE_W                17
                     58: #define SCODE_E                18
                     59: #define SCODE_R                19
                     60: #define SCODE_T                20
                     61: #define SCODE_Y                21
                     62: #define SCODE_U                22
                     63: #define SCODE_I                23
                     64: #define SCODE_O                24
                     65: #define SCODE_P                25
                     66: 
                     67: #define SCODE_A                30
                     68: #define SCODE_S                31
                     69: #define SCODE_D                32
                     70: #define SCODE_F                33
                     71: #define SCODE_G                34
                     72: #define SCODE_H                35
                     73: #define SCODE_J                36
                     74: #define SCODE_K                37
                     75: #define SCODE_L                38
                     76: 
                     77: #define SCODE_Z                44
                     78: #define SCODE_X                45
                     79: #define SCODE_C                46
                     80: #define SCODE_V                47
                     81: #define SCODE_B                48
                     82: #define SCODE_N                49
                     83: #define SCODE_M                50
                     84: 
                     85: #define SCODE_ESCAPE           1
                     86: #define SCODE_ENTER            28
                     87: #define SCODE_RIGHTCONTROL     97
                     88: #define SCODE_CONTROL  97
                     89: #define SCODE_RIGHTALT 100
                     90: #define SCODE_LEFTCONTROL      29
                     91: #define SCODE_LEFTALT  56
                     92: #define SCODE_SPACE            57
                     93: 
                     94: #define SCODE_F1               59
                     95: #define SCODE_F2               60
                     96: #define SCODE_F3               61
                     97: #define SCODE_F4               62
                     98: #define SCODE_F5               63
                     99: #define SCODE_F6               64
                    100: #define SCODE_F7               65
                    101: #define SCODE_F8               66
                    102: #define SCODE_F9               67
                    103: #define SCODE_F10              68
                    104: 
                    105: #define SCODE_0 11
                    106: #define SCODE_1 2
                    107: #define SCODE_2 3
                    108: #define SCODE_3 4
                    109: #define SCODE_4 5 
                    110: #define SCODE_5 6
                    111: #define SCODE_6 7 
                    112: #define SCODE_7 8
                    113: #define SCODE_8 9
                    114: #define SCODE_9 10
                    115: 
                    116: #define SCODE_LEFTSHIFT 42
                    117: #define SCODE_RIGHTSHIFT 54
                    118: #define SCODE_TAB 15
                    119: 
                    120: #define SCODE_F11 87
                    121: #define SCODE_F12 88
                    122: #define SCODE_NEXT 81
                    123: #define SCODE_PRIOR 73
                    124: #define SCODE_BS 14
1.1.1.2 ! root      125: 
        !           126: #define SCODE_asciicircum 41
        !           127: 
1.1       root      128: #define SCODE_bracketleft 26
                    129: #define SCODE_bracketright 27
                    130: #define SCODE_comma 51
                    131: #define SCODE_period 52
                    132: #define SCODE_slash 53
                    133: #define SCODE_semicolon 39
                    134: #define SCODE_grave 40
                    135: #define SCODE_minus 12
                    136: #define SCODE_equal 13
                    137: #define SCODE_numbersign 43
                    138: #define SCODE_ltgt 86
                    139: #define SCODE_scrolllock 70
                    140: 
                    141: #define SCODE_LWIN95 125
                    142: #define SCODE_RWIN95 126
                    143: #define SCODE_MWIN95 127
                    144: 
                    145: void setup_brkhandler(void)
                    146: {
                    147: }
                    148: 
1.1.1.2 ! root      149: static int bitdepth, bit_unit, using_linear;
1.1       root      150: static vga_modeinfo modeinfo;
                    151: static char *linear_mem = NULL;
                    152: static int need_dither;
                    153: 
                    154: static UBYTE dither_buf[1000]; /* I hate having to think about array bounds */
                    155: 
                    156: xcolnr xcolors[4096];
                    157: 
                    158: struct vidbuf_description gfxvidinfo;
1.1.1.2 ! root      159: #define MAX_SCREEN_MODES 6
1.1       root      160: 
1.1.1.2 ! root      161: static int x_size_table[MAX_SCREEN_MODES] = { 320, 320, 320, 640, 640, 800 };
        !           162: static int y_size_table[MAX_SCREEN_MODES] = { 200, 240, 400, 350, 480, 600 };
1.1       root      163: 
1.1.1.2 ! root      164: static int vga_mode_table[MAX_SCREEN_MODES][MAX_COLOR_MODES+1] =
1.1       root      165:  { { G320x200x256, G320x200x32K, G320x200x64K, G320x200x256, G320x200x16, G320x200x16M32 },
                    166:    { G320x240x256, -1, -1, G320x240x256, -1, -1 },
                    167:    { G320x400x256, -1, -1, G320x400x256, -1, -1 },
1.1.1.2 ! root      168:    { -1, -1, -1, -1, G640x350x16, -1 },
1.1       root      169:    { G640x480x256, G640x480x32K, G640x480x64K, G640x480x256, G640x480x16, G640x480x16M32 },
                    170:    { G800x600x256, G800x600x32K, G800x600x64K, G800x600x256, G800x600x16, G800x600x16M32 } };
                    171: 
                    172: static int mode_bitdepth[MAX_COLOR_MODES+1][3] =
                    173:   { { 8, 8, 0 }, { 15, 16, 0 }, { 16, 16, 0 }, { 8, 8, 1 }, { 4, 8, 1 }, { 24, 32, 0 } };
                    174: 
                    175: void flush_line(int y)
                    176: {
                    177:     int target_y = y;
                    178: 
                    179:     if (linear_mem == NULL) {
                    180:        char *addr = gfxvidinfo.bufmem + y*gfxvidinfo.rowbytes;
                    181:        if (target_y < modeinfo.height && target_y >= 0) {
                    182:            if (need_dither) {
1.1.1.2 ! root      183:                DitherLine(dither_buf, (UWORD *)addr, 0, y, gfxvidinfo.maxlinetoscr, bit_unit);
1.1       root      184:                addr = dither_buf;
                    185:            } 
                    186:            vga_drawscanline(target_y, addr);
                    187:        }
                    188:     } else {
                    189:        if (need_dither && target_y >= 0) {
                    190:            char *addr = gfxvidinfo.bufmem + y*gfxvidinfo.rowbytes;
1.1.1.2 ! root      191:            DitherLine(linear_mem + modeinfo.linewidth * target_y, (UWORD *)addr, 0, y,
        !           192:                       gfxvidinfo.maxlinetoscr, bit_unit);
1.1       root      193:        }
                    194:     }
                    195: }
                    196: 
                    197: void flush_block(int a, int b)
                    198: {
                    199:     abort();
                    200: }
                    201: 
                    202: void flush_screen(int a, int b)
                    203: {
                    204: }
                    205: 
                    206: static int colors_allocated;
                    207: 
                    208: static int get_color(int r, int g, int b, xcolnr *cnp)
                    209: {
                    210:     if (colors_allocated == 256)
                    211:        return -1;
                    212:     *cnp = colors_allocated;
                    213:     vga_setpalette(colors_allocated, doMask(r, 6, 0), doMask(g, 6, 0), doMask(b, 6, 0));
                    214:     colors_allocated++;
                    215:     return 1;
                    216: }
                    217: 
                    218: static void init_colors(void)
                    219: {
                    220:     if (need_dither) {
                    221:        setup_dither(bitdepth, get_color);
                    222:     } else {
                    223:        int rw = 5, gw = 5, bw = 5;
                    224:        colors_allocated = 0;
                    225:        if (color_mode == 2) gw = 6;
                    226: 
                    227:        switch (gfxvidinfo.pixbytes) {
                    228:         case 4:
                    229:            alloc_colors64k(8, 8, 8, 16, 8, 0);
                    230:            break;
                    231:         case 2:
                    232:            alloc_colors64k(rw, gw, bw, gw+bw, bw, 0);
                    233:            break;
                    234:         case 1:
                    235:            alloc_colors256(get_color);
                    236:            break;
                    237:         default:
                    238:            abort();
                    239:        }
                    240:     }
                    241: }
                    242: 
                    243: int buttonstate[3] = { 0, 0, 0 };
                    244: int lastmx, lastmy;
                    245: int newmousecounters = 0;
                    246: 
                    247: static int keystate[256];
                    248: 
                    249: static int scancode2amiga(int scancode)
                    250: {
                    251:     switch(scancode) {
                    252:      case SCODE_A: return AK_A;
                    253:      case SCODE_B: return AK_B;
                    254:      case SCODE_C: return AK_C;
                    255:      case SCODE_D: return AK_D;
                    256:      case SCODE_E: return AK_E;
                    257:      case SCODE_F: return AK_F;
                    258:      case SCODE_G: return AK_G;
                    259:      case SCODE_H: return AK_H;
                    260:      case SCODE_I: return AK_I;
                    261:      case SCODE_J: return AK_J;
                    262:      case SCODE_K: return AK_K;
                    263:      case SCODE_L: return AK_L;
                    264:      case SCODE_M: return AK_M;
                    265:      case SCODE_N: return AK_N;
                    266:      case SCODE_O: return AK_O;
                    267:      case SCODE_P: return AK_P;
                    268:      case SCODE_Q: return AK_Q;
                    269:      case SCODE_R: return AK_R;
                    270:      case SCODE_S: return AK_S;
                    271:      case SCODE_T: return AK_T;
                    272:      case SCODE_U: return AK_U;
                    273:      case SCODE_V: return AK_V;
                    274:      case SCODE_W: return AK_W;
                    275:      case SCODE_X: return AK_X;
                    276:      case SCODE_Y: return AK_Y;
                    277:      case SCODE_Z: return AK_Z;
                    278:        
                    279:      case SCODE_0: return AK_0;
                    280:      case SCODE_1: return AK_1;
                    281:      case SCODE_2: return AK_2;
                    282:      case SCODE_3: return AK_3;
                    283:      case SCODE_4: return AK_4;
                    284:      case SCODE_5: return AK_5;
                    285:      case SCODE_6: return AK_6;
                    286:      case SCODE_7: return AK_7;
                    287:      case SCODE_8: return AK_8;
                    288:      case SCODE_9: return AK_9;
                    289:        
                    290:      case SCODE_KEYPAD0: return AK_NP0;
                    291:      case SCODE_KEYPAD1: return AK_NP1;
                    292:      case SCODE_KEYPAD2: return AK_NP2;
                    293:      case SCODE_KEYPAD3: return AK_NP3;
                    294:      case SCODE_KEYPAD4: return AK_NP4;
                    295:      case SCODE_KEYPAD5: return AK_NP5;
                    296:      case SCODE_KEYPAD6: return AK_NP6;
                    297:      case SCODE_KEYPAD7: return AK_NP7;
                    298:      case SCODE_KEYPAD8: return AK_NP8;
                    299:      case SCODE_KEYPAD9: return AK_NP9;
                    300:        
                    301:      case SCODE_F1: return AK_F1;
                    302:      case SCODE_F2: return AK_F2;
                    303:      case SCODE_F3: return AK_F3;
                    304:      case SCODE_F4: return AK_F4;
                    305:      case SCODE_F5: return AK_F5;
                    306:      case SCODE_F6: return AK_F6;
                    307:      case SCODE_F7: return AK_F7;
                    308:      case SCODE_F8: return AK_F8;
                    309:      case SCODE_F9: return AK_F9;
                    310:      case SCODE_F10: return AK_F10;
                    311:        
                    312:      case SCODE_BS: return AK_BS;
                    313:      case SCODE_LEFTCONTROL: return AK_CTRL;
                    314:      case SCODE_RIGHTCONTROL: return AK_CTRL;
                    315:      case SCODE_TAB: return AK_TAB;
                    316:      case SCODE_LEFTALT: return AK_LALT;
                    317:      case SCODE_RIGHTALT: return AK_RALT;
                    318:      case SCODE_ENTER: return AK_RET;
                    319:      case SCODE_SPACE: return AK_SPC;
                    320:      case SCODE_LEFTSHIFT: return AK_LSH;
                    321:      case SCODE_RIGHTSHIFT: return AK_RSH;
                    322:      case SCODE_ESCAPE: return AK_ESC;
                    323:        
                    324:      case SCODE_INSERT:
                    325:      case SCODE_END:   
                    326:      case SCODE_HOME: break;
                    327: 
                    328:      case SCODE_DELETE: return AK_DEL;
                    329:      case SCODE_CURSORBLOCKUP: return AK_UP;
                    330:      case SCODE_CURSORBLOCKDOWN: return AK_DN;
                    331:      case SCODE_CURSORBLOCKLEFT: return AK_LF;
                    332:      case SCODE_CURSORBLOCKRIGHT: return AK_RT;
                    333:        
                    334:      case SCODE_F11: return AK_BACKSLASH;
                    335:      case SCODE_asciicircum: return AK_00;
                    336:      case SCODE_bracketleft: return AK_LBRACKET;
                    337:      case SCODE_bracketright: return AK_RBRACKET;
                    338:      case SCODE_comma: return AK_COMMA;
                    339:      case SCODE_period: return AK_PERIOD;
                    340:      case SCODE_slash: return AK_SLASH;
                    341:      case SCODE_semicolon: return AK_SEMICOLON;
                    342:      case SCODE_grave: return AK_QUOTE;
                    343:      case SCODE_minus: return AK_MINUS;
                    344:      case SCODE_equal: return AK_EQUAL;
                    345:        
                    346:        /* This one turns off screen updates. */
                    347:      case SCODE_scrolllock: return AK_inhibit;
                    348: 
                    349:      case SCODE_PGUP: case SCODE_RWIN95: return AK_RAMI;
                    350:      case SCODE_PGDN: case SCODE_LWIN95: return AK_LAMI; 
                    351:        
                    352: /*#ifdef KBD_LANG_DE*/
                    353:      case SCODE_numbersign: return AK_NUMBERSIGN;
                    354:      case SCODE_ltgt: return AK_LTGT;
                    355: /*#endif*/
                    356:     }
                    357:     return -1;
                    358: }
                    359: 
                    360: static void my_kbd_handler(int scancode, int newstate)
                    361: {
                    362:     int akey = scancode2amiga(scancode);
                    363:     
                    364:     assert(scancode >= 0 && scancode < 0x100);
                    365:     if (scancode == SCODE_F12) {
                    366:        regs.spcflags |= SPCFLAG_BRK;
                    367:        quit_program = 1;
                    368:     }
                    369:     if (keystate[scancode] == newstate)
                    370:        return;
                    371:     keystate[scancode] = newstate;
                    372: 
                    373:     if (akey == -1) {
                    374:        return;
                    375:     }
                    376: 
                    377:     if (newstate == KEY_EVENTPRESS) {
                    378:        if (akey == AK_inhibit)
                    379:            inhibit_frame ^= 1;
                    380:        else
                    381:            record_key (akey << 1);
                    382:     } else
                    383:        record_key ((akey << 1) | 1);
                    384:     
                    385:     /* "Affengriff" */
                    386:     if(keystate[AK_CTRL] && keystate[AK_LAMI] && keystate[AK_RAMI])
                    387:        m68k_reset();
                    388: }
                    389: 
                    390: int graphics_init(void)
                    391: {
                    392:     int i;
                    393:     int vgamode;
1.1.1.2 ! root      394:     int mode_nr0, mode_nr;
1.1       root      395:     need_dither = 0;
                    396:     using_linear = 0;
                    397: 
1.1.1.2 ! root      398:     fprintf (stderr, "Initializing SVGAlib.\n");
        !           399:     mode_nr0 = 0;
        !           400:     for (i = 1; i < MAX_SCREEN_MODES; i++) {
        !           401:        if (x_size_table[mode_nr0] >= gfx_requested_width)
        !           402:            break;
        !           403:        if (x_size_table[i-1] != x_size_table[i])
        !           404:            mode_nr0 = i;
        !           405:     }
        !           406:     mode_nr = -1;
        !           407:     for (i = mode_nr0; i < MAX_SCREEN_MODES && x_size_table[i] == x_size_table[mode_nr0]; i++) {
        !           408:        if ((y_size_table[i] >= gfx_requested_height 
        !           409:             || i + 1 == MAX_SCREEN_MODES 
        !           410:             || x_size_table[i+1] != x_size_table[mode_nr0])
        !           411:            && vga_mode_table[i][color_mode] != -1)
        !           412:        {
        !           413:            mode_nr = i;
        !           414:            break;
        !           415:        }
        !           416:     }
        !           417:     if (mode_nr == -1) {
1.1       root      418:        fprintf(stderr, "Sorry, this combination of color and video mode is not supported.\n");
                    419:        return 0;
                    420:     }
1.1.1.2 ! root      421:     vgamode = vga_mode_table[mode_nr][color_mode];
        !           422:     if (vgamode == -1) {
        !           423:        fprintf(stderr, "Bug!\n");
        !           424:        abort();
        !           425:     }
        !           426:     fprintf(stderr, "Desired resolution: %dx%d, using: %dx%d\n", 
        !           427:            gfx_requested_width, gfx_requested_height,
        !           428:            x_size_table[mode_nr], y_size_table[mode_nr]);
1.1       root      429:     
1.1.1.2 ! root      430:     gfx_requested_width = x_size_table[mode_nr];
        !           431:     gfx_requested_height = y_size_table[mode_nr];
        !           432: 
1.1       root      433:     bitdepth = mode_bitdepth[color_mode][0];
                    434:     bit_unit = mode_bitdepth[color_mode][1];
                    435:     need_dither = mode_bitdepth[color_mode][2];
                    436:     
                    437:     vga_init();
                    438:     modeinfo = *vga_getmodeinfo (vgamode);
                    439:     
                    440:     gfxvidinfo.pixbytes = modeinfo.bytesperpixel;
                    441:     if (!need_dither) {
                    442:        if (modeinfo.bytesperpixel == 0) {
1.1.1.2 ! root      443:            printf("Got a bogus value from SVGAlib...\n");
1.1       root      444:            gfxvidinfo.pixbytes = 1;
                    445:        }
                    446:     } else {
                    447:        gfxvidinfo.pixbytes = 2;
                    448:     }
                    449:     
                    450:     if (vga_setmode(vgamode) < 0) {
                    451:        sleep(1);
                    452:        vga_setmode(TEXT);
                    453:        fprintf(stderr, "SVGAlib doesn't like my video mode. Giving up.\n");
                    454:        return 0;
                    455:     }
                    456: 
                    457:     if ((modeinfo.flags & CAPABLE_LINEAR) && !no_xhair) {
                    458:        if (vga_setlinearaddressing() != -1) {
                    459:            linear_mem = (char *)vga_getgraphmem();
                    460:            printf("Using linear addressing: %p.\n", linear_mem);
                    461:            using_linear = !need_dither;
                    462:        }
                    463:     }
1.1.1.2 ! root      464: 
1.1       root      465:     gfxvidinfo.maxblocklines = 0;
                    466: 
1.1.1.2 ! root      467:     gfxvidinfo.maxlinetoscr = modeinfo.width;
        !           468:     gfxvidinfo.maxline = modeinfo.height;
        !           469: 
1.1       root      470:     if (using_linear) {
                    471:        gfxvidinfo.bufmem = linear_mem;
                    472:        gfxvidinfo.rowbytes = modeinfo.linewidth;
                    473:     } else {
1.1.1.2 ! root      474:        gfxvidinfo.rowbytes = (modeinfo.width * gfxvidinfo.pixbytes + 3) & ~3;
        !           475:        gfxvidinfo.bufmem = malloc(gfxvidinfo.rowbytes * modeinfo.height);
        !           476:        memset(gfxvidinfo.bufmem, 0, gfxvidinfo.rowbytes * modeinfo.height);
1.1       root      477:     }
                    478: 
                    479:     init_colors();
                    480:     vga_setmousesupport(1);
1.1.1.2 ! root      481:     mouse_init("/dev/mouse", vga_getmousetype(), 10);
1.1       root      482:     if (keyboard_init() != 0)
                    483:        abort();
                    484:     keyboard_seteventhandler(my_kbd_handler);
                    485:     keyboard_translatekeys(DONT_CATCH_CTRLC);
                    486:     
                    487:     buttonstate[0] = buttonstate[1] = buttonstate[2] = 0;
                    488:     for(i = 0; i < 256; i++) 
                    489:        keystate[i] = 0;
                    490: 
                    491:     lastmx = lastmy = 0;
                    492:     newmousecounters = 0;
                    493: 
                    494:     mouse_setxrange(-1000,1000);
                    495:     mouse_setyrange(-1000,1000);
                    496:     mouse_setposition(0,0);
                    497:     
                    498:     return 1;
                    499: }
                    500: 
                    501: void graphics_leave(void)
                    502: {
                    503:     sleep(1); /* Maybe this will fix the "screen full of garbage" problem */
                    504:     vga_setmode(TEXT);
                    505:     keyboard_close();
                    506:     dumpcustom();
                    507: }
                    508: 
                    509: void handle_events(void)
                    510: {
                    511:     int button = mouse_getbutton();
                    512:     
                    513:     keyboard_update();
                    514:     mouse_update();
                    515:     lastmx += mouse_getx();
                    516:     lastmy += mouse_gety();
                    517:     mouse_setposition(0,0);
                    518: 
                    519:     buttonstate[0] = button & 4;
                    520:     buttonstate[1] = button & 2;
                    521:     buttonstate[2] = button & 1;
                    522: }
                    523: 
                    524: int debuggable(void)
                    525: {
                    526:     return 0;
                    527: }
                    528: 
                    529: int needmousehack(void)
                    530: {
                    531:     return 0;
                    532: }
                    533: 
                    534: void LED(int on)
                    535: {
                    536: }
                    537: 
                    538: void target_specific_usage(void)
                    539: {
1.1.1.2 ! root      540:     printf("  -S n         : Sound emulation accuracy (n = 0, 1, 2 or 3)\n"
        !           541:           "                 For sound emulation, n = 2 is recommended\n");
        !           542:     printf("  -b n         : Use n bits for sound output (8 or 16)\n");
        !           543:     printf("  -R n         : Use n Hz to output sound. Common values are\n"
        !           544:           "                 22050 Hz or 44100 Hz\n");
        !           545:     printf("  -B n         : Use a sound buffer of n bytes (use small\n"
        !           546:           "                 values on fast machines)\n");
        !           547:     printf("  -x           : Don't use SVGAlib linear framebuffer, even if available.\n");
        !           548:     printf("  -p command   : Use command to pipe printer output to.\n");
        !           549:     printf("  -I device    : Name of the used serial device (i.e. /dev/ttyS1\n");
1.1       root      550: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.