Main Page | Data Structures | File List | Data Fields | Globals

gfx.c

00001 /*=========================================================================
00002 
00003 GFX - a small graphics library 
00004 
00005 Copyright (C) 2004  Rafael de Oliveira Jannone
00006 
00007 This library is free software; you can redistribute it and/or
00008 modify it under the terms of the GNU Lesser General Public
00009 License as published by the Free Software Foundation; either
00010 version 2.1 of the License, or (at your option) any later version.
00011 
00012 This library is distributed in the hope that it will be useful,
00013 but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015 Lesser General Public License for more details.
00016 
00017 You should have received a copy of the GNU Lesser General Public
00018 License along with this library; if not, write to the Free Software
00019 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020 
00021 Contact the author:
00022         by e-mail : rafael AT jannone DOT org
00023         homepage  : http://jannone.org/gfxlib
00024         ICQ UIN   : 10115284
00025 
00026 See the License at http://www.gnu.org/copyleft/lesser.txt
00027 
00028 =========================================================================*/
00029 
00030 // GFX.C : main library functions
00031 
00032 /* === WARNING ==
00033 
00034         This is a work-in-progress, meaning that most of this code is unstable
00035         and it's subject to future changes.  Also, most of it is very hackish,
00036         not properly cleaned up nor tested.
00037 
00038    === WARNING == */
00039 
00040 #include "gfx.h"
00041 
00042 // do a interslot call to BIOS
00043 
00044 #asm
00045 
00046 psect text
00047 
00048 ;callbios: ld (callbios0), ix
00049 ;       defb 0CDh
00050 ;callbios0:
00051 ;       defw 0000h
00052 ;       ret
00053 
00054 callbios:
00055         ld      (callbios1), ix
00056         rst     030h
00057 callbios0:
00058         defb    0
00059 callbios1:
00060         defw    0
00061         ret
00062 
00063 psect data
00064 global _st_dir
00065 _st_dir:
00066         defb 0000B ; 0
00067         defb 0001B ; 1
00068         defb 0011B ; 2
00069         defb 0010B ; 3
00070         defb 0110B ; 4
00071         defb 0100B ; 5
00072         defb 1100B ; 6
00073         defb 1000B ; 7
00074         defb 1001B ; 8
00075 
00076 #endasm
00077 
00078 static int rnd = 0;
00079 
00080 void seed_rnd(int seed) {
00081         rnd = seed;
00082 }
00083 
00084 u_char get_rnd() {
00085         rnd = ((rnd + 1) & 0x0FFF);
00086         return *(u_char*)rnd;
00087 }
00088 
00089 void init() {
00090 #asm
00091         ;in a, (0A8h)
00092         ;and 0FCh
00093         ;out (0A8h), a
00094 #endasm
00095 }
00096 
00097 /*
00098 
00099 // this is not currently compiling... must investigate
00100 
00101 void *set_sprite(u_char, void*);
00102 void *put_sprite(u_char, int, int, u_char, u_char);
00103 
00104 void _init_sprites() {
00105         u_char m = get_vdp(1);
00106         if (m & sprite_large) {
00107                 set_sprite = set_sprite_16;
00108                 put_sprite = put_sprite_16;
00109         } else {
00110                 set_sprite = set_sprite_8;
00111                 put_sprite = put_sprite_8;
00112         }
00113 }
00114 */
00115 #define _init_sprites()
00116 
00117 void set_vdp(u_char reg, u_char value) {
00118 #asm
00119         f_wrtvdp equ 047h
00120 
00121         push bc
00122         push ix
00123 
00124         ld c, (ix+6)
00125         ld b, (ix+8)
00126 
00127         ld ix, f_wrtvdp
00128         call callbios
00129         
00130         pop ix
00131         pop bc
00132 #endasm
00133 }
00134 
00135 u_char get_vdp(u_char reg) {
00136         return *(u_char*)(0xF3DF + reg);
00137 }
00138 
00139 void set_mode(u_int mode) {
00140 #asm
00141         push bc
00142         push ix
00143         ld c, (ix+6)
00144         ld b, (ix+7)
00145         push bc
00146         pop ix
00147         call callbios
00148         pop ix
00149         pop bc
00150 #endasm
00151         _init_sprites();
00152 }
00153 
00154 void set_mangled_mode() {
00155         set_mode(mode_1);
00156         set_mode(0x7E);
00157         vwrite((void*)0x1BBF, 0x0800, 0x800);   
00158         vwrite((void*)0x1BBF, 0x1000, 0x800);   
00159         fill(MODE2_ATTR, 0xF0, 0x17FF);
00160         fill(0xFF8, 0xFF, 8);
00161         fill(0x17F8, 0xFF, 8);
00162 
00163         _init_sprites();
00164 }
00165 
00166 void set_color(u_char front, u_char back, u_char border) {
00167         *(u_char*)0xf3e9 = front;
00168         *(u_char*)0xf3ea = back;
00169         *(u_char*)0xf3eb = border;
00170 #asm
00171         f_chgclr equ 062h
00172 
00173         push ix
00174         ld ix, f_chgclr
00175         call callbios
00176         pop ix  
00177 #endasm
00178 }
00179 
00180 void fill(u_int addr, u_char value, u_int count) {
00181 #asm
00182         f_filvrm equ 056h
00183 
00184         push hl
00185         push bc
00186         push ix
00187 
00188         ld l, (ix+6)
00189         ld h, (ix+7)
00190         ld c, (ix+10)
00191         ld b, (ix+11)
00192         ld a, (ix+8)
00193 
00194         ld ix, f_filvrm
00195         call callbios
00196         pop ix
00197         pop bc
00198         pop hl
00199 #endasm
00200 }
00201 
00202 void vpoke(u_int addr, u_char value) {
00203 #asm
00204         f_wrtvrm equ 04Dh
00205 
00206         ;push hl
00207         ;push ix
00208 
00209         ;ld l, (ix+6)
00210         ;ld h, (ix+7)
00211         ;ld a, (ix+8)
00212         
00213         ;ld ix, f_wrtvrm
00214         ;call callbios
00215 
00216         ;pop ix
00217         ;pop hl
00218 
00219         p_vdp_data equ 098H
00220         p_vdp_cmd  equ 099H
00221 
00222         ; enter vdp address pointer
00223 
00224         ld a, (ix+6)
00225         di
00226         out (p_vdp_cmd), a
00227         ld a, (ix+7)
00228         and 00111111B
00229         or  01000000B
00230         ei
00231         out (p_vdp_cmd), a
00232 
00233         ; enter data
00234 
00235         ld a, (ix+8)
00236         out (p_vdp_data), a
00237                 
00238 #endasm
00239 }
00240 
00241 u_char vpeek(u_int addr) {
00242 #asm
00243         f_rdvrm equ 04Ah
00244 
00245         ;push hl
00246         ;push ix
00247         ;ld l, (ix+6)
00248         ;ld h, (ix+7)
00249         ;ld ix, f_rdvrm
00250         ;call callbios
00251         ;pop ix
00252         ;pop hl
00253         ;ld l, a
00254 
00255         ; enter vdp address pointer
00256 
00257         ld a, (ix+6)
00258         di
00259         out (p_vdp_cmd), a
00260         ld a, (ix+7)
00261         and 00111111B
00262         ei
00263         out (p_vdp_cmd), a
00264 
00265         ; read data
00266 
00267         in a, (p_vdp_data)
00268         ld l, a
00269 #endasm
00270 }
00271 
00272 void vmerge(u_int addr, u_char value) {
00273 #asm
00274         ;f_wrtvrm equ 04Dh
00275         ;f_rdvrm equ 04Ah
00276 
00277         ;push hl
00278         ;push ix
00279 
00280         ;ld l, (ix+6)
00281         ;ld h, (ix+7)
00282         ;ld ix, f_rdvrm
00283         ;call callbios
00284 
00285         ;pop ix
00286         ;push ix
00287 
00288         ;or (ix+8)
00289         ;ld ix, f_wrtvrm
00290         ;call callbios
00291 
00292         ;pop ix
00293         ;pop hl
00294 
00295         ; enter vdp address pointer
00296 
00297         ld l, (ix+6)
00298         ld h, (ix+7)
00299         ld c, p_vdp_cmd
00300         ld b, c
00301 
00302         di
00303         out (c), l
00304         ld a, h
00305         and 00111111B
00306         ei
00307         out (c), a
00308 
00309         ; read data
00310 
00311         ld c, p_vdp_data
00312         in h, (c)
00313         ld c, b
00314 
00315         ; enter same address
00316 
00317         di
00318         out (c), l
00319         or  01000000B
00320         ei
00321         out (c), a
00322 
00323         ld a, (ix+8)
00324         out (p_vdp_data), a
00325 #endasm
00326 }
00327 
00328 void vwrite(void *source, u_int dest, u_int count) {
00329 #asm
00330         f_ldirvm equ 05Ch
00331 
00332         push hl
00333         push bc
00334         push de
00335         push ix
00336 
00337         ld l, (ix+6)
00338         ld h, (ix+7)
00339         ld e, (ix+8)
00340         ld d, (ix+9)
00341         ld c, (ix+10)
00342         ld b, (ix+11)
00343 
00344         ld ix, f_ldirvm
00345         call callbios
00346 
00347         pop ix
00348         pop de
00349         pop bc
00350         pop hl
00351 #endasm
00352 }
00353 
00354 void vread(u_int source, void* dest, u_int count) {
00355 #asm
00356         f_ldirmv equ 056h
00357 
00358         push hl
00359         push bc
00360         push de
00361         push ix
00362 
00363         ld l, (ix+6)
00364         ld h, (ix+7)
00365         ld e, (ix+8)
00366         ld d, (ix+9)
00367         ld c, (ix+10)
00368         ld b, (ix+11)
00369 
00370         ld ix, f_ldirmv
00371         call callbios
00372 
00373         pop ix
00374         pop de
00375         pop bc
00376         pop hl
00377 #endasm
00378 }
00379 
00380 void locate(u_char x, u_char y) {
00381 #asm
00382         f_posit equ 0C6h
00383         
00384         push hl
00385         push ix
00386 
00387         ld h, (ix+6)
00388         ld l, (ix+8)
00389         
00390         ld ix, f_posit
00391         call callbios
00392 
00393         pop ix
00394         pop hl
00395 #endasm
00396 }
00397 
00398 void pset(int x, int y) {
00399         vmerge(map_pixel(x,y), map_subpixel(x));
00400 }
00401 
00402 void set_char_form(char c, void* form, u_char place) {
00403         u_int addr = c;
00404         addr <<= 3;
00405         if (place & place_1) vwrite(form, addr, 8);
00406         if (place & place_2) vwrite(form, (256 * 8) + addr, 8);
00407         if (place & place_3) vwrite(form, (256 * 8 * 2) + addr, 8);
00408 }
00409 
00410 void set_char_attr(char c, void *attr, u_char place) {
00411         u_int addr = c;
00412         addr <<= 3;
00413         addr += MODE2_ATTR;
00414 
00415         if (place & place_1) vwrite(attr, addr, 8);
00416         if (place & place_2) vwrite(attr, (256 * 8) + addr, 8);
00417         if (place & place_3) vwrite(attr, (256 * 8 * 2) + addr, 8);
00418 }
00419 
00420 void set_char_color(char c, u_char color, u_char place) {
00421         u_int addr = c;
00422         addr <<= 3;
00423         addr += MODE2_ATTR;
00424 
00425         if (place & place_1) fill(addr, color, 8);
00426         if (place & place_2) fill((256 * 8) + addr, color, 8);
00427         if (place & place_3) fill((256 * 8 * 2) + addr, color, 8);
00428 }
00429 
00430 void set_char(char c, void* form, void *attr, u_char color, u_char place) {
00431         set_char_form(c, form, place);
00432         if (attr)
00433                 set_char_attr(c, attr, place);
00434         else
00435                 set_char_color(c, color, place);
00436 }
00437 
00438 void fill_v(u_int addr, u_char value, u_char count) {
00439         u_char diff;
00440 
00441         diff = addr & 7;
00442         if (diff) {
00443                 diff = 8 - diff;
00444                 if (diff > count)
00445                         diff = count;
00446                 fill(addr, value, diff);
00447                 addr = (addr & ~(7)) + 256;
00448                 count -= diff;
00449         }
00450 
00451         diff = count >> 3;
00452         while (diff--) {
00453                 fill(addr, value, 8);
00454                 addr += 256;
00455                 count -= 8;     
00456         }
00457 
00458         if (count > 0)
00459                 fill(addr, value, count);
00460 
00461 }
00462 
00463 u_char get_stick(u_char id) {
00464 #asm
00465         f_gtstck equ 0D5h
00466 
00467         push hl
00468         push de
00469         push bc
00470         push ix
00471 
00472         ld a, (ix+6)
00473         ld ix, f_gtstck
00474         call callbios
00475 
00476         pop ix
00477         pop bc
00478         pop de
00479         pop hl
00480         
00481         ld l, a
00482 #endasm
00483 }
00484 
00485 bool get_trigger(u_char id) {
00486 #asm
00487         f_gttrig equ 0D8h
00488 
00489         push ix
00490         ld a, (ix+6)
00491 
00492         ld ix, f_gttrig
00493         call callbios
00494         pop ix
00495         ld l, a 
00496 #endasm
00497 }
00498 
00499 void set_sprite_mode(u_char mode) {
00500         u_char m = get_vdp(1);
00501         set_vdp(1, (m & 0xFC) | mode);
00502 
00503         _init_sprites();
00504 }
00505 
00506 void set_sprite_8(u_char handle, void* data) {
00507         vwrite(data, 14336 + (handle << 3), 8);
00508 }
00509 
00510 void set_sprite_16(u_char handle, void* data) {
00511         vwrite(data, 14336 + (handle << 5), 32);
00512 }
00513 
00514 void put_sprite_8(u_char id, int x, int y, u_char handle, u_char color) {
00515         sprite_t sp;
00516         if (x < 0) {
00517                 x += 32;
00518                 color |= 128;
00519         }
00520         sp.y = y - 1;
00521         sp.x = x;
00522         sp.handle = handle;
00523         sp.color = color;
00524         vwrite(&sp, 6912 + (id << 2), 4);
00525 }
00526 
00527 void put_sprite_16(u_char id, int x, int y, u_char handle, u_char color) {
00528         sprite_t sp;
00529         if (x < 0) {
00530                 x += 32;
00531                 color |= 128;
00532         }
00533         sp.y = y - 1;
00534         sp.x = x;
00535         sp.handle = (handle << 2);
00536         sp.color = color;
00537         vwrite(&sp, 6912 + (id << 2), 4);
00538 }
00539 
00540 void blit_ram_vram(u_char* source, u_int dest, u_char w, u_char h, int sjmp, int djmp) {
00541         while (h--) {
00542                 vwrite(source, dest, w);
00543                 source += sjmp;
00544                 dest += djmp;           
00545         }
00546 }
00547 
00548 void blit_fill_vram(u_int dest, u_char value, u_char w, u_char h, int djmp) {
00549         while (h--) {
00550                 fill(dest, value, w);
00551                 dest += djmp;           
00552         }
00553 }
00554 
00555 /* unfinished
00556 void blit_ram_vram(surface_t *source, surface_t *dest, rect_t *from, rect_t *to) {
00557 
00558         int s_jmp, d_jmp, h;
00559         u_char* s_addr;
00560         u_int   d_addr;
00561 
00562         s_jmp = source->width - from->width;
00563         d_jmp = dest->width - from->width;
00564         h = from->height;
00565 
00566         s_addr = 0; // ?
00567         d_addr = 0; // ?
00568 }
00569 
00570 void blit(surface_t *source, surface_t *dest, rect_t *from, rect_t *to) {
00571         // one can always dream :)      
00572 }
00573 
00574 */
00575 
00576 void psg_init() {
00577 #asm
00578         f_gicini equ 090h
00579 
00580         push ix
00581         ld ix, f_gicini
00582         call callbios
00583         pop ix
00584 #endasm
00585 }
00586 
00587 void psg_set(u_char reg, u_char value) {
00588 #asm
00589         f_wrtpsg equ 093h
00590 
00591         push de
00592         push ix
00593         ld a, (ix + 8)
00594         ld e, a
00595         ld a, (ix + 6)
00596         ld ix, f_wrtpsg
00597         call callbios
00598         pop ix
00599         pop de
00600 #endasm
00601 }
00602 
00603 u_char psg_get(u_char reg) {
00604 #asm
00605         f_rdpsg equ 096h
00606 
00607         push ix
00608         ld a, (ix + 6)
00609         ld ix, f_rdpsg
00610         call callbios
00611         pop ix
00612 #endasm
00613 }
00614 
00615 void psg_tone(u_char channel, int period) {
00616         channel <<= 1;
00617         psg_set(channel, period & 255);
00618         psg_set(channel + 1, period >> 8);
00619 }
00620 
00621 void psg_noise(u_char period) {
00622         psg_set(6, period & 31);
00623 }
00624 
00625 void psg_volume(u_char channel, u_char volume) {
00626         psg_set(channel + 8, volume & 15);
00627 }
00628 
00629 void psg_envelope(u_char waveform, int period, u_char channels) {
00630         psg_set(13, waveform);
00631         psg_set(11, period & 255);
00632         psg_set(12, period >> 8);
00633         if (channels & 1)
00634                 psg_set(8, 16);
00635         if (channels & 2)
00636                 psg_set(9, 16);
00637         if (channels & 4)
00638                 psg_set(10, 16);
00639         // FIXME: perhaps we should mute all others?
00640 }
00641 
00642 void psg_channels(u_char tone_channels, u_char noise_channels) {
00643         psg_set(7, (tone_channels << 3) | noise_channels);
00644 }
00645 
00646 u_char psg_noise_channels() {
00647         return psg_get(7) & 7;
00648 }
00649 
00650 u_char psg_tone_channels() {
00651         return (psg_get(7) >> 3) & 7;
00652 }

Generated on Thu Mar 3 19:55:02 2005 for GFX lib by  doxygen 1.4.1