Subversion Repositories SvarDOS

Compare Revisions

Ignore whitespace Rev 1536 → Rev 1542

/sved/trunk/mdr/inc/mdr/bios.h
32,4 → 32,8
* works on IBM PC, XT, AT - ie. it's always safe */
void mdr_bios_tickswait(unsigned short ticks);
 
/* returns the current BIOS tick counter (18.2 Hz, 1 tick is roughly 55ms, an
* hour has 65543 ticks). works on IBM PC, XT, AT - ie. it's always safe */
unsigned short mdr_bios_ticks(void);
 
#endif
/sved/trunk/mdr/inc/mdr/dos.h
108,7 → 108,7
/* Determine the canonical name of the specified filename or path and writes
* the result into result. The input path does not need to actually exist.
* This function requires a 3.x+ DOS kernel.
* result is zeroed to an empty string on error. */
* name is simply copied to result on error. */
void mdr_dos_truename(char *result, const char *name);
 
#endif
/sved/trunk/mdr/inc/mdr/mouse.h
4,7 → 4,7
* This file is part of the Mateusz' DOS Routines (MDR): http://mdr.osdn.io
* Published under the terms of the MIT License, as stated below.
*
* Copyright (C) 2014-2022 Mateusz Viste
* Copyright (C) 2014-2023 Mateusz Viste
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
29,20 → 29,32
#define MDR_MOUSE_H
 
/* init the mouse driver (and checks for presence of mouse support at same time)
* returns 0 if no mouse is present, and the number of buttons otherwise */
int mouse_init(void);
* returns 0 if no mouse is present, and the number of buttons otherwise.
* after initialization the mouse cursor is hidden, use mdr_mouse_show() to
* make it visible. */
int mdr_mouse_init(void);
 
/* shows the mouse pointer */
void mouse_show(void);
void mdr_mouse_show(void);
 
/* hides the mouse pointer */
void mouse_hide(void);
void mdr_mouse_hide(void);
 
/* get x/y coordinates of the mouse, and returns a bitfield with state of buttons */
int mouse_getstate(int *x, int *y);
int mdr_mouse_getstate(int *x, int *y);
 
/* get x/y coordinates of the mouse when the last button release occured since last check.
returns the id of the button pressed (1 or 2), or 0 if no event occured. */
int mouse_fetchrelease(int *x, int *y);
int mdr_mouse_fetchrelease(int *x, int *y);
 
/* set graphic pointer shape. icon is 64-bytes long, two sets of 32. each set
* of 32 bytes is organized as a 16x16 bitmap, ie. 16 rows of 16-bit values.
* a) the first set of 16 shorts defines the background mask - that is, the
* background will show through wherever there is a 1-bit in that data.
* b) the second set defines the "XOR mask" - that is, the pixels matching the
* 1-bit in this data set are toggled.
* hotspotx and hotspoty define respectively the horizontal and vertical hot
* spot of the pointer (default being [0,0], that is the top left corner). */
void mdr_mouse_setcursor(const unsigned short *icon, unsigned char hotspotx, unsigned char hotspoty);
 
#endif
/sved/trunk/mdr/inc/mdr/opl.h
0,0 → 1,241
/*
* Library to access OPL2/OPL3 hardware (YM3812 / YMF262)
*
* This file is part of the Mateusz' DOS Routines (MDR): http://mdr.osdn.io
* Published under the terms of the MIT License, as stated below.
*
* Copyright (C) 2015-2023 Mateusz Viste
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
 
#ifndef mdr_opl_h
#define mdr_opl_h
 
struct mdr_opl_timbre {
unsigned char mod_ws, car_ws; /* waveform select (0-4), reg Exh */
unsigned char mod_sr, car_sr; /* sustain/release, reg 8xh */
unsigned char mod_ad, car_ad; /* attack/decay, reg 6xh */
unsigned char mod_20, car_20; /* tremolo/vibrato/sustain..., reg 2xh */
unsigned char mod_40, car_40; /* reg 4xh */
unsigned char feedconn;
};
 
