From 713cf74d27c6f55fec306b020679aebc3677ec22 Mon Sep 17 00:00:00 2001 From: Wei-ju Wu Date: Mon, 13 Jun 2016 08:49:14 -0700 Subject: [PATCH] added audio and scrolling_tricks --- devices/Makefile | 12 +- devices/audio.c | 78 ++++ requesters/Makefile | 9 +- requesters/filereq.c | 26 +- scrolling_tricks/Makefile | 20 + scrolling_tricks/README.md | 6 + scrolling_tricks/blocks/demoblocks.raw | Bin 0 -> 40992 bytes scrolling_tricks/blocks/raceblocks.raw | Bin 0 -> 32032 bytes scrolling_tricks/cop.asm | 226 ++++++++++ scrolling_tricks/cop.h | 29 ++ scrolling_tricks/hardware.c | 160 +++++++ scrolling_tricks/hardware.h | 27 ++ scrolling_tricks/main.c | 543 ++++++++++++++++++++++++ scrolling_tricks/map.h | 12 + scrolling_tricks/maps/Large.map | Bin 0 -> 16054 bytes scrolling_tricks/maps/Large.map.info | Bin 0 -> 6941 bytes scrolling_tricks/maps/Race.map | Bin 0 -> 10054 bytes scrolling_tricks/maps/Race.map.info | Bin 0 -> 6941 bytes scrolling_tricks/maps/Race.raw | Bin 0 -> 10012 bytes scrolling_tricks/maps/Readme | 11 + scrolling_tricks/maps/Readme.info | Bin 0 -> 2963 bytes scrolling_tricks/maps/Scroller.map | Bin 0 -> 20054 bytes scrolling_tricks/maps/Scroller.map.info | Bin 0 -> 6941 bytes scrolling_tricks/maps/Scroller.raw | Bin 0 -> 20012 bytes scrolling_tricks/maps/large.raw | Bin 0 -> 16012 bytes utils/decode_cloanto_rom.py | 2 +- utils/soundconvert.rkt | 23 + utils/wav2ami.py | 25 ++ 28 files changed, 1199 insertions(+), 10 deletions(-) create mode 100644 devices/audio.c create mode 100644 scrolling_tricks/Makefile create mode 100644 scrolling_tricks/README.md create mode 100644 scrolling_tricks/blocks/demoblocks.raw create mode 100644 scrolling_tricks/blocks/raceblocks.raw create mode 100644 scrolling_tricks/cop.asm create mode 100644 scrolling_tricks/cop.h create mode 100644 scrolling_tricks/hardware.c create mode 100644 scrolling_tricks/hardware.h create mode 100644 scrolling_tricks/main.c create mode 100644 scrolling_tricks/map.h create mode 100644 scrolling_tricks/maps/Large.map create mode 100644 scrolling_tricks/maps/Large.map.info create mode 100644 scrolling_tricks/maps/Race.map create mode 100644 scrolling_tricks/maps/Race.map.info create mode 100644 scrolling_tricks/maps/Race.raw create mode 100644 scrolling_tricks/maps/Readme create mode 100644 scrolling_tricks/maps/Readme.info create mode 100644 scrolling_tricks/maps/Scroller.map create mode 100644 scrolling_tricks/maps/Scroller.map.info create mode 100644 scrolling_tricks/maps/Scroller.raw create mode 100644 scrolling_tricks/maps/large.raw create mode 100644 utils/soundconvert.rkt create mode 100755 utils/wav2ami.py diff --git a/devices/Makefile b/devices/Makefile index 973fbe8..b937103 100644 --- a/devices/Makefile +++ b/devices/Makefile @@ -1,15 +1,17 @@ -CC=vc +aos68k -CC13=vc +kick13 +CC=vc +kick13 # Note: VBCC comes with linker library replacements, that should be used. # If not, printf() stops working in the expected way, because it is part # of amiga.lib CFLAGS=-c99 -I$(NDK_INC) -all: timer +all: timer audio clean: - rm -f timer + rm -f timer audio timer: timer.c - $(CC13) $(CFLAGS) timer.c -o timer -lamiga + $(CC) $(CFLAGS) $^ -o $@ -lamiga + +audio: audio.c + $(CC) $(CFLAGS) $^ -o $@ -lamiga -lauto diff --git a/devices/audio.c b/devices/audio.c new file mode 100644 index 0000000..48e9fba --- /dev/null +++ b/devices/audio.c @@ -0,0 +1,78 @@ +/* audio.c + This is a cleaned up version of the example program in Commodore RKM (Devices) + */ +#include +#include +#include +#include +#include + +#include +#include +#include + +#define CLOCK_NTSC (3579545) +#define CLOCK_PAL (3546895) +#define SAMPLE_BYTES (2) +#define DURATION_SECS (3) +#define FREQUENCY (440) +#define SAMPLE_CYCLES (1) +#define VOLUME (64) + +extern struct GfxBase *GfxBase; +UBYTE whichannel[] = {1, 2, 4, 8}; + +int main(int argc, char **argv) +{ + struct IOAudio *AudioIO; + struct MsgPort *AudioMP; + struct Message *AudioMSG; + BYTE *waveptr; + ULONG error; + LONG clock; + + clock = (GfxBase->DisplayFlags & PAL) ? CLOCK_PAL : CLOCK_NTSC; + + AudioIO = (struct IOAudio *) AllocMem(sizeof(struct IOAudio), MEMF_PUBLIC | MEMF_CLEAR); + if (AudioIO) { + puts("IO block created..."); + AudioMP = CreatePort(0, 0); + if (AudioMP) { + puts("Port created..."); + AudioIO->ioa_Request.io_Message.mn_ReplyPort = AudioMP; + AudioIO->ioa_Request.io_Message.mn_Node.ln_Pri = 0; + AudioIO->ioa_Request.io_Command = ADCMD_ALLOCATE; + AudioIO->ioa_Request.io_Flags = ADIOF_NOWAIT; + AudioIO->ioa_AllocKey = 0; + AudioIO->ioa_Data = whichannel; + AudioIO->ioa_Length = sizeof(whichannel); + puts("I/O block initialized for channel allocation..."); + error = OpenDevice(AUDIONAME, 0L, (struct IORequest *) AudioIO, 0L); + if (!error) { + printf("'%s' opened, channel allocated...\n", AUDIONAME); + waveptr = (BYTE *) AllocMem(SAMPLE_BYTES, MEMF_CHIP|MEMF_PUBLIC); + waveptr[0] = 127; + waveptr[1] = -127; + puts("Wave data ready..."); + AudioIO->ioa_Request.io_Message.mn_ReplyPort = AudioMP; + AudioIO->ioa_Request.io_Command = CMD_WRITE; + AudioIO->ioa_Request.io_Flags = ADIOF_PERVOL; + AudioIO->ioa_Data = (BYTE *) waveptr; + AudioIO->ioa_Length = SAMPLE_BYTES; + AudioIO->ioa_Period = clock * SAMPLE_CYCLES / (SAMPLE_BYTES * FREQUENCY); + AudioIO->ioa_Volume = VOLUME; + AudioIO->ioa_Cycles = FREQUENCY * DURATION_SECS / SAMPLE_CYCLES; + puts("I/O block initialized to play tone..."); + puts("Starting tone now..."); + BeginIO((struct IORequest *) AudioIO); + WaitPort(AudioMP); + AudioMSG = GetMsg(AudioMP); + if (waveptr) FreeMem(waveptr, SAMPLE_BYTES); + CloseDevice((struct IORequest *) AudioIO); + } + DeletePort(AudioMP); + } + FreeMem(AudioIO, sizeof(struct IOAudio)); + } + return 0; +} diff --git a/requesters/Makefile b/requesters/Makefile index 3d6870e..dff31c4 100644 --- a/requesters/Makefile +++ b/requesters/Makefile @@ -7,12 +7,17 @@ all: main clean: rm -f *.o main -main: main.o filereq.o dos13.o file_list.o +main: main.o filereq.o dos13.o file_list.o dos_compat.o $(CC) $(CFLAGS) $^ -lamiga -lauto -o $@ -check: file_list_test +check: file_list_test dos_compat_test file_list_test: file_list.c file_list_test.c chibi.c gcc $^ -o $@ ./file_list_test + + +dos_compat_test: dos_compat.c dos_compat_test.c chibi.c + gcc $^ -o $@ + ./dos_compat_test diff --git a/requesters/filereq.c b/requesters/filereq.c index 353824f..2004811 100644 --- a/requesters/filereq.c +++ b/requesters/filereq.c @@ -231,6 +231,9 @@ static struct RastPort filelist_rastport; static UWORD font_baseline, font_height; +#define DIR_BUFFER_SIZE 300 +static char dir_buffer[DIR_BUFFER_SIZE]; + static void close_requester() { if (req_opened) { @@ -477,8 +480,25 @@ static void handle_events() update_string_gadgets(entry); } else if (entry != NULL && is_doubleclick) { printf("double click on: %s\n", entry->name); - if (entry->file_type == FILETYPE_VOLUME || entry->file_type == FILETYPE_DIR) { - reload_file_list(entry->name); + if (entry->file_type == FILETYPE_VOLUME) { + strncpy(dir_buffer, entry->name, DIR_BUFFER_SIZE); + reload_file_list(dir_buffer); + } else if (entry->file_type == FILETYPE_DIR) { + printf("DIR_BUFFER was: '%s'\n", dir_buffer); + int dblen = strlen(dir_buffer); + // We have to implement the DOS functions AddPart()/PathPart()/FilePart() + // ourselves on 1.x, because they only exist after 2.x + // TODO: maybe put path operations in their own module so + // unit testing becomes possible + // append directory separator to path if not a volume + if (dir_buffer[dblen - 1] != ':' && dblen < DIR_BUFFER_SIZE) { + dir_buffer[dblen] = '/'; + dir_buffer[dblen + 1] = '\0'; + dblen++; + } + strncat(dir_buffer, entry->name, DIR_BUFFER_SIZE - dblen); + printf("DIR_BUFFER is NOW: '%s'\n", dir_buffer); + reload_file_list(dir_buffer); } } } @@ -497,6 +517,7 @@ static void handle_events() done = TRUE; break; case REQ_DRIVES_BUTTON_ID: + dir_buffer[0] = '\0'; reload_file_list(NULL); break; case REQ_PARENT_BUTTON_ID: @@ -635,6 +656,7 @@ static void open_request_window(struct Window *window) filelist_rastport.BitMap = &filelist_bitmap; if (req_opened = Request(&requester, req_window)) { + dir_buffer[0] = '\0'; reload_file_list(NULL); handle_events(); free_file_list(current_files); diff --git a/scrolling_tricks/Makefile b/scrolling_tricks/Makefile new file mode 100644 index 0000000..2c7ffad --- /dev/null +++ b/scrolling_tricks/Makefile @@ -0,0 +1,20 @@ +ASM=vasmm68k_mot +ASM_FLAGS = -Fhunk -devpac +.SUFFIXES = .o .asm .c + +CC=vc +kick13 +CFLAGS=-c99 -I$(NDK_INC) -DDEBUG + +all: main + +clean: + rm -f main hardware.o cop.o main.o + +cop.o: cop.asm + $(ASM) $(ASM_FLAGS) -o $@ $< + +.c.o: + $(CC) $(CFLAGS) -c -o $@ $^ + +main: hardware.o cop.o main.o + $(CC) -o $@ $^ -lamiga -lauto diff --git a/scrolling_tricks/README.md b/scrolling_tricks/README.md new file mode 100644 index 0000000..2d69f73 --- /dev/null +++ b/scrolling_tricks/README.md @@ -0,0 +1,6 @@ +# Scrolling Tricks + +This is a project to rework the Aminet Scrolling Tricks into a +version that works on all Amiga OS releases from 1.3 and has +higher reuse. The ScrollingTricks tutorial has tremendous learning +value, but requires at least AmigaOS3.0 to run diff --git a/scrolling_tricks/blocks/demoblocks.raw b/scrolling_tricks/blocks/demoblocks.raw new file mode 100644 index 0000000000000000000000000000000000000000..6c9c0a1d728cff0dd8a029d8db3a328ff39b7393 GIT binary patch literal 40992 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 L1C;~6*be+J2R(_$ literal 0 HcmV?d00001 diff --git a/scrolling_tricks/blocks/raceblocks.raw b/scrolling_tricks/blocks/raceblocks.raw new file mode 100644 index 0000000000000000000000000000000000000000..2c48597e5ed6e95389cd00c24aee5c574e73507d GIT binary patch literal 32032 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 literal 0 HcmV?d00001 diff --git a/scrolling_tricks/cop.asm b/scrolling_tricks/cop.asm new file mode 100644 index 0000000..a1085e7 --- /dev/null +++ b/scrolling_tricks/cop.asm @@ -0,0 +1,226 @@ + + SECTION copperlist,DATA,CHIP + + XDEF _CopperList + XDEF _CopFETCHMODE + XDEF _CopBPLCON0 + XDEF _CopBPLCON1 + XDEF _CopBPLCON3 + XDEF _CopBPLMODA + XDEF _CopBPLMODB + XDEF _CopDIWSTART + XDEF _CopDIWSTOP + XDEF _CopDDFSTART + XDEF _CopDDFSTOP + XDEF _CopPLANE1H + XDEF _CopPLANE1L + XDEF _CopPLANE2H + XDEF _CopPLANE2L + XDEF _CopPLANE3H + XDEF _CopPLANE3L + XDEF _CopPLANE4H + XDEF _CopPLANE4L + XDEF _CopPLANE5H + XDEF _CopPLANE5L + XDEF _CopPLANE6H + XDEF _CopPLANE6L + XDEF _CopPLANE7H + XDEF _CopPLANE7L + XDEF _CopPLANE8H + XDEF _CopPLANE8L + XDEF _CopSKY + +_CopperList: + dc.w $180,0 + +_CopFETCHMODE: + dc.w $1FC,0 + +_CopBPLCON0: + dc.w $100,0 + +_CopBPLCON1: + dc.w $102,0 + +_CopBPLCON3: + dc.w $106,0 + +_CopBPLMODA: + dc.w $108,0 + +_CopBPLMODB: + dc.w $10A,0 + +_CopDIWSTART: + dc.w $8e,0 + +_CopDIWSTOP: + dc.w $90,0 + +_CopDDFSTART: + dc.w $92,0 + +_CopDDFSTOP: + dc.w $94,0 + +_CopPLANE1H: + dc.w $e0,0 + +_CopPLANE1L: + dc.w $e2,0 + +_CopPLANE2H: + dc.w $e4,0 + +_CopPLANE2L: + dc.w $e6,0 + +_CopPLANE3H: + dc.w $e8,0 + +_CopPLANE3L: + dc.w $ea,0 + +_CopPLANE4H: + dc.w $ec,0 + +_CopPLANE4L: + dc.w $ee,0 + +_CopPLANE5H: + dc.w $f0,0 + +_CopPLANE5L: + dc.w $f2,0 + +_CopPLANE6H: + dc.w $f4,0 + +_CopPLANE6L: + dc.w $f6,0 + +_CopPLANE7H: + dc.w $f8,0 + +_CopPLANE7L: + dc.w $fa,0 + +_CopPLANE8H: + dc.w $fc,0 + +_CopPLANE8L: + dc.w $fe,0 + +_CopSKY: + dc.w -1,-2 + dc.w $180,$FFF + + dc.w $390f,-2 + dc.w $180,$EEF + dc.w $3A0f,-2 + dc.w $180,$FFF + dc.w $3B0f,-2 + dc.w $180,$EEF + + dc.w $490f,-2 + dc.w $180,$DDF + dc.w $4a0f,-2 + dc.w $180,$EEF + dc.w $4b0f,-2 + dc.w $180,$DDF + + dc.w $590f,-2 + dc.w $180,$CCF + dc.w $5A0f,-2 + dc.w $180,$DDF + dc.w $5B0f,-2 + dc.w $180,$CCF + + dc.w $690f,-2 + dc.w $180,$BBF + dc.w $6A0f,-2 + dc.w $180,$CCF + dc.w $6B0f,-2 + dc.w $180,$BBF + + dc.w $790f,-2 + dc.w $180,$AAF + dc.w $7A0f,-2 + dc.w $180,$BBF + dc.w $7B0f,-2 + dc.w $180,$AAF + + dc.w $890f,-2 + dc.w $180,$99E + dc.w $8A0f,-2 + dc.w $180,$AAF + dc.w $8B0f,-2 + dc.w $180,$99E + + dc.w $990f,-2 + dc.w $180,$88E + dc.w $9A0f,-2 + dc.w $180,$99E + dc.w $9B0f,-2 + dc.w $180,$88E + + dc.w $A90f,-2 + dc.w $180,$77E + dc.w $AA0f,-2 + dc.w $180,$88E + dc.w $AB0f,-2 + dc.w $180,$77E + + dc.w $B90f,-2 + dc.w $180,$66E + dc.w $BA0f,-2 + dc.w $180,$77E + dc.w $BB0f,-2 + dc.w $180,$66E + + dc.w $C90f,-2 + dc.w $180,$55D + dc.w $CA0f,-2 + dc.w $180,$66E + dc.w $CB0f,-2 + dc.w $180,$55D + + dc.w $D90f,-2 + dc.w $180,$44D + dc.w $DA0f,-2 + dc.w $180,$55D + dc.w $DB0f,-2 + dc.w $180,$44D + + dc.w $E90f,-2 + dc.w $180,$33D + dc.w $EA0f,-2 + dc.w $180,$44D + dc.w $EB0f,-2 + dc.w $180,$33D + + dc.w $F90f,-2 + dc.w $180,$22C + dc.w $FA0f,-2 + dc.w $180,$33D + dc.w $FB0f,-2 + dc.w $180,$22C + + dc.w $FFDF,-2 + dc.w $090F,-2 + dc.w $180,$11C + dc.w $0A0F,-2 + dc.w $180,$22C + dc.w $0B0F,-2 + dc.w $180,$11C + + dc.w $190f,-2 + dc.w $180,$00B + dc.w $1A0f,-2 + dc.w $180,$11C + dc.w $1B0f,-2 + dc.w $180,$00B + + dc.w -1,-2 + END + diff --git a/scrolling_tricks/cop.h b/scrolling_tricks/cop.h new file mode 100644 index 0000000..4b392b7 --- /dev/null +++ b/scrolling_tricks/cop.h @@ -0,0 +1,29 @@ +extern WORD CopperList[]; +extern WORD CopFETCHMODE[]; +extern WORD CopBPLCON0[]; +extern WORD CopBPLCON1[]; +extern WORD CopBPLCON3[]; +extern WORD CopBPLMODA[]; +extern WORD CopBPLMODB[]; +extern WORD CopDIWSTART[]; +extern WORD CopDIWSTOP[]; +extern WORD CopDDFSTART[]; +extern WORD CopDDFSTOP[]; +extern WORD CopPLANE1H[]; +extern WORD CopPLANE1L[]; +extern WORD CopPLANE2H[]; +extern WORD CopPLANE2L[]; +extern WORD CopPLANE3H[]; +extern WORD CopPLANE3L[]; +extern WORD CopPLANE4H[]; +extern WORD CopPLANE4L[]; +extern WORD CopPLANE5H[]; +extern WORD CopPLANE5L[]; +extern WORD CopPLANE6H[]; +extern WORD CopPLANE6L[]; +extern WORD CopPLANE7H[]; +extern WORD CopPLANE7L[]; +extern WORD CopPLANE8H[]; +extern WORD CopPLANE8L[]; +extern WORD CopSKY[]; + diff --git a/scrolling_tricks/hardware.c b/scrolling_tricks/hardware.c new file mode 100644 index 0000000..cc0d6ce --- /dev/null +++ b/scrolling_tricks/hardware.c @@ -0,0 +1,160 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "hardware.h" + +static UWORD old_dmacon; +static UWORD old_intena; +static UWORD old_adkcon; +static UWORD old_intreq; + +static struct MsgPort *inputmp; +static struct IOStdReq *inputreq; +static struct Interrupt inputhandler; +static BOOL inputdeviceok; + +static struct View *oldview; +static struct Window *old_processwinptr; +static struct Process *thisprocess; + +extern struct IntuitionBase *IntuitionBase; +extern struct GfxBase *GfxBase; + +static LONG NullInputHandler(void) +{ + // kills all input + return 0; +} + +void KillSystem(void) +{ + thisprocess = (struct Process *)FindTask(0); + + // safe actual view and install null view + + oldview = GfxBase->ActiView; + LoadView(0); + WaitTOF(); + WaitTOF(); + + // install NullInputHandler to kill all input events + if ((inputmp = CreateMsgPort())) { + if ((inputreq = CreateIORequest(inputmp,sizeof(*inputreq)))) { + if (OpenDevice("input.device",0,(struct IORequest *)inputreq,0) == 0) { + inputdeviceok = TRUE; + inputhandler.is_Node.ln_Type = NT_INTERRUPT; + inputhandler.is_Node.ln_Pri = 127; + inputhandler.is_Data = 0; + inputhandler.is_Code = (APTR)NullInputHandler; + inputreq->io_Command = IND_ADDHANDLER; + inputreq->io_Data = &inputhandler; + DoIO((struct IORequest *)inputreq); + } + } + } + + // disable requesters for our process + old_processwinptr = thisprocess->pr_WindowPtr; + thisprocess->pr_WindowPtr = (APTR)-1; + + // lock blitter + OwnBlitter(); + WaitBlit(); + + // no multitasking/interrupts + Disable(); + + // save important custom registers + old_dmacon = custom->dmaconr | 0x8000; + old_intena = custom->intenar | 0x8000; + old_adkcon = custom->adkconr | 0x8000; + old_intreq = custom->intreqr | 0x8000; +} + +void ActivateSystem(void) +{ + // reset important custom registers + custom->dmacon = 0x7FFF; + custom->intena = 0x7FFF; + custom->adkcon = 0x7FFF; + custom->intreq = 0x7FFF; + + custom->dmacon = old_dmacon; + custom->intena = old_intena; + custom->adkcon = old_adkcon; + custom->intreq = old_intreq; + + // enable multitasking/interrupts + Enable(); + + // unlock blitter + WaitBlit(); + DisownBlitter(); + + // enable requesters for our process + thisprocess->pr_WindowPtr = old_processwinptr; + + // remove null inputhandler + if (inputdeviceok) + { + inputreq->io_Command = IND_REMHANDLER; + inputreq->io_Data = &inputhandler; + DoIO((struct IORequest *)inputreq); + CloseDevice((struct IORequest *)inputreq); + } + + if (inputreq) DeleteIORequest(inputreq); + if (inputmp) DeleteMsgPort(inputmp); + + // reset old view + LoadView(oldview); + WaitTOF(); + WaitTOF(); +} + +void WaitVBL(void) +{ + UBYTE b; + + b = *(UBYTE *)0xbfe801; + while(*(UBYTE *)0xbfe801 == b) ; +} + +void WaitVBeam(ULONG line) +{ + ULONG vpos; + + line *= 0x100; + + do { + vpos = *(ULONG *)0xdff004; + } while ((vpos & 0x1FF00) != line); +} + +void HardWaitBlit(void) +{ + if (custom->dmaconr & DMAF_BLTDONE) ; + while (custom->dmaconr & DMAF_BLTDONE) ; +} + +void HardWaitLMB(void) +{ + while (((*(UBYTE *)0xbfe001) & 64) != 0) ; + while (((*(UBYTE *)0xbfe001) & 64) == 0) ; +} + +BOOL JoyLeft(void) { return (custom->joy1dat & 512) ? TRUE : FALSE; } +BOOL JoyRight(void) { return (custom->joy1dat & 2) ? TRUE : FALSE; } +BOOL JoyFire(void) { return ((*(UBYTE *)0xbfe001) & 128) ? FALSE : TRUE; } +BOOL LMBDown(void) { return ((*(UBYTE *)0xbfe001) & 64) ? FALSE : TRUE; } diff --git a/scrolling_tricks/hardware.h b/scrolling_tricks/hardware.h new file mode 100644 index 0000000..05a9783 --- /dev/null +++ b/scrolling_tricks/hardware.h @@ -0,0 +1,27 @@ +#ifdef custom +#undef custom +#endif + +#define mycustombase ((struct Custom *)0xdff000) +#define custom mycustombase + +#define BPL0_USEBPLCON3_F 0x1 +#define BPL0_COLOR_F 0x200 +#define BPL0_BPU0_F 0x1000 +#define BPL0_BPU3_F 0x10 +#define BPL0_BPUMASK 0x7000 + +void KillSystem(void); +void ActivateSystem(void); +void WaitVBL(void); +void WaitVBeam(ULONG line); +void HardWaitBlit(void); +void HardWaitLMB(void); + +BOOL JoyLeft(void); +BOOL JoyRight(void); +BOOL JoyUp(void); +BOOL JoyDown(void); +BOOL JoyFire(void); +BOOL LMBDown(void); + diff --git a/scrolling_tricks/main.c b/scrolling_tricks/main.c new file mode 100644 index 0000000..1fe8d8d --- /dev/null +++ b/scrolling_tricks/main.c @@ -0,0 +1,543 @@ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include "hardware.h" +#include "cop.h" +#include "map.h" + + +#define ARG_TEMPLATE "SPEED/S,NTSC/S,HOW/S,SKY/S,FMODE/N/K" +#define ARG_SPEED 0 +#define ARG_NTSC 1 +#define ARG_HOW 2 +#define ARG_SKY 3 +#define ARG_FMODE 4 +#define NUM_ARGS 5 + +#define MAPNAME "maps/large.raw" +#define BLOCKSNAME "blocks/demoblocks.raw" + +#define SCREENWIDTH 320 +#define SCREENHEIGHT 256 +#define EXTRAWIDTH 32 +#define SCREENBYTESPERROW (SCREENWIDTH / 8) + +#define BITMAPWIDTH ((SCREENWIDTH + EXTRAWIDTH) * 2) +#define BITMAPBYTESPERROW (BITMAPWIDTH / 8) +#define HALFBITMAPWIDTH (BITMAPWIDTH / 2) +#define BITMAPHEIGHT SCREENHEIGHT + +#define BLOCKSWIDTH 320 +#define BLOCKSHEIGHT 256 +#define BLOCKSDEPTH 4 +#define BLOCKSCOLORS (1L << BLOCKSDEPTH) +#define BLOCKWIDTH 16 +#define BLOCKHEIGHT 16 +#define BLOCKSBYTESPERROW (BLOCKSWIDTH / 8) +#define BLOCKSPERROW (BLOCKSWIDTH / BLOCKWIDTH) + +#define NUMSTEPS BLOCKWIDTH + +#define BITMAPBLOCKSPERROW (BITMAPWIDTH / BLOCKWIDTH) +#define HALFBITMAPBLOCKSPERROW (BITMAPBLOCKSPERROW / 2) +#define BITMAPBLOCKSPERCOL (BITMAPHEIGHT / BLOCKHEIGHT) + +#define BITMAPPLANELINES (BITMAPHEIGHT * BLOCKSDEPTH) +#define BLOCKPLANELINES (BLOCKHEIGHT * BLOCKSDEPTH) + +#define DIWSTART 0x2981 +#define DIWSTOP 0x29C1 + +#define PALSIZE (BLOCKSCOLORS * 2) +#define BLOCKSFILESIZE (BLOCKSWIDTH * BLOCKSHEIGHT * BLOCKSPLANES / 8 + PALSIZE) + +struct Screen *scr; +struct RastPort *ScreenRastPort; +struct BitMap *BlocksBitmap, *ScreenBitmap; +struct RawMap *Map; +UBYTE *frontbuffer,*blocksbuffer; + +WORD mapposx,videoposx; + +LONG mapwidth; +UBYTE *mapdata; + +UWORD colors[BLOCKSCOLORS]; + +LONG Args[NUM_ARGS]; + +BOOL option_ntsc,option_how,option_speed,option_sky; +WORD option_fetchmode; + +BPTR MyHandle; +char s[256]; + +struct FetchInfo +{ + WORD ddfstart; + WORD ddfstop; + WORD modulooffset; + WORD bitmapoffset; + WORD scrollpixels; + +} fetchinfo [] = +{ + {0x30,0xD0,2,0,16}, /* normal */ + {0x28,0xC8,4,16,32}, /* BPL32 */ + {0x28,0xC8,4,16,32}, /* BPAGEM */ + {0x18,0xB8,8,48,64} /* BPL32 + BPAGEM */ +}; + +/********************* MACROS ***********************/ + +#define ROUND2BLOCKWIDTH(x) ((x) & ~(BLOCKWIDTH - 1)) + +/********************* COMPATIBILITY ***********************/ + +/* AllocBitMap() is V39, provide a version here, that works on all AmigaOS versions */ +struct BitMap *MyAllocBitMap(ULONG sizex, ULONG sizey, ULONG depth, ULONG flags, + struct BitMap *friend_bitmap) +{ + return AllocBitMap(sizex, sizey, depth, flags, friend_bitmap); +} + +/* FreeBitMap() is V39, provide a version here that works on all AmigaOS versions */ +void MyFreeBitMap(struct BitMap *bitmap) +{ + FreeBitMap(bitmap); +} + +ULONG is_bitmap_interleaved(struct BitMap *bitmap) +{ + /* GetBitMapAttr() is V39, provide a version here that works on all AmigaOS versions */ + return (GetBitMapAttr(bitmap, BMA_FLAGS) & BMF_INTERLEAVED) == BMF_INTERLEAVED; +} + +/************* SETUP/CLEANUP ROUTINES ***************/ + +static void Cleanup(char *msg) +{ + WORD rc; + + if (msg) { + printf("Error: %s\n",msg); + rc = RETURN_WARN; + } else rc = RETURN_OK; + + if (scr) CloseScreen(scr); + + if (ScreenBitmap) { + WaitBlit(); + MyFreeBitMap(ScreenBitmap); + } + + if (BlocksBitmap) { + WaitBlit(); + MyFreeBitMap(BlocksBitmap); + } + + if (Map) free(Map); + if (MyHandle) Close(MyHandle); + exit(rc); +} + +static void GetArguments(void) +{ + struct RDArgs *MyArgs; + + if (!(MyArgs = ReadArgs(ARG_TEMPLATE,Args,0))) { + Fault(IoErr(),0,s,255); + Cleanup(s); + } + + if (Args[ARG_SPEED]) option_speed = TRUE; + if (Args[ARG_NTSC]) option_ntsc = TRUE; + if (Args[ARG_HOW]) { + option_how = TRUE; + option_speed = FALSE; + } + if (Args[ARG_SKY] && (!option_speed)) { + option_sky = TRUE; + } + if (Args[ARG_FMODE]) { + option_fetchmode = *(LONG *)Args[ARG_FMODE]; + } + FreeArgs(MyArgs); + + if (option_fetchmode < 0 || option_fetchmode > 3) { + Cleanup("Invalid fetch mode. Must be 0 .. 3!"); + } +} + +static void OpenMap(void) +{ + LONG l; + + if (!(MyHandle = Open(MAPNAME,MODE_OLDFILE))) { + Fault(IoErr(),0,s,255); + Cleanup(s); + } + + Seek(MyHandle,0,OFFSET_END); + l = Seek(MyHandle,0,OFFSET_BEGINNING); + + if (!(Map = calloc(l, sizeof(UBYTE)))) { + Cleanup("Out of memory!"); + } + + if (Read(MyHandle,Map,l) != l) { + Fault(IoErr(),0,s,255); + Cleanup(s); + } + Close(MyHandle); + MyHandle = 0; + + mapdata = Map->data; + mapwidth = Map->mapwidth; +} + +static void OpenBlocks(void) +{ + LONG l; + + if (!(BlocksBitmap = MyAllocBitMap(BLOCKSWIDTH, + BLOCKSHEIGHT, + BLOCKSDEPTH, + BMF_STANDARD | BMF_INTERLEAVED, + 0))) { + Cleanup("Can't alloc blocks bitmap!"); + } + + if (!(MyHandle = Open(BLOCKSNAME,MODE_OLDFILE))) { + Fault(IoErr(),0,s,255); + Cleanup(s); + } + + if (Read(MyHandle,colors,PALSIZE) != PALSIZE) { + Fault(IoErr(),0,s,255); + Cleanup(s); + } + + l = BLOCKSWIDTH * BLOCKSHEIGHT * BLOCKSDEPTH / 8; + + if (Read(MyHandle,BlocksBitmap->Planes[0],l) != l) { + Fault(IoErr(),0,s,255); + Cleanup(s); + } + Close(MyHandle);MyHandle = 0; + blocksbuffer = BlocksBitmap->Planes[0]; +} + +// V36: GetDisplayInfoData(), OpenScreenTags(), FindDisplayInfo() +static void OpenDisplay(void) +{ + struct DimensionInfo diminfo; + DisplayInfoHandle dih; + ULONG modeid; + LONG bmflags; + + if (!(ScreenBitmap = MyAllocBitMap(BITMAPWIDTH,BITMAPHEIGHT + 3,BLOCKSDEPTH, + BMF_STANDARD | BMF_INTERLEAVED | BMF_CLEAR,0))) { + Cleanup("Can't alloc screen bitmap!"); + } + frontbuffer = ScreenBitmap->Planes[0]; + frontbuffer += (fetchinfo[option_fetchmode].bitmapoffset / 8); + + if (!(TypeOfMem(ScreenBitmap->Planes[0]) & MEMF_CHIP)) { + Cleanup("Screen bitmap is not in CHIP RAM!?? If you have a gfx card try disabling \"planes to fast\" or similiar options in your RTG system!"); + } + + if (!is_bitmap_interleaved(ScreenBitmap)) { + Cleanup("Screen bitmap is not in interleaved format!??"); + } + + if (option_how) { + modeid = INVALID_ID; + + if ((dih = FindDisplayInfo(VGAPRODUCT_KEY))) { + if (GetDisplayInfoData(dih,(APTR)&diminfo,sizeof(diminfo),DTAG_DIMS,0)) { + if (diminfo.MaxDepth >= BLOCKSDEPTH) modeid = VGAPRODUCT_KEY; + } + } + if (modeid == INVALID_ID) { + if (option_ntsc) modeid = NTSC_MONITOR_ID | HIRESLACE_KEY; + else modeid = PAL_MONITOR_ID | HIRESLACE_KEY; + } + } else { + if (option_ntsc) modeid = NTSC_MONITOR_ID; + else modeid = PAL_MONITOR_ID; + } + + if (!(scr = OpenScreenTags(0,SA_Width,BITMAPWIDTH, + SA_Height,BITMAPHEIGHT + 3, + SA_Depth,BLOCKSDEPTH, + SA_DisplayID,modeid, + SA_BitMap,ScreenBitmap, + option_how ? SA_Overscan : TAG_IGNORE,OSCAN_TEXT, + option_how ? SA_AutoScroll : TAG_IGNORE,TRUE, + SA_Quiet,TRUE, + TAG_DONE))) { + Cleanup("Can't open screen!"); + } + + if (scr->RastPort.BitMap->Planes[0] != ScreenBitmap->Planes[0]) { + Cleanup("Screen was not created with the custom bitmap I supplied!??"); + } + ScreenRastPort = &scr->RastPort; + LoadRGB4(&scr->ViewPort,colors,BLOCKSCOLORS); +} + +static void InitCopperlist(void) +{ + WORD *wp; + LONG l; + + WaitVBL(); + custom->dmacon = 0x7FFF; + custom->beamcon0 = option_ntsc ? 0 : DISPLAYPAL; + CopFETCHMODE[1] = option_fetchmode; + + // bitplane control registers + CopBPLCON0[1] = ((BLOCKSDEPTH * BPL0_BPU0_F) & BPL0_BPUMASK) + + ((BLOCKSDEPTH / 8) * BPL0_BPU3_F) + + BPL0_COLOR_F + + (option_speed ? 0 : BPL0_USEBPLCON3_F); + + CopBPLCON1[1] = 0; + CopBPLCON3[1] = BPLCON3_BRDNBLNK; + + // bitplane modulos + l = BITMAPBYTESPERROW * BLOCKSDEPTH - + SCREENBYTESPERROW - fetchinfo[option_fetchmode].modulooffset; + + CopBPLMODA[1] = l; + CopBPLMODB[1] = l; + + // display window start/stop + CopDIWSTART[1] = DIWSTART; + CopDIWSTOP[1] = DIWSTOP; + + // display data fetch start/stop + CopDDFSTART[1] = fetchinfo[option_fetchmode].ddfstart; + CopDDFSTOP[1] = fetchinfo[option_fetchmode].ddfstop; + + // plane pointers + + wp = CopPLANE1H; + + for (l = 0;l < BLOCKSDEPTH;l++) { + wp[1] = (WORD)(((ULONG)ScreenBitmap->Planes[l]) >> 16); + wp[3] = (WORD)(((ULONG)ScreenBitmap->Planes[l]) & 0xFFFF); + wp += 4; + } + + if (option_sky) { + // activate copper sky + CopSKY[0] = 0x290f; + } + + custom->intena = 0x7FFF; + custom->dmacon = DMAF_SETCLR | DMAF_BLITTER | DMAF_COPPER | DMAF_RASTER | DMAF_MASTER; + custom->cop2lc = (ULONG)CopperList; +} + +/******************* SCROLLING **********************/ + +static void DrawBlock(LONG x,LONG y,LONG mapx,LONG mapy) +{ + UBYTE block; + + // x = in pixels + // y = in "planelines" (1 realline = BLOCKSDEPTH planelines) + x = x / 8; + y = y * BITMAPBYTESPERROW; + + block = mapdata[mapy * mapwidth + mapx]; + + mapx = (block % BLOCKSPERROW) * (BLOCKWIDTH / 8); + mapy = (block / BLOCKSPERROW) * (BLOCKPLANELINES * BLOCKSBYTESPERROW); + + if (option_how) OwnBlitter(); + + HardWaitBlit(); + + custom->bltcon0 = 0x9F0; // use A and D. Op: D = A + custom->bltcon1 = 0; + custom->bltafwm = 0xFFFF; + custom->bltalwm = 0xFFFF; + custom->bltamod = BLOCKSBYTESPERROW - (BLOCKWIDTH / 8); + custom->bltdmod = BITMAPBYTESPERROW - (BLOCKWIDTH / 8); + custom->bltapt = blocksbuffer + mapy + mapx; + custom->bltdpt = frontbuffer + y + x; + custom->bltsize = BLOCKPLANELINES * 64 + (BLOCKWIDTH / 16); + + if (option_how) DisownBlitter(); +} + +static void FillScreen(void) +{ + WORD a,b,x,y; + + for (b = 0;b < BITMAPBLOCKSPERCOL;b++) { + for (a = 0;a < HALFBITMAPBLOCKSPERROW;a++) { + x = a * BLOCKWIDTH; + y = b * BLOCKPLANELINES; + DrawBlock(x,y,a,b); + DrawBlock(x + HALFBITMAPWIDTH,y,a,b); + } + } +} + +static void ScrollLeft(void) +{ + WORD mapx,mapy,x,y; + + if (mapposx < 1) return; + + mapposx--; + videoposx = mapposx % HALFBITMAPWIDTH; + + mapx = mapposx / BLOCKWIDTH; + mapy = mapposx & (NUMSTEPS - 1); + + x = ROUND2BLOCKWIDTH(videoposx); + y = mapy * BLOCKPLANELINES; + + DrawBlock(x,y,mapx,mapy); + DrawBlock(x + HALFBITMAPWIDTH,y,mapx,mapy); +} + +static void ScrollRight(void) +{ + WORD mapx,mapy,x,y; + + if (mapposx >= (mapwidth * BLOCKWIDTH - SCREENWIDTH - BLOCKWIDTH)) return; + + mapx = mapposx / BLOCKWIDTH + HALFBITMAPBLOCKSPERROW; + mapy = mapposx & (NUMSTEPS - 1); + + x = ROUND2BLOCKWIDTH(videoposx); + y = mapy * BLOCKPLANELINES; + + DrawBlock(x,y,mapx,mapy); + DrawBlock(x + HALFBITMAPWIDTH,y,mapx,mapy); + + mapposx++; + videoposx = mapposx % HALFBITMAPWIDTH; +} + +static void CheckJoyScroll(void) +{ + WORD i,count; + + if (JoyFire()) count = 8; else count = 1; + if (JoyLeft()) { + for (i = 0; i < count; i++) ScrollLeft(); + } + + if (JoyRight()) { + for (i = 0; i < count; i++) ScrollRight(); + } +} + +static void UpdateCopperlist(void) +{ + ULONG pl; + WORD xpos,planeaddx,scroll,i; + WORD *wp; + + i = fetchinfo[option_fetchmode].scrollpixels; + + xpos = videoposx + i - 1; + + planeaddx = (xpos / i) * (i / 8); + i = (i - 1) - (xpos & (i - 1)); + + scroll = (i & 15) * 0x11; + if (i & 16) scroll |= (0x400 + 0x4000); + if (i & 32) scroll |= (0x800 + 0x8000); + + // set scroll register in BPLCON1 + CopBPLCON1[1] = scroll; + + // set plane pointers + wp = CopPLANE1H; + + for (i = 0;i < BLOCKSDEPTH;i++) { + pl = ((ULONG)ScreenBitmap->Planes[i]) + planeaddx; + wp[1] = (WORD)(pl >> 16); + wp[3] = (WORD)(pl & 0xFFFF); + wp += 4; + } +} + +static void ShowWhatCopperWouldDo(void) +{ + SetWriteMask(ScreenRastPort,1); + SetAPen(ScreenRastPort,0); + RectFill(ScreenRastPort,0,BITMAPHEIGHT + 1,BITMAPWIDTH - 1,BITMAPHEIGHT + 1); + SetAPen(ScreenRastPort,1); + RectFill(ScreenRastPort,videoposx + BLOCKWIDTH,BITMAPHEIGHT + 1, + videoposx + BLOCKWIDTH + SCREENWIDTH - 1,BITMAPHEIGHT + 1); +} + +static void MainLoop(void) +{ + if (!option_how) { + // activate copperlist + HardWaitBlit(); + WaitVBL(); + custom->copjmp2 = 0; + } + + while (!LMBDown()) { + if (!option_how) { + WaitVBeam(199); + WaitVBeam(200); + } else Delay(1); + + if (option_speed) *(WORD *)0xdff180 = 0xFF0; + + CheckJoyScroll(); + + if (option_speed) *(WORD *)0xdff180 = 0xF00; + if (!option_how) UpdateCopperlist(); + else ShowWhatCopperWouldDo(); + } +} + +/********************* MAIN *************************/ + +int main(int argc, char **argv) +{ + //OpenLibs(); + GetArguments(); + OpenMap(); + OpenBlocks(); + OpenDisplay(); + + if (!option_how) { + Delay(2*50); + KillSystem(); + InitCopperlist(); + } + FillScreen(); + MainLoop(); + + if (!option_how) ActivateSystem(); + Cleanup(0); + return 0; +} diff --git a/scrolling_tricks/map.h b/scrolling_tricks/map.h new file mode 100644 index 0000000..993452a --- /dev/null +++ b/scrolling_tricks/map.h @@ -0,0 +1,12 @@ +struct RawMap +{ + WORD mapwidth; + WORD mapheight; + WORD maplayers; + WORD blockwidth; + WORD blockheight; + BYTE bytesperblock; + BYTE transparentblock; + UBYTE data[1]; +}; + diff --git a/scrolling_tricks/maps/Large.map b/scrolling_tricks/maps/Large.map new file mode 100644 index 0000000000000000000000000000000000000000..93985f45a8bb70ab81c0470c17fe9cf10586ec1b GIT binary patch literal 16054 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 literal 0 HcmV?d00001 diff --git a/scrolling_tricks/maps/Scroller.raw b/scrolling_tricks/maps/Scroller.raw new file mode 100644 index 0000000000000000000000000000000000000000..d14096396ec5d57194e68e003f7615d173154727 GIT binary patch literal 20012 zcmd^{S##Yq6vy2-PRlaoCKHk_kkFQNT1Z;j0&zM(;EQycPU$kk@=)5xvOU}n!1m6R zq0GQA6h1;9_*m#1ZAZ2w%aWY<7Nxb1WLY{t{U!U#^1a2s#m(YSF)1d8ipWq!o;S>C zCr-W+S@3u`7{jX9D?CeS(f|Dv2m8vXGBPPm`NBIMmayfH17=VLrY9`IOz4w5YwhjQcS8*j?8=VT~1w~ifeIt46}xV^u=$NmCz zkacC}I4w&q%LN%&(&knVr&#_k?z2B#RHvmmEEgE)J-0rl;g)E3+OJq+Dm99u?{-!h zlmYb!%E>b^Ctl)Szy*ekFGvJ$Z}OvJD`S+y$Ux-i;YB-ZUp-g}XV^Gn|KI|{$Jdu% z6$Si{;K(IM*;fz7u}wx9zaYvM_Upl}q(+y5v(n^1=V5^FRcP`pCa6Pg>1-)*5xFOV zz!Tk$vvu^VL^-fC!2rKsp~<(Hpbpu*wx>-+5J%5QbztAYktPT4Oj+~*-y0m;R1nI+ z`c)$&%E2$TL+MdcK`2K9f<+VM7*>yx3gYERm1AH%s34T1)vr?J7+4P~2ykqWxe%IS z(w!`advAGXHLly+W#Fpk|1KjIu_ zzsev-W<9Lv=lRr>a>#ClgFc5GT#vf8I*==Ia|=ETH#kn5l+O!t$gv-Ku;#E#s4rZU zbL=eBK=I)`SJNL@IdzR6&kwBrTosQ<4>kA$3^m77Gd^zQYL=980^C-c90~_QiA<^r}t3Q{Z3%2V!_gV*GWTGa!e=aFV!u zib)@igJ3vFV*GWTGZ=@7;UK}<)rL(9)Pq-*C=C~YNXKjgjE@#Z0LchBY#5y+J{fjS6`kLK&EUO*?7%md0gMkNfa)e>{ zNpP_^(07_GBS$cXpM-iBZs+6ZgW)5IQzRQlPYfSPxC$yKTqp`y({F4sL!Zy>{V|Y) zE(j~9Vie(TptiSAXb+Ak3`U}tyA(y7v2zv9Yi}VnoFf*4u0KMJG8l^Bs*60r_QpYy z?lglrqA`L5*{#^BOG*gkNWgFjq8t6rUB+?e?mlp&U~~#1SGvht{HjYqOJ^4vHAnqkZGeM8RGzlq>W$CpMO_UoDYw zZp-FPqa0?V!HdP|JxcaOxk7KeXA7^{-Y6dG;C0n|kaFloYrY&Uy-C>X6?*Lt%yb{* z=P0qR0T>W}a|=GI*77w^*keMi<#@JFlA7& zS>RwS%3qi9EOG!V++umq7D*LmDTQOQXlc2`B#$10aX9KsB5{<7&8}6@Rt`NJ zbtZC1&-8v*JloRVYfI)DU%x`no;>>buSb6iCx_;kbv^XM*rYCGJz4e>x*tjpd%+LMDlOg?-BIQUa# zYn@4nb91iKFJGCmFSYX-BISTdK41U9={_oFvv4Jgf3m^DbmOWsKHbg1zWJzTyOaYR z@3D@<^2fUue5RiRih-H?ROrGPVB73h`bdZs>|SujZVo7Fia(q{pF+$i2V*gxsLU=0 z=mISK*DfmgqZd(oC@XIW>{p~x{%aSN{Lzc3Jt;1e`TynMzuHmBAMc3TXA*%Fv#>xS G+WZe1A_r#x literal 0 HcmV?d00001 diff --git a/scrolling_tricks/maps/large.raw b/scrolling_tricks/maps/large.raw new file mode 100644 index 0000000000000000000000000000000000000000..f7fd4fc53195677df1ed8a0f7abaf0f11f50f5af GIT binary patch literal 16012 zcmeI2>5~;T5Woj_M-;8Mi}lki(Pfqqntx0C@0C zzgSvjm8JMc`DfUjPA8q2B$JspEJBfaZ_-I-a`taJ$;{Zl*<`i`{*!C6EX(1qoe(*y zQ@=maX?DTPJ~b&;GEouX61BgRY!6|*RZi-pf{~^~la@~{+jJ*jqZ6eM;5z&#J6mxp zCEq;4g{x3nbewOy{f;}At?QBmn`>BFP0suCvm*>tgIg`#R!X@&I#4MY;5B{d>{E`* zWvJ}{D?OE*fAM8%jVjj_D}{}70ya8Py2iQfsEGPZP2c~(gTK;1F7X?*;a zapOR=weDQ%&ku%ewY*tnEZtU0$ssaODYvU@pp}EcisNz_YCFJPa-OZo<~RYFkRo@- z`J7V2O(})8x#n`(^Qq}ATP@;B>XL-hXX=g|G#h?@U;O#6i_m!VK_#u2HmeP_Zjrb^;x!k z2fLkFh7k?iM<0KZW$I*Z8in)Sd!94-G#3=+QO*bEQ8%-&*nspaopW3|9tL;huq&CJ zg4N=D-A&+bZa%d2cX&DXQ$99kpZE0{*IZF&%}<}v_MG$aRMb2M`I?qKVLq^0?&R~> zg#W^Or1=Yqj0`=-}5G)m~haSNSMbt=K=054F(NJztTD9?y?GHC6#tn zavq|b3_AD8h<=JacP8tXj&sJ`W6+W5GUw3nWYoX^;m0gfC(~W4!TDJ(ZE`&ynZ`WM zIX~)VU>)Cp^lO}Rhg*McJieTVS)TcsrwZ9~X9j6=97(F+6QMlSpwn(^e9zTq&*$!w zE+1#k&z*-RLPeD?T5GyT#3hTS;Rf@7LHBSDg;Y?-8DH4(uJ(qFcK6LnDV4_hCfIX& zMRM2O_uT7d%9z)1P6i##xpIj%{TkE0;i zT^e+sJ-N_SDOG$>awa4sNs-qn`iq;PH@ zmPwq`D-tO0p@$!F*4GB}8qUd}lQ~zNA}egVr7ZjpIfstZN>Z+@Kdd%U3~zR4jIJh1 zO04)Z;@BYPXszH6vpn-N<*pLvb(E(XbZ%?J_u2C@=de3m=TM>Bv91SASaZ;8vkxU| z9(%e9)GH0jRScd5=S5+`N#WeqBZc$+maPiT3ZWMBVql(;RRQk9N1ZX}m3(Y<9O<%i z-t)Z^{hXYvsdwW-T>!SVXWroofimul^Qq}-uZx&f;k=&m4h?$6{K5P5Hk_j>wql)z z&c(d4LXX;WQXodX(ja5c_d^xgp5t?iNw4MHS^o&m*9Km_lo|s&X}3}x1?I&-&Y4Ow zb|yUPggM8U`W?B;&iRb*0qx=3Y+OkAl?=9ZrVU2nHqDgHiIG@H)0F(wZ zaXpc3f2pLFiiHyA_Tx_8ERjCsy#%^j`O#9Y!nxKDRuk}9glgrFnhC)+!xs@2rMxIy z&iC#sx$xT-rRAbWDx$7OBIRJvH_LTje|}d(#|_Or-@}crStY0mWnh~D-=YS|29muv<;9n5PvAI$pl zfd?SzviFSk{K==3dm6+P&XGF*g3H4>Xx zYl!(S-PJ|ju|3CeLYK@sG`xzrnzrJ5F#KyL?70|APE|fG`;#&<_a;JzQvd{T zprV|6%rNxFYzgyv&WF6&uKJTt!wJ%5?-@CNhBV<>5Dn)C#k#pSVHU?soqwX3;JcRX1MGN z+jF_!Zk3HlpP3CEP5}@=<%x3cHN(&z{Mc1EuQqE9=MMDwv!u)3^P%lKb~5K6s^vP? z|EyRy&&;aDahW>Hxm<0rgF&0j&kjDhyc!UCj{p0xD&$jcD*y=HN&be+|%`8 z=U(WBfn=mWjFY)6&BEU0x|()Usi7a20}a-(#OX7I)<{yl}G15 prWF0t1?Lcf=xv->$GNO=SoTtW;&>|3-s^mQ6N}>(g{iP9{{awM(G&mx literal 0 HcmV?d00001 diff --git a/utils/decode_cloanto_rom.py b/utils/decode_cloanto_rom.py index 97fa6b6..346a835 100755 --- a/utils/decode_cloanto_rom.py +++ b/utils/decode_cloanto_rom.py @@ -41,7 +41,7 @@ if __name__ == '__main__': with open(args.romfile, 'rb') as infile: file_id = infile.read(len(CLOANTO_ID)) if file_id == CLOANTO_ID: - data = infile.read() + data = infile.read() size = len(data) if size not in ROM_SIZES: raise Exception("invalid rom size") diff --git a/utils/soundconvert.rkt b/utils/soundconvert.rkt new file mode 100644 index 0000000..425294b --- /dev/null +++ b/utils/soundconvert.rkt @@ -0,0 +1,23 @@ +#lang racket +(require rsound) +(require rsound/draw) +(require ffi/vector) + +(define (play-sound s n) + (cond [(> n 0) + (play s) + (sleep 0.1) + ;;(play (resample 2 sound)) + (play-sound s (- n 1))])) + +(define (analyze-sound s) + (let ([v (rsound-data s)]) + v)) + + +(let ([sound (rs-read "/home/weiju/Desktop/Laser_Shoot7.wav")]) + ;;(rsound-fft-draw sound) + (play-sound sound 3) + (play-sound sound 3) + ;;(s16vector->list (analyze-sound sound)) + ) diff --git a/utils/wav2ami.py b/utils/wav2ami.py new file mode 100755 index 0000000..b330e85 --- /dev/null +++ b/utils/wav2ami.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python +import argparse +import wave +import struct + +def conv_amplitude(amp_bstr): + """converts 16 bit amplitudes into 8 bit amplitudes""" + return struct.unpack(">H", amp_bstr)[0] >> 8 + + +if __name__ == '__main__': + parser = argparse.ArgumentParser(description="wav2ami 1.0") + parser.add_argument('wavfile') + + args = parser.parse_args() + print args.wavfile + infile = wave.open(args.wavfile) + print "# channels: ", infile.getnchannels() + print "sample width: ", infile.getsampwidth() + print "frame rate: ", infile.getframerate() + print "# frames: ", infile.getnframes() + num_frames = infile.getnframes() + data = [conv_amplitude(infile.readframes(1)) for _ in range(num_frames)] + #print data + infile.close()