//------------------------------------------------------------------- // horizpan.cpp // // This program shows how to implement horizontal panning over // an image in video memory whose width is eight screens wide, // using the ATI Radeon's CRTC_PITCH and CRTC_START registers. // // compile using: $ g++ horizpan.cpp int86.cpp -o horizpan // // programmer: ALLAN CRUSE // written on: 01 NOV 2005 //------------------------------------------------------------------- #include // for printf(), perror() #include // for open() #include // for exit() #include // for read(), write(), close() #include // for mmap() #include // for inb(), outb(), etc. #include "int86.h" // for init8086(), int86() #define VENDOR_ID 0x1002 // Advanced Technologies, Inc #define DEVICE_ID 0x5B60 // ATI Radeon X300 //#define DEVICE_ID 0x5159 // ATI Radeon 7000 //#define DEVICE_ID 0x5960 // ATI Radeon 9250 Pro #define CRTC_START 0x0224 // Start-Address register #define CRTC_PITCH 0x022C // Scanline-Width register unsigned char *vram = (unsigned char*)0xA0000000; int vesa_mode = 0x4107, hres = 1280, vres = 1024; int iobase, pitch = hres*8; struct vm86plus_struct vm; int main( int argc, char **argv ) { // obtain the Radeon engine's i/o port-address init8086(); vm.regs.eax = 0xB102; // PCI Find Device vm.regs.ecx = DEVICE_ID; vm.regs.edx = VENDOR_ID; vm.regs.esi = 0; int86( 0x1A, vm ); if ( ( vm.regs.eax & 0xFF00 ) == 0 ) { vm.regs.eax = 0xB10A; // PCI Read Config Dword vm.regs.edi = 0x0014; // address of resource 1 int86( 0x1A, vm ); iobase = vm.regs.ecx & ~3; printf( "\nRadeon i/o port: %04X \n", iobase ); getchar(); } else { fprintf( stderr, "Radeon device not detected\n" ); exit(1); } // memory-map the display-memory into user-space int vd = open( "/dev/vram", O_RDWR ); if ( vd < 0 ) { perror( "/dev/vram" ); exit(1); } int size = lseek( vd, 0, SEEK_END ); int prot = PROT_READ | PROT_WRITE; int flag = MAP_FIXED | MAP_SHARED; if ( mmap( (void*)vram, size, prot, flag, vd, 0 ) == MAP_FAILED ) { perror( "mmap" ); exit(1); } // enter graphics mode vm.regs.eax = 0x4F02; vm.regs.ebx = vesa_mode; int86( 0x10, vm ); // set pitch for wide view outl( CRTC_PITCH, iobase + 0 ); outl( 8*inl( iobase + 4 ), iobase + 4 ); // draw widescreen border int x = 0, y = 0, color = 15; do { vram[ y * pitch + x ] = color; ++x; } while ( x < pitch-1 ); do { vram[ y * pitch + x ] = color; ++y; } while ( y < vres-1 ); do { vram[ y * pitch + x ] = color; --x; } while ( x > 0 ); do { vram[ y * pitch + x ] = color; --y; } while ( y > 0 ); getchar(); // color differently some upper scanlines on the eight pages for (int i = 0; i < 8; i++) { unsigned char *dstn = vram + i*hres; int color = 33 + i; for (int y = 2; y < vres/6; y++) for( int x = 2; x < hres-2; x++) dstn[ y * pitch + x ] = color; } getchar(); // main loop to do the horizontal panning int step_size = pitch / 64; int num_steps = 64; for (int i = 1; i < num_steps; i++) { int crtc_start = i * step_size; outl( CRTC_START, iobase + 0 ); outl( crtc_start, iobase + 4 ); getchar(); } // leave graphics mode vm.regs.eax = 0x0003; int86( 0x10, vm ); printf( "\n" ); }