struct mdr_opl_timbretemplate {
struct {
unsigned char ws; /* waveform select 0..3 */
unsigned char sustlev; /* sustain level 0..15 */
unsigned char release; /* release level 0..15 */
unsigned char attack; /* attack rate 0..15 */
unsigned char decay; /* decay rate 0..15 */
unsigned char tremolo; /* tremolo flag 0..1 */
unsigned char vibrato; /* vibrato flag 0..1 */
unsigned char sustain; /* sustain flag 0..1 */
unsigned char ksr; /* KSR (envelope scaling) flag 0..1 */
unsigned char mult; /* frequency multiplication factor 0..15 */
unsigned char ksl; /* Key Scale Level 0..3 */
unsigned char outlev; /* output level 0..63 */
} carrier;
struct {
unsigned char ws; /* waveform select 0..3 */
unsigned char sustlev; /* sustain level 0..15 */
unsigned char release; /* release level 0..15 */
unsigned char attack; /* attack rate 0..15 */
unsigned char decay; /* decay rate 0..15 */
unsigned char tremolo; /* tremolo flag 0..1 */
unsigned char vibrato; /* vibrato flag 0..1 */
unsigned char sustain; /* sustain flag 0..1 */
unsigned char ksr; /* KSR (envelope scaling) flag 0..1 */
unsigned char mult; /* frequency multiplication factor 0..15 */
unsigned char ksl; /* Key Scale Level 0..3 */
unsigned char outlev; /* output level 0..63 */
} modultr;
unsigned char feedback;/* FeedBack Modulation Factor 0..7 */
unsigned char conn; /* Synthesis type: 0=FM / 1=Additive */
};
 
enum MDR_OPL_TIMER {
MDR_OPL_TIMER_80US = 2,
MDR_OPL_TIMER_320US = 3
};
 
 
/* frequency groups, to be used with mdr_opl_noteon() and mdr_opl_notebend().
* There are 7 frequency groups to choose from. Each group supports a different
* span of frequencies. Higher groups have wider spans, but at the cost of larger
* difference between adjacent notes:
*
* Block Note 0 Note 1023 Step gap between adjacent notes
* FGROUP0 0.047 Hz 48.503 Hz 0.048 Hz
* FGROUP1 0.094 Hz 97.006 Hz 0.095 Hz
* FGROUP2 0.189 Hz 194.013 Hz 0.190 Hz
* FGROUP3 0.379 Hz 388.026 Hz 0.379 Hz
* FGROUP4 0.758 Hz 776.053 Hz 0.759 Hz
* FGROUP5 1.517 Hz 1552.107 Hz 1.517 Hz
* FGROUP6 3.034 Hz 3104.215 Hz 3.034 Hz
* FGROUP7 6.068 Hz 6208.431 Hz 6.069 Hz
*
* This shows that block 7 is capable of reaching the highest note (6.2kHz) but
* since there are 6 Hz between notes the accuracy suffers. Example: note A-4
* is 440Hz but in this block, the two closest frequency numbers are 72 and 73,
* which create tones at 437Hz and 443Hz respectively, neither of which is
* particularly accurate. Blocks 3 and below are unable to reach as high as
* 440Hz, but block 4 can. With block 4, frequency numbers 579 and 580 produce
* 439.4 Hz and 440.2 Hz, considerably closer to the intended frequency.
*
* In other words, when calculating notes, the best accuracy is achieved by
* selecting the lowest possible block number that can reach the desired note
* frequency.
*
* More details: https://moddingwiki.shikadi.net/wiki/OPL_chip#A0-A8:_Frequency_Number
*/
 
enum mdr_opl_fgroup_t {
MDR_OPL_FGROUP0 = 0,
MDR_OPL_FGROUP1 = 1 << 2,
MDR_OPL_FGROUP2 = 2 << 2,
MDR_OPL_FGROUP3 = 3 << 2,
MDR_OPL_FGROUP4 = 4 << 2,
MDR_OPL_FGROUP5 = 5 << 2,
MDR_OPL_FGROUP6 = 6 << 2,
MDR_OPL_FGROUP7 = 7 << 2
};
 
/* Hardware detection and initialization. Must be called before any other
* OPL function. Returns 0 on success, non-zero otherwise. */
int mdr_opl_init(void);
 
/* close OPL device */
void mdr_opl_close(void);
 
/* turns off all notes */
void mdr_opl_clear(void);
 
