Advertisement
Guest User

Untitled

a guest
Feb 28th, 2015
315
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 45.42 KB | None | 0 0
  1. /* tab:8
  2. *
  3. * modex.c - VGA mode X graphics routines
  4. *
  5. * "Copyright (c) 2004-2009 by Steven S. Lumetta."
  6. *
  7. * Permission to use, copy, modify, and distribute this software and its
  8. * documentation for any purpose, without fee, and without written agreement is
  9. * hereby granted, provided that the above copyright notice and the following
  10. * two paragraphs appear in all copies of this software.
  11. *
  12. * IN NO EVENT SHALL THE AUTHOR OR THE UNIVERSITY OF ILLINOIS BE LIABLE TO
  13. * ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
  14. * DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,
  15. * EVEN IF THE AUTHOR AND/OR THE UNIVERSITY OF ILLINOIS HAS BEEN ADVISED
  16. * OF THE POSSIBILITY OF SUCH DAMAGE.
  17. *
  18. * THE AUTHOR AND THE UNIVERSITY OF ILLINOIS SPECIFICALLY DISCLAIM ANY
  19. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  20. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
  21. * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND NEITHER THE AUTHOR NOR
  22. * THE UNIVERSITY OF ILLINOIS HAS ANY OBLIGATION TO PROVIDE MAINTENANCE,
  23. * SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
  24. *
  25. * Author: Steve Lumetta
  26. * Version: 3
  27. * Creation Date: Fri Sep 10 09:59:17 2004
  28. * Filename: modex.c
  29. * History:
  30. * SL 1 Fri Sep 10 09:59:17 2004
  31. * First written.
  32. * SL 2 Sat Sep 12 16:41:45 2009
  33. * Integrated original release back into main code base.
  34. * SL 3 Sat Sep 12 17:58:20 2009
  35. * Added display re-enable to VGA blank routine and comments
  36. * on other VirtualPC->QEMU migration changes.
  37. */
  38.  
  39. #include <fcntl.h>
  40. #include <stdio.h>
  41. #include <string.h>
  42. #include <stdlib.h>
  43. #include <sys/io.h>
  44. #include <sys/mman.h>
  45. #include <unistd.h>
  46.  
  47. #include "blocks.h"
  48. #include "modex.h"
  49. #include "text.h"
  50. #include <time.h>
  51.  
  52. /*
  53. * Calculate the image build buffer parameters. SCROLL_SIZE is the space
  54. * needed for one plane of an image. SCREEN_SIZE is the space needed for
  55. * all four planes. The extra +1 supports logical view x coordinates that
  56. * are not multiples of four. In these cases, some plane addresses are
  57. * shifted by 1 byte forward. The planes are stored in the build buffer
  58. * in reverse order to allow those planes that shift forward to do so
  59. * without running into planes that aren't shifted. For example, when
  60. * the leftmost x pixel in the logical view is 3 mod 4, planes 2, 1, and 0
  61. * are shifted forward, while plane 3 is not, so there is one unused byte
  62. * between the image of plane 3 and that of plane 2. BUILD_BUF_SIZE is
  63. * the size of the space allocated for building images. We add 20000 bytes
  64. * to reduce the number of memory copies required during scrolling.
  65. * Strictly speaking (try it), no extra space is necessary, but the minimum
  66. * means an extra 64kB memory copy with every scroll pixel. Finally,
  67. * BUILD_BASE_INIT places initial (or transferred) logical view in the
  68. * middle of the available buffer area.
  69. */
  70. #define SCROLL_SIZE (SCROLL_X_WIDTH * SCROLL_Y_DIM)
  71. #define SCREEN_SIZE (SCROLL_SIZE * 4 + 1)
  72. #define BUILD_BUF_SIZE (SCREEN_SIZE + 20000)
  73. #define BUILD_BASE_INIT ((BUILD_BUF_SIZE - SCREEN_SIZE) / 2)
  74.  
  75. /* Mode X and general VGA parameters */
  76. #define VID_MEM_SIZE 131072
  77. #define MODE_X_MEM_SIZE 65536
  78. #define NUM_SEQUENCER_REGS 5
  79. #define NUM_CRTC_REGS 25
  80. #define NUM_GRAPHICS_REGS 9
  81. #define NUM_ATTR_REGS 22
  82.  
  83. /* VGA register settings for mode X */
  84. static unsigned short mode_X_seq[NUM_SEQUENCER_REGS] = {
  85. 0x0100, 0x2101, 0x0F02, 0x0003, 0x0604
  86. };
  87.  
  88. /*Register for the status bar*/
  89. static unsigned short mode_X_CRTC[NUM_CRTC_REGS] = {
  90. 0x5F00, 0x4F01, 0x5002, 0x8203, 0x5404, 0x8005, 0xBF06, 0x1F07,
  91. 0x0008, 0x0109, 0x200A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
  92. 0x9C10, 0x8E11, 0x8F12, 0x2813, 0x0014, 0x9615, 0xB916, 0xE317,
  93. 0x6B18
  94. };
  95. static unsigned char mode_X_attr[NUM_ATTR_REGS * 2] = {
  96. 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03,
  97. 0x04, 0x04, 0x05, 0x05, 0x06, 0x06, 0x07, 0x07,
  98. 0x08, 0x08, 0x09, 0x09, 0x0A, 0x0A, 0x0B, 0x0B,
  99. 0x0C, 0x0C, 0x0D, 0x0D, 0x0E, 0x0E, 0x0F, 0x0F,
  100. 0x10, 0x41, 0x11, 0x00, 0x12, 0x0F, 0x13, 0x00,
  101. 0x14, 0x00, 0x15, 0x00
  102. };
  103. static unsigned short mode_X_graphics[NUM_GRAPHICS_REGS] = {
  104. 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x4005, 0x0506, 0x0F07,
  105. 0xFF08
  106. };
  107.  
  108. /* VGA register settings for text mode 3 (color text) */
  109. static unsigned short text_seq[NUM_SEQUENCER_REGS] = {
  110. 0x0100, 0x2001, 0x0302, 0x0003, 0x0204
  111. };
  112. static unsigned short text_CRTC[NUM_CRTC_REGS] = {
  113. 0x5F00, 0x4F01, 0x5002, 0x8203, 0x5504, 0x8105, 0xBF06, 0x1F07,
  114. 0x0008, 0x4F09, 0x0D0A, 0x0E0B, 0x000C, 0x000D, 0x000E, 0x000F,
  115. 0x9C10, 0x8E11, 0x8F12, 0x2813, 0x1F14, 0x9615, 0xB916, 0xA317,
  116. 0xFF18
  117. };
  118. static unsigned char text_attr[NUM_ATTR_REGS * 2] = {
  119. 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03,
  120. 0x04, 0x04, 0x05, 0x05, 0x06, 0x06, 0x07, 0x07,
  121. 0x08, 0x08, 0x09, 0x09, 0x0A, 0x0A, 0x0B, 0x0B,
  122. 0x0C, 0x0C, 0x0D, 0x0D, 0x0E, 0x0E, 0x0F, 0x0F,
  123. 0x10, 0x0C, 0x11, 0x00, 0x12, 0x0F, 0x13, 0x08,
  124. 0x14, 0x00, 0x15, 0x00
  125. };
  126. static unsigned short text_graphics[NUM_GRAPHICS_REGS] = {
  127. 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x1005, 0x0E06, 0x0007,
  128. 0xFF08
  129. };
  130.  
  131.  
  132. /* local functions--see function headers for details */
  133. static int open_memory_and_ports ();
  134. static void VGA_blank (int blank_bit);
  135. static void set_seq_regs_and_reset (unsigned short table[NUM_SEQUENCER_REGS],
  136. unsigned char val);
  137. static void set_CRTC_registers (unsigned short table[NUM_CRTC_REGS]);
  138. static void set_attr_registers (unsigned char table[NUM_ATTR_REGS * 2]);
  139. static void set_graphics_registers (unsigned short table[NUM_GRAPHICS_REGS]);
  140. static void fill_palette ();
  141. static void write_font_data ();
  142. static void set_text_mode_3 (int clear_scr);
  143. static void copy_image (unsigned char* img, unsigned short scr_addr);
  144. static void copy_status (unsigned char* img, unsigned short scr_addr);
  145.  
  146.  
  147. /*
  148. * Images are built in this buffer, then copied to the video memory.
  149. * Copying to video memory with REP MOVSB is vastly faster than anything
  150. * else with emulation, probably because it is a single instruction
  151. * and translates to a native loop. It's also a pretty good technique
  152. * in normal machines (albeit not as elegant as some others for reducing
  153. * the number of video memory writes; unfortunately, these techniques
  154. * are slower in emulation...).
  155. *
  156. * The size allows the four plane images to move within an area of
  157. * about twice the size necessary (to reduce the need to deal with
  158. * the boundary conditions by moving the data within the buffer).
  159. *
  160. * Plane 3 is first, followed by 2, 1, and 0. The reverse ordering
  161. * is used because the logical address of 0 increases first; if plane
  162. * 0 were first, we would need a buffer byte to keep it from colliding
  163. * with plane 1 when plane 0 was offset by 1 from plane 1, i.e., when
  164. * displaying a one-pixel left shift.
  165. *
  166. * The memory fence (included when NDEBUG is not defined) allocates
  167. * the build buffer with extra space on each side. The extra space
  168. * is filled with magic numbers (something unlikely to be written in
  169. * error), and the fence areas are checked for those magic values at
  170. * the end of the program to detect array access bugs (writes past
  171. * the ends of the build buffer).
  172. */
  173. #if !defined(NDEBUG)
  174. #define MEM_FENCE_WIDTH 256
  175. #else
  176. #define MEM_FENCE_WIDTH 0
  177. #endif
  178. #define MEM_FENCE_MAGIC 0xF3
  179. static unsigned char build[BUILD_BUF_SIZE + 2 * MEM_FENCE_WIDTH];
  180. static int img3_off; /* offset of upper left pixel */
  181. static unsigned char* img3; /* pointer to upper left pixel */
  182. static int show_x, show_y; /* logical view coordinates */
  183.  
  184. static unsigned char bitmask_buf[BLOCK_X_DIM * BLOCK_Y_DIM]; /*This is the buffer we will use for the translation*/
  185. static unsigned char extras[BLOCK_Y_DIM * BLOCK_X_DIM];
  186.  
  187. /* displayed video memory variables */
  188. static unsigned char* mem_image; /* pointer to start of video memory */
  189. static unsigned short target_img; /* offset of displayed screen image */
  190.  
  191.  
  192. /*
  193. * functions provided by the caller to set_mode_X() and used to obtain
  194. * graphic images of lines (pixels) to be mapped into the build buffer
  195. * planes for display in mode X
  196. */
  197. static void (*horiz_line_fn) (int, int, unsigned char[SCROLL_X_DIM]);
  198. static void (*vert_line_fn) (int, int, unsigned char[SCROLL_Y_DIM]);
  199.  
  200.  
  201. /*
  202. * macro used to target a specific video plane or planes when writing
  203. * to video memory in mode X; bits 8-11 in the mask_hi_bits enable writes
  204. * to planes 0-3, respectively
  205. */
  206. #define SET_WRITE_MASK(mask_hi_bits) \
  207. do { \
  208. asm volatile (" \
  209. movw $0x03C4,%%dx /* set write mask */;\
  210. movb $0x02,%b0 ;\
  211. outw %w0,(%%dx) \
  212. " : : "a" ((mask_hi_bits)) : "edx", "memory"); \
  213. } while (0)
  214.  
  215. /* macro used to write a byte to a port */
  216. #define OUTB(port,val) \
  217. do { \
  218. asm volatile (" \
  219. outb %b1,(%w0) \
  220. " : /* no outputs */ \
  221. : "d" ((port)), "a" ((val)) \
  222. : "memory", "cc"); \
  223. } while (0)
  224.  
  225. /* macro used to write two bytes to two consecutive ports */
  226. #define OUTW(port,val) \
  227. do { \
  228. asm volatile (" \
  229. outw %w1,(%w0) \
  230. " : /* no outputs */ \
  231. : "d" ((port)), "a" ((val)) \
  232. : "memory", "cc"); \
  233. } while (0)
  234.  
  235. /*
  236. * macro used to write an array of two-byte values to two consecutive ports
  237. */
  238. #define REP_OUTSW(port,source,count) \
  239. do { \
  240. asm volatile (" \
  241. 1: movw 0(%1),%%ax ;\
  242. outw %%ax,(%w2) ;\
  243. addl $2,%1 ;\
  244. decl %0 ;\
  245. jne 1b \
  246. " : /* no outputs */ \
  247. : "c" ((count)), "S" ((source)), "d" ((port)) \
  248. : "eax", "memory", "cc"); \
  249. } while (0)
  250.  
  251. /*
  252. * macro used to write an array of one-byte values to two consecutive ports
  253. */
  254. #define REP_OUTSB(port,source,count) \
  255. do { \
  256. asm volatile (" \
  257. 1: movb 0(%1),%%al ;\
  258. outb %%al,(%w2) ;\
  259. incl %1 ;\
  260. decl %0 ;\
  261. jne 1b \
  262. " : /* no outputs */ \
  263. : "c" ((count)), "S" ((source)), "d" ((port)) \
  264. : "eax", "memory", "cc"); \
  265. } while (0)
  266.  
  267.  
  268. /*
  269. * set_mode_X
  270. * DESCRIPTION: Puts the VGA into mode X.
  271. * INPUTS: horiz_fill_fn -- this function is used as a callback (by
  272. * draw_horiz_line) to obtain a graphical
  273. * image of a particular logical line for
  274. * drawing to the build buffer
  275. * vert_fill_fn -- this function is used as a callback (by
  276. * draw_vert_line) to obtain a graphical
  277. * image of a particular logical line for
  278. * drawing to the build buffer
  279. * OUTPUTS: none
  280. * RETURN VALUE: 0 on success, -1 on failure
  281. * SIDE EFFECTS: initializes the logical view window; maps video memory
  282. * and obtains permission for VGA ports; clears video memory
  283. */
  284. int
  285. set_mode_X (void (*horiz_fill_fn) (int, int, unsigned char[SCROLL_X_DIM]),
  286. void (*vert_fill_fn) (int, int, unsigned char[SCROLL_Y_DIM]))
  287. {
  288. int i; /* loop index for filling memory fence with magic numbers */
  289.  
  290. /*
  291. * Record callback functions for obtaining horizontal and vertical
  292. * line images.
  293. */
  294. if (horiz_fill_fn == NULL || vert_fill_fn == NULL)
  295. return -1;
  296. horiz_line_fn = horiz_fill_fn;
  297. vert_line_fn = vert_fill_fn;
  298.  
  299. /* Initialize the logical view window to position (0,0). */
  300. show_x = show_y = 0;
  301. img3_off = BUILD_BASE_INIT;
  302. img3 = build + img3_off + MEM_FENCE_WIDTH;
  303.  
  304. /* Set up the memory fence on the build buffer. */
  305. for (i = 0; i < MEM_FENCE_WIDTH; i++) {
  306. build[i] = MEM_FENCE_MAGIC;
  307. build[BUILD_BUF_SIZE + MEM_FENCE_WIDTH + i] = MEM_FENCE_MAGIC;
  308. }
  309.  
  310. /* One display page goes at the start of video memory. */
  311. target_img = 0x05A0;
  312.  
  313. /* Map video memory and obtain permission for VGA port access. */
  314. if (open_memory_and_ports () == -1)
  315. return -1;
  316.  
  317. /*
  318. * The code below was produced by recording a call to set mode 0013h
  319. * with display memory clearing and a windowed frame buffer, then
  320. * modifying the code to set mode X instead. The code was then
  321. * generalized into functions...
  322. *
  323. * modifications from mode 13h to mode X include...
  324. * Sequencer Memory Mode Register: 0x0E to 0x06 (0x3C4/0x04)
  325. * Underline Location Register : 0x40 to 0x00 (0x3D4/0x14)
  326. * CRTC Mode Control Register : 0xA3 to 0xE3 (0x3D4/0x17)
  327. */
  328.  
  329. VGA_blank (1); /* blank the screen */
  330. set_seq_regs_and_reset (mode_X_seq, 0x63); /* sequencer registers */
  331. set_CRTC_registers (mode_X_CRTC); /* CRT control registers */
  332. set_attr_registers (mode_X_attr); /* attribute registers */
  333. set_graphics_registers (mode_X_graphics); /* graphics registers */
  334. fill_palette (); /* palette colors */
  335. clear_screens (); /* zero video memory */
  336. VGA_blank (0); /* unblank the screen */
  337.  
  338. /* Return success. */
  339. return 0;
  340. }
  341.  
  342.  
  343. /*
  344. * clear_mode_X
  345. * DESCRIPTION: Puts the VGA into text mode 3 (color text).
  346. * INPUTS: none
  347. * OUTPUTS: none
  348. * RETURN VALUE: none
  349. * SIDE EFFECTS: restores font data to video memory; clears screens;
  350. * unmaps video memory; checks memory fence integrity
  351. */
  352. void
  353. clear_mode_X ()
  354. {
  355. int i; /* loop index for checking memory fence */
  356.  
  357. /* Put VGA into text mode, restore font data, and clear screens. */
  358. set_text_mode_3 (1);
  359.  
  360. /* Unmap video memory. */
  361. (void)munmap (mem_image, VID_MEM_SIZE);
  362.  
  363. /* Check validity of build buffer memory fence. Report breakage. */
  364. for (i = 0; i < MEM_FENCE_WIDTH; i++) {
  365. if (build[i] != MEM_FENCE_MAGIC) {
  366. puts ("lower build fence was broken");
  367. break;
  368. }
  369. }
  370. for (i = 0; i < MEM_FENCE_WIDTH; i++) {
  371. if (build[BUILD_BUF_SIZE + MEM_FENCE_WIDTH + i] != MEM_FENCE_MAGIC) {
  372. puts ("upper build fence was broken");
  373. break;
  374. }
  375. }
  376. }
  377.  
  378.  
  379. /*
  380. * set_view_window
  381. * DESCRIPTION: Set the logical view window, moving its location within
  382. * the build buffer if necessary to keep all on-screen data
  383. * in the build buffer. If the location within the build
  384. * buffer moves, this function copies all data from the old
  385. * window that are within the new screen to the appropriate
  386. * new location, so only data not previously on the screen
  387. * must be drawn before calling show_screen.
  388. * INPUTS: (scr_x,scr_y) -- new upper left pixel of logical view window
  389. * OUTPUTS: none
  390. * RETURN VALUE: none
  391. * SIDE EFFECTS: may shift position of logical view window within build
  392. * buffer
  393. */
  394. void
  395. set_view_window (int scr_x, int scr_y)
  396. {
  397. int old_x, old_y; /* old position of logical view window */
  398. int start_x, start_y; /* starting position for copying from old to new */
  399. int end_x, end_y; /* ending position for copying from old to new */
  400. int start_off; /* offset of copy start relative to old build */
  401. /* buffer start position */
  402. int length; /* amount of data to be copied */
  403. int i; /* copy loop index */
  404. unsigned char* start_addr; /* starting memory address of copy */
  405. unsigned char* target_addr; /* destination memory address for copy */
  406.  
  407. /* Record the old position. */
  408. old_x = show_x;
  409. old_y = show_y;
  410.  
  411. /* Keep track of the new view window. */
  412. show_x = scr_x;
  413. show_y = scr_y;
  414.  
  415. /*
  416. * If the new view window fits within the boundaries of the build
  417. * buffer, we need move nothing around.
  418. */
  419. if (img3_off + (scr_x >> 2) + scr_y * SCROLL_X_WIDTH >= 0 &&
  420. img3_off + 3 * SCROLL_SIZE +
  421. ((scr_x + SCROLL_X_DIM - 1) >> 2) +
  422. (scr_y + SCROLL_Y_DIM - 1) * SCROLL_X_WIDTH < BUILD_BUF_SIZE)
  423. return;
  424.  
  425. /*
  426. * If the new screen does not overlap at all with the old screen, none
  427. * of the old data need to be saved, and we can simply reposition the
  428. * valid window of the build buffer in the middle of that buffer.
  429. */
  430. if (scr_x <= old_x - SCROLL_X_DIM || scr_x >= old_x + SCROLL_X_DIM ||
  431. scr_y <= old_y - SCROLL_Y_DIM || scr_y >= old_y + SCROLL_Y_DIM) {
  432. img3_off = BUILD_BASE_INIT - (scr_x >> 2) - scr_y * SCROLL_X_WIDTH;
  433. img3 = build + img3_off + MEM_FENCE_WIDTH;
  434. return;
  435. }
  436.  
  437. /*
  438. * Any still-visible portion of the old screen should be retained.
  439. * Rather than clipping exactly, we copy all contiguous data between
  440. * a clipped starting point to a clipped ending point (which may
  441. * include non-visible data).
  442. *
  443. * The starting point is the maximum (x,y) coordinates between the
  444. * new and old screens. The ending point is the minimum (x,y)
  445. * coordinates between the old and new screens (offset by the screen
  446. * size).
  447. */
  448. if (scr_x > old_x) {
  449. start_x = scr_x;
  450. end_x = old_x;
  451. } else {
  452. start_x = old_x;
  453. end_x = scr_x;
  454. }
  455. end_x += SCROLL_X_DIM - 1;
  456. if (scr_y > old_y) {
  457. start_y = scr_y;
  458. end_y = old_y;
  459. } else {
  460. start_y = old_y;
  461. end_y = scr_y;
  462. }
  463. end_y += SCROLL_Y_DIM - 1;
  464.  
  465. /*
  466. * We now calculate the starting and ending addresses for the copy
  467. * as well as the new offsets for use with the build buffer. The
  468. * length to be copied is basically the ending offset minus the starting
  469. * offset plus one (plus the three screens in between planes 3 and 0).
  470. */
  471. start_off = (start_x >> 2) + start_y * SCROLL_X_WIDTH;
  472. start_addr = img3 + start_off;
  473. length = (end_x >> 2) + end_y * SCROLL_X_WIDTH + 1 - start_off +
  474. 3 * SCROLL_SIZE;
  475. img3_off = BUILD_BASE_INIT - (show_x >> 2) - show_y * SCROLL_X_WIDTH;
  476. img3 = build + img3_off + MEM_FENCE_WIDTH;
  477. target_addr = img3 + start_off;
  478.  
  479. /*
  480. * Copy the relevant portion of the screen from the old location to the
  481. * new one. The areas may overlap, so copy direction is important.
  482. * (You should be able to explain why!)
  483. */
  484. if (start_addr < target_addr)
  485. for (i = length; i-- > 0; )
  486. target_addr[i] = start_addr[i];
  487. else
  488. for (i = 0; i < length; i++)
  489. target_addr[i] = start_addr[i];
  490. }
  491.  
  492.  
  493. /*
  494. * show_screen
  495. * DESCRIPTION: Show the logical view window on the video display.
  496. * INPUTS: none
  497. * OUTPUTS: none
  498. * RETURN VALUE: none
  499. * SIDE EFFECTS: copies from the build buffer to video memory;
  500. * shifts the VGA display source to point to the new image
  501. */
  502. void
  503. show_screen ()
  504. {
  505. unsigned char* addr; /* source address for copy */
  506. int p_off; /* plane offset of first display plane */
  507. int i; /* loop index over video planes */
  508.  
  509. /*
  510. * Calculate offset of build buffer plane to be mapped into plane 0
  511. * of display.
  512. */
  513. p_off = (3 - (show_x & 3));
  514.  
  515. /* Switch to the other target screen in video memory. */
  516. target_img ^= 0x4000;
  517.  
  518. /* Calculate the source address. */
  519. addr = img3 + (show_x >> 2) + show_y * SCROLL_X_WIDTH;
  520.  
  521.  
  522. /* Draw to each plane in the video memory. */
  523. for (i = 0; i < 4; i++) {
  524. SET_WRITE_MASK (1 << (i + 8));
  525. copy_image (addr + ((p_off - i + 4) & 3) * SCROLL_SIZE + (p_off < i),
  526. target_img);
  527. }
  528.  
  529.  
  530.  
  531. /*
  532. * Change the VGA registers to point the top left of the screen
  533. * to the video memory that we just filled.
  534. */
  535. OUTW (0x03D4, (target_img & 0xFF00) | 0x0C);
  536. OUTW (0x03D4, ((target_img & 0x00FF) << 8) | 0x0D);
  537. }
  538.  
  539. void
  540. show_status(int color, int level, int fruit, int time){
  541. //unsigned char* addr; /* source address for copy */
  542. //int p_off; /* plane offset of first display plane */
  543.  
  544. /* Calculate the source address. */
  545.  
  546. //int minute
  547. build_buffer(color);
  548. char c[100];
  549.  
  550. int second,high_sec,low_sec;
  551. int minute,high_min,low_min;
  552.  
  553. minute = time / 60;
  554. high_min=minute/10;
  555. low_min=minute%10;
  556. minute = time % 60;
  557. high_sec=minute/10;
  558. low_sec=minute%10;
  559.  
  560. if(fruit >= 2){
  561. sprintf(c, "Level: %d %d Fruits %d%d:%d%d",level,fruit,high_min,low_min,high_sec,low_sec);
  562. }
  563. else{
  564. sprintf(c, "Level: %d %d Fruit %d%d:%d%d",level,fruit,high_min,low_min,high_sec,low_sec);
  565.  
  566. }
  567.  
  568. // *c = 'level';
  569. textGraphic(c);//,buf[4][1440]);
  570. /* Draw to each plane in the video memory. */
  571. int i;
  572. for (i = 0; i < 4; i++) {
  573. SET_WRITE_MASK (1 << (i + 8));
  574.  
  575. copy_status(&buf[i][0],0x000);
  576. }
  577.  
  578. }
  579.  
  580. void
  581. build_buffer(int color){
  582. int i;
  583. int j;
  584.  
  585. int c = rand() % 30; //Generate a random color
  586.  
  587. for(i = 0; i < 4; i++){
  588. for(j = 0; j < 1440; j++){
  589. buf[i][j] = c;
  590. }
  591. }
  592.  
  593.  
  594.  
  595.  
  596.  
  597. }
  598.  
  599. /*
  600. * clear_screens
  601. * DESCRIPTION: Fills the video memory with zeroes.
  602. * INPUTS: none
  603. * OUTPUTS: none
  604. * RETURN VALUE: none
  605. * SIDE EFFECTS: fills all 256kB of VGA video memory with zeroes
  606. */
  607. void
  608. clear_screens ()
  609. {
  610. /* Write to all four planes at once. */
  611. SET_WRITE_MASK (0x0F00);
  612.  
  613. /* Set 64kB to zero (times four planes = 256kB). */
  614. memset (mem_image, 0, MODE_X_MEM_SIZE);
  615. }
  616.  
  617.  
  618. /*
  619. * draw_full_block
  620. * DESCRIPTION: Draw a BLOCK_X_DIM x BLOCK_Y_DIM block at absolute
  621. * coordinates. Mask any portion of the block not inside
  622. * the logical view window.
  623. * INPUTS: (pos_x,pos_y) -- coordinates of upper left corner of block
  624. * blk -- image data for block (one byte per pixel, as a C array
  625. * of dimensions [BLOCK_Y_DIM][BLOCK_X_DIM])
  626. * OUTPUTS: none
  627. * RETURN VALUE: none
  628. * SIDE EFFECTS: draws into the build buffer
  629. */
  630. void
  631. draw_full_block (int pos_x, int pos_y, unsigned char* blk)
  632. {
  633. int dx, dy; /* loop indices for x and y traversal of block */
  634. int x_left, x_right; /* clipping limits in horizontal dimension */
  635. int y_top, y_bottom; /* clipping limits in vertical dimension */
  636.  
  637. /* If block is completely off-screen, we do nothing. */
  638. if (pos_x + BLOCK_X_DIM <= show_x || pos_x >= show_x + SCROLL_X_DIM ||
  639. pos_y + BLOCK_Y_DIM <= show_y || pos_y >= show_y + SCROLL_Y_DIM)
  640. return;
  641.  
  642. /* Clip any pixels falling off the left side of screen. */
  643. if ((x_left = show_x - pos_x) < 0)
  644. x_left = 0;
  645. /* Clip any pixels falling off the right side of screen. */
  646. if ((x_right = show_x + SCROLL_X_DIM - pos_x) > BLOCK_X_DIM)
  647. x_right = BLOCK_X_DIM;
  648. /* Skip the first x_left pixels in both screen position and block data. */
  649. pos_x += x_left;
  650. blk += x_left;
  651. /*
  652. * Adjust x_right to hold the number of pixels to be drawn, and x_left
  653. * to hold the amount to skip between rows in the block, which is the
  654. * sum of the original left clip and (BLOCK_X_DIM - the original right
  655. * clip).
  656. */
  657. x_right -= x_left;
  658. x_left = BLOCK_X_DIM - x_right;
  659.  
  660. /* Clip any pixels falling off the top of the screen. */
  661. if ((y_top = show_y - pos_y) < 0)
  662. y_top = 0;
  663. /* Clip any pixels falling off the bottom of the screen. */
  664. if ((y_bottom = show_y + SCROLL_Y_DIM - pos_y) > BLOCK_Y_DIM)
  665. y_bottom = BLOCK_Y_DIM;
  666. /*
  667. * Skip the first y_left pixel in screen position and the first
  668. * y_left rows of pixels in the block data.
  669. */
  670. pos_y += y_top;
  671. blk += y_top * BLOCK_X_DIM;
  672. /* Adjust y_bottom to hold the number of pixel rows to be drawn. */
  673. y_bottom -= y_top;
  674.  
  675. /* Draw the clipped image. */
  676. for (dy = 0; dy < y_bottom; dy++, pos_y++) {
  677. for (dx = 0; dx < x_right; dx++, pos_x++, blk++)
  678. *(img3 + (pos_x >> 2) + pos_y * SCROLL_X_WIDTH +
  679. (3 - (pos_x & 3)) * SCROLL_SIZE) = *blk;
  680. pos_x -= x_right;
  681. blk += x_left;
  682. }
  683. }
  684.  
  685. /*void
  686. background_shit(unsigned char * back_shit){
  687. int x;
  688. int y;
  689.  
  690. /**Draw the block background*/
  691. /*for(x = 0; x < BLOCK_X_DIM; x++){
  692. for(y = 0; y < BLOCK_Y_DIM; y++){
  693. *(img3 + (pos_x >> 2) + pos_y * SCROLL_X_WIDTH +
  694. (3 - (pos_x & 3)) * SCROLL_SIZE);
  695. }
  696. }
  697. }*/
  698.  
  699.  
  700. void
  701. combine_bit_block (int pos_x, int pos_y, unsigned char* player_blk, unsigned * player_mask)
  702. {
  703. int dx, dy; /* loop indices for x and y traversal of block */
  704. int x_left, x_right; /* clipping limits in horizontal dimension */
  705. int y_top, y_bottom; /* clipping limits in vertical dimension */
  706.  
  707. /* If block is completely off-screen, we do nothing. */
  708. if (pos_x + BLOCK_X_DIM <= show_x || pos_x >= show_x + SCROLL_X_DIM ||
  709. pos_y + BLOCK_Y_DIM <= show_y || pos_y >= show_y + SCROLL_Y_DIM)
  710. return;
  711.  
  712. /* Clip any pixels falling off the left side of screen. */
  713. if ((x_left = show_x - pos_x) < 0)
  714. x_left = 0;
  715. /* Clip any pixels falling off the right side of screen. */
  716. if ((x_right = show_x + SCROLL_X_DIM - pos_x) > BLOCK_X_DIM)
  717. x_right = BLOCK_X_DIM;
  718. /* Skip the first x_left pixels in both screen position and block data. */
  719. pos_x += x_left;
  720. player_blk += x_left;
  721. player_mask+= x_left;
  722. /*
  723. * Adjust x_right to hold the number of pixels to be drawn, and x_left
  724. * to hold the amount to skip between rows in the block, which is the
  725. * sum of the original left clip and (BLOCK_X_DIM - the original right
  726. * clip).
  727. */
  728. x_right -= x_left;
  729. x_left = BLOCK_X_DIM - x_right;
  730.  
  731. /* Clip any pixels falling off the top of the screen. */
  732. if ((y_top = show_y - pos_y) < 0)
  733. y_top = 0;
  734. /* Clip any pixels falling off the bottom of the screen. */
  735. if ((y_bottom = show_y + SCROLL_Y_DIM - pos_y) > BLOCK_Y_DIM)
  736. y_bottom = BLOCK_Y_DIM;
  737.  
  738.  
  739. /* Skip the first y_left pixel in screen position and the first
  740. * y_left rows of pixels in the block data.
  741. */
  742. pos_y += y_top;
  743. player_blk += y_top * BLOCK_X_DIM;
  744. player_mask+= y_top;
  745. /* Adjust y_bottom to hold the number of pixel rows to be drawn. */
  746. y_bottom -= y_top;
  747. //unmasking(player_blk, player_mask);
  748.  
  749. /* Draw the clipped image. */
  750. for (dy = 0; dy < y_bottom; dy++, pos_y++) {
  751. for (dx = 0; dx < x_right; dx++, pos_x++, player_blk++, player_mask++)
  752. if(*player_mask == 1){
  753. *player_mask = *player_blk;
  754. }
  755. else{
  756. *player_blk = *(img3 + (pos_x >> 2) + pos_y * SCROLL_X_WIDTH +
  757. (3 - (pos_x & 3)) * SCROLL_SIZE);
  758. }
  759.  
  760.  
  761.  
  762. pos_x -= x_right;
  763. player_mask += x_left;
  764. player_blk += x_left;
  765. }
  766. }
  767.  
  768. void unmasking( unsigned char * player_blk, unsigned char * player_mask, unsigned char * new_player, unsigned char * back){
  769.  
  770. /*row = x, column = y */
  771. int row,column;
  772.  
  773. for(row = 0; row < BLOCK_Y_DIM; row++){
  774. for(column = 0; column < BLOCK_X_DIM; column++){
  775. back[row * (BLOCK_X_DIM) + column] = *(img3 + show_x + show_y * 320 + column + (row * 320));
  776. //*((img3 + show_x + show_y*(320)) + row + 320 * column);
  777. }
  778. }
  779.  
  780.  
  781.  
  782.  
  783.  
  784. for(row = 0; row < BLOCK_Y_DIM; row++){
  785. for(column = 0; column < BLOCK_X_DIM; column++){
  786. if(player_mask[row * BLOCK_X_DIM + column] == 1){
  787. new_player[row*BLOCK_X_DIM + column] = player_blk[row*BLOCK_X_DIM + column];
  788. }
  789. else{
  790. new_player[row*BLOCK_X_DIM + column] = player_blk[row * BLOCK_X_DIM + column];
  791. }
  792. }
  793. }
  794.  
  795. }
  796.  
  797.  
  798. /*
  799. * The functions inside the preprocessor block below rely on functions
  800. * in maze.c to generate graphical images of the maze. These functions
  801. * are neither available nor necessary for the text restoration program
  802. * based on this file, and are omitted to simplify linking that program.
  803. */
  804. #if !defined(TEXT_RESTORE_PROGRAM)
  805.  
  806.  
  807. /*
  808. * draw_vert_line
  809. * DESCRIPTION: Draw a vertical map line into the build buffer. The
  810. * line should be offset from the left side of the logical
  811. * view window screen by the given number of pixels.
  812. * INPUTS: x -- the 0-based pixel column number of the line to be drawn
  813. * within the logical view window (equivalent to the number
  814. * of pixels from the leftmost pixel to the line to be
  815. * drawn)
  816. * OUTPUTS: none
  817. * RETURN VALUE: Returns 0 on success. If x is outside of the valid
  818. * SCROLL range, the function returns -1.
  819. * SIDE EFFECTS: draws into the build buffer
  820. */
  821. int
  822. draw_vert_line (int x)
  823. {
  824. /* Return success. */
  825. /* to be written... */
  826. unsigned char buf[SCROLL_Y_DIM]; /*buffer for grapihcal image of line*/
  827. unsigned char* addr; /*address of the first pixel in build*/
  828.  
  829. int p_off; /*offset of plane of first pixel*/
  830. int i;
  831.  
  832. if(x < 0 || x >= SCROLL_X_DIM){
  833. return -1;
  834. }
  835.  
  836. x += show_x;
  837.  
  838. /*Get the image of the vertical line*/
  839. (*vert_line_fn)(x,show_y,buf);
  840.  
  841. addr = img3 + (x >> 2) + show_y * SCROLL_X_WIDTH;
  842.  
  843. /*Calculate the plane offset of first pixel*/
  844. p_off = (3 - (x & 3));
  845.  
  846. for(i = 0; i < SCROLL_Y_DIM; i++){
  847. addr[p_off * SCROLL_SIZE] = buf[i];
  848. addr += 80;
  849. }
  850. return 0;
  851.  
  852. }
  853.  
  854.  
  855. /*
  856. * draw_horiz_line
  857. * DESCRIPTION: Draw a horizontal map line into the build buffer. The
  858. * line should be offset from the top of the logical view
  859. * window screen by the given number of pixels.
  860. * INPUTS: y -- the 0-based pixel row number of the line to be drawn
  861. * within the logical view window (equivalent to the number
  862. * of pixels from the top pixel to the line to be drawn)
  863. * OUTPUTS: none
  864. * RETURN VALUE: Returns 0 on success. If y is outside of the valid
  865. * SCROLL range, the function returns -1.
  866. * SIDE EFFECTS: draws into the build buffer
  867. */
  868. int
  869. draw_horiz_line (int y)
  870. {
  871. unsigned char buf[SCROLL_X_DIM]; /* buffer for graphical image of line */
  872. unsigned char* addr; /* address of first pixel in build */
  873. /* buffer (without plane offset) */
  874. int p_off; /* offset of plane of first pixel */
  875. int i; /* loop index over pixels */
  876.  
  877. /* Check whether requested line falls in the logical view window. */
  878. if (y < 0 || y >= SCROLL_Y_DIM)
  879. return -1;
  880.  
  881. /* Adjust y to the logical row value. */
  882. y += show_y;
  883.  
  884. /* Get the image of the line. */
  885. (*horiz_line_fn) (show_x, y, buf);
  886.  
  887. /* Calculate starting address in build buffer. */
  888. addr = img3 + (show_x >> 2) + y * SCROLL_X_WIDTH;
  889.  
  890. /* Calculate plane offset of first pixel. */
  891. p_off = (3 - (show_x & 3));
  892.  
  893. /* Copy image data into appropriate planes in build buffer. */
  894. for (i = 0; i < SCROLL_X_DIM; i++) {
  895. addr[p_off * SCROLL_SIZE] = buf[i];
  896. if (--p_off < 0) {
  897. p_off = 3;
  898. addr++;
  899. }
  900. }
  901.  
  902. /* Return success. */
  903. return 0;
  904. }
  905.  
  906. #endif /* !defined(TEXT_RESTORE_PROGRAM) */
  907.  
  908.  
  909. /*
  910. * open_memory_and_ports
  911. * DESCRIPTION: Map video memory into our address space; obtain permission
  912. * to access VGA ports.
  913. * INPUTS: none
  914. * OUTPUTS: none
  915. * RETURN VALUE: 0 on success, -1 on failure
  916. * SIDE EFFECTS: prints an error message to stdout on failure
  917. */
  918. static int
  919. open_memory_and_ports ()
  920. {
  921. int mem_fd; /* file descriptor for physical memory image */
  922.  
  923. /* Obtain permission to access ports 0x03C0 through 0x03DA. */
  924. if (ioperm (0x03C0, 0x03DA - 0x03C0 + 1, 1) == -1) {
  925. perror ("set port permissions");
  926. return -1;
  927. }
  928.  
  929. /* Open file to access physical memory. */
  930. if ((mem_fd = open ("/dev/mem", O_RDWR)) == -1) {
  931. perror ("open /dev/mem");
  932. return -1;
  933. }
  934.  
  935. /* Map video memory (0xA0000 - 0xBFFFF) into our address space. */
  936. if ((mem_image = mmap (0, VID_MEM_SIZE, PROT_READ | PROT_WRITE,
  937. MAP_SHARED, mem_fd, 0xA0000)) == MAP_FAILED) {
  938. perror ("mmap video memory");
  939. return -1;
  940. }
  941.  
  942. /* Close /dev/mem file descriptor and return success. */
  943. (void)close (mem_fd);
  944. return 0;
  945. }
  946.  
  947.  
  948. /*
  949. * VGA_blank
  950. * DESCRIPTION: Blank or unblank the VGA display.
  951. * INPUTS: blank_bit -- set to 1 to blank, 0 to unblank
  952. * OUTPUTS: none
  953. * RETURN VALUE: none
  954. * SIDE EFFECTS: none
  955. */
  956. static void
  957. VGA_blank (int blank_bit)
  958. {
  959. /*
  960. * Move blanking bit into position for VGA sequencer register
  961. * (index 1).
  962. */
  963. blank_bit = ((blank_bit & 1) << 5);
  964.  
  965. asm volatile (
  966. "movb $0x01,%%al /* Set sequencer index to 1. */ ;"
  967. "movw $0x03C4,%%dx ;"
  968. "outb %%al,(%%dx) ;"
  969. "incw %%dx ;"
  970. "inb (%%dx),%%al /* Read old value. */ ;"
  971. "andb $0xDF,%%al /* Calculate new value. */ ;"
  972. "orl %0,%%eax ;"
  973. "outb %%al,(%%dx) /* Write new value. */ ;"
  974. "movw $0x03DA,%%dx /* Enable display (0x20->P[0x3C0]) */ ;"
  975. "inb (%%dx),%%al /* Set attr reg state to index. */ ;"
  976. "movw $0x03C0,%%dx /* Write index 0x20 to enable. */ ;"
  977. "movb $0x20,%%al ;"
  978. "outb %%al,(%%dx) "
  979. : : "g" (blank_bit) : "eax", "edx", "memory");
  980. }
  981.  
  982.  
  983. /*
  984. * set_seq_regs_and_reset
  985. * DESCRIPTION: Set VGA sequencer registers and miscellaneous output
  986. * register; array of registers should force a reset of
  987. * the VGA sequencer, which is restored to normal operation
  988. * after a brief delay.
  989. * INPUTS: table -- table of sequencer register values to use
  990. * val -- value to which miscellaneous output register should be set
  991. * OUTPUTS: none
  992. * RETURN VALUE: none
  993. * SIDE EFFECTS: none
  994. */
  995. static void
  996. set_seq_regs_and_reset (unsigned short table[NUM_SEQUENCER_REGS],
  997. unsigned char val)
  998. {
  999. /*
  1000. * Dump table of values to sequencer registers. Includes forced reset
  1001. * as well as video blanking.
  1002. */
  1003. REP_OUTSW (0x03C4, table, NUM_SEQUENCER_REGS);
  1004.  
  1005. /* Delay a bit... */
  1006. {volatile int ii; for (ii = 0; ii < 10000; ii++);}
  1007.  
  1008. /* Set VGA miscellaneous output register. */
  1009. OUTB (0x03C2, val);
  1010.  
  1011. /* Turn sequencer on (array values above should always force reset). */
  1012. OUTW (0x03C4,0x0300);
  1013. }
  1014.  
  1015.  
  1016. /*
  1017. * set_CRTC_registers
  1018. * DESCRIPTION: Set VGA cathode ray tube controller (CRTC) registers.
  1019. * INPUTS: table -- table of CRTC register values to use
  1020. * OUTPUTS: none
  1021. * RETURN VALUE: none
  1022. * SIDE EFFECTS: none
  1023. */
  1024. static void
  1025. set_CRTC_registers (unsigned short table[NUM_CRTC_REGS])
  1026. {
  1027. /* clear protection bit to enable write access to first few registers */
  1028. OUTW (0x03D4, 0x0011);
  1029. REP_OUTSW (0x03D4, table, NUM_CRTC_REGS);
  1030. }
  1031.  
  1032.  
  1033. /*
  1034. * set_attr_registers
  1035. * DESCRIPTION: Set VGA attribute registers. Attribute registers use
  1036. * a single port and are thus written as a sequence of bytes
  1037. * rather than a sequence of words.
  1038. * INPUTS: table -- table of attribute register values to use
  1039. * OUTPUTS: none
  1040. * RETURN VALUE: none
  1041. * SIDE EFFECTS: none
  1042. */
  1043. static void
  1044. set_attr_registers (unsigned char table[NUM_ATTR_REGS * 2])
  1045. {
  1046. /* Reset attribute register to write index next rather than data. */
  1047. asm volatile (
  1048. "inb (%%dx),%%al"
  1049. : : "d" (0x03DA) : "eax", "memory");
  1050. REP_OUTSB (0x03C0, table, NUM_ATTR_REGS * 2);
  1051. }
  1052.  
  1053.  
  1054. /*
  1055. * set_graphics_registers
  1056. * DESCRIPTION: Set VGA graphics registers.
  1057. * INPUTS: table -- table of graphics register values to use
  1058. * OUTPUTS: none
  1059. * RETURN VALUE: none
  1060. * SIDE EFFECTS: none
  1061. */
  1062. static void
  1063. set_graphics_registers (unsigned short table[NUM_GRAPHICS_REGS])
  1064. {
  1065. REP_OUTSW (0x03CE, table, NUM_GRAPHICS_REGS);
  1066. }
  1067.  
  1068.  
  1069. /*
  1070. * fill_palette
  1071. * DESCRIPTION: Fill VGA palette with necessary colors for the maze game.
  1072. * Only the first 64 (of 256) colors are written.
  1073. * INPUTS: none
  1074. * OUTPUTS: none
  1075. * RETURN VALUE: none
  1076. * SIDE EFFECTS: changes the first 64 palette colors
  1077. */
  1078. static void
  1079. fill_palette ()
  1080. {
  1081. /* 6-bit RGB (red, green, blue) values for first 64 colors */
  1082. static unsigned char palette_RGB[64][3] = {
  1083. {0x00, 0x00, 0x00}, {0x00, 0x00, 0x2A}, /* palette 0x00 - 0x0F */
  1084. {0x00, 0x2A, 0x00}, {0x00, 0x2A, 0x2A}, /* basic VGA colors */
  1085. {0x2A, 0x00, 0x00}, {0x2A, 0x00, 0x2A},
  1086. {0x2A, 0x15, 0x00}, {0x2A, 0x2A, 0x2A},
  1087. {0x15, 0x15, 0x15}, {0x15, 0x15, 0x3F},
  1088. {0x15, 0x3F, 0x15}, {0x15, 0x3F, 0x3F},
  1089. {0x3F, 0x15, 0x15}, {0x3F, 0x15, 0x3F},
  1090. {0x3F, 0x3F, 0x15}, {0x3F, 0x3F, 0x3F},
  1091. {0x00, 0x00, 0x00}, {0x05, 0x05, 0x05}, /* palette 0x10 - 0x1F */
  1092. {0x08, 0x08, 0x08}, {0x0B, 0x0B, 0x0B}, /* VGA grey scale */
  1093. {0x0E, 0x0E, 0x0E}, {0x11, 0x11, 0x11},
  1094. {0x14, 0x14, 0x14}, {0x18, 0x18, 0x18},
  1095. {0x1C, 0x1C, 0x1C}, {0x20, 0x20, 0x20},
  1096. {0x24, 0x24, 0x24}, {0x28, 0x28, 0x28},
  1097. {0x2D, 0x2D, 0x2D}, {0x32, 0x32, 0x32},
  1098. {0x38, 0x38, 0x38}, {0x3F, 0x3F, 0x3F},
  1099. {0x3F, 0x3F, 0x3F}, {0x3F, 0x3F, 0x3F}, /* palette 0x20 - 0x2F */
  1100. {0x00, 0x00, 0x3F}, {0x00, 0x00, 0x00}, /* wa ll and player colors */
  1101. {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00},
  1102. {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00},
  1103. {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00},
  1104. {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00},
  1105. {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00},
  1106. {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00},
  1107. {0x10, 0x08, 0x00}, {0x18, 0x0C, 0x00}, /* palette 0x30 - 0x3F */
  1108. {0x20, 0x10, 0x00}, {0x28, 0x14, 0x00}, /* browns for maze floor */
  1109. {0x30, 0x18, 0x00}, {0x38, 0x1C, 0x00},
  1110. {0x3F, 0x20, 0x00}, {0x3F, 0x20, 0x10},
  1111. {0x20, 0x18, 0x10}, {0x28, 0x1C, 0x10},
  1112. {0x3F, 0x20, 0x10}, {0x38, 0x24, 0x10},
  1113. {0x3F, 0x28, 0x10}, {0x3F, 0x2C, 0x10},
  1114. {0x3F, 0x30, 0x10}, {0x3F, 0x20, 0x10}
  1115. };
  1116.  
  1117. /* Start writing at color 0. */
  1118. OUTB (0x03C8, 0x00);
  1119.  
  1120. /* Write all 64 colors from array. */
  1121. REP_OUTSB (0x03C9, palette_RGB, 64 * 3);
  1122. }
  1123.  
  1124.  
  1125. /*
  1126. * write_font_data
  1127. * DESCRIPTION: Copy font data into VGA memory, changing and restoring
  1128. * VGA register values in order to do so.
  1129. * INPUTS: none
  1130. * OUTPUTS: none
  1131. * RETURN VALUE: none
  1132. * SIDE EFFECTS: leaves VGA registers in final text mode state
  1133. */
  1134. static void
  1135. write_font_data ()
  1136. {
  1137. int i; /* loop index over characters */
  1138. int j; /* loop index over font bytes within characters */
  1139. unsigned char* fonts; /* pointer into video memory */
  1140.  
  1141. /* Prepare VGA to write font data into video memory. */
  1142. OUTW (0x3C4, 0x0402);
  1143. OUTW (0x3C4, 0x0704);
  1144. OUTW (0x3CE, 0x0005);
  1145. OUTW (0x3CE, 0x0406);
  1146. OUTW (0x3CE, 0x0204);
  1147.  
  1148. /* Copy font data from array into video memory. */
  1149. for (i = 0, fonts = mem_image; i < 256; i++) {
  1150. for (j = 0; j < 16; j++)
  1151. fonts[j] = font_data[i][j];
  1152. fonts += 32; /* skip 16 bytes between characters */
  1153. }
  1154.  
  1155. /* Prepare VGA for text mode. */
  1156. OUTW (0x3C4, 0x0302);
  1157. OUTW (0x3C4, 0x0304);
  1158. OUTW (0x3CE, 0x1005);
  1159. OUTW (0x3CE, 0x0E06);
  1160. OUTW (0x3CE, 0x0004);
  1161. }
  1162.  
  1163.  
  1164. /*
  1165. * set_text_mode_3
  1166. * DESCRIPTION: Put VGA into text mode 3 (color text).
  1167. * INPUTS: clear_scr -- if non-zero, clear screens; otherwise, do not
  1168. * OUTPUTS: none
  1169. * RETURN VALUE: none
  1170. * SIDE EFFECTS: may clear screens; writes font data to video memory
  1171. */
  1172. static void
  1173. set_text_mode_3 (int clear_scr)
  1174. {
  1175. unsigned long* txt_scr; /* pointer to text screens in video memory */
  1176. int i; /* loop over text screen words */
  1177.  
  1178. VGA_blank (1); /* blank the screen */
  1179. /*
  1180. * The value here had been changed to 0x63, but seems to work
  1181. * fine in QEMU (and VirtualPC, where I got it) with the 0x04
  1182. * bit set (VGA_MIS_DCLK_28322_720).
  1183. */
  1184. set_seq_regs_and_reset (text_seq, 0x67); /* sequencer registers */
  1185. set_CRTC_registers (text_CRTC); /* CRT control registers */
  1186. set_attr_registers (text_attr); /* attribute registers */
  1187. set_graphics_registers (text_graphics); /* graphics registers */
  1188. fill_palette (); /* palette colors */
  1189. if (clear_scr) { /* clear screens if needed */
  1190. txt_scr = (unsigned long*)(mem_image + 0x18000);
  1191. for (i = 0; i < 8192; i++)
  1192. *txt_scr++ = 0x07200720;
  1193. }
  1194. write_font_data (); /* copy fonts to video mem */
  1195. VGA_blank (0); /* unblank the screen */
  1196. }
  1197.  
  1198.  
  1199. /*
  1200. * copy_image
  1201. * DESCRIPTION: Copy one plane of a screen from the build buffer to the
  1202. * video memory.
  1203. * INPUTS: img -- a pointer to a single screen plane in the build buffer
  1204. * scr_addr -- the destination offset in video memory
  1205. * OUTPUTS: none
  1206. * RETURN VALUE: none
  1207. * SIDE EFFECTS: copies a plane from the build buffer to video memory
  1208. */
  1209. static void
  1210. copy_image (unsigned char* img, unsigned short scr_addr)
  1211. {
  1212. /*
  1213. * memcpy is actually probably good enough here, and is usually
  1214. * implemented using ISA-specific features like those below,
  1215. * but the code here provides an example of x86 string moves
  1216. */
  1217. asm volatile (
  1218. "cld ;"
  1219. "movl $16000,%%ecx ;"
  1220. "rep movsb # copy ECX bytes from M[ESI] to M[EDI] "
  1221. : /* no outputs */
  1222. : "S" (img), "D" (mem_image + scr_addr)
  1223. : "eax", "ecx", "memory"
  1224. );
  1225. }
  1226.  
  1227. /*
  1228. * copy_image
  1229. * DESCRIPTION: Copy one plane of a screen from the build buffer to the
  1230. * video memory.
  1231. * INPUTS: img -- a pointer to a single screen plane in the build buffer
  1232. * scr_addr -- the destination offset in video memory
  1233. * OUTPUTS: none
  1234. * RETURN VALUE: none
  1235. * SIDE EFFECTS: copies a plane from the build buffer to video memory
  1236. */
  1237. static void
  1238. copy_status (unsigned char* img, unsigned short scr_addr)
  1239. {
  1240. /*
  1241. * memcpy is actually probably good enough here, and is usually
  1242. * implemented using ISA-specific features like those below,
  1243. * but the code here provides an example of x86 string moves
  1244. */
  1245. asm volatile (
  1246. "cld ;"
  1247. "movl $1440,%%ecx ;"
  1248. "rep movsb # copy ECX bytes from M[ESI] to M[EDI] "
  1249. : /* no outputs */
  1250. : "S" (img), "D" (mem_image + scr_addr)
  1251. : "eax", "ecx", "memory"
  1252. );
  1253. }
  1254.  
  1255. #if defined(TEXT_RESTORE_PROGRAM)
  1256.  
  1257. /*
  1258. * main -- for the "tr" program
  1259. * DESCRIPTION: Put the VGA into text mode 3 without clearing the screens,
  1260. * which serves as a useful debugging tool when trying to
  1261. * debug programs that rely on having the VGA in mode X for
  1262. * normal operation. Writes font data to video memory.
  1263. * INPUTS: none (command line arguments are ignored)
  1264. * OUTPUTS: none
  1265. * RETURN VALUE: 0 on success, 3 in panic scenarios
  1266. */
  1267. int
  1268. main ()
  1269. {
  1270. /* Map video memory and obtain permission for VGA port access. */
  1271. if (open_memory_and_ports () == -1)
  1272. return 3;
  1273.  
  1274. /* Put VGA into text mode without clearing the screen. */
  1275. set_text_mode_3 (0);
  1276.  
  1277. /* Unmap video memory. */
  1278. (void)munmap (mem_image, VID_MEM_SIZE);
  1279.  
  1280. /* Return success. */
  1281. return 0;
  1282. }
  1283.  
  1284. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement