aboutsummaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorspicyjpeg <thatspicyjpeg@gmail.com>2023-07-03 08:13:23 +0200
committerspicyjpeg <thatspicyjpeg@gmail.com>2023-07-03 08:13:23 +0200
commit06e65bea3a778b2dae5af77a7935ae3868ddd4d3 (patch)
tree3af954ebead7540c9478d0a026ca2e59f3cf7b64 /examples
parent472cf1c254ea5be5aff8a6c7067cbed2d467d85b (diff)
downloadpsn00bsdk-06e65bea3a778b2dae5af77a7935ae3868ddd4d3.tar.gz
Fix setjmp.h, FntSort(), examples, rewrite system/timer
Diffstat (limited to 'examples')
-rw-r--r--examples/sound/cdstream/main.c52
-rw-r--r--examples/sound/cdstream/stream.c76
-rw-r--r--examples/sound/cdstream/stream.h67
-rw-r--r--examples/system/timer/main.c255
4 files changed, 255 insertions, 195 deletions
diff --git a/examples/sound/cdstream/main.c b/examples/sound/cdstream/main.c
index fbca65e..2bd2142 100644
--- a/examples/sound/cdstream/main.c
+++ b/examples/sound/cdstream/main.c
@@ -159,13 +159,13 @@ typedef struct {
(((uint32_t) (x) & 0xff000000) >> 24) \
)
-/* Interrupt callbacks */
+/* Helper functions */
#define DUMMY_BLOCK_ADDR 0x1000
#define STREAM_BUFFER_ADDR 0x1010
typedef struct {
- int start_lba, stream_length;
+ int start_lba, stream_length, sample_rate;
volatile int next_sector;
volatile size_t refill_length;
@@ -175,13 +175,11 @@ static Stream_Context stream_ctx;
static StreamReadContext read_ctx;
void cd_read_handler(CdlIntrResult event, uint8_t *payload) {
- // Mark the data as valid.
+ // Mark the data that has just been read as valid.
if (event != CdlDiskError)
Stream_Feed(&stream_ctx, read_ctx.refill_length * 2048);
}
-/* Helper functions */
-
// This isn't actually required for this example, however it is necessary if the
// stream buffers are going to be allocated into a region of SPU RAM that was
// previously used (to make sure the IRQ is not going to be triggered by any
@@ -254,14 +252,12 @@ void setup_stream(const CdlLOC *pos) {
int num_chunks =
(SWAP_ENDIAN(vag->size) + vag->interleave - 1) / vag->interleave;
- config.spu_address = STREAM_BUFFER_ADDR;
- config.channel_mask = 0;
- config.interleave = vag->interleave;
- config.buffer_size = RAM_BUFFER_SIZE;
- config.refill_threshold = 0;
- config.sample_rate = SWAP_ENDIAN(vag->sample_rate);
- config.refill_callback = (void *) 0;
- config.underrun_callback = (void *) 0;
+ __builtin_memset(&config, 0, sizeof(Stream_Config));
+
+ config.spu_address = STREAM_BUFFER_ADDR;
+ config.interleave = vag->interleave;
+ config.buffer_size = RAM_BUFFER_SIZE;
+ config.sample_rate = SWAP_ENDIAN(vag->sample_rate);
// Use the first N channels of the SPU and pan them left/right in pairs
// (this assumes the stream contains one or more stereo tracks).
@@ -277,6 +273,7 @@ void setup_stream(const CdlLOC *pos) {
read_ctx.start_lba = CdPosToInt(pos) + 1;
read_ctx.stream_length =
(num_channels * num_chunks * vag->interleave + 2047) / 2048;
+ read_ctx.sample_rate = config.sample_rate;
read_ctx.next_sector = 0;
read_ctx.refill_length = 0;
@@ -315,10 +312,9 @@ int main(int argc, const char* argv[]) {
Stream_Start(&stream_ctx, false);
int sectors_per_chunk = (stream_ctx.chunk_size + 2047) / 2048;
- int vag_sample_rate = getSPUSampleRate(stream_ctx.config.sample_rate);
bool paused = false;
- int sample_rate = vag_sample_rate;
+ int sample_rate = read_ctx.sample_rate;
uint16_t last_buttons = 0xffff;
@@ -326,12 +322,12 @@ int main(int argc, const char* argv[]) {
bool buffering = feed_stream();
FntPrint(-1, "PLAYING SPU STREAM\n\n");
- FntPrint(-1, "BUFFER: %d (%d)\n", stream_ctx.db_active, stream_ctx.chunk_counter);
+ FntPrint(-1, "BUFFER: %d\n", stream_ctx.db_active);
FntPrint(-1, "STATUS: %s\n\n", buffering ? "READING" : "IDLE");
FntPrint(-1, "BUFFERED: %d/%d\n", stream_ctx.buffer.length, stream_ctx.config.buffer_size);
FntPrint(-1, "POSITION: %d/%d\n", read_ctx.next_sector, read_ctx.stream_length);
- FntPrint(-1, "SMP RATE: %5d HZ\n\n", (sample_rate * 44100) >> 12);
+ FntPrint(-1, "SMP RATE: %5d HZ\n\n", sample_rate);
FntPrint(-1, "[START] %s\n", paused ? "RESUME" : "PAUSE");
FntPrint(-1, "[LEFT/RIGHT] SEEK\n");
@@ -371,16 +367,18 @@ int main(int argc, const char* argv[]) {
if ((last_buttons & PAD_CIRCLE) && !(pad->btn & PAD_CIRCLE))
read_ctx.next_sector = 0;
- if (!(pad->btn & PAD_DOWN) && (sample_rate > 0x400))
- sample_rate -= 0x40;
- if (!(pad->btn & PAD_UP) && (sample_rate < 0x2000))
- sample_rate += 0x40;
- if ((last_buttons & PAD_CROSS) && !(pad->btn & PAD_CROSS))
- sample_rate = vag_sample_rate;
-
- // Only set the sample rate registers if necessary.
- if (pad->btn != 0xffff)
- Stream_SetSampleRate(&stream_ctx, (sample_rate * 44100) >> 12);
+ if (!(pad->btn & PAD_DOWN) && (sample_rate > 11000)) {
+ sample_rate -= 100;
+ Stream_SetSampleRate(&stream_ctx, sample_rate);
+ }
+ if (!(pad->btn & PAD_UP) && (sample_rate < 88200)) {
+ sample_rate += 100;
+ Stream_SetSampleRate(&stream_ctx, sample_rate);
+ }
+ if ((last_buttons & PAD_CROSS) && !(pad->btn & PAD_CROSS)) {
+ sample_rate = read_ctx.sample_rate;
+ Stream_SetSampleRate(&stream_ctx, sample_rate);
+ }
last_buttons = pad->btn;
}
diff --git a/examples/sound/cdstream/stream.c b/examples/sound/cdstream/stream.c
index aaf5703..624b6e1 100644
--- a/examples/sound/cdstream/stream.c
+++ b/examples/sound/cdstream/stream.c
@@ -7,8 +7,8 @@
#include <stddef.h>
#include <stdbool.h>
#include <stdlib.h>
-#include <string.h>
#include <assert.h>
+#include <psxgpu.h>
#include <psxspu.h>
#include <psxetc.h>
#include <psxapi.h>
@@ -27,10 +27,20 @@
#define _min(x, y) (((x) < (y)) ? (x) : (y))
-/* Interrupt handlers */
+/* Private utilities */
static volatile Stream_Context *_active_ctx = (void *) 0;
+static Stream_Time _default_timer_function(void) {
+ return VSync(-1);
+}
+
+static int _get_default_timer_rate(void) {
+ return (GetVideoMode() == MODE_PAL) ? 50 : 60;
+}
+
+/* Interrupt handlers */
+
static void _spu_irq_handler(void) {
Stream_Context *ctx = _active_ctx;
@@ -59,7 +69,9 @@ static void _spu_irq_handler(void) {
// once the buffer's length is below the refill threshold.
ctx->db_active ^= 1;
ctx->buffering = true;
- ctx->chunk_counter++;
+
+ ctx->play_time += ctx->samples_per_chunk;
+ ctx->last_updated = ctx->config.timer_function();
size_t tail = ctx->buffer.tail;
uint8_t *ptr = &ctx->buffer.data[ctx->buffer.tail];
@@ -82,12 +94,16 @@ static void _spu_irq_handler(void) {
uint32_t address =
ctx->config.spu_address + (ctx->db_active ? ctx->chunk_size : 0);
+ int sample_rate = ctx->new_sample_rate;
+ ctx->config.sample_rate = sample_rate;
+
SPU_IRQ_ADDR = getSPUAddr(address);
for (uint32_t ch = 0, mask = ctx->config.channel_mask; mask; ch++, mask >>= 1) {
if (!(mask & 1))
continue;
+ SPU_CH_FREQ (ch) = getSPUSampleRate(sample_rate);
SPU_CH_LOOP_ADDR(ch) = getSPUAddr(address + offset);
offset += ctx->config.interleave;
@@ -110,8 +126,8 @@ static void _spu_dma_handler(void) {
/* Public API */
void Stream_Init(Stream_Context *ctx, const Stream_Config *config) {
- memset(ctx, 0, sizeof(Stream_Context));
- memcpy(&(ctx->config), config, sizeof(Stream_Config));
+ __builtin_memset(ctx, 0, sizeof(Stream_Context));
+ __builtin_memcpy(&(ctx->config), config, sizeof(Stream_Config));
ctx->num_channels = 0;
for (uint32_t mask = config->channel_mask; mask; mask >>= 1) {
@@ -121,8 +137,15 @@ void Stream_Init(Stream_Context *ctx, const Stream_Config *config) {
assert(ctx->num_channels);
- ctx->chunk_size = ctx->config.interleave * ctx->num_channels;
- ctx->buffer.data = malloc(config->buffer_size);
+ if (!ctx->config.timer_function) {
+ ctx->config.timer_rate = _get_default_timer_rate();
+ ctx->config.timer_function = &_default_timer_function;
+ }
+
+ ctx->chunk_size = ctx->config.interleave * ctx->num_channels;
+ ctx->samples_per_chunk = ctx->config.interleave / 16 * 28;
+ ctx->new_sample_rate = ctx->config.sample_rate;
+ ctx->buffer.data = malloc(config->buffer_size);
assert(ctx->buffer.data);
@@ -160,6 +183,9 @@ bool Stream_Start(Stream_Context *ctx, bool resume) {
uint32_t address =
ctx->config.spu_address + (ctx->db_active ? ctx->chunk_size : 0);
+ int sample_rate = ctx->new_sample_rate;
+ ctx->config.sample_rate = sample_rate;
+
SpuSetKey(0, ctx->config.channel_mask);
for (uint32_t ch = 0, mask = ctx->config.channel_mask; mask; ch++, mask >>= 1) {
@@ -167,7 +193,7 @@ bool Stream_Start(Stream_Context *ctx, bool resume) {
continue;
SPU_CH_ADDR (ch) = getSPUAddr(address);
- SPU_CH_FREQ (ch) = getSPUSampleRate(ctx->config.sample_rate);
+ SPU_CH_FREQ (ch) = getSPUSampleRate(sample_rate);
SPU_CH_ADSR1(ch) = 0x00ff;
SPU_CH_ADSR2(ch) = 0x0000;
@@ -197,26 +223,40 @@ bool Stream_Stop(void) {
SpuSetKey(1, ctx->config.channel_mask);
- _active_ctx = (void *) 0;
+ ctx->last_stopped = ctx->config.timer_function();
+ _active_ctx = (void *) 0;
+
return true;
}
void Stream_SetSampleRate(Stream_Context *ctx, int value) {
- ctx->config.sample_rate = value;
-
- if (!Stream_IsActive(ctx))
- return;
-
- for (uint32_t ch = 0, mask = ctx->config.channel_mask; mask; ch++, mask >>= 1) {
- if (mask & 1)
- SPU_CH_FREQ(ch) = getSPUSampleRate(value);
- }
+ ctx->new_sample_rate = value;
}
bool Stream_IsActive(const Stream_Context *ctx) {
return (ctx == _active_ctx);
}
+uint32_t Stream_GetSamplesPlayed(const Stream_Context *ctx) {
+ // Calculate the time elapsed from the last update (or since the stream was
+ // stopped) and use the value to estimate how many samples have been played
+ // since then.
+ Stream_Time delta;
+
+ if (ctx == _active_ctx)
+ delta = ctx->config.timer_function() - ctx->last_updated;
+ else
+ delta = ctx->last_stopped - ctx->last_updated;
+
+ return ctx->play_time + (
+ (delta * ctx->config.sample_rate) / ctx->config.timer_rate
+ );
+}
+
+void Stream_ResetSamplesPlayed(Stream_Context *ctx) {
+ ctx->play_time = 0;
+}
+
size_t Stream_GetRefillLength(const Stream_Context *ctx) {
int unbuf_total = (int) ctx->config.buffer_size - (int) ctx->buffer.length;
diff --git a/examples/sound/cdstream/stream.h b/examples/sound/cdstream/stream.h
index aa384ed..ab28f50 100644
--- a/examples/sound/cdstream/stream.h
+++ b/examples/sound/cdstream/stream.h
@@ -32,7 +32,9 @@
/* Type definitions */
-typedef uint32_t *(*Stream_Callback)(void);
+typedef uint32_t Stream_Time;
+typedef void (*Stream_Callback)(void);
+typedef Stream_Time (*Stream_TimerFunction)(void);
/**
* @brief Stream initialization settings structure.
@@ -45,20 +47,24 @@ typedef uint32_t *(*Stream_Callback)(void);
* cannot be used. The channel mask is a bitfield whose bits represent which SPU
* channels the stream is going to use: for instance, a value of 0b1101 will
* assign the first channel of the stream to SPU channel 0, the second channel
- * to SPU channel 2 and the third channel to SPU channel 3. The sample rate is
- * in Hertz, while the interleave and buffer size are in bytes.
- *
- * The refill threshold, refill callback and underrun callback are optional. If
- * provided, the callbacks will be invoked by the SPU IRQ handler once the
- * FIFO's length goes below the specified threshold and once it reaches zero,
- * respectively.
+ * to SPU channel 2 and the third channel to SPU channel 3. The sample rate and
+ * optional timer rate are in Hertz, while the interleave and buffer size are in
+ * bytes.
+ *
+ * The refill threshold, refill callback, underrun callback and timer function
+ * are optional. If provided, the callbacks will be invoked by the SPU IRQ
+ * handler once the FIFO's length goes below the specified threshold and once it
+ * reaches zero, respectively. The timer function will be used to improve the
+ * accuracy of Stream_GetSamplesPlayed(); if not provided, VSync(-1) will be
+ * used by default.
*/
typedef struct {
uint32_t spu_address, channel_mask;
size_t interleave, buffer_size, refill_threshold;
- int sample_rate;
+ int sample_rate, timer_rate;
- Stream_Callback refill_callback, underrun_callback;
+ Stream_Callback refill_callback, underrun_callback;
+ Stream_TimerFunction timer_function;
} Stream_Config;
typedef struct {
@@ -71,20 +77,20 @@ typedef struct {
*
* @details This structure represents a single audio stream. An arbitrary number
* of streams may be created concurrently, however only one can be active at a
- * time (as the SPU only provides a single interrupt). With the exception of the
- * chunk counter, most fields are only used internally and shall not be accessed
- * directly.
+ * time (as the SPU only provides a single interrupt). All fields are only used
+ * internally and shall not be accessed directly.
*/
typedef struct {
Stream_Config config;
volatile Stream_Buffer buffer;
void *old_irq_handler, *old_dma_handler;
- size_t chunk_size;
+ size_t chunk_size, samples_per_chunk;
uint8_t num_channels;
- volatile uint8_t db_active, buffering, callback_issued;
- volatile uint32_t chunk_counter;
+ volatile uint8_t db_active, buffering, callback_issued;
+ volatile Stream_Time last_updated, last_stopped, play_time;
+ volatile int new_sample_rate;
} Stream_Context;
/* Public API */
@@ -146,9 +152,9 @@ bool Stream_Stop(void);
/**
* @brief Changes the sampling rate of a stream.
*
- * @details If the stream is currently active the pitch of the SPU channels
- * assigned to it is changed to match the new value, otherwise the new sampling
- * rate will be applied once the stream is started.
+ * @details If the stream is currently active the change will apply on the next
+ * FIFO data pull, otherwise the new sampling rate will be applied once the
+ * stream is started or resumed.
*
* @param ctx
* @param value
@@ -164,6 +170,29 @@ void Stream_SetSampleRate(Stream_Context *ctx, int value);
bool Stream_IsActive(const Stream_Context *ctx);
/**
+ * @brief Returns an estimate of how many audio samples have been played so far.
+ *
+ * @details The returned value can be divided by the stream's sampling rate to
+ * obtain the total playback time in seconds. The value is interpolated over
+ * time using VSync(-1) as a time reference by default. If greater accuracy is
+ * required, a custom timer function can be provided instead by setting the
+ * appropriate fields in the configuration object before calling Stream_Init().
+ *
+ * @param ctx
+ * @return Number of audio samples
+ *
+ * @see Stream_ResetSamplesPlayed()
+ */
+uint32_t Stream_GetSamplesPlayed(const Stream_Context *ctx);
+
+/**
+ * @brief Resets the audio sample counter returned by Stream_GetSamplesPlayed().
+ *
+ * @param ctx
+ */
+void Stream_ResetSamplesPlayed(Stream_Context *ctx);
+
+/**
* @brief Returns how many bytes in a stream's FIFO are currently empty and can
* be filled.
*
diff --git a/examples/system/timer/main.c b/examples/system/timer/main.c
index eb62712..c424e84 100644
--- a/examples/system/timer/main.c
+++ b/examples/system/timer/main.c
@@ -1,156 +1,149 @@
-#include <sys/types.h>
-#include <stdio.h>
+/*
+ * PSn00bSDK hardware timer example
+ * (C) 2023 spicyjpeg - MPL licensed
+ */
+
+#include <stdint.h>
#include <psxgpu.h>
-#include <psxapi.h>
#include <psxetc.h>
+#include <psxapi.h>
#include <hwregs_c.h>
-/* OT and Packet Buffer sizes */
-#define OT_LEN 256
-#define PACKET_LEN 1024
+/* Display/GPU context utilities */
-/* Screen resolution */
-#define SCREEN_XRES 320
-#define SCREEN_YRES 240
+#define SCREEN_XRES 320
+#define SCREEN_YRES 240
-/* Screen center position */
-#define CENTERX SCREEN_XRES>>1
-#define CENTERY SCREEN_YRES>>1
+#define BGCOLOR_R 48
+#define BGCOLOR_G 24
+#define BGCOLOR_B 0
+typedef struct {
+ DISPENV disp;
+ DRAWENV draw;
+} Framebuffer;
-/* Double buffer structure */
typedef struct {
- DISPENV disp; /* Display environment */
- DRAWENV draw; /* Drawing environment */
-} DB;
+ Framebuffer db[2];
+ int db_active;
+} RenderContext;
+
+void init_context(RenderContext *ctx) {
+ Framebuffer *db;
+
+ ResetGraph(0);
+ ctx->db_active = 0;
+
+ db = &(ctx->db[0]);
+ SetDefDispEnv(&(db->disp), 0, 0, SCREEN_XRES, SCREEN_YRES);
+ SetDefDrawEnv(&(db->draw), SCREEN_XRES, 0, SCREEN_XRES, SCREEN_YRES);
+ setRGB0(&(db->draw), BGCOLOR_R, BGCOLOR_G, BGCOLOR_B);
+ db->draw.isbg = 1;
+ db->draw.dtd = 1;
+
+ db = &(ctx->db[1]);
+ SetDefDispEnv(&(db->disp), SCREEN_XRES, 0, SCREEN_XRES, SCREEN_YRES);
+ SetDefDrawEnv(&(db->draw), 0, 0, SCREEN_XRES, SCREEN_YRES);
+ setRGB0(&(db->draw), BGCOLOR_R, BGCOLOR_G, BGCOLOR_B);
+ db->draw.isbg = 1;
+ db->draw.dtd = 1;
+
+ PutDrawEnv(&(db->draw));
+ //PutDispEnv(&(db->disp));
+
+ // Create a text stream at the top of the screen.
+ FntLoad(960, 0);
+ FntOpen(8, 16, 304, 208, 2, 512);
+}
+
+void display(RenderContext *ctx) {
+ Framebuffer *db;
+
+ DrawSync(0);
+ VSync(0);
+ ctx->db_active ^= 1;
-/* Double buffer variables */
-DB db[2];
-int db_active = 0;
+ db = &(ctx->db[ctx->db_active]);
+ PutDrawEnv(&(db->draw));
+ PutDispEnv(&(db->disp));
+ SetDispMask(1);
+}
+
+/* Interrupt handlers */
+typedef struct {
+ int irq_count, last_irq_count, irqs_per_sec;
+} TimerState;
-/* Function declarations */
-void init();
-void display();
+static volatile TimerState timer_state[3];
+static void timer0_handler(void) {
+ timer_state[0].irq_count++;
+}
-volatile int timer_calls = 0;
+static void timer1_handler(void) {
+ timer_state[1].irq_count++;
+}
-void timer_func()
-{
- timer_calls++;
+static void timer2_handler(void) {
+ timer_state[2].irq_count++;
}
-volatile int vsync_count = 0;
-volatile int tick_count = 0;
-volatile int tick_value = 0;
-
-void vsync_func()
-{
- vsync_count++;
- if( vsync_count > 60 )
- {
- tick_value = timer_calls-tick_count;
- tick_count = timer_calls;
- vsync_count = 0;
+static void vblank_handler(void) {
+ int refresh_rate = (GetVideoMode() == MODE_PAL) ? 50 : 60;
+
+ // Only update once per second (every 50 or 60 vblanks).
+ if (VSync(-1) % refresh_rate)
+ return;
+
+ for (int i = 0; i < 3; i++) {
+ TimerState *state = &timer_state[i];
+
+ int count = state->irq_count;
+ state->irqs_per_sec = count - state->last_irq_count;
+ state->last_irq_count = count;
}
}
-/* Main function */
-int main() {
-
- int counter;
-
- /* Init graphics and GTE */
- init();
-
-
+/* Main */
+
+static RenderContext ctx;
+
+int main(int argc, const char* argv[]) {
+ init_context(&ctx);
+
+ // Set up the timers and register callbacks for their interrupts.
+ TIMER_CTRL(0) = 0x0160; // Dotclock input, repeated IRQ on overflow
+ TIMER_CTRL(1) = 0x0160; // Hblank input, repeated IRQ on overflow
+ TIMER_CTRL(2) = 0x0260; // CLK/8 input, repeated IRQ on overflow
+
+ __builtin_memset(timer_state, 0, sizeof(timer_state));
+
EnterCriticalSection();
- //SetRCnt(RCntCNT2, 0xF040, RCntMdINTR);
-
- // NTSC clock base
- counter = 4304000/560;
-
- // PAL clock base
- //counter = 5163000/560;
-
- SetRCnt(RCntCNT2, counter, RCntMdINTR);
- TIMER_CTRL(2) = 0x1E58;
- InterruptCallback(6, timer_func);
- StartRCnt(RCntCNT2);
- ChangeClearRCnt(2, 0);
+ InterruptCallback(IRQ_TIMER0, &timer0_handler);
+ InterruptCallback(IRQ_TIMER1, &timer1_handler);
+ InterruptCallback(IRQ_TIMER2, &timer2_handler);
+ VSyncCallback(&vblank_handler);
ExitCriticalSection();
-
- VSyncCallback(vsync_func);
-
- /* Main loop */
- while( 1 ) {
-
- FntPrint(-1, "TIMER COUNT=%d\n", timer_calls);
- FntPrint(-1, "TICKS/SEC=%d\n", tick_value);
-
- /* Swap buffers and draw text */
- display();
-
+
+ while (1) {
+ FntPrint(-1, "HARDWARE TIMER EXAMPLE\n\n");
+
+ for (int i = 0; i < 3; i++) {
+ TimerState *state = &timer_state[i];
+
+ FntPrint(-1, "TIMER %d:\n", i);
+ FntPrint(-1, " VALUE: %d\n", TIMER_VALUE(i));
+ FntPrint(-1, " IRQS: %d\n", state->irq_count);
+ FntPrint(-1, " IRQS/S: %d\n\n", state->irqs_per_sec);
+ }
+
+ FntPrint(-1, "VBLANK COUNTER:\n");
+ FntPrint(-1, " VALUE: %d\n\n", VSync(-1));
+
+ FntFlush(-1);
+ display(&ctx);
}
-
- return 0;
-
-}
-void init() {
-
- /* Reset the GPU, also installs a VSync event handler */
- ResetGraph( 0 );
- //SetVideoMode(MODE_PAL);
-
- /* Set display and draw environment areas */
- /* (display and draw areas must be separate, otherwise hello flicker) */
- SetDefDispEnv( &db[0].disp, 0, 0, SCREEN_XRES, SCREEN_YRES );
- SetDefDrawEnv( &db[0].draw, SCREEN_XRES, 0, SCREEN_XRES, SCREEN_YRES );
-
- /* Enable draw area clear and dither processing */
- setRGB0( &db[0].draw, 63, 0, 127 );
- db[0].draw.isbg = 1;
- db[0].draw.dtd = 1;
-
-
- /* Define the second set of display/draw environments */
- SetDefDispEnv( &db[1].disp, SCREEN_XRES, 0, SCREEN_XRES, SCREEN_YRES );
- SetDefDrawEnv( &db[1].draw, 0, 0, SCREEN_XRES, SCREEN_YRES );
-
- //db[0].disp.screen.y = 24;
- //db[1].disp.screen.y = 24;
-
- setRGB0( &db[1].draw, 63, 0, 127 );
- db[1].draw.isbg = 1;
- db[1].draw.dtd = 1;
-
-
- /* Apply the drawing environment of the first double buffer */
- PutDrawEnv( &db[0].draw );
-
- FntLoad(960, 0);
- FntOpen(0, 8, 320, 216, 0, 100);
-
+ return 0;
}
-
-void display() {
-
- FntFlush(-1);
-
- /* Wait for GPU to finish drawing and vertical retrace */
- DrawSync( 0 );
- VSync( 0 );
-
- /* Swap buffers */
- db_active ^= 1;
-
- /* Apply display/drawing environments */
- PutDrawEnv( &db[db_active].draw );
- PutDispEnv( &db[db_active].disp );
-
- /* Enable display */
- SetDispMask( 1 );
-
-} \ No newline at end of file