/* loads an instrument described by properties in a timbre_t struct into
* the defined voice channel. The OPL2 chip supports up to 9 voice channels,
* from 0 to 8. The timbre struct can be freed right after this call. */
void mdr_opl_loadinstrument(unsigned char voice, const struct mdr_opl_timbre *timbre);
 
/* generate a timbre structure based on a timbre template. this is a
* convenience function meant to provide a human-compatible (more readable)
* way of generating a timbre struct. */
int mdr_opl_timbre_gen(struct mdr_opl_timbre *timbre, const struct mdr_opl_timbretemplate *tpl);
 
/* Triggers a note on selected voice channel.
* freqid is a value between 0 and 1023. The following formula can be used to
* determine the freq number for a given note frequency (Hz) and block:
*
* freqid = frequency * 2^(20 - block) / 49716
*
* The note will be kept "pressed" until mdr_opl_noteoff() is called. */
void mdr_opl_noteon(unsigned char voice, unsigned short freqid, enum mdr_opl_fgroup_t fgroup);
 
/* changes the frequency of the note currently playing on voice channel, this
* can be used for pitch bending. */
void mdr_opl_notebend(unsigned char voice, unsigned short freqid, enum mdr_opl_fgroup_t fgroup);
 
/* releases a note on selected voice. */
void mdr_opl_noteoff(unsigned char voice);
 
/* adjusts volume of a voice. volume goes from 63 (mute) to 0 (loudest) */
void mdr_opl_voicevolume(unsigned char voice, unsigned char volume);
 
/* this is a LOW-LEVEL function that writes a data byte into the reg register
* of the OPL chip. Use this only if you know exactly what you are doing. */
void mdr_opl_regwr(unsigned char reg, unsigned char data);
 
 
/*****************************************************************************
* IMF AUDIO FILES PLAYBACK *
* *
* It is possible to mix IMF playback calls with manual notes, but you must *
* take care to use only voices not used by your IMF audio. Typically games *
* tend to use the voice #0 for sound effects and voices #1 to #8 for music. *
* *
* The IMF API comes in two version: the normal one, or "imfeasy". The easy *
* version is easier to use, but requires to have the entire IMF audio file *
* loaded in memory, while the normal (non-easy) allows for more flexibility *
* in this regard, potentially allowing for playback of huge IMF files. *
*****************************************************************************/
 
/*** EASY INTERFACE ***/
 
/* playback initialization, easy interface. imf points to the start of the IMF
* file. The imf pointer must not be freed as long as playback is ongoing.
* imflength is the size (in bytes) of the IMF data.
* clock must be an incrementing value that wraps to 0 after 65535. The clock
* speed will control the playback's tempo.
* loopscount tells how many times the song will have to be looped (0 means
* "loop forever").
* returns 0 on success, non-zero otherwise. */
int mdr_opl_imfeasy_init(void *imf, unsigned short imflength, unsigned short clock, unsigned char loopscount);
 
/* Playback of an IMF file preloaded via mdr_opl_imfeasy_init(). This function
* must be called repeatedly at a high frequency for best playback quality.
* Returns 0 on success, 1 if playback ended, -1 on error. */
int mdr_opl_imfeasy_play(unsigned short clock);
 
/*** ADVANCED INTERFACE ***/
 
/* playback initialization, this function must be called immediately before
* playback. imf points to the start of the IMF file and must contain at least
* the first 6 bytes of the audio file.
* clock must be an incrementing value that wraps to 0 after 65535.
* the clock speed will control the playback's tempo.
* returns the amount of consumed bytes (0, 4 or 6) */
unsigned short mdr_opl_imf_init(void *imf, unsigned short clock);
 
/* Playback, advanced version. Feeds the IMF playback routine with IMF data.
* Returns the amount of bytes that have been consumed, hence the next call
* should provide an imf pointer advanced by this many bytes (and imflen
* decreased accordingly). Such approach might not be the most intuitive, but
* it allows to load an imf song partially and provide only short chunks of
* data for playback instead of having to buffer the entire song in memory.
* For a simpler call that requires to buffer the entire IMF file in memory,
* see mdr_opl_imf_playeasy().
* This function must be called repeatedly at a high frequency for best
* playback quality. */
unsigned short mdr_opl_imf_play(void *imf, unsigned short imflen, unsigned short clock);
 
 
/*****************************************************************************
* OPL TIMER FUNCTIONS *
*****************************************************************************/
 
