00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <p24FJ64GA002.h>
00021
00022 #include "types.h"
00023 #include "table.h"
00024
00025 #include "librtc.h"
00026 #include "libfontx2.h"
00027 #include "libvideo.h"
00028
00029
00030
00031
00032
00033 #define abs(a) (((a)>0) ? (a) : -(a))
00034
00035
00036 #define NTSC_SYNC LATBbits.LATB12
00037 #define NTSC_VIDEO LATBbits.LATB13
00038
00039
00040 #define NTSC_LINE 263
00041 #define NTSC_LINE_SYNC 13
00042 #define NTSC_LINE_SPACE_TOP 29
00043
00044
00045 #define NTSC_DEFAULT_FCY cpu_fcy[0]
00046 #define NTSC_HORIZON_PULSE 1015
00047 #define NTSC_SERRATION_PULSE 936
00048 #define NTSC_EQUALIZING_PULSE 70
00049 #define NTSC_LEFT_SPACE 220
00050 #define NTSC_VIDEO_WIDTH 256
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062 static unsigned int __attribute__((far)) video_memory[ NTSC_VRAM_SIZE / 2 ];
00063
00064
00065 NTSC_T ntsc = {
00066 video_memory,
00067 0,
00068
00069 {
00070 video_memory,
00071 NTSC_LINE,
00072 NTSC_LINE_SYNC,
00073 NTSC_LINE_SYNC + NTSC_LINE_SPACE_TOP,
00074 NTSC_LINE_SYNC + NTSC_LINE_SPACE_TOP + NTSC_HEIGHT,
00075 NTSC_HORIZON_PULSE,
00076 NTSC_SERRATION_PULSE,
00077 NTSC_EQUALIZING_PULSE,
00078 NTSC_LEFT_SPACE,
00079 NTSC_WIDTH,
00080 0x0000,
00081 0x0000,
00082 0x0000,
00083 },
00084
00085 {
00086 video_memory,
00087 NTSC_LINE,
00088 NTSC_LINE_SYNC,
00089 NTSC_LINE_SYNC + NTSC_LINE_SPACE_TOP + 10,
00090 NTSC_LINE_SYNC + NTSC_LINE_SPACE_TOP + 10 + NTSC_HEIGHT,
00091 NTSC_HORIZON_PULSE,
00092 NTSC_SERRATION_PULSE,
00093 NTSC_EQUALIZING_PULSE,
00094 NTSC_LEFT_SPACE,
00095 NTSC_WIDTH,
00096 0x0000,
00097 0x0000,
00098 0x0000,
00099 },
00100
00101 };
00102
00103
00104 VIDEO_T video;
00105
00106
00107
00108
00109
00110 inline static void VIDEO_init_superimpose(void);
00111
00112
00113
00114
00115
00116 void VIDEO_init(void)
00117 {
00118
00119 video.cx = 0;
00120 video.cy = 0;
00121 VIDEO_vram_clear(0x0000);
00122
00123
00124
00125 VIDEO_init_clock();
00126 RPOR6bits.RP13R = 7;
00127
00128
00129 SPI1CON1 = 0b0000010000110111;
00130 SPI1CON2 = 0b0000000000000000;
00131 SPI1STAT = 0b1000000000000000;
00132 IPC2bits.SPI1IP = 7;
00133 IEC0bits.SPI1IE = 1;
00134 IFS0bits.SPI1IF = 0;
00135 IPC0bits.OC1IP = 7;
00136 IEC0bits.OC1IE = 1;
00137 IFS0bits.OC1IF = 0;
00138 IPC1bits.OC2IP = 7;
00139 IEC0bits.OC2IE = 1;
00140 IFS0bits.OC2IF = 0;
00141
00142 PR2 = ntsc.monitor.horizon_pulse;
00143 TMR2 = 0x0000;
00144 IPC1bits.T2IP = 7;
00145 IEC0bits.T2IE = 1;
00146 IFS0bits.T2IF = 0;
00147
00148
00149 T2CON = 0b1000000000000000;
00150
00151
00152 VIDEO_init_superimpose();
00153
00154 return;
00155 }
00156
00157 inline static void VIDEO_init_superimpose(void)
00158 {
00159 RPOR7bits.RP15R = 10;
00160
00161
00162 RPINR0bits.INT1R = 10;
00163 INTCON2bits.INT1EP = 1;
00164 IPC5bits.INT1IP = 6;
00165 IEC1bits.INT1IE = 1;
00166 IFS1bits.INT1IF = 0;
00167
00168
00169 RPINR1bits.INT2R = 11;
00170 INTCON2bits.INT2EP = 0;
00171 IPC7bits.INT2IP = 6;
00172 IEC1bits.INT2IE = 1;
00173 IFS1bits.INT2IF = 0;
00174
00175
00176
00177 SPI2CON1 = 0b0000010000110111;
00178 SPI2CON2 = 0b0000000000000000;
00179 SPI2STAT = 0b1000000000000000;
00180 IPC8bits.SPI2IP = 6;
00181 IEC2bits.SPI2IE = 1;
00182 IFS2bits.SPI2IF = 0;
00183
00184 IPC6bits.OC3IP = 6;
00185 IEC1bits.OC3IE = 0;
00186 IFS1bits.OC3IF = 0;
00187
00188 PR3 = 0xffff;
00189 TMR3 = 0x0000;
00190 T3CON = 0x8000;
00191 IPC2bits.T3IP = 6;
00192 IEC0bits.T3IE = 1;
00193 IFS0bits.T3IF = 0;
00194
00195 return;
00196 }
00197
00198
00199
00200
00201
00202 void VIDEO_init_clock(void)
00203 {
00204 ntsc.monitor.horizon_pulse = (double)NTSC_HORIZON_PULSE * ((double)cpu_fcy[ OSCTUN ] / (double)NTSC_DEFAULT_FCY);
00205 ntsc.monitor.serration_pulse = (double)NTSC_SERRATION_PULSE * ((double)cpu_fcy[ OSCTUN ] / (double)NTSC_DEFAULT_FCY);
00206 ntsc.monitor.equalizing_pulse = (double)NTSC_EQUALIZING_PULSE * ((double)cpu_fcy[ OSCTUN ] / (double)NTSC_DEFAULT_FCY);
00207 ntsc.monitor.left_space = (double)NTSC_LEFT_SPACE * ((double)cpu_fcy[ OSCTUN ] / (double)NTSC_DEFAULT_FCY);
00208 ntsc.monitor.video_width = (double)NTSC_VIDEO_WIDTH * ((double)cpu_fcy[ OSCTUN ] / (double)NTSC_DEFAULT_FCY);
00209
00210 if(ntsc.monitor.video_width > NTSC_WIDTH) ntsc.monitor.video_width = NTSC_WIDTH;
00211 ntsc.monitor.video_width = ntsc.monitor.video_width >> 4;
00212
00213 ntsc.superimpose.left_space = (double)108 * ((double)cpu_fcy[ OSCTUN ] / (double)NTSC_DEFAULT_FCY);
00214 ntsc.superimpose.video_width = ntsc.monitor.video_width;
00215
00216 return;
00217 }
00218
00219
00220
00221
00222
00223 void __attribute__((interrupt, no_auto_psv, shadow)) _T2Interrupt(void)
00224 {
00225 IFS0bits.T2IF = 0;
00226 NTSC_SYNC = 0;
00227 ntsc.monitor.vsync++;
00228
00229
00230 if(ntsc.monitor.vsync < ntsc.monitor.line_sync){
00231 OC1R = ntsc.monitor.serration_pulse;
00232 OC1CON = 0x0001;
00233 ntsc.output = 0;
00234
00235
00236 } else if(ntsc.monitor.vsync < ntsc.monitor.line_space_top){
00237 OC1R = ntsc.monitor.equalizing_pulse;
00238 OC1CON = 0x0001;
00239
00240
00241 } else if(ntsc.monitor.vsync < ntsc.monitor.line_video){
00242 OC1R = ntsc.monitor.equalizing_pulse;
00243 OC1CON = 0x0001;
00244 OC2R = ntsc.monitor.left_space;
00245 OC2CON = 0x0001;
00246
00247
00248 } else if(ntsc.monitor.vsync < ntsc.monitor.line - 1){
00249 OC1R = ntsc.monitor.equalizing_pulse;
00250 OC1CON = 0x0001;
00251
00252 } else {
00253 OC1R = ntsc.monitor.equalizing_pulse;
00254 OC1CON = 0x0001;
00255 PR2 = ntsc.monitor.horizon_pulse;
00256 ntsc.monitor.vsync = 0;
00257 ntsc.monitor.vram = ntsc.vram;
00258
00259
00260 RPOR7bits.RP15R = 0;
00261 LATBbits.LATB15 = 1;
00262 ntsc.output = 0;
00263
00264 }
00265
00266 return;
00267 }
00268
00269 void __attribute__((interrupt, no_auto_psv, shadow)) _OC1Interrupt(void)
00270 {
00271 IFS0bits.OC1IF = 0;
00272 NTSC_SYNC = 1;
00273 return;
00274 }
00275
00276
00277 void __attribute__((interrupt, no_auto_psv, shadow)) _OC2Interrupt(void)
00278 {
00279 unsigned int dummy;
00280
00281 IFS0bits.OC2IF = 0;
00282
00283 SPI1BUF = *ntsc.monitor.vram++;
00284 ntsc.monitor.hsync = 2;
00285 while(SPI1STATbits.SPITBF);
00286 dummy = SPI1BUF;
00287 SPI1BUF = *ntsc.monitor.vram++;
00288 return;
00289 }
00290
00291 void __attribute__((interrupt, no_auto_psv, shadow)) _SPI1Interrupt(void)
00292 {
00293 unsigned int dummy;
00294
00295 IFS0bits.SPI1IF = 0;
00296
00297 if(ntsc.monitor.hsync == 0){
00298 SPI1BUF = (*ntsc.monitor.vram++) & 0x7fff;
00299 ntsc.monitor.hsync++;
00300
00301 } else if(ntsc.monitor.hsync < ntsc.monitor.video_width - 1){
00302 SPI1BUF = *ntsc.monitor.vram++;
00303 ntsc.monitor.hsync++;
00304
00305 } else if(ntsc.monitor.hsync < ntsc.monitor.video_width){
00306 SPI1BUF = (*ntsc.monitor.vram++) & 0xfffe;
00307 ntsc.monitor.hsync++;
00308
00309 } else {
00310 for(;ntsc.monitor.hsync < (NTSC_WIDTH >> 4); ntsc.monitor.hsync++){
00311 ntsc.monitor.vram++;
00312 }
00313 }
00314
00315 dummy = SPI1BUF;
00316 return;
00317 }
00318
00319
00320
00321
00322
00323 void __attribute__((interrupt, auto_psv)) _INT1Interrupt(void)
00324 {
00325 unsigned int dummy;
00326
00327 IFS1bits.INT1IF = 0;
00328
00329
00330 IEC0bits.T2IE = 0;
00331
00332
00333 VIDEO_init_superimpose();
00334 ntsc.output = 1;
00335
00336 dummy = SPI2BUF;
00337 ntsc.superimpose.vram = ntsc.vram;
00338 ntsc.superimpose.vsync = 0;
00339
00340 return;
00341 }
00342
00343
00344 void __attribute__((interrupt, auto_psv)) _INT2Interrupt(void)
00345 {
00346 unsigned int dummy;
00347
00348 IFS1bits.INT2IF = 0;
00349
00350 ntsc.superimpose.vsync++;
00351
00352
00353 if(ntsc.superimpose.vsync < ntsc.superimpose.line_space_top){
00354
00355
00356
00357 } else if (ntsc.superimpose.vsync < ntsc.superimpose.line_video){
00358 TMR3 = 0x0000;
00359 OC3R = ntsc.superimpose.left_space;
00360 OC3CON = 0b0000000000001001;
00361 IEC1bits.OC3IE = 1;
00362 dummy = SPI2BUF;
00363
00364 } else {
00365 IEC1bits.INT2IE = 0;
00366 dummy = SPI2BUF;
00367 }
00368
00369 return;
00370 }
00371
00372 void __attribute__((interrupt, auto_psv)) _OC3Interrupt(void)
00373 {
00374 unsigned int dummy;
00375
00376 IFS1bits.OC3IF = 0;
00377
00378 SPI2BUF = *ntsc.superimpose.vram++;
00379 ntsc.superimpose.hsync = 2;
00380 while(SPI2STATbits.SPITBF);
00381 dummy = SPI2BUF;
00382 SPI2BUF = *ntsc.superimpose.vram++;
00383
00384 IEC1bits.OC3IE = 0;
00385 return;
00386 }
00387
00388 void __attribute__((interrupt, no_auto_psv)) _SPI2Interrupt(void)
00389 {
00390 unsigned int dummy;
00391
00392 IFS2bits.SPI2IF = 0;
00393
00394 if(ntsc.superimpose.hsync == 0){
00395 SPI2BUF = (*ntsc.superimpose.vram++) & 0x7fff;
00396 ntsc.superimpose.hsync++;
00397
00398 } else if(ntsc.superimpose.hsync < ntsc.superimpose.video_width - 1){
00399 SPI2BUF = *ntsc.superimpose.vram++;
00400 ntsc.superimpose.hsync++;
00401
00402 } else if(ntsc.superimpose.hsync < ntsc.superimpose.video_width){
00403 SPI2BUF = (*ntsc.superimpose.vram++) & 0xfffe;
00404 ntsc.superimpose.hsync++;
00405
00406 } else {
00407 for(;ntsc.superimpose.hsync < (NTSC_WIDTH >> 4); ntsc.superimpose.hsync++){
00408 ntsc.superimpose.vram++;
00409 }
00410 }
00411
00412 dummy = SPI2BUF;
00413 return;
00414 }
00415
00416 void __attribute__((interrupt, auto_psv)) _T3Interrupt(void)
00417 {
00418
00419 IFS0bits.T3IF = 0;
00420
00421 IEC0bits.T2IE = 1;
00422 IEC0bits.T3IE = 0;
00423 IEC1bits.INT2IE = 0;
00424
00425 ntsc.output = 0;
00426
00427 return;
00428 }
00429
00430
00431
00432
00433
00434
00435 void VIDEO_vram_clear(unsigned int pattern)
00436 {
00437 unsigned int i, *vram;
00438
00439 vram = ntsc.vram;
00440
00441 for(i = 0; i < (NTSC_VRAM_SIZE >> 1); i++){
00442 *vram = pattern;
00443 vram++;
00444 }
00445
00446 return;
00447 }
00448
00449
00450
00451
00452
00453 unsigned char VIDEO_get_output(void)
00454 {
00455 return(ntsc.output);
00456 }
00457
00458
00459
00460
00461
00462 unsigned int VIDEO_get_point(unsigned int x, unsigned int y)
00463 {
00464 const unsigned int table[] = {
00465
00466 0b1000000000000000,
00467 0b0100000000000000,
00468 0b0010000000000000,
00469 0b0001000000000000,
00470 0b0000100000000000,
00471 0b0000010000000000,
00472 0b0000001000000000,
00473 0b0000000100000000,
00474 0b0000000010000000,
00475 0b0000000001000000,
00476 0b0000000000100000,
00477 0b0000000000010000,
00478 0b0000000000001000,
00479 0b0000000000000100,
00480 0b0000000000000010,
00481 0b0000000000000001,
00482 };
00483
00484 #ifndef VIDEO_FAST
00485 if(x >= NTSC_WIDTH) x = NTSC_WIDTH - 1;
00486 if(y >= NTSC_HEIGHT) y = NTSC_HEIGHT - 1;
00487 #endif
00488
00489 #ifdef VIDEO_MIRROR
00490 x = (NTSC_WIDTH - 1) - x;
00491 #endif
00492
00493 return(ntsc.vram[ (y << 4) + (x >> 4) ] & table[ (x & 0x0f) ] ? 1 : 0);
00494 }
00495
00496
00497
00498
00499
00500 inline void VIDEO_point(unsigned int x, unsigned int y)
00501 {
00502 #ifndef VIDEO_FAST
00503 if(x >= NTSC_WIDTH) x = NTSC_WIDTH - 1;
00504 if(y >= NTSC_HEIGHT) y = NTSC_HEIGHT - 1;
00505 #endif
00506
00507 #ifdef VIDEO_MIRROR
00508 x = (NTSC_WIDTH - 1) - x;
00509 #endif
00510
00511 ntsc.vram[ ((NTSC_HEIGHT - 1 - y) << 4) + (x >> 4) ] |= (0x8000 >> (x & 0x0f));
00512 return;
00513 }
00514 inline void VIDEO_point_(unsigned int x, unsigned int y)
00515 {
00516 #ifndef VIDEO_FAST
00517 if(x >= NTSC_WIDTH) x = NTSC_WIDTH - 1;
00518 if(y >= NTSC_HEIGHT) y = NTSC_HEIGHT - 1;
00519 #endif
00520
00521 #ifdef VIDEO_MIRROR
00522 x = (NTSC_WIDTH - 1) - x;
00523 #endif
00524
00525 ntsc.vram[ ((NTSC_HEIGHT - 1 - y) << 4) + (x >> 4) ] &= ‾(0x8000 >> (x & 0x0f));
00526 return;
00527 }
00528
00529
00530
00531
00532
00533 void VIDEO_line(int x0, int y0, int x1, int y1)
00534 {
00535 int steep, t;
00536 int deltax, deltay, error;
00537 int x, y;
00538 int ystep;
00539
00540 #ifndef VIDEO_FAST
00541 if(x0 < 0) x0 = 0;
00542 if(x0 >= NTSC_WIDTH) x0 = NTSC_WIDTH - 1;
00543 if(x1 < 0) x1 = 0;
00544 if(x1 >= NTSC_WIDTH) x1 = NTSC_WIDTH - 1;
00545 if(y0 < 0) y0 = 0;
00546 if(y0 >= NTSC_HEIGHT) y0 = NTSC_HEIGHT - 1;
00547 if(y1 < 0) y1 = 0;
00548 if(y1 >= NTSC_HEIGHT) y1 = NTSC_HEIGHT - 1;
00549 #endif
00550
00551 steep = (abs(y1 - y0) > abs(x1 - x0));
00552
00553 if(steep){
00554 t = x0; x0 = y0; y0 = t;
00555 t = x1; x1 = y1; y1 = t;
00556 }
00557 if(x0 > x1) {
00558 t = x0; x0 = x1; x1 = t;
00559 t = y0; y0 = y1; y1 = t;
00560 }
00561
00562 deltax = x1 - x0;
00563 deltay = abs(y1 - y0);
00564 error = 0;
00565 y = y0;
00566
00567 if(y0 < y1) ystep = 1;
00568 else ystep = -1;
00569
00570 if(steep){
00571 for(x = x0; x < x1; x++) {
00572 VIDEO_point(y,x);
00573
00574 error += deltay;
00575
00576 if((error << 1) >= deltax){
00577 y += ystep;
00578 error -= deltax;
00579 }
00580 }
00581 } else {
00582 for(x = x0; x < x1; x++) {
00583 VIDEO_point(x,y);
00584
00585 error += deltay;
00586
00587 if((error << 1) >= deltax){
00588 y += ystep;
00589 error -= deltax;
00590 }
00591 }
00592 }
00593
00594 return;
00595 }
00596
00597 void VIDEO_line_(int x0, int y0, int x1, int y1)
00598 {
00599 int steep, t;
00600 int deltax, deltay, error;
00601 int x, y;
00602 int ystep;
00603
00604 #ifndef VIDEO_FAST
00605 if(x0 < 0) x0 = 0;
00606 if(x0 >= NTSC_WIDTH) x0 = NTSC_WIDTH - 1;
00607 if(x1 < 0) x1 = 0;
00608 if(x1 >= NTSC_WIDTH) x1 = NTSC_WIDTH - 1;
00609 if(y0 < 0) y0 = 0;
00610 if(y0 >= NTSC_HEIGHT) y0 = NTSC_HEIGHT - 1;
00611 if(y1 < 0) y1 = 0;
00612 if(y1 >= NTSC_HEIGHT) y1 = NTSC_HEIGHT - 1;
00613 #endif
00614
00615 steep = (abs(y1 - y0) > abs(x1 - x0));
00616
00617 if(steep){
00618 t = x0; x0 = y0; y0 = t;
00619 t = x1; x1 = y1; y1 = t;
00620 }
00621 if(x0 > x1) {
00622 t = x0; x0 = x1; x1 = t;
00623 t = y0; y0 = y1; y1 = t;
00624 }
00625
00626 deltax = x1 - x0;
00627 deltay = abs(y1 - y0);
00628 error = 0;
00629 y = y0;
00630
00631 if(y0 < y1) ystep = 1;
00632 else ystep = -1;
00633
00634 if(steep){
00635 for(x = x0; x < x1; x++) {
00636 VIDEO_point_(y,x);
00637
00638 error += deltay;
00639
00640 if((error << 1) >= deltax){
00641 y += ystep;
00642 error -= deltax;
00643 }
00644 }
00645 } else {
00646 for(x = x0; x < x1; x++) {
00647 VIDEO_point_(x,y);
00648
00649 error += deltay;
00650
00651 if((error << 1) >= deltax){
00652 y += ystep;
00653 error -= deltax;
00654 }
00655 }
00656 }
00657
00658 return;
00659 }
00660
00661
00662
00663
00664
00665 void VIDEO_arc (unsigned int x, unsigned int y, unsigned int r, unsigned int start, unsigned int end)
00666 {
00667 unsigned int deg;
00668
00669 #ifndef VIDEO_FAST
00670 if(start > end){
00671 deg = end;
00672 end = start;
00673 start = deg;
00674 }
00675 #endif
00676
00677 for(deg = start; deg < end; deg++){
00678 VIDEO_point (x + (double)r * tcos[deg], y + (double)r * tsin[deg]);
00679 }
00680
00681 return;
00682 }
00683
00684 void VIDEO_arc_(unsigned int x, unsigned int y, unsigned int r, unsigned int start, unsigned int end)
00685 {
00686 unsigned int deg;
00687
00688 #ifndef VIDEO_FAST
00689 if(start > end){
00690 deg = end;
00691 end = start;
00692 start = deg;
00693 }
00694 #endif
00695
00696 for(deg = start; deg < end; deg++){
00697 VIDEO_point_(x + (double)r * tcos[deg], y + (double)r * tsin[deg]);
00698 }
00699
00700 return;
00701 }
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713 #ifdef VIDEO_MIRROR
00714 inline static unsigned char reverse (unsigned char buf)
00715 {
00716 return(
00717 ((buf & 0b00000001) << 7)
00718 + ((buf & 0b00000010) << 5)
00719 + ((buf & 0b00000100) << 3)
00720 + ((buf & 0b00001000) << 1)
00721 + ((buf & 0b00010000) >> 1)
00722 + ((buf & 0b00100000) >> 3)
00723 + ((buf & 0b01000000) >> 5)
00724 + ((buf & 0b10000000) >> 7)
00725 );
00726
00727 }
00728 #endif
00729
00730
00731
00732
00733
00734 void VIDEO_locate(unsigned int x, unsigned int y)
00735 {
00736 #ifdef VIDEO_MIRROR
00737 video.cx = NTSC_WIDTH / FONTX2_get_ascii_width() - x - 1;
00738 #else
00739 video.cx = x;
00740 #endif
00741 video.cy = y;
00742 return;
00743 }
00744
00745
00746
00747
00748
00749 void VIDEO_putch(unsigned char c)
00750 {
00751
00752 #ifdef VIDEO_MIRROR
00753 if(video.cx == 0){
00754 video.cx = NTSC_WIDTH / FONTX2_get_ascii_width();
00755
00756 }
00757 #else
00758 if(video.cx >= (NTSC_WIDTH / FONTX2_get_ascii_width())){
00759 video.cx = 0;
00760 video.cy++;
00761 }
00762 #endif
00763
00764 if(video.cy >= (NTSC_HEIGHT / FONTX2_get_ascii_height())){
00765 video.cy = 0;
00766 }
00767
00768 #if defined FONT_FAST8
00769 {
00770
00771 unsigned char i;
00772 unsigned int *vram;
00773 unsigned char *font;
00774
00775 vram = &ntsc.vram[ video.cy * FONTX2_get_ascii_height() * (NTSC_WIDTH >> 4) + (video.cx >> 1)];
00776 font = FONTX2_get_ascii_font(c);
00777
00778 if(video.cx & 0x01){
00779 for(i = 0; i < FONTX2_get_ascii_height(); i++){
00780 *vram &= 0xff00;
00781 #ifdef VIDEO_MIRROR
00782 *vram |= (int)reverse(*font++);
00783 #else
00784 *vram |= (int)(*font++);
00785 #endif
00786 vram += (NTSC_WIDTH >> 4);
00787 }
00788 } else {
00789 for(i = 0; i < FONTX2_get_ascii_height(); i++){
00790 *vram &= 0x00ff;
00791 #ifdef VIDEO_MIRROR
00792 *vram |= (int)reverse(*font++) << 8;
00793 #else
00794 *vram |= (int)(*font++) << 8;
00795 #endif
00796 vram += (NTSC_WIDTH >> 4);
00797 }
00798 }
00799 }
00800 #else
00801 {
00802
00803
00804 unsigned int x, y, i, j, k;
00805 unsigned char grif;
00806
00807 for(y = 0; y < FONTX2_get_ascii_height(); y++){
00808
00809 i = FONTX2_get_ascii_height() * video.cy + y;
00810
00811 for(j = 0; j < FONTX2_get_ascii_width_byte(); j++){
00812
00813 #ifdef VIDEO_MIRROR
00814 grif = reverse(FONTX2_get_ascii_font_data(c, j, y));
00815 #else
00816 grif = FONTX2_get_ascii_font_data(c, j, y);
00817 #endif
00818
00819 for(x = 0; x < 8 && (j * 8 + x) < FONTX2_get_ascii_width(); x++){
00820
00821 k = x + video.cx * FONTX2_get_ascii_width();
00822
00823 if(grif & 0x80) ntsc.vram[(i << 4) + (k >> 4)] |= (0x8000 >> (k & 0x0F));
00824 else ntsc.vram[(i << 4) + (k >> 4)] &= ‾(0x8000 >> (k & 0x0F));
00825
00826 grif = grif << 1;
00827 }
00828 }
00829 }
00830 }
00831 #endif
00832
00833 #ifdef VIDEO_MIRROR
00834 video.cx--;
00835 #else
00836 video.cx++;
00837 #endif
00838 return;
00839 }
00840
00841
00842
00843
00844
00845 void VIDEO_putstr(const char *s)
00846 {
00847 while(*s){
00848 VIDEO_putch(*s++);
00849 }
00850
00851 return;
00852 }
00853
00854
00855
00856
00857 void VIDEO_puthex(unsigned char a)
00858 {
00859 VIDEO_putch(hex[(a >> 4) & 0x0f]);
00860 VIDEO_putch(hex[ a & 0x0f]);
00861 return;
00862 }
00863
00864
00865
00866
00867
00868 void VIDEO_putbin(unsigned char a)
00869 {
00870 VIDEO_putch('0' + ((a >> 7) & 0x01));
00871 VIDEO_putch('0' + ((a >> 6) & 0x01));
00872 VIDEO_putch('0' + ((a >> 5) & 0x01));
00873 VIDEO_putch('0' + ((a >> 4) & 0x01));
00874 VIDEO_putch('0' + ((a >> 3) & 0x01));
00875 VIDEO_putch('0' + ((a >> 2) & 0x01));
00876 VIDEO_putch('0' + ((a >> 1) & 0x01));
00877 VIDEO_putch('0' + ( a & 0x01));
00878
00879 return;
00880 }
00881
00882
00883
00884
00885
00886 void VIDEO_putuint(unsigned int digit, unsigned char size)
00887 {
00888 if(size > 4){ if(digit > 9999){ VIDEO_putch('0' + digit / 10000 % 10); } else { VIDEO_putch(' '); }; };
00889 if(size > 3){ if(digit > 999){ VIDEO_putch('0' + digit / 1000 % 10); } else { VIDEO_putch(' '); }; };
00890 if(size > 2){ if(digit > 99){ VIDEO_putch('0' + digit / 100 % 10); } else { VIDEO_putch(' '); }; };
00891 if(size > 1){ if(digit > 9){ VIDEO_putch('0' + digit / 10 % 10); } else { VIDEO_putch(' '); }; };
00892
00893 VIDEO_putch('0' + digit % 10);
00894 return;
00895 }
00896
00897
00898 void VIDEO_putint(int digit, unsigned char size)
00899 {
00900 if(digit < 0) VIDEO_putch('-');
00901 else VIDEO_putch(' ');
00902
00903 digit = abs(digit);
00904
00905 if(size > 4){ if(digit > 9999){ VIDEO_putch('0' + digit / 10000 % 10); } else { VIDEO_putch(' '); }; };
00906 if(size > 3){ if(digit > 999){ VIDEO_putch('0' + digit / 1000 % 10); } else { VIDEO_putch(' '); }; };
00907 if(size > 2){ if(digit > 99){ VIDEO_putch('0' + digit / 100 % 10); } else { VIDEO_putch(' '); }; };
00908 if(size > 1){ if(digit > 9){ VIDEO_putch('0' + digit / 10 % 10); } else { VIDEO_putch(' '); }; };
00909
00910 VIDEO_putch('0' + digit % 10);
00911 return;
00912 }
00913
00914
00915 void VIDEO_putdouble(double digit, unsigned char size, unsigned char size2)
00916 {
00917 if(digit < 0) VIDEO_putch('-');
00918 else VIDEO_putch(' ');
00919
00920 digit = abs(digit);
00921
00922 if(size > 4){ if((unsigned int)digit > 9999){ VIDEO_putch('0' + (unsigned char)((unsigned int)(digit / 10000) % 10)); } else { VIDEO_putch(' '); }; };
00923 if(size > 3){ if((unsigned int)digit > 999){ VIDEO_putch('0' + (unsigned char)((unsigned int)(digit / 1000) % 10)); } else { VIDEO_putch(' '); }; };
00924 if(size > 2){ if((unsigned int)digit > 99){ VIDEO_putch('0' + (unsigned char)((unsigned int)(digit / 100) % 10)); } else { VIDEO_putch(' '); }; };
00925 if(size > 1){ if((unsigned int)digit > 9){ VIDEO_putch('0' + (unsigned char)((unsigned int)(digit / 10) % 10)); } else { VIDEO_putch(' '); }; };
00926 VIDEO_putch('0' + (unsigned char)((unsigned int)digit % 10));
00927 VIDEO_putch('.');
00928 VIDEO_putch('0' + (unsigned int)((unsigned int)(digit * 10.0) % 10));
00929 if(size2 > 1) VIDEO_putch('0' + (unsigned int)((unsigned int)(digit * 100.0) % 10));
00930 if(size2 > 2) VIDEO_putch('0' + (unsigned int)((unsigned int)(digit * 1000.0) % 10));
00931 if(size2 > 3) VIDEO_putch('0' + (unsigned int)((unsigned int)(digit * 10000.0) % 10));
00932
00933 return;
00934 }
00935
00936
00937
00938
00939
00940 void GRAPH_init(pGRAPH_T graph, unsigned int x, unsigned int y, unsigned int width, unsigned int height)
00941 {
00942 unsigned int i;
00943
00944 #ifndef VIDEO_FAST
00945 if(width >= GRAPH_SIZE){
00946 width = GRAPH_SIZE;
00947 }
00948 if(x + width > NTSC_WIDTH){
00949 width = NTSC_WIDTH - x;
00950 }
00951 if(y + height > NTSC_HEIGHT){
00952 height = NTSC_HEIGHT - y;
00953 }
00954 #endif
00955
00956 graph->x = x;
00957 graph->y = y;
00958 graph->width = width;
00959 graph->height = height;
00960 graph->ptr = 0;
00961
00962 for(i = 0; i < GRAPH_SIZE; i++){
00963 graph->data[i] = 0;
00964 }
00965
00966 return;
00967 }
00968
00969
00970
00971
00972
00973 void GRAPH_putdata(pGRAPH_T graph, unsigned int data)
00974 {
00975 if(data > 100) data = 100;
00976
00977 graph->data[graph->ptr] = data;
00978 graph->ptr = (graph->ptr + 1) % graph->width;
00979
00980 return;
00981 }
00982
00983
00984
00985
00986
00987 void GRAPH_draw_point(pGRAPH_T graph)
00988 {
00989 unsigned int i, w, x, y;
00990
00991 for(i = graph->y; i < graph->y + graph->height; i++){
00992 VIDEO_point_(graph->x, i);
00993 }
00994
00995 w = graph->width * 2;
00996 for(i = graph->width; i < w; i++){
00997 x = graph->x + i - graph->width;
00998
00999 y = graph->y + (((unsigned int)graph->data[(graph->ptr + i - 1) % graph->width] * graph->height) / 100);
01000 VIDEO_point_(x, y);
01001
01002 y = graph->y + (((unsigned int)graph->data[(graph->ptr + i ) % graph->width] * graph->height) / 100);
01003 VIDEO_point(x, y);
01004 }
01005
01006 return;
01007 }
01008
01009 void GRAPH_draw_line(pGRAPH_T graph)
01010 {
01011 unsigned int i, w, x, y1, y2, y3;
01012
01013 w = graph->width * 2 - 2;
01014 for(i = graph->width + 1; i < w; i++){
01015 x = graph->x + i - graph->width;
01016 y1 = graph->y + (((unsigned int)graph->data[(graph->ptr + i - 1) % graph->width] * graph->height) / 100);
01017 y2 = graph->y + (((unsigned int)graph->data[(graph->ptr + i ) % graph->width] * graph->height) / 100);
01018 y3 = graph->y + (((unsigned int)graph->data[(graph->ptr + i + 1) % graph->width] * graph->height) / 100);
01019 VIDEO_line_(x, y1, x + 1, y2);
01020 VIDEO_line (x, y2, x + 1, y3);
01021 }
01022
01023 for(i = graph->y; i < graph->y + graph->height; i++){
01024 VIDEO_point_(graph->x, i);
01025 VIDEO_point_(graph->x + graph->width, i);
01026 }
01027
01028 return;
01029 }
01030
01031 void GRAPH_draw_bar(pGRAPH_T graph)
01032 {
01033 unsigned int i, x, y;
01034
01035 for(i = 0; i < graph->width; i++){
01036 x = graph->x + i;
01037 y = graph->y + (((unsigned int)graph->data[(graph->ptr + i) % graph->width] * graph->height) / 100);
01038 VIDEO_line_(x, graph->y, x, y);
01039 VIDEO_line (x, y , x, graph->y + graph->height);
01040 }
01041
01042 return;
01043 }
01044
01045
01046
01047
01048
01049 void METER_init(pMETER_T meter, unsigned int x, unsigned int y, unsigned char r)
01050 {
01051 meter->x = x;
01052 meter->y = y;
01053 meter->r = r;
01054 meter->old = 0;
01055
01056 VIDEO_arc(x, y, r, 270, 360);
01057
01058 return;
01059 }
01060
01061
01062
01063
01064
01065 void METER_draw(pMETER_T meter, unsigned int value)
01066 {
01067 double rc, rs;
01068
01069 if(value > 100) value = 100;
01070
01071 rc = (double)meter->r * tcos[0];
01072 rs = (double)meter->r * tsin[0];
01073 VIDEO_line(meter->x + rc, meter->y + rs, meter->x + 0.7 * rc, meter->y + 0.7 * rs);
01074
01075 rc = (double)meter->r * tcos[270];
01076 rs = (double)meter->r * tsin[270];
01077 VIDEO_line(meter->x + rc, meter->y + rs, meter->x + 0.7 * rc, meter->y + 0.7 * rs);
01078
01079 rc = (double)meter->r * tcos[meter->old];
01080 rs = (double)meter->r * tsin[meter->old];
01081 VIDEO_line_(meter->x + rc, meter->y + rs, meter->x + 0.7 * rc, meter->y + 0.7 * rs);
01082
01083 meter->old = ((100 - value) * 27) / 10;
01084 rc = (double)meter->r * tcos[meter->old];
01085 rs = (double)meter->r * tsin[meter->old];
01086 VIDEO_line (meter->x + rc, meter->y + rs, meter->x + 0.7 * rc, meter->y + 0.7 * rs);
01087
01088 return;
01089 }
01090
01091
01092
01093
01094
01095 void TRACK_init(pTRACK_T track, unsigned int x, unsigned int y, unsigned int width, unsigned int height)
01096 {
01097 unsigned int i;
01098
01099 track->x = x;
01100 track->y = y;
01101 track->width = width;
01102 track->height = height;
01103 track->ptr = 0;
01104
01105 for(i = 0; i < TRACK_SIZE; i++){
01106 track->data[i][0] = 0;
01107 track->data[i][1] = 0;
01108 }
01109
01110 return;
01111 }
01112
01113
01114
01115
01116
01117 void TRACK_putdata(pTRACK_T track, unsigned int x, unsigned int y)
01118 {
01119 if(x > 100) x = 100;
01120 if(y > 100) y = 100;
01121
01122 track->ptr = (track->ptr + 1) % TRACK_SIZE;
01123 track->data[ track->ptr ][0] = x;
01124 track->data[ track->ptr ][1] = y;
01125
01126 return;
01127 }
01128
01129
01130
01131
01132
01133 void TRACK_draw_point(pTRACK_T track)
01134 {
01135 unsigned int tmp;
01136
01137
01138 tmp = (track->ptr + 1) % TRACK_SIZE;
01139 VIDEO_point_(track->x + (track->width * track->data[ tmp ][0]) / 100,
01140 track->y + (track->height * track->data[ tmp ][1]) / 100);
01141
01142 VIDEO_point_(track->x + (track->width * track->data[ tmp ][0]) / 100 + 1,
01143 track->y + (track->height * track->data[ tmp ][1]) / 100);
01144
01145 VIDEO_point_(track->x + (track->width * track->data[ tmp ][0]) / 100,
01146 track->y + (track->height * track->data[ tmp ][1]) / 100 + 1);
01147
01148 VIDEO_point_(track->x + (track->width * track->data[ tmp ][0]) / 100 + 1,
01149 track->y + (track->height * track->data[ tmp ][1]) / 100 + 1);
01150
01151 VIDEO_point_(track->x + (track->width * track->data[ tmp ][0]) / 100 + 2,
01152 track->y + (track->height * track->data[ tmp ][1]) / 100);
01153
01154 VIDEO_point_(track->x + (track->width * track->data[ tmp ][0]) / 100,
01155 track->y + (track->height * track->data[ tmp ][1]) / 100 + 2);
01156
01157 VIDEO_point_(track->x + (track->width * track->data[ tmp ][0]) / 100 + 1,
01158 track->y + (track->height * track->data[ tmp ][1]) / 100 + 2);
01159
01160 VIDEO_point_(track->x + (track->width * track->data[ tmp ][0]) / 100 + 2,
01161 track->y + (track->height * track->data[ tmp ][1]) / 100 + 1);
01162
01163 VIDEO_point_(track->x + (track->width * track->data[ tmp ][0]) / 100 + 2,
01164 track->y + (track->height * track->data[ tmp ][1]) / 100 + 2);
01165
01166
01167
01168 VIDEO_point(track->x + (track->width * track->data[ track->ptr ][0]) / 100,
01169 track->y + (track->height * track->data[ track->ptr ][1]) / 100);
01170
01171 VIDEO_point(track->x + (track->width * track->data[ track->ptr ][0]) / 100 + 1,
01172 track->y + (track->height * track->data[ track->ptr ][1]) / 100);
01173
01174 VIDEO_point(track->x + (track->width * track->data[ track->ptr ][0]) / 100,
01175 track->y + (track->height * track->data[ track->ptr ][1]) / 100 + 1);
01176
01177 VIDEO_point(track->x + (track->width * track->data[ track->ptr ][0]) / 100 + 1,
01178 track->y + (track->height * track->data[ track->ptr ][1]) / 100 + 1);
01179
01180 VIDEO_point(track->x + (track->width * track->data[ track->ptr ][0]) / 100 + 2,
01181 track->y + (track->height * track->data[ track->ptr ][1]) / 100);
01182
01183 VIDEO_point(track->x + (track->width * track->data[ track->ptr ][0]) / 100,
01184 track->y + (track->height * track->data[ track->ptr ][1]) / 100 + 2);
01185
01186 VIDEO_point(track->x + (track->width * track->data[ track->ptr ][0]) / 100 + 1,
01187 track->y + (track->height * track->data[ track->ptr ][1]) / 100 + 2);
01188
01189 VIDEO_point(track->x + (track->width * track->data[ track->ptr ][0]) / 100 + 2,
01190 track->y + (track->height * track->data[ track->ptr ][1]) / 100 + 1);
01191
01192 VIDEO_point(track->x + (track->width * track->data[ track->ptr ][0]) / 100 + 2,
01193 track->y + (track->height * track->data[ track->ptr ][1]) / 100 + 2);
01194
01195
01196
01197 tmp = track->y + (track->height >> 1);
01198 VIDEO_line(track->x, tmp, track->x + track->width, tmp);
01199
01200 tmp = track->x + (track->width >> 1);
01201 VIDEO_line(tmp, track->y, tmp, track->y + track->height);
01202
01203 return;
01204 }