# HG changeset patch # User John Tsiombikas # Date 1508949293 -10800 # Node ID a4788c95991855fe759e02ae07a063d4d913107a initial commit diff -r 000000000000 -r a4788c959918 .hgignore --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.hgignore Wed Oct 25 19:34:53 2017 +0300 @@ -0,0 +1,7 @@ +\.o$ +\.d$ +\.swp$ +\.uaem$ +^imgv$ +^logfile$ +convhammer$ diff -r 000000000000 -r a4788c959918 Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Makefile Wed Oct 25 19:34:53 2017 +0300 @@ -0,0 +1,14 @@ +src = $(wildcard src/*.c) $(wildcard src/amiga/*.c) +obj = $(src:.c=.o) +bin = imgv + +CC = vc +CFLAGS = -Isrc -Isrc/amiga +LDFLAGS = -lamiga + +$(bin): $(obj) + $(CC) -o $@ $(obj) $(LDFLAGS) + +.PHONY: clean +clean: + rm -f $(obj) $(bin) diff -r 000000000000 -r a4788c959918 src/amiga/copper.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/amiga/copper.c Wed Oct 25 19:34:53 2017 +0300 @@ -0,0 +1,113 @@ +#include +#include +#include +#include +#include "copper.h" +#include "hwregs.h" + +uint32_t *copperlist, *copperlist_end; +static uint32_t *copmem, *curlist; +static void *savedlist, *savedview; +static int mode, copmem_size; + +struct GfxBase *GfxBase; + +int init_copper(int maxlist, int nlists) +{ + /* save copper list (TODO) */ + if((GfxBase = (struct GfxBase*)OpenLibrary("graphics.library", 0))) { + savedlist = GfxBase->copinit; + savedview = GfxBase->ActiView; + LoadView(0); + WaitTOF(); + WaitTOF(); + + CloseLibrary(GfxBase); + GfxBase = 0; + } + + /* allocate and set new copper lists */ + if(maxlist <= 0) maxlist = 256; + mode = nlists >= COPPER_DOUBLE ? COPPER_DOUBLE : COPPER_SINGLE; + + copmem_size = maxlist * 4 * mode; + if(!(copmem = (uint32_t*)AllocMem(copmem_size, MEMF_CHIP))) { + printf("failed to allocate chip memory for %d copper lists of %d instructions\n", + mode, maxlist); + return -1; + } + + curlist = copperlist = copmem; + *curlist = COPPER_END; + + if(mode == COPPER_DOUBLE) { + copperlist = curlist + maxlist; + *copperlist = COPPER_END; + } + copperlist_end = copperlist; + + REG32_COP1LC = (uint32_t)curlist; + REG_COPJMP1 = 0; /* causes copper to read COP1LC */ + return 0; +} + +void cleanup_copper(void) +{ + /* restore copper list */ + REG32_COP1LC = (uint32_t)savedlist; + + if((GfxBase = (struct GfxBase*)OpenLibrary("graphics.library", 0))) { + GfxBase->copinit = savedlist; + LoadView(savedview); + WaitTOF(); + WaitTOF(); + CloseLibrary(GfxBase); + GfxBase = 0; + } + + if(copmem) { + FreeMem(copmem, copmem_size); + } +} + +void enable_copper(void) +{ + REG_DMACON = SETBITS(DMA_COPPER); +} + +void disable_copper(void) +{ + REG_DMACON = CLRBITS(DMA_COPPER); +} + +void clear_copper(void) +{ + copperlist_end = copperlist; + *copperlist_end = COPPER_END; +} + +void add_copper(uint32_t cmd) +{ + *copperlist_end++ = cmd; +} + +void sort_copper(void) +{ + /* TODO */ +} + +void swap_copper(void) +{ + if(mode == COPPER_DOUBLE) { + uint32_t *tmpptr; + tmpptr = curlist; + curlist = copperlist; + copperlist = copperlist_end = tmpptr; + + REG32_COP1LC = (uint32_t)curlist; + REG_COPJMP1 = 0; + } else { + copperlist_end = curlist; + } + *copperlist_end = COPPER_END; +} diff -r 000000000000 -r a4788c959918 src/amiga/copper.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/amiga/copper.h Wed Oct 25 19:34:53 2017 +0300 @@ -0,0 +1,38 @@ +#ifndef COPPER_H_ +#define COPPER_H_ + +#include "inttypes.h" + +#define COPPER_MOVE(reg, data) (((uint32_t)(reg) << 16) | ((uint32_t)(data) & 0xffff)) +#define COPPER_WAIT(x, y) \ + (0x0001fffe | ((uint32_t)((x) + 0x81) << 16) | ((uint32_t)((y) + 0x2c) << 24)) +#define COPPER_WAIT_OVERSCAN(x, y) \ + (0x0001fffe | ((uint32_t)(x) << 16) | ((uint32_t)(y) << 24)) +#define COPPER_VWAIT(s) (0x0001ff00 | ((uint32_t)((s) + 0x2c) << 24)) +#define COPPER_VWAIT_OVERSCAN(s) \ + (0x0001ff00 | ((uint32_t)(s) << 24)) +#define COPPER_END 0xfffffffe + +extern uint32_t *copperlist, *copperlist_end; + +enum { + COPPER_SINGLE = 1, + COPPER_DOUBLE = 2 +}; + +int init_copper(int maxlist, int nlists); +void cleanup_copper(void); + +/* enables copper DMA */ +void enable_copper(void); +/* disables copper DMA */ +void disable_copper(void); + +void clear_copper(void); +void add_copper(uint32_t cmd); +void sort_copper(void); /* TODO */ + +void swap_copper(void); + + +#endif /* COPPER_H_ */ diff -r 000000000000 -r a4788c959918 src/amiga/gfx.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/amiga/gfx.c Wed Oct 25 19:34:53 2017 +0300 @@ -0,0 +1,203 @@ +#include +#include +#include "gfx.h" +#include "copper.h" +#include "hwregs.h" +#include "logger.h" + +static int scr_width, scr_height; +static int fb_width, fb_height; +static int num_bitplanes; +static uint16_t prev_intena, prev_intreq, prev_adkcon, prev_dmacon; + +static unsigned char *framebuf; +static unsigned long fbsize; +static int own_framebuf; + +int gfx_init(int nbpl, unsigned int flags) +{ + uint16_t bplcon0; + + num_bitplanes = nbpl; + scr_width = fb_width = (flags & GFX_HIRES) ? 640 : 320; + scr_height = fb_height = (flags & GFX_ILACE) ? 512 : 256; + + Forbid(); + + prev_dmacon = REG_DMACONR; + REG_DMACON = CLRBITS(DMA_ALL); + + prev_intena = REG_INTENAR; + prev_intreq = REG_INTREQR; + prev_adkcon = REG_ADKCONR; + + if(init_copper(0, 0) == -1) { + return -1; + } + + if(!gfx_set_framebuffer(0, scr_width, scr_height)) { + gfx_shutdown(); + return -1; + } + + bplcon0 = BPLCON0_COUNT(nbpl) | BPLCON0_COLOR; + if(flags & GFX_HIRES) bplcon0 |= BPLCON0_HIRES; + if(flags & GFX_ILACE) bplcon0 |= BPLCON0_LACE; + if(flags & GFX_HAM) bplcon0 |= BPLCON0_HOMOD; + if(flags & GFX_DBLPF) bplcon0 |= BPLCON0_DBLPF; + + REG_BPLCON0 = bplcon0; + REG_BPLCON1 = 0; /* h-scroll */ + REG_DIWSTART = 0x2c81; /* 81h horiz start, 2ch vertical start */ + REG_DIWSTOP = 0x2cc1; + REG_DDFSTART = (flags & GFX_HIRES) ? 0x3c : 0x38; + REG_DDFSTOP = (flags & GFX_HIRES) ? 0xd4 : 0xd0; + + gfx_wait_vblank(); + gfx_begin_copperlist(); + add_copper(COPPER_END); + + REG_DMACON = SETBITS(DMA_BPL | DMA_COPPER | DMA_MASTER); + return 0; +} + +void gfx_shutdown(void) +{ + REG_DMACON = CLRBITS(DMA_ALL); + REG_DMACON = SETBITS(prev_dmacon); + + REG_INTREQ = CLRBITS(0x7fff); + REG_INTREQ = SETBITS(prev_intreq); + + REG_ADKCON = CLRBITS(0x7fff); + REG_ADKCON = SETBITS(prev_adkcon); + + REG_INTENA = CLRBITS(INTEN_ALL); + REG_INTENA = SETBITS(prev_intena); + + if(framebuf && own_framebuf) { + FreeMem(framebuf, fbsize); + } + framebuf = 0; + + cleanup_copper(); + Permit(); +} + +int gfx_screen_width(void) +{ + return scr_width; +} + +int gfx_screen_height(void) +{ + return scr_height; +} + +void *gfx_set_framebuffer(void *fb, int width, int height) +{ + /*unsigned int bpl_scanline_sz = width / 8;*/ + unsigned long sz = width * height / 8 * num_bitplanes; + uint32_t bpladdr; + uint16_t bplmod; + + if(framebuf && own_framebuf) { + FreeMem(framebuf, fbsize); + } + + if(fb) { + framebuf = fb; + own_framebuf = 0; + } else { + if(!(framebuf = AllocMem(sz, MEMF_CHIP))) { + logmsg("gfx_set_framebuffer failed to allocate %lu bytes of chip mem for framebuffer\n", sz); + return 0; + } + own_framebuf = 1; + } + + fb_width = width; + fb_height = height; + fbsize = sz; + + bpladdr = (uint32_t)framebuf; + logmsg("bitplane address: %lx\n", (unsigned long)bpladdr); + + bplmod = (fb_width - scr_width) / 8 + fb_width / 8 * num_bitplanes; + REG_BPL1MOD = bplmod; + REG_BPL2MOD = bplmod; + + /* + REG32_BPL1PT = bpladdr; bpladdr += bpl_scanline_sz; + REG32_BPL2PT = bpladdr; bpladdr += bpl_scanline_sz; + REG32_BPL3PT = bpladdr; bpladdr += bpl_scanline_sz; + REG32_BPL4PT = bpladdr; bpladdr += bpl_scanline_sz; + REG32_BPL5PT = bpladdr; bpladdr += bpl_scanline_sz; + REG32_BPL6PT = bpladdr; + */ + return framebuf; +} + +void *gfx_get_framebuffer(void) +{ + return framebuf; +} + +int gfx_framebuffer_width(void) +{ + return fb_width; +} + +int gfx_framebuffer_height(void) +{ + return fb_height; +} + +void gfx_begin_copperlist(void) +{ + static const uint16_t bplptr[] = { + REGN_BPL1PTH, REGN_BPL2PTH, REGN_BPL3PTH, REGN_BPL4PTH, REGN_BPL5PTH, REGN_BPL6PTH + }; + int i; + uint32_t bpladdr; + bpladdr = (uint32_t)framebuf; + + for(i=0; i> 16)); + add_copper(COPPER_MOVE(bplptr[i] + 2, bpladdr)); + bpladdr += fb_width / 8 * num_bitplanes; + } +} + +static int mouse_bnstate(void) +{ + return (REG_CIAA_PORTA & CIAA_PA_FIR0) ? 0 : 1; +} + +int gfx_next_event(union gfx_event *ev, int block) +{ + /* TODO */ + if(block) { + while(!mouse_bnstate()); + ev->type = GFX_EV_QUIT; + return 1; + } + + if(mouse_bnstate()) { + ev->type = GFX_EV_QUIT; + return 1; + } + + return 0; +} + +void gfx_wait_vpos(int x) +{ + x <<= 8; + while((REG32_VPOSR & 0x1ff00) < x); +} + +void gfx_wait_vblank(void) +{ + gfx_wait_vpos(300); +} diff -r 000000000000 -r a4788c959918 src/amiga/hwregs.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/amiga/hwregs.h Wed Oct 25 19:34:53 2017 +0300 @@ -0,0 +1,410 @@ +#ifndef HWREGS_H_ +#define HWREGS_H_ + +#include "inttypes.h" + +#define REG_BASE_ADDR 0xdff000 + +#define REGN_BLTDDAT 0x000 +#define REGN_DMACONR 0x002 +#define REGN_VPOSR 0x004 +#define REGN_VHPOSR 0x006 +#define REGN_DSKDATR 0x008 +#define REGN_JOY0DAT 0x00a +#define REGN_JOY1DAT 0x00c +#define REGN_CLXDAT 0x00e +#define REGN_ADKCONR 0x010 +#define REGN_POT0DAT 0x012 +#define REGN_POT1DAT 0x014 +#define REGN_POTGOR 0x016 +#define REGN_SERDATR 0x018 +#define REGN_DSKBYTR 0x01a +#define REGN_INTENAR 0x01c +#define REGN_INTREQR 0x01e +#define REGN_DSKPTH 0x020 +#define REGN_DSKPTL 0x022 +#define REGN_DSKLEN 0x024 +#define REGN_DSKDAT 0x026 +#define REGN_REFPTR 0x028 +#define REGN_VPOSW 0x02a +#define REGN_VHPOSW 0x02c +#define REGN_COPCON 0x02e +#define REGN_SERDAT 0x030 +#define REGN_SERPER 0x032 +#define REGN_POTGO 0x034 +#define REGN_JOYTEST 0x036 +#define REGN_STREQU 0x038 +#define REGN_STRVBL 0x03a +#define REGN_STRHOR 0x03c +#define REGN_STRLONG 0x03e +#define REGN_BLTCON0 0x040 +#define REGN_BLTCON1 0x042 +#define REGN_BLTAFWM 0x044 +#define REGN_BLTALWM 0x046 +#define REGN_BLTCPTH 0x048 +#define REGN_BLTCPTL 0x04a +#define REGN_BLTBPTH 0x04c +#define REGN_BLTBPTL 0x04e +#define REGN_BLTAPTH 0x050 +#define REGN_BLTAPTL 0x052 +#define REGN_BLTDPTH 0x054 +#define REGN_BLTDPTL 0x056 +#define REGN_BLTSIZE 0x058 +#define REGN_BLTCON0L 0x05a +#define REGN_BLTSIZV 0x05c +#define REGN_BLTSIZH 0x05e +#define REGN_BLTCMOD 0x060 +#define REGN_BLTBMOD 0x062 +#define REGN_BLTAMOD 0x064 +#define REGN_BLTDMOD 0x066 +#define REGN_BLTCDAT 0x070 +#define REGN_BLTBDAT 0x072 +#define REGN_BLTADAT 0x074 +#define REGN_SPRHDAT 0x078 +#define REGN_DENISEID 0x07c +#define REGN_DSKSYNC 0x07e +#define REGN_COP1LCH 0x080 +#define REGN_COP1LCL 0x082 +#define REGN_COP2LCH 0x084 +#define REGN_COP2LCL 0x086 +#define REGN_CMPJMP1 0x088 +#define REGN_CMPJMP2 0x08a +#define REGN_COPINS 0x08c +#define REGN_DIWSTART 0x08e +#define REGN_DIWSTOP 0x090 +#define REGN_DDFSTART 0x092 +#define REGN_DDFSTOP 0x094 +#define REGN_DMACON 0x096 +#define REGN_CLXCON 0x098 +#define REGN_INTENA 0x09a +#define REGN_INTREQ 0x09c +#define REGN_ADKCON 0x09e + +#define REGN_AUDIO_LCH(c) (REGN_AUDIO0_BASE + (c) * 16 + 0) +#define REGN_AUDIO_LCL(c) (REGN_AUDIO0_BASE + (c) * 16 + 2) +#define REGN_AUDIO_LEN(c) (REGN_AUDIO0_BASE + (c) * 16 + 4) +#define REGN_AUDIO_PER(c) (REGN_AUDIO0_BASE + (c) * 16 + 6) +#define REGN_AUDIO_VOL(c) (REGN_AUDIO0_BASE + (c) * 16 + 8) +#define REGN_AUDIO_DAT(c) (REGN_AUDIO0_BASE + (c) * 16 + 10) + +#define REGN_AUDIO0_BASE 0x0a0 +#define REGN_AUD0LCH (REGN_AUDIO0_BASE + 0) +#define REGN_AUD0LCL (REGN_AUDIO0_BASE + 2) +#define REGN_AUD0LEN (REGN_AUDIO0_BASE + 4) +#define REGN_AUD0PER (REGN_AUDIO0_BASE + 6) +#define REGN_AUD0VOL (REGN_AUDIO0_BASE + 8) +#define REGN_AUD0DAT (REGN_AUDIO0_BASE + 10) +#define REGN_AUDIO1_BASE 0x0b0 +#define REGN_AUD1LCH (REGN_AUDIO1_BASE + 0) +#define REGN_AUD1LCL (REGN_AUDIO1_BASE + 2) +#define REGN_AUD1LEN (REGN_AUDIO1_BASE + 4) +#define REGN_AUD1PER (REGN_AUDIO1_BASE + 6) +#define REGN_AUD1VOL (REGN_AUDIO1_BASE + 8) +#define REGN_AUD1DAT (REGN_AUDIO1_BASE + 10) +#define REGN_AUDIO2_BASE 0x0c0 +#define REGN_AUD2LCH (REGN_AUDIO2_BASE + 0) +#define REGN_AUD2LCL (REGN_AUDIO2_BASE + 2) +#define REGN_AUD2LEN (REGN_AUDIO2_BASE + 4) +#define REGN_AUD2PER (REGN_AUDIO2_BASE + 6) +#define REGN_AUD2VOL (REGN_AUDIO2_BASE + 8) +#define REGN_AUD2DAT (REGN_AUDIO2_BASE + 10) +#define REGN_AUDIO3_BASE 0x0d0 +#define REGN_AUD3LCH (REGN_AUDIO3_BASE + 0) +#define REGN_AUD3LCL (REGN_AUDIO3_BASE + 2) +#define REGN_AUD3LEN (REGN_AUDIO3_BASE + 4) +#define REGN_AUD3PER (REGN_AUDIO3_BASE + 6) +#define REGN_AUD3VOL (REGN_AUDIO3_BASE + 8) +#define REGN_AUD3DAT (REGN_AUDIO3_BASE + 10) + +#define REGN_BPL1PTH 0x0e0 +#define REGN_BPL1PTL 0x0e2 +#define REGN_BPL2PTH 0x0e4 +#define REGN_BPL2PTL 0x0e6 +#define REGN_BPL3PTH 0x0e8 +#define REGN_BPL3PTL 0x0ea +#define REGN_BPL4PTH 0x0ec +#define REGN_BPL4PTL 0x0ee +#define REGN_BPL5PTH 0x0f0 +#define REGN_BPL5PTL 0x0f2 +#define REGN_BPL6PTH 0x0f4 +#define REGN_BPL6PTL 0x0f6 +#define REGN_BPLCON0 0x100 +#define REGN_BPLCON1 0x102 +#define REGN_BPLCON2 0x104 +#define REGN_BPLCON3 0x106 +#define REGN_BPL1MOD 0x108 +#define REGN_BPL2MOD 0x10a +#define REGN_BPL1DAT 0x110 +#define REGN_BPL2DAT 0x112 +#define REGN_BPL3DAT 0x114 +#define REGN_BPL4DAT 0x116 +#define REGN_BPL5DAT 0x118 +#define REGN_BPL6DAT 0x11a + +#define REGN_SPR0PTH 0x120 +#define REGN_SPR0PTL 0x122 +#define REGN_SPR1PTH 0x124 +#define REGN_SPR1PTL 0x126 +#define REGN_SPR2PTH 0x128 +#define REGN_SPR2PTL 0x12a +#define REGN_SPR3PTH 0x12c +#define REGN_SPR3PTL 0x12e +#define REGN_SPR4PTH 0x130 +#define REGN_SPR4PTL 0x132 +#define REGN_SPR5PTH 0x134 +#define REGN_SPR5PTL 0x136 +#define REGN_SPR6PTH 0x138 +#define REGN_SPR6PTL 0x13a +#define REGN_SPR7PTH 0x13c +#define REGN_SPR7PTL 0x13e + +#define REGN_SPRITE_POS(s) (REGN_SPRITE0_BASE + (s) * 8 + 0) +#define REGN_SPRITE_CTL(s) (REGN_SPRITE0_BASE + (s) * 8 + 2) +#define REGN_SPRITE_DATA(s) (REGN_SPRITE0_BASE + (s) * 8 + 4) +#define REGN_SPRITE_DATB(s) (REGN_SPRITE0_BASE + (s) * 8 + 6) + +#define REGN_SPRITE0_BASE 0x140 +#define REGN_SPR0POS REGN_SPRITE_POS(0) +#define REGN_SPR0CTL REGN_SPRITE_CTL(0) +#define REGN_SPR0DATA REGN_SPRITE_DATA(0) +#define REGN_SPR0DATB REGN_SPRITE_DATB(0) +#define REGN_SPRITE1_BASE 0x148 +#define REGN_SPR1POS REGN_SPRITE_POS(1) +#define REGN_SPR1CTL REGN_SPRITE_CTL(1) +#define REGN_SPR1DATA REGN_SPRITE_DATA(1) +#define REGN_SPR1DATB REGN_SPRITE_DATB(1) +#define REGN_SPRITE2_BASE 0x150 +#define REGN_SPR2POS REGN_SPRITE_POS(2) +#define REGN_SPR2CTL REGN_SPRITE_CTL(2) +#define REGN_SPR2DATA REGN_SPRITE_DATA(2) +#define REGN_SPR2DATB REGN_SPRITE_DATB(2) +#define REGN_SPRITE3_BASE 0x158 +#define REGN_SPR3POS REGN_SPRITE_POS(3) +#define REGN_SPR3CTL REGN_SPRITE_CTL(3) +#define REGN_SPR3DATA REGN_SPRITE_DATA(3) +#define REGN_SPR3DATB REGN_SPRITE_DATB(3) +#define REGN_SPRITE4_BASE 0x160 +#define REGN_SPR4POS REGN_SPRITE_POS(4) +#define REGN_SPR4CTL REGN_SPRITE_CTL(4) +#define REGN_SPR4DATA REGN_SPRITE_DATA(4) +#define REGN_SPR4DATB REGN_SPRITE_DATB(4) +#define REGN_SPRITE5_BASE 0x168 +#define REGN_SPR5POS REGN_SPRITE_POS(5) +#define REGN_SPR5CTL REGN_SPRITE_CTL(5) +#define REGN_SPR5DATA REGN_SPRITE_DATA(5) +#define REGN_SPR5DATB REGN_SPRITE_DATB(5) +#define REGN_SPRITE6_BASE 0x170 +#define REGN_SPR6POS REGN_SPRITE_POS(6) +#define REGN_SPR6CTL REGN_SPRITE_CTL(6) +#define REGN_SPR6DATA REGN_SPRITE_DATA(6) +#define REGN_SPR6DATB REGN_SPRITE_DATB(6) +#define REGN_SPRITE7_BASE 0x178 +#define REGN_SPR7POS REGN_SPRITE_POS(7) +#define REGN_SPR7CTL REGN_SPRITE_CTL(7) +#define REGN_SPR7DATA REGN_SPRITE_DATA(7) +#define REGN_SPR7DATB REGN_SPRITE_DATB(7) + +#define REGN_COLOR_BASE 0x180 +#define REGN_COLOR(idx) (REGN_COLOR_BASE + (idx) * 2) + +#define REGN_COLOR0 REGN_COLOR(0) +#define REGN_COLOR1 REGN_COLOR(1) +#define REGN_COLOR2 REGN_COLOR(2) +#define REGN_COLOR3 REGN_COLOR(3) +#define REGN_COLOR4 REGN_COLOR(4) +#define REGN_COLOR5 REGN_COLOR(5) +#define REGN_COLOR6 REGN_COLOR(6) +#define REGN_COLOR7 REGN_COLOR(7) +#define REGN_COLOR8 REGN_COLOR(8) +#define REGN_COLOR9 REGN_COLOR(9) +#define REGN_COLOR10 REGN_COLOR(10) +#define REGN_COLOR11 REGN_COLOR(11) +#define REGN_COLOR12 REGN_COLOR(12) +#define REGN_COLOR13 REGN_COLOR(13) +#define REGN_COLOR14 REGN_COLOR(14) +#define REGN_COLOR15 REGN_COLOR(15) +#define REGN_COLOR16 REGN_COLOR(16) +#define REGN_COLOR17 REGN_COLOR(17) +#define REGN_COLOR18 REGN_COLOR(18) +#define REGN_COLOR19 REGN_COLOR(19) +#define REGN_COLOR20 REGN_COLOR(20) +#define REGN_COLOR21 REGN_COLOR(21) +#define REGN_COLOR22 REGN_COLOR(22) +#define REGN_COLOR23 REGN_COLOR(23) +#define REGN_COLOR24 REGN_COLOR(24) +#define REGN_COLOR25 REGN_COLOR(25) +#define REGN_COLOR26 REGN_COLOR(26) +#define REGN_COLOR27 REGN_COLOR(27) +#define REGN_COLOR28 REGN_COLOR(28) +#define REGN_COLOR29 REGN_COLOR(29) +#define REGN_COLOR30 REGN_COLOR(30) +#define REGN_COLOR31 REGN_COLOR(31) + +#define REGN_HTOTAL 0x1c0 +#define REGN_HSSTOP 0x1c2 +#define REGN_HBSTART 0x1c4 +#define REGN_HBSTOP 0x1c6 +#define REGN_VTOTAL 0x1c8 +#define REGN_VSSTOP 0x1ca +#define REGN_VBSTART 0x1cc +#define REGN_VBSTOP 0x1ce +#define REGN_BEAMCON0 0x1dc +#define REGN_HSSTART 0x1de +#define REGN_VSSTART 0x1e0 +#define REGN_HCENTER 0x1e2 +#define REGN_DIWHIGH 0x1e4 + +#define REGN_COP1LCH 0x080 +#define REGN_COP1LCL 0x082 +#define REGN_COP2LCH 0x084 +#define REGN_COP2LCL 0x086 +#define REGN_COPJMP1 0x088 +#define REGN_COPJMP2 0x08a + +#define REG(r) (*(volatile uint16_t*)(REG_BASE_ADDR | (r))) + +#define REG_CIAA_PORTA *(volatile uint8_t*)0xbfe001 + +#define REG_INTENA REG(REGN_INTENA) +#define REG_INTENAR REG(REGN_INTENAR) +#define REG_INTREQ REG(REGN_INTREQ) +#define REG_INTREQR REG(REGN_INTREQR) +#define REG_ADKCON REG(REGN_ADKCON) +#define REG_ADKCONR REG(REGN_ADKCONR) +#define REG_DMACON REG(REGN_DMACON) +#define REG_DMACONR REG(REGN_DMACONR) +#define REG_BPLCON0 REG(REGN_BPLCON0) +#define REG_BPLCON1 REG(REGN_BPLCON1) +#define REG_BPLCON2 REG(REGN_BPLCON2) +#define REG_BPL1PTH REG(REGN_BPL1PTH) +#define REG_BPL2PTH REG(REGN_BPL2PTH) +#define REG_BPL3PTH REG(REGN_BPL3PTH) +#define REG_BPL4PTH REG(REGN_BPL4PTH) +#define REG_BPL5PTH REG(REGN_BPL5PTH) +#define REG_BPL6PTH REG(REGN_BPL6PTH) +#define REG_BPL1PTL REG(REGN_BPL1PTL) +#define REG_BPL2PTL REG(REGN_BPL2PTL) +#define REG_BPL3PTL REG(REGN_BPL3PTL) +#define REG_BPL4PTL REG(REGN_BPL4PTL) +#define REG_BPL5PTL REG(REGN_BPL5PTL) +#define REG_BPL6PTL REG(REGN_BPL6PTL) +#define REG32_BPL1PT *(volatile uint32_t*)(REG_BASE_ADDR | REGN_BPL1PTH) +#define REG32_BPL2PT *(volatile uint32_t*)(REG_BASE_ADDR | REGN_BPL2PTH) +#define REG32_BPL3PT *(volatile uint32_t*)(REG_BASE_ADDR | REGN_BPL3PTH) +#define REG32_BPL4PT *(volatile uint32_t*)(REG_BASE_ADDR | REGN_BPL4PTH) +#define REG32_BPL5PT *(volatile uint32_t*)(REG_BASE_ADDR | REGN_BPL5PTH) +#define REG32_BPL6PT *(volatile uint32_t*)(REG_BASE_ADDR | REGN_BPL6PTH) +#define REG_BPL1MOD REG(REGN_BPL1MOD) +#define REG_BPL2MOD REG(REGN_BPL2MOD) +#define REG_DIWSTART REG(REGN_DIWSTART) +#define REG_DIWSTOP REG(REGN_DIWSTOP) +#define REG_DDFSTART REG(REGN_DDFSTART) +#define REG_DDFSTOP REG(REGN_DDFSTOP) +#define REG_VPOS REG(REGN_VPOS) +#define REG_VPOSR REG(REGN_VPOSR) +#define REG_VHPOS REG(REGN_VHPOS) +#define REG_VHPOSR REG(REGN_VHPOSR) +#define REG32_VPOSR *(volatile uint32_t*)(REG_BASE_ADDR | REGN_VPOSR) + +#define REG_COLOR_PTR ((volatile uint16_t*)(REG_BASE_ADDR | REGN_COLOR0)) +#define REG_COLOR0 REG(REGN_COLOR0) +#define REG_COLOR1 REG(REGN_COLOR1) +#define REG_COLOR2 REG(REGN_COLOR2) +#define REG_COLOR3 REG(REGN_COLOR3) +#define REG_COLOR4 REG(REGN_COLOR4) +#define REG_COLOR5 REG(REGN_COLOR5) +#define REG_COLOR6 REG(REGN_COLOR6) +#define REG_COLOR7 REG(REGN_COLOR7) +#define REG_COLOR8 REG(REGN_COLOR8) +#define REG_COLOR9 REG(REGN_COLOR9) +#define REG_COLOR10 REG(REGN_COLOR10) +#define REG_COLOR11 REG(REGN_COLOR11) +#define REG_COLOR12 REG(REGN_COLOR12) +#define REG_COLOR13 REG(REGN_COLOR13) +#define REG_COLOR14 REG(REGN_COLOR14) +#define REG_COLOR15 REG(REGN_COLOR15) +#define REG_COLOR16 REG(REGN_COLOR16) +#define REG_COLOR17 REG(REGN_COLOR17) +#define REG_COLOR18 REG(REGN_COLOR18) +#define REG_COLOR19 REG(REGN_COLOR19) +#define REG_COLOR20 REG(REGN_COLOR20) +#define REG_COLOR21 REG(REGN_COLOR21) +#define REG_COLOR22 REG(REGN_COLOR22) +#define REG_COLOR23 REG(REGN_COLOR23) +#define REG_COLOR24 REG(REGN_COLOR24) +#define REG_COLOR25 REG(REGN_COLOR25) +#define REG_COLOR26 REG(REGN_COLOR26) +#define REG_COLOR27 REG(REGN_COLOR27) +#define REG_COLOR28 REG(REGN_COLOR28) +#define REG_COLOR29 REG(REGN_COLOR29) +#define REG_COLOR30 REG(REGN_COLOR30) +#define REG_COLOR31 REG(REGN_COLOR31) + +#define REG32_COP1LC *(volatile uint32_t*)(REG_BASE_ADDR | REGN_COP1LCH) +#define REG32_COP2LC *(volatile uint32_t*)(REG_BASE_ADDR | REGN_COP2LCH) +#define REG_COPJMP1 REG(REGN_COPJMP1) +#define REG_COPJMP2 REG(REGN_COPJMP2) + +/* ------ bits ------- */ +#define SETBITS(x) ((x) | 0x8000) +#define CLRBITS(x) (x) + +/* interrupt enable flags */ +enum { + INTEN_TBE = 0x0001, + INTEN_DSKBLK = 0x0002, + INTEN_SOFT = 0x0004, + INTEN_PORTS = 0x0008, + INTEN_COPPER = 0x0010, + INTEN_VERTB = 0x0020, + INTEN_BLITTER = 0x0040, + INTEN_AUDIO0 = 0x0080, + INTEN_AUDIO1 = 0x0100, + INTEN_AUDIO2 = 0x0200, + INTEN_AUDIO3 = 0x0400, + INTEN_RBF = 0x0800, + INTEN_DSKSYN = 0x1000, + INTEN_EXTER = 0x2000, + INTEN_MASTER = 0x4000, + + INTEN_ALL = 0x7fff +}; + +/* DMA control flags */ +enum { + DMA_AUD0 = 0x0001, + DMA_AUD1 = 0x0002, + DMA_AUD2 = 0x0004, + DMA_AUD3 = 0x0008, + DMA_AUDIO = 0x000f, /* all the above */ + DMA_DISK = 0x0010, + DMA_SPRITE = 0x0020, + DMA_BLITTER = 0x0040, + DMA_COPPER = 0x0080, + DMA_BPL = 0x0100, + DMA_MASTER = 0x0200, + + DMA_ALL = 0x01ff +}; + +/* Bitplane control */ +enum { + BPLCON0_ERSY = 0x0002, + BPLCON0_LACE = 0x0004, + BPLCON0_LPEN = 0x0008, + BPLCON0_GAUD = 0x0100, + BPLCON0_COLOR = 0x0200, + BPLCON0_DBLPF = 0x0400, + BPLCON0_HOMOD = 0x0800, + BPLCON0_BPU0 = 0x1000, + BPLCON0_BPU1 = 0x2000, + BPLCON0_BPU2 = 0x4000, + BPLCON0_HIRES = 0x8000 +}; + +#define BPLCON0_COUNT(x) ((x) << 12) + +#define CIAA_PA_FIR0 0x40 +#define CIAA_PA_FIR1 0x80 + +#endif /* HWREGS_H_ */ diff -r 000000000000 -r a4788c959918 src/amiga/inttypes.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/amiga/inttypes.h Wed Oct 25 19:34:53 2017 +0300 @@ -0,0 +1,11 @@ +#ifndef INTTYPES_H_ +#define INTTYPES_H_ + +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef short int16_t; +typedef unsigned short uint16_t; +typedef long int32_t; +typedef unsigned long uint32_t; + +#endif /* INTTYPES_H_ */ diff -r 000000000000 -r a4788c959918 src/amiga/mouse.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/amiga/mouse.c Wed Oct 25 19:34:53 2017 +0300 @@ -0,0 +1,69 @@ +#include +#include "mouse.h" +#include "inttypes.h" + + +#define REG_BASE_ADDR 0xdff000 +#define REGNO_JOY0DAT 0x00a +#define REG_JOY0DAT *(volatile uint16_t*)(REG_BASE_ADDR | REGNO_JOY0DAT) +#define REG_CIAA_PORTA *(volatile uint8_t*)0xbfe001 + +#define CIAA_PA_FIR0 0x40 +#define CIAA_PA_FIR1 0x80 + +static int xrng[2] = {0, 320}; +static int yrng[2] = {0, 240}; + +void set_mouse_bounds(int x0, int y0, int x1, int y1) +{ + xrng[0] = x0; + xrng[1] = x1; + yrng[0] = y0; + yrng[1] = y1; +} + +int mouse_state(int *x, int *y) +{ + mouse_pos(x, y); + return mouse_bnstate(); +} + +int mouse_bnstate(void) +{ + /* TODO: handle right mouse button */ + return (REG_CIAA_PORTA & CIAA_PA_FIR0) ? 0 : 1; +} + +/* TODO: for when I feel like making a proper mouse handler + * use vblank interrupt vector to read the mouse register once + * and have mouse_pos (and friends) simply access the global data + */ +void mouse_pos(int *x, int *y) +{ + static int xpos, ypos; + static int prev_xcount, prev_ycount; + int xcount, ycount, dx, dy; + uint16_t raw = REG_JOY0DAT; + + xcount = raw & 0xff; + ycount = raw >> 8; + + dx = xcount - prev_xcount; + dy = ycount - prev_ycount; + + if(abs(dx) > 127) dx = 255 - (xcount - prev_xcount); + if(abs(dy) > 127) dy = 255 - (ycount - prev_ycount); + prev_xcount = xcount; + prev_ycount = ycount; + + xpos += dx; + ypos += dy; + + if(xpos < xrng[0]) xpos = xrng[0]; + if(ypos < yrng[0]) ypos = yrng[0]; + if(xpos >= xrng[1]) xpos = xrng[1] - 1; + if(ypos >= yrng[1]) ypos = yrng[1] - 1; + + *x = xpos; + *y = ypos; +} diff -r 000000000000 -r a4788c959918 src/amiga/mouse.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/amiga/mouse.h Wed Oct 25 19:34:53 2017 +0300 @@ -0,0 +1,9 @@ +#ifndef MOUSE_H_ +#define MOUSE_H_ + +int mouse_state(int *x, int *y); + +int mouse_bnstate(void); +void mouse_pos(int *x, int *y); + +#endif /* MOUSE_H_ */ diff -r 000000000000 -r a4788c959918 src/gfx.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/gfx.h Wed Oct 25 19:34:53 2017 +0300 @@ -0,0 +1,69 @@ +#ifndef GFX_H_ +#define GFX_H_ + +enum { + GFX_HIRES = 1, + GFX_ILACE = 2, + GFX_HAM = 4, + GFX_DBLPF = 8 +}; + +enum { GFX_EVLOOP_BLOCK, GFX_EVLOOP_NONBLOCK }; + +enum { + GFX_EV_QUIT, + GFX_EV_KEY, + GFX_EV_BUTTON, + GFX_EV_MOTION +}; + +struct gfx_event_key { + int type; + int key; + int pressed; +}; + +struct gfx_event_button { + int type; + int bn; + int pressed; + int x, y; +}; + +struct gfx_event_motion { + int type; + int x, y; +}; + +union gfx_event { + int type; + struct gfx_event_key key; + struct gfx_event_button button; + struct gfx_event_motion motion; +}; + +struct gfx_rect { + int x, y; + int width, height; +}; + +int gfx_init(int nbpl, unsigned int flags); +void gfx_shutdown(void); + +int gfx_screen_width(void); +int gfx_screen_height(void); + +void *gfx_set_framebuffer(void *fb, int width, int height); +void *gfx_get_framebuffer(void); + +int get_framebuffer_width(void); +int get_framebuffer_height(void); + +void gfx_begin_copperlist(void); + +int gfx_next_event(union gfx_event *ev, int block); + +void gfx_wait_vpos(int x); +void gfx_wait_vblank(void); + +#endif /* GFX_H_ */ diff -r 000000000000 -r a4788c959918 src/image.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/image.c Wed Oct 25 19:34:53 2017 +0300 @@ -0,0 +1,55 @@ +#include +#include +#include "image.h" + +struct ham_image *load_ham_image(const char *fname) +{ + return 0; /* TODO */ +} + +struct ham_image *gen_ham_image(int w, int h, int nbpl) +{ + int i, x, y; + struct ham_image *img; + unsigned char *pptr; + unsigned char pixval; + /*static const uint16_t defpal[] = { + 0x000, 0xf00, 0xff0, 0x0f0, 0x0ff, 0x00f, 0xf0f, 0xfff, + 0x444, 0x800, 0x880, 0x080, 0x088, 0x008, 0x808, 0x888 + };*/ + + if(!(img = malloc(sizeof *img))) { + return 0; + } + if(!(img->pixels = calloc(w * h / 8 * nbpl, 1))) { + free(img); + return 0; + } + img->width = w; + img->height = h; + img->chglist = 0; + + img->nbitplanes = nbpl; + /*memcpy(img->palette, defpal, sizeof defpal);*/ + for(i=0; i<16; i++) { + img->palette[i] = i | (i << 4) | (i << 8); + } + + pptr = img->pixels; + for(i=0; i<4; i++) { + pptr = img->pixels + i * w / 8; + for(y=0; y> 1) | ((((x ^ y) >> i) & 1) ? 0x80 : 0); + if((x & 7) == 7) { + *pptr++ = pixval; + pixval = 0; + } + } + pptr += w / 8 * (img->nbitplanes - 1); + } + } + + return img; +} diff -r 000000000000 -r a4788c959918 src/image.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/image.h Wed Oct 25 19:34:53 2017 +0300 @@ -0,0 +1,23 @@ +#ifndef IMAGE_H_ +#define IMAGE_H_ + +#include "inttypes.h" + +struct palchange { + int line; + uint16_t entry; /* [ idx | r | g | b ] */ + struct palchange *next; +}; + +struct ham_image { + int width, height; + unsigned char *pixels; + uint16_t palette[16]; + int nbitplanes; + struct palchange *chglist; +}; + +struct ham_image *load_ham_image(const char *fname); +struct ham_image *gen_ham_image(int w, int h, int nbpl); + +#endif /* IMAGE_H_ */ diff -r 000000000000 -r a4788c959918 src/logger.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/logger.c Wed Oct 25 19:34:53 2017 +0300 @@ -0,0 +1,26 @@ +#include +#include +#include +#include "logger.h" + +static FILE *fp; + +static void init(void) +{ + if(!(fp = fopen("logfile", "w"))) { + printf("failed to open logfile\n"); + abort(); + } + setvbuf(fp, 0, _IONBF, 0); +} + +void logmsg(const char *fmt, ...) +{ + va_list ap; + + if(!fp) init(); + + va_start(ap, fmt); + vfprintf(fp, fmt, ap); + va_end(ap); +} diff -r 000000000000 -r a4788c959918 src/logger.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/logger.h Wed Oct 25 19:34:53 2017 +0300 @@ -0,0 +1,6 @@ +#ifndef LOGGER_H_ +#define LOGGER_H_ + +void logmsg(const char *fmt, ...); + +#endif /* LOGGER_H_ */ diff -r 000000000000 -r a4788c959918 src/main.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/main.c Wed Oct 25 19:34:53 2017 +0300 @@ -0,0 +1,106 @@ +#include +#include +#include +#include +#include "gfx.h" +#include "image.h" +#include "logger.h" + +#include "hwregs.h" +#include "copper.h" + + +static int proc_event(union gfx_event *ev); +static void show_ham_image(struct ham_image *img); + +static int win_width, win_height; + +int main(int argc, char **argv) +{ + struct ham_image *img; + + if(argv[1]) { + if(!(img = load_ham_image(argv[1]))) { + fprintf(stderr, "failed to load image: %s\n", argv[1]); + return 1; + } + } else { + printf("generating test image ...\n"); + if(!(img = gen_ham_image(320, 256, 6))) { + fprintf(stderr, "failed to generate image\n"); + return 1; + } + } + + if(gfx_init(6, GFX_HAM) == -1) { + return 1; + } + gfx_wait_vblank(); + show_ham_image(img); + + for(;;) { + union gfx_event ev; + if(gfx_next_event(&ev, GFX_EVLOOP_BLOCK)) { + if(proc_event(&ev) == -1) { + break; + } + } + } + + gfx_shutdown(); + return 0; +} + +static int proc_event(union gfx_event *ev) +{ + switch(ev->type) { + case GFX_EV_QUIT: + return -1; + + case GFX_EV_KEY: + switch(ev->key.key) { + case 27: + return -1; + default: + break; + } + break; + + default: + break; + } + return 0; +} + +#define NUM_BPL 6 +static void show_ham_image(struct ham_image *img) +{ + int i, j, k, fbwidth, fbheight, ncolors, prev_line; + unsigned char *fbptr = gfx_get_framebuffer(); + struct palchange *chg = img->chglist; + + fbwidth = gfx_framebuffer_width(); + fbheight = gfx_framebuffer_height(); + + memcpy(fbptr, img->pixels, fbwidth * fbheight / 8 * NUM_BPL); + + /* create copper list that handles the palette */ + clear_copper(); + gfx_begin_copperlist(); + /* initial palette at the start of frame */ + for(i=0; i<16; i++) { + add_copper(COPPER_MOVE(REGN_COLOR(i), img->palette[i])); + logmsg("copper palette[%d]: %x\n", i, (unsigned int)img->palette[i]); + } + /* add copper instructions for palette changes according to the image changelist */ + prev_line = -1; + while(chg) { + assert(chg->line >= prev_line); + if(chg->line != prev_line) { + prev_line = chg->line; + add_copper(COPPER_VWAIT(chg->line)); + } + add_copper(COPPER_MOVE(REGN_COLOR(chg->entry >> 12), chg->entry & 0xfff)); + } + add_copper(COPPER_END); +} diff -r 000000000000 -r a4788c959918 tools/convhammer/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/convhammer/Makefile Wed Oct 25 19:34:53 2017 +0300 @@ -0,0 +1,12 @@ +src = $(wildcard *.c) +obj = $(src:.c=.o) +bin = convhammer + +CFLAGS = -pedantic -Wall -g -I../../src + +$(bin): $(obj) + $(CC) -o $@ $(obj) $(LDFLAGS) + +.PHONY: clean +clean: + rm -f $(obj) $(bin) diff -r 000000000000 -r a4788c959918 tools/convhammer/main.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/convhammer/main.c Wed Oct 25 19:34:53 2017 +0300 @@ -0,0 +1,10 @@ +#include +#include +#include "image.h" + +struct ham_image *load_hammer(const char *fname); +int save_ham(struct ham_image *img, const char *fname); + +int main(int argc, char **argv) +{ +}