/* configures and starts a timer given type so it emits a tick every count
* periods. Two timer types are available:
* MDR_OPL_TIMER_80US - with a period of 80us
* MDR_OPL_TIMER_320US - with a period of 320us
* count may range from 0 to 255, but 0 means "256 periods".
*
* You may use only one timer at a time.
*
* EXAMPLE: setting up MDR_OPL_TIMER_80US with a count of 25 would make the
* timer tick every 2ms (25 * 80us). */
void mdr_opl_timer_set(enum MDR_OPL_TIMER timertype, unsigned char count);
 
/* returns 1 if timer tick occured, 0 otherwise. After a tick has been
* returned, this function will return 0 until next tick.
*
* it is important to note that there is no way to know whether one tick
* passed since last time, or more, so it is up to you to make sure you call
* this function fast enough. */
unsigned char mdr_opl_timer_tick(void);
 
#endif
/sved/trunk/mdr/inc/mdr/pcx.h
4,7 → 4,7
* This file is part of the Mateusz' DOS Routines (MDR): http://mdr.osdn.io
* Published under the terms of the MIT License, as stated below.
*
* Copyright (C) 2022 Mateusz Viste
* Copyright (C) 2022-2023 Mateusz Viste
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
28,6 → 28,8
#ifndef MDR_PCX_H
#define MDR_PCX_H
 
#include <stdio.h> /* FILE */
 
struct pcx_hdr {
unsigned char rle;
unsigned char bpp;
41,10 → 43,35
} pal[256];
};
 
int pcx_anal(struct pcx_hdr *h, FILE *fd, unsigned long offset, unsigned short len);
int pcx_load(void *ptr, size_t ptrsz, const struct pcx_hdr *h, FILE *fd, unsigned long offset);
/* analyzes the header of a PCX file and fills the pcx_hdr struct accordingly.
* fd must be a valid (open) file descriptor.
* offset is the address inside the file where the PCX data is located
* (usually 0, unless the file is some kind of container).
* len is the total length of the PCX data. len=0 means "same as file size"
* returns 0 on success, non-zero otherwise. */
int mdr_pcx_anal(struct pcx_hdr *h, FILE *fd, unsigned long offset, unsigned long len);
 
/* convert img to 8bpp if needed (ie unpack 2 and 4bpp data to 8bpp) */
int pcx_convto8bpp(void *img, const struct pcx_hdr *h);
/* this function should be called to load the next row of a PCX file into a
* buffer pointed at by bufptr. you will typically want to call this function
* h->max_y times. ptr must be at least (h->max_x + 1) bytes large for 8bpp.
* the pcx_hdr struct must have been produced by pcx_anal().
* returns 0 on success, non-zero otherwise. */
int mdr_pcx_loadrow(void *bufptr, const struct pcx_hdr *h, FILE *fd);
 
/* load an entire PCX file into a pixel buffer. the PCX data must have been
* previously analyzed by pcx_anal() and the fd file pointer must not have been
* modified since then. the destination buffer must be large enough to hold all
* pixels, ie. (h->max_x + 1) * (h->max_y + 1) for 8 bpp.
* returns 0 on success, non-zero otherwise. */
int mdr_pcx_load(void *ptr, const struct pcx_hdr *h, FILE *fd);
 
/* convert img to 8bpp if needed (ie unpack 2 and 4bpp data to 8bpp).
* the conversion is performed in-place, make sure the img buffer is large
* enough to accomodate the size of the data after conversion (ie. twice as
* big on 4bpp source, 4x times as big on 2bpp source and 8x as big on 1bpp
* source).
* if rowflag is set to a non-zero value, then the routine assumes img
* contains only a single row of pixels */
int mdr_pcx_to8bpp(void *img, const struct pcx_hdr *h, unsigned char rowflag);
 
#endif
/sved/trunk/mdr/inc/mdr/timer.h
4,7 → 4,7
* This file is part of the Mateusz' DOS Routines (MDR): http://mdr.osdn.io
* Published under the terms of the MIT License, as stated below.
*
* Copyright (C) 2014-2022 Mateusz Viste
* Copyright (C) 2014-2023 Mateusz Viste
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
28,25 → 28,24
#ifndef MDR_TIMER_H
#define MDR_TIMER_H
 
/* reset the timer value, this can be used by the application to make sure
* no timer wrap occurs during critical parts of the code flow */
void timer_reset(void);
/* Starts the timer by reprogramming the 8253 chip from its default 18.2 Hz
* frequency to about 1.1 kHz. It is mandatory to revert the timer to its
* original frequency via mdr_timer_stop() before your application quits. */
void mdr_timer_init(void);
 
/* This routine will stop the fast clock if it is going. It has void return
* value so that it can be an exit procedure. */
void timer_stop(void);
/* Fills res with the amount of microseconds that elapsed since either
* mdr_timer_init() or mdr_timer_reset(), whichever was called last.
* Note that the res counter wraps around approximately every 71 minutes if
* mdr_timer_reset() is not called. */
void mdr_timer_read(unsigned long *res);
 
/* This routine will start the fast clock rate by installing the
* handle_clock routine as the interrupt service routine for the clock
* interrupt and then setting the interrupt rate up to its higher speed
* by programming the 8253 timer chip.
* This routine does nothing if the clock rate is already set to
* its higher rate, but then it returns -1 to indicate the error. */
void timer_init(void);
/* Reset the timer value, this can be used by the application to make sure
* no timer wrap occurs during critical parts of your code flow */
void mdr_timer_reset(void);
 
/* This routine will return the present value of the time, which is
* read from the nowtime structure. Interrupts are disabled during this
* time to prevent the clock from changing while it is being read. */
void timer_read(unsigned long *res);
/* Stops (uninstalls) the timer. This must be called before your application
* quits, otherwise the system will likely crash. This function has a void
* return value so that it can be registered as an atexit() procedure. */
void mdr_timer_stop(void);
 
#endif
/sved/trunk/mdr/inc/mdr/vid12.h
4,7 → 4,7
* This file is part of the Mateusz' DOS Routines (MDR): http://mdr.osdn.io
* Published under the terms of the MIT License, as stated below.
*
* Copyright (C) 2022 Mateusz Viste
* Copyright (C) 2022-2023 Mateusz Viste
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
29,12 → 29,16
 
#define MDR_VID12_H
 
/* init video mode 12h (640x480x16c) */
/* init video mode 12h (640x480x16c)
* remember to call vid12_close() at exit time */
void vid12_init(void);
 
/* Wait until VBLANK */
/* wait until VBLANK */
void vid12_waitvblank(void);
 
/* wait until ANY blank: either VBLANK or HBLANK */
void vid12_waitblank(void);
 
/* clear screen using color
* this function is fastest when color is 0 or 15 */
void vid12_cls(unsigned char color);
48,15 → 52,27
* pattern must be 8 bytes long */
void vid12_linepat(unsigned short linefirst, unsigned short linelast, const unsigned char *pattern);
 
/* deinit video mode 12h and resets to previous mode */
void vid12_close(void);
 
/* puts a pixel on screen */
void vid12_putpixel(unsigned short x, unsigned short y, unsigned char col);
 
/* draws a horizonatal line from [x1,y] to [x2,y] */
void vid12_hline(unsigned short y, unsigned short x1, unsigned short x2, unsigned char color);
 
/* write an entire scanline (640 pixels) to screen. the pixels data must be
* a serie of 640 bytes having values in the range [0..15] */
void vid12_putscanline(unsigned short scanline, const unsigned char *pixels);
 
/* set index palette color to given R,G,B value. each R,G,B component must be
* a 6 bit value in the range [0..63] (where 63 is the maximum luminosity) */
void vid12_setpalette(unsigned char index, unsigned char r, unsigned char g, unsigned char b);
 
/*****************************
* VRAM TO VRAM operations *
*****************************/
 
/* prepares VGA for a VRAM-to-VRAM copy operation */
void vid12_vramcpy_prep(void);
 
68,5 → 84,4
/* sets VGA back to its normal state after VRAM-to-VRAM operations */
void vid12_vramcpy_done(void);
 
void vid12_setpalette(unsigned char index, unsigned char r, unsigned char g, unsigned char b);
#endif