├── A5200DS.nds ├── Makefile ├── arm7 ├── Makefile └── source │ ├── emusoundfifo.c │ └── main.c ├── arm9 ├── Makefile ├── data │ ├── clickNoQuit.wav │ └── mus_intro.wav ├── gfx │ ├── bgBottom.png │ ├── bgFileSel.png │ ├── bgHighScore.png │ ├── bgStarRaiders.png │ ├── bgTop.png │ ├── pdev_bg0.png │ └── pdev_tbg0.png └── source │ ├── a5200utils.c │ ├── a5200utils.h │ ├── emu │ ├── altirra_5200_os.c │ ├── altirra_5200_os.h │ ├── antic.c │ ├── antic.h │ ├── atari.c │ ├── atari.h │ ├── atari_nds.c │ ├── cartridge.c │ ├── cartridge.h │ ├── config.h │ ├── cpu.c │ ├── cpu.h │ ├── gtia.c │ ├── gtia.h │ ├── hash.c │ ├── hash.h │ ├── input.c │ ├── input.h │ ├── memory.c │ ├── memory.h │ ├── pia.c │ ├── pia.h │ ├── platform.h │ ├── pokey.c │ ├── pokey.h │ ├── pokeysnd.c │ └── pokeysnd.h │ ├── highscore.c │ ├── highscore.h │ ├── intro.c │ ├── intro.h │ ├── main.c │ ├── main.h │ ├── printf.c │ └── printf.h ├── logo.bmp └── readme.md /A5200DS.nds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wavemotion-dave/A5200DS/8f6e3bb302fcedf0cd6a1d19f2b32fb4a53d656d/A5200DS.nds -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | #--------------------------------------------------------------------------------- 2 | .SUFFIXES: 3 | #--------------------------------------------------------------------------------- 4 | ifeq ($(strip $(DEVKITARM)),) 5 | $(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") 6 | endif 7 | 8 | include $(DEVKITARM)/ds_rules 9 | 10 | export TARGET := A5200DS 11 | export TOPDIR := $(CURDIR) 12 | 13 | VERSION = 3.8 14 | 15 | ICON := -b $(CURDIR)/logo.bmp "A5200DS $(VERSION);wavemotion-dave;http://https://github.com/wavemotion-dave/A5200DS" 16 | 17 | .PHONY: arm7/$(TARGET).elf arm9/$(TARGET).elf 18 | 19 | #--------------------------------------------------------------------------------- 20 | # main targets 21 | #--------------------------------------------------------------------------------- 22 | all: $(TARGET).nds 23 | 24 | #--------------------------------------------------------------------------------- 25 | $(TARGET).nds : arm7/$(TARGET).elf arm9/$(TARGET).elf 26 | ndstool -c $(TARGET).nds -7 arm7/$(TARGET).elf -9 arm9/$(TARGET).elf $(ICON) 27 | 28 | #--------------------------------------------------------------------------------- 29 | arm7/$(TARGET).elf: 30 | $(MAKE) -C arm7 31 | 32 | #--------------------------------------------------------------------------------- 33 | arm9/$(TARGET).elf: 34 | $(MAKE) -C arm9 35 | 36 | #--------------------------------------------------------------------------------- 37 | clean: 38 | $(MAKE) -C arm9 clean 39 | $(MAKE) -C arm7 clean 40 | rm -f $(TARGET).nds $(TARGET).arm7 $(TARGET).arm9 41 | -------------------------------------------------------------------------------- /arm7/Makefile: -------------------------------------------------------------------------------- 1 | #--------------------------------------------------------------------------------- 2 | .SUFFIXES: 3 | #--------------------------------------------------------------------------------- 4 | ifeq ($(strip $(DEVKITARM)),) 5 | $(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") 6 | endif 7 | 8 | include $(DEVKITARM)/ds_rules 9 | 10 | #--------------------------------------------------------------------------------- 11 | # BUILD is the directory where object files & intermediate files will be placed 12 | # SOURCES is a list of directories containing source code 13 | # INCLUDES is a list of directories containing extra header files 14 | # DATA is a list of directories containing binary files 15 | # all directories are relative to this makefile 16 | #--------------------------------------------------------------------------------- 17 | BUILD := build 18 | SOURCES := source 19 | INCLUDES := include build 20 | DATA := 21 | 22 | #--------------------------------------------------------------------------------- 23 | # options for code generation 24 | #--------------------------------------------------------------------------------- 25 | ARCH := -mthumb-interwork 26 | 27 | CFLAGS := -g -Wall -O2\ 28 | -mcpu=arm7tdmi -mtune=arm7tdmi -fomit-frame-pointer\ 29 | -ffast-math \ 30 | $(ARCH) 31 | 32 | CFLAGS += $(INCLUDE) -DARM7 33 | CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -fno-rtti 34 | 35 | 36 | ASFLAGS := -g $(ARCH) 37 | LDFLAGS = -specs=ds_arm7.specs -g $(ARCH) -Wl,-Map,$(notdir $*).map 38 | 39 | #LIBS := -ldswifi7 -lmm7 -lnds7 40 | LIBS := -ldswifi7 -lnds7 41 | 42 | #--------------------------------------------------------------------------------- 43 | # list of directories containing libraries, this must be the top level containing 44 | # include and lib 45 | #--------------------------------------------------------------------------------- 46 | LIBDIRS := $(LIBNDS) 47 | 48 | 49 | #--------------------------------------------------------------------------------- 50 | # no real need to edit anything past this point unless you need to add additional 51 | # rules for different file extensions 52 | #--------------------------------------------------------------------------------- 53 | ifneq ($(BUILD),$(notdir $(CURDIR))) 54 | #--------------------------------------------------------------------------------- 55 | 56 | export ARM7ELF := $(CURDIR)/$(TARGET).elf 57 | export DEPSDIR := $(CURDIR)/$(BUILD) 58 | 59 | export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) 60 | 61 | CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) 62 | CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) 63 | SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) 64 | BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) 65 | 66 | export OFILES := $(addsuffix .o,$(BINFILES)) \ 67 | $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) 68 | 69 | export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ 70 | $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ 71 | -I$(CURDIR)/$(BUILD) 72 | 73 | export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) 74 | 75 | #--------------------------------------------------------------------------------- 76 | # use CXX for linking C++ projects, CC for standard C 77 | #--------------------------------------------------------------------------------- 78 | ifeq ($(strip $(CPPFILES)),) 79 | #--------------------------------------------------------------------------------- 80 | export LD := $(CC) 81 | #--------------------------------------------------------------------------------- 82 | else 83 | #--------------------------------------------------------------------------------- 84 | export LD := $(CXX) 85 | #--------------------------------------------------------------------------------- 86 | endif 87 | #--------------------------------------------------------------------------------- 88 | 89 | .PHONY: $(BUILD) clean 90 | 91 | #--------------------------------------------------------------------------------- 92 | $(BUILD): 93 | @[ -d $@ ] || mkdir -p $@ 94 | @make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile 95 | 96 | #--------------------------------------------------------------------------------- 97 | clean: 98 | @echo clean ... 99 | @rm -fr $(BUILD) *.elf 100 | 101 | 102 | #--------------------------------------------------------------------------------- 103 | else 104 | 105 | DEPENDS := $(OFILES:.o=.d) 106 | 107 | #--------------------------------------------------------------------------------- 108 | # main targets 109 | #--------------------------------------------------------------------------------- 110 | $(ARM7ELF) : $(OFILES) 111 | @echo linking $(notdir $@) 112 | @$(LD) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@ 113 | 114 | 115 | #--------------------------------------------------------------------------------- 116 | # you need a rule like this for each extension you use as binary data 117 | #--------------------------------------------------------------------------------- 118 | %.bin.o : %.bin 119 | #--------------------------------------------------------------------------------- 120 | @echo $(notdir $<) 121 | @$(bin2o) 122 | 123 | -include $(DEPENDS) 124 | 125 | #--------------------------------------------------------------------------------------- 126 | endif 127 | #--------------------------------------------------------------------------------------- 128 | -------------------------------------------------------------------------------- /arm7/source/emusoundfifo.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | typedef enum { 6 | EMUARM7_INIT_SND = 0x123C, 7 | EMUARM7_STOP_SND = 0x123D, 8 | EMUARM7_PLAY_SND = 0x123E, 9 | } FifoMesType; 10 | 11 | //--------------------------------------------------------------------------------- 12 | void soundEmuDataHandler(int bytes, void *user_data) { 13 | int channel = -1; 14 | 15 | FifoMessage msg; 16 | 17 | fifoGetDatamsg(FIFO_USER_01, bytes, (u8*)&msg); 18 | 19 | switch (msg.type) { 20 | case EMUARM7_PLAY_SND: 21 | channel = (msg.SoundPlay.format & 0xF0)>>4; 22 | SCHANNEL_SOURCE(channel) = (u32)msg.SoundPlay.data; 23 | SCHANNEL_REPEAT_POINT(channel) = msg.SoundPlay.loopPoint; 24 | SCHANNEL_LENGTH(channel) = msg.SoundPlay.dataSize; 25 | SCHANNEL_TIMER(channel) = SOUND_FREQ(msg.SoundPlay.freq); 26 | SCHANNEL_CR(channel) = SCHANNEL_ENABLE | SOUND_VOL(msg.SoundPlay.volume) | SOUND_PAN(msg.SoundPlay.pan) | ((msg.SoundPlay.format & 0xF) << 29) | (msg.SoundPlay.loop ? SOUND_REPEAT : SOUND_ONE_SHOT); 27 | break; 28 | 29 | case EMUARM7_INIT_SND: 30 | break; 31 | 32 | case EMUARM7_STOP_SND: 33 | break; 34 | } 35 | } 36 | 37 | //--------------------------------------------------------------------------------- 38 | void soundEmuCommandHandler(u32 command, void* userdata) { 39 | int cmd = (command ) & 0x00F00000; 40 | int data = command & 0xFFFF; 41 | int channel = (command >> 16) & 0xF; 42 | 43 | switch(cmd) { 44 | 45 | case SOUND_SET_VOLUME: 46 | SCHANNEL_CR(channel) &= ~0xFF; 47 | SCHANNEL_CR(channel) |= data; 48 | break; 49 | 50 | case SOUND_SET_PAN: 51 | SCHANNEL_CR(channel) &= ~SOUND_PAN(0xFF); 52 | SCHANNEL_CR(channel) |= SOUND_PAN(data); 53 | break; 54 | 55 | case SOUND_SET_FREQ: 56 | SCHANNEL_TIMER(channel) = SOUND_FREQ(data); 57 | break; 58 | 59 | case SOUND_SET_WAVEDUTY: 60 | SCHANNEL_CR(channel) &= ~(7 << 24); 61 | SCHANNEL_CR(channel) |= (data) << 24; 62 | break; 63 | 64 | case SOUND_KILL: 65 | case SOUND_PAUSE: 66 | SCHANNEL_CR(channel) &= ~SCHANNEL_ENABLE; 67 | break; 68 | 69 | case SOUND_RESUME: 70 | SCHANNEL_CR(channel) |= SCHANNEL_ENABLE; 71 | break; 72 | 73 | default: break; 74 | } 75 | } 76 | 77 | //--------------------------------------------------------------------------------- 78 | void installSoundEmuFIFO(void) { 79 | fifoSetDatamsgHandler(FIFO_USER_01, soundEmuDataHandler, 0); 80 | fifoSetValue32Handler(FIFO_USER_01, soundEmuCommandHandler, 0); 81 | } 82 | -------------------------------------------------------------------------------- /arm7/source/main.c: -------------------------------------------------------------------------------- 1 | /*--------------------------------------------------------------------------------- 2 | 3 | default ARM7 core 4 | 5 | Copyright (C) 2005 - 2010 6 | Michael Noland (joat) 7 | Jason Rogers (dovoto) 8 | Dave Murphy (WinterMute) 9 | 10 | This software is provided 'as-is', without any express or implied 11 | warranty. In no event will the authors be held liable for any 12 | damages arising from the use of this software. 13 | 14 | Permission is granted to anyone to use this software for any 15 | purpose, including commercial applications, and to alter it and 16 | redistribute it freely, subject to the following restrictions: 17 | 18 | 1. The origin of this software must not be misrepresented; you 19 | must not claim that you wrote the original software. If you use 20 | this software in a product, an acknowledgment in the product 21 | documentation would be appreciated but is not required. 22 | 23 | 2. Altered source versions must be plainly marked as such, and 24 | must not be misrepresented as being the original software. 25 | 26 | 3. This notice may not be removed or altered from any source 27 | distribution. 28 | 29 | ---------------------------------------------------------------------------------*/ 30 | #include 31 | #include 32 | 33 | extern void installSoundEmuFIFO(void); 34 | 35 | //--------------------------------------------------------------------------------- 36 | void VblankHandler(void) { 37 | //--------------------------------------------------------------------------------- 38 | Wifi_Update(); 39 | } 40 | 41 | 42 | //--------------------------------------------------------------------------------- 43 | void VcountHandler() { 44 | //--------------------------------------------------------------------------------- 45 | inputGetAndSend(); 46 | } 47 | 48 | volatile bool exitflag = false; 49 | 50 | //--------------------------------------------------------------------------------- 51 | void powerButtonCB() { 52 | //--------------------------------------------------------------------------------- 53 | exitflag = true; 54 | } 55 | 56 | //--------------------------------------------------------------------------------- 57 | int main() { 58 | //--------------------------------------------------------------------------------- 59 | readUserSettings(); 60 | 61 | irqInit(); 62 | // Start the RTC tracking IRQ 63 | initClockIRQ(); 64 | touchInit(); 65 | fifoInit(); 66 | 67 | SetYtrigger(80); 68 | 69 | installWifiFIFO(); 70 | installSoundFIFO(); 71 | 72 | installSystemFIFO(); 73 | 74 | installSoundEmuFIFO(); 75 | 76 | irqSet(IRQ_VCOUNT, VcountHandler); 77 | irqSet(IRQ_VBLANK, VblankHandler); 78 | 79 | irqEnable( IRQ_VBLANK | IRQ_VCOUNT | IRQ_NETWORK); 80 | 81 | setPowerButtonCB(powerButtonCB); 82 | 83 | // Keep the ARM7 mostly idle 84 | while (!exitflag) { 85 | if ( 0 == (REG_KEYINPUT & (KEY_SELECT | KEY_START | KEY_L | KEY_R))) { 86 | exitflag = true; 87 | } 88 | 89 | swiWaitForVBlank(); 90 | } 91 | return 0; 92 | } 93 | -------------------------------------------------------------------------------- /arm9/Makefile: -------------------------------------------------------------------------------- 1 | #--------------------------------------------------------------------------------- 2 | .SUFFIXES: 3 | #--------------------------------------------------------------------------------- 4 | ifeq ($(strip $(DEVKITARM)),) 5 | $(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") 6 | endif 7 | 8 | include $(DEVKITARM)/ds_rules 9 | 10 | #--------------------------------------------------------------------------------- 11 | # BUILD is the directory where object files & intermediate files will be placed 12 | # SOURCES is a list of directories containing source code 13 | # INCLUDES is a list of directories containing extra header files 14 | # DATA is a list of directories containing binary files 15 | # all directories are relative to this makefile 16 | #--------------------------------------------------------------------------------- 17 | BUILD := build 18 | SOURCES := source/emu source 19 | INCLUDES := source/emu source 20 | DATA := data 21 | GRAPHICS := gfx 22 | 23 | #--------------------------------------------------------------------------------- 24 | # options for code generation 25 | #--------------------------------------------------------------------------------- 26 | ARCH := 27 | 28 | CFLAGS := -Wall -Warray-bounds=0 -O2 -march=armv5te -mtune=arm946e-s -fomit-frame-pointer -ffast-math $(ARCH) -frename-registers -finline-functions -fpredictive-commoning -floop-interchange -ftree-partial-pre -fno-semantic-interposition 29 | 30 | CFLAGS += $(INCLUDE) -DARM9 31 | CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions 32 | 33 | ASFLAGS := $(ARCH) -march=armv5te -mtune=arm946e-s 34 | 35 | LDFLAGS = -specs=ds_arm9.specs $(ARCH) -Wl,-Map,$(notdir $*.map) 36 | 37 | #--------------------------------------------------------------------------------- 38 | # any extra libraries we wish to link with the project 39 | #--------------------------------------------------------------------------------- 40 | LIBS := -lfat -lnds9 -lmm9 41 | 42 | #--------------------------------------------------------------------------------- 43 | # list of directories containing libraries, this must be the top level containing 44 | # include and lib 45 | #--------------------------------------------------------------------------------- 46 | LIBDIRS := $(LIBNDS) 47 | 48 | #--------------------------------------------------------------------------------- 49 | # no real need to edit anything past this point unless you need to add additional 50 | # rules for different file extensions 51 | #--------------------------------------------------------------------------------- 52 | ifneq ($(BUILD),$(notdir $(CURDIR))) 53 | #--------------------------------------------------------------------------------- 54 | 55 | export ARM9ELF := $(CURDIR)/$(TARGET).elf 56 | export DEPSDIR := $(CURDIR)/$(BUILD) 57 | 58 | export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ 59 | $(foreach dir,$(GRAPHICS),$(CURDIR)/$(dir)) \ 60 | $(foreach dir,$(DATA),$(CURDIR)/$(dir)) 61 | 62 | CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) 63 | CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) 64 | SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) 65 | BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) 66 | PNGFILES := $(foreach dir,$(GRAPHICS),$(notdir $(wildcard $(dir)/*.png))) 67 | 68 | #--------------------------------------------------------------------------------- 69 | # use CXX for linking C++ projects, CC for standard C 70 | #--------------------------------------------------------------------------------- 71 | ifeq ($(strip $(CPPFILES)),) 72 | #--------------------------------------------------------------------------------- 73 | export LD := $(CC) 74 | #--------------------------------------------------------------------------------- 75 | else 76 | #--------------------------------------------------------------------------------- 77 | export LD := $(CXX) 78 | #--------------------------------------------------------------------------------- 79 | endif 80 | #--------------------------------------------------------------------------------- 81 | 82 | export OFILES := $(addsuffix .o,$(BINFILES)) \ 83 | $(PNGFILES:.png=.o) $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) 84 | 85 | export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ 86 | $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ 87 | -I$(CURDIR)/$(BUILD) 88 | 89 | export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) 90 | 91 | .PHONY: $(BUILD) clean 92 | 93 | #--------------------------------------------------------------------------------- 94 | $(BUILD): 95 | @[ -d $@ ] || mkdir -p $@ 96 | @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile 97 | 98 | #--------------------------------------------------------------------------------- 99 | clean: 100 | @echo clean ... 101 | @rm -fr $(BUILD) *.elf *.nds* *.bin 102 | 103 | 104 | #--------------------------------------------------------------------------------- 105 | else 106 | 107 | #--------------------------------------------------------------------------------- 108 | # main targets 109 | #--------------------------------------------------------------------------------- 110 | $(ARM9ELF) : $(OFILES) 111 | @echo linking $(notdir $@) 112 | @$(LD) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@ 113 | 114 | #--------------------------------------------------------------------------------- 115 | # you need a rule like this for each extension you use as binary data 116 | #--------------------------------------------------------------------------------- 117 | %.bin.o : %.bin 118 | @echo $(notdir $<) 119 | @$(bin2o) 120 | 121 | %.s %.h : %.png 122 | grit $^ -o $@ -gt -mrt -mR8 -mLs -gzl -mzl 123 | 124 | %.wav.o : %.wav 125 | @echo $(notdir $<) 126 | @$(bin2o) 127 | 128 | -include $(DEPSDIR)/*.d 129 | 130 | #--------------------------------------------------------------------------------------- 131 | endif 132 | #--------------------------------------------------------------------------------------- 133 | -------------------------------------------------------------------------------- /arm9/data/clickNoQuit.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wavemotion-dave/A5200DS/8f6e3bb302fcedf0cd6a1d19f2b32fb4a53d656d/arm9/data/clickNoQuit.wav -------------------------------------------------------------------------------- /arm9/data/mus_intro.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wavemotion-dave/A5200DS/8f6e3bb302fcedf0cd6a1d19f2b32fb4a53d656d/arm9/data/mus_intro.wav -------------------------------------------------------------------------------- /arm9/gfx/bgBottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wavemotion-dave/A5200DS/8f6e3bb302fcedf0cd6a1d19f2b32fb4a53d656d/arm9/gfx/bgBottom.png -------------------------------------------------------------------------------- /arm9/gfx/bgFileSel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wavemotion-dave/A5200DS/8f6e3bb302fcedf0cd6a1d19f2b32fb4a53d656d/arm9/gfx/bgFileSel.png -------------------------------------------------------------------------------- /arm9/gfx/bgHighScore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wavemotion-dave/A5200DS/8f6e3bb302fcedf0cd6a1d19f2b32fb4a53d656d/arm9/gfx/bgHighScore.png -------------------------------------------------------------------------------- /arm9/gfx/bgStarRaiders.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wavemotion-dave/A5200DS/8f6e3bb302fcedf0cd6a1d19f2b32fb4a53d656d/arm9/gfx/bgStarRaiders.png -------------------------------------------------------------------------------- /arm9/gfx/bgTop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wavemotion-dave/A5200DS/8f6e3bb302fcedf0cd6a1d19f2b32fb4a53d656d/arm9/gfx/bgTop.png -------------------------------------------------------------------------------- /arm9/gfx/pdev_bg0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wavemotion-dave/A5200DS/8f6e3bb302fcedf0cd6a1d19f2b32fb4a53d656d/arm9/gfx/pdev_bg0.png -------------------------------------------------------------------------------- /arm9/gfx/pdev_tbg0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wavemotion-dave/A5200DS/8f6e3bb302fcedf0cd6a1d19f2b32fb4a53d656d/arm9/gfx/pdev_tbg0.png -------------------------------------------------------------------------------- /arm9/source/a5200utils.h: -------------------------------------------------------------------------------- 1 | #ifndef _A5200UTILS_H 2 | #define _A5200UTILS_H 3 | 4 | #define A5200_MENUINIT 0x01 5 | #define A5200_MENUSHOW 0x02 6 | #define A5200_PLAYINIT 0x03 7 | #define A5200_PLAYGAME 0x04 8 | #define A5200_QUITSTDS 0x05 9 | 10 | extern unsigned short int etatEmu; 11 | 12 | typedef enum { 13 | EMUARM7_INIT_SND = 0x123C, 14 | EMUARM7_STOP_SND = 0x123D, 15 | EMUARM7_PLAY_SND = 0x123E, 16 | } FifoMesType; 17 | 18 | typedef struct FICtoLoad { 19 | char filename[254]; 20 | u8 directory; 21 | unsigned int uCrc; 22 | } FICA5200; 23 | 24 | #define ds_GetTicks() (TIMER0_DATA) 25 | 26 | extern int bg0, bg1, bg0b,bg1b, bg2, bg3; 27 | extern unsigned int video_height; // Actual video height 28 | extern unsigned int gameCRC; // crc checksum of file 29 | 30 | extern void FadeToColor(unsigned char ucSens, unsigned short ucBG, unsigned char ucScr, unsigned char valEnd, unsigned char uWait); 31 | 32 | extern void vblankIntr(); 33 | 34 | extern void dsInitScreenMain(void); 35 | extern void dsInitTimer(void); 36 | extern void dsShowScreenEmu(void); 37 | extern void dsShowScreenMain(void); 38 | extern void dsFreeEmu(void); 39 | extern void VsoundHandler(void); 40 | extern void VsoundHandlerDSi(void); 41 | extern void dsLoadGame(char *filename); 42 | extern unsigned int dsReadPad(void); 43 | extern bool dsWaitOnQuit(void); 44 | extern void dsDisplayFiles(unsigned int NoDebGame,u32 ucSel); 45 | extern unsigned int dsWaitForRom(void); 46 | extern unsigned int dsWaitOnMenu(unsigned int actState); 47 | extern void dsPrintValue(int x, int y, unsigned int isSelect, char *pchStr); 48 | extern void dsInstallSoundEmuFIFO(void); 49 | extern void dsMainLoop(void); 50 | extern int a52Filescmp (const void *c1, const void *c2); 51 | extern void a52FindFiles(void); 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /arm9/source/emu/altirra_5200_os.c: -------------------------------------------------------------------------------- 1 | /* 2 | * altirra_5200_os.c - 5200 OS ROM replacement 3 | * 4 | * Compiled from Altirra-3.20-test4 source file 5 | * src/Kernel/source/SuperKernel/main.asm 6 | * 7 | * Altirra - Atari 800/800XL/5200 emulator 8 | * 5200 OS ROM replacement 9 | * Copyright (C) 2008-2010 Avery Lee 10 | * 11 | * Copying and distribution of this file, with or without modification, 12 | * are permitted in any medium without royalty provided the copyright 13 | * notice and this notice are preserved. This file is offered as-is, 14 | * without any warranty. 15 | */ 16 | 17 | #include "config.h" 18 | #include "atari.h" 19 | 20 | unsigned char const ROM_altirra_5200_os[0x800] = 21 | { 22 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 23 | 0x00,0x18,0x18,0x18,0x18,0x00,0x18,0x00, 24 | 0x00,0x66,0x66,0x66,0x00,0x00,0x00,0x00, 25 | 0x00,0x66,0xff,0x66,0x66,0xff,0x66,0x00, 26 | 0x18,0x3e,0x60,0x3c,0x06,0x7c,0x18,0x00, 27 | 0x00,0x66,0x6c,0x18,0x30,0x66,0x46,0x00, 28 | 0x1c,0x36,0x1c,0x38,0x6f,0x66,0x3b,0x00, 29 | 0x00,0x18,0x18,0x18,0x00,0x00,0x00,0x00, 30 | 0x00,0x0e,0x1c,0x18,0x18,0x1c,0x0e,0x00, 31 | 0x00,0x70,0x38,0x18,0x18,0x38,0x70,0x00, 32 | 0x00,0x66,0x3c,0xff,0x3c,0x66,0x00,0x00, 33 | 0x00,0x18,0x18,0x7e,0x18,0x18,0x00,0x00, 34 | 0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x30, 35 | 0x00,0x00,0x00,0x7e,0x00,0x00,0x00,0x00, 36 | 0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00, 37 | 0x00,0x06,0x0c,0x18,0x30,0x60,0x40,0x00, 38 | 0x00,0x3c,0x66,0x6e,0x76,0x66,0x3c,0x00, 39 | 0x00,0x18,0x38,0x18,0x18,0x18,0x7e,0x00, 40 | 0x00,0x3c,0x66,0x0c,0x18,0x30,0x7e,0x00, 41 | 0x00,0x7e,0x0c,0x18,0x0c,0x66,0x3c,0x00, 42 | 0x00,0x0c,0x1c,0x3c,0x6c,0x7e,0x0c,0x00, 43 | 0x00,0x7e,0x60,0x7c,0x06,0x66,0x3c,0x00, 44 | 0x00,0x3c,0x60,0x7c,0x66,0x66,0x3c,0x00, 45 | 0x00,0x7e,0x06,0x0c,0x18,0x30,0x30,0x00, 46 | 0x00,0x3c,0x66,0x3c,0x66,0x66,0x3c,0x00, 47 | 0x00,0x3c,0x66,0x3e,0x06,0x0c,0x38,0x00, 48 | 0x00,0x00,0x18,0x18,0x00,0x18,0x18,0x00, 49 | 0x00,0x00,0x18,0x18,0x00,0x18,0x18,0x30, 50 | 0x06,0x0c,0x18,0x30,0x18,0x0c,0x06,0x00, 51 | 0x00,0x00,0x7e,0x00,0x00,0x7e,0x00,0x00, 52 | 0x60,0x30,0x18,0x0c,0x18,0x30,0x60,0x00, 53 | 0x00,0x3c,0x66,0x0c,0x18,0x00,0x18,0x00, 54 | 0x00,0x3c,0x66,0x6e,0x6e,0x60,0x3e,0x00, 55 | 0x00,0x18,0x3c,0x66,0x66,0x7e,0x66,0x00, 56 | 0x00,0x7c,0x66,0x7c,0x66,0x66,0x7c,0x00, 57 | 0x00,0x3c,0x66,0x60,0x60,0x66,0x3c,0x00, 58 | 0x00,0x78,0x6c,0x66,0x66,0x6c,0x78,0x00, 59 | 0x00,0x7e,0x60,0x7c,0x60,0x60,0x7e,0x00, 60 | 0x00,0x7e,0x60,0x7c,0x60,0x60,0x60,0x00, 61 | 0x00,0x3e,0x60,0x60,0x6e,0x66,0x3e,0x00, 62 | 0x00,0x66,0x66,0x7e,0x66,0x66,0x66,0x00, 63 | 0x00,0x7e,0x18,0x18,0x18,0x18,0x7e,0x00, 64 | 0x00,0x06,0x06,0x06,0x06,0x66,0x3c,0x00, 65 | 0x00,0x66,0x6c,0x78,0x78,0x6c,0x66,0x00, 66 | 0x00,0x60,0x60,0x60,0x60,0x60,0x7e,0x00, 67 | 0x00,0x63,0x77,0x7f,0x6b,0x63,0x63,0x00, 68 | 0x00,0x66,0x76,0x7e,0x7e,0x6e,0x66,0x00, 69 | 0x00,0x3c,0x66,0x66,0x66,0x66,0x3c,0x00, 70 | 0x00,0x7c,0x66,0x66,0x7c,0x60,0x60,0x00, 71 | 0x00,0x3c,0x66,0x66,0x66,0x6c,0x36,0x00, 72 | 0x00,0x7c,0x66,0x66,0x7c,0x6c,0x66,0x00, 73 | 0x00,0x3c,0x60,0x3c,0x06,0x06,0x3c,0x00, 74 | 0x00,0x7e,0x18,0x18,0x18,0x18,0x18,0x00, 75 | 0x00,0x66,0x66,0x66,0x66,0x66,0x7e,0x00, 76 | 0x00,0x66,0x66,0x66,0x66,0x3c,0x18,0x00, 77 | 0x00,0x63,0x63,0x6b,0x7f,0x77,0x63,0x00, 78 | 0x00,0x66,0x66,0x3c,0x3c,0x66,0x66,0x00, 79 | 0x00,0x66,0x66,0x3c,0x18,0x18,0x18,0x00, 80 | 0x00,0x7e,0x0c,0x18,0x30,0x60,0x7e,0x00, 81 | 0x00,0x1e,0x18,0x18,0x18,0x18,0x1e,0x00, 82 | 0x00,0x40,0x60,0x30,0x18,0x0c,0x06,0x00, 83 | 0x00,0x78,0x18,0x18,0x18,0x18,0x78,0x00, 84 | 0x00,0x08,0x1c,0x36,0x63,0x00,0x00,0x00, 85 | 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00, 86 | 0x00,0x36,0x7f,0x7f,0x3e,0x1c,0x08,0x00, 87 | 0x18,0x18,0x18,0x1f,0x1f,0x18,0x18,0x18, 88 | 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03, 89 | 0x18,0x18,0x18,0xf8,0xf8,0x00,0x00,0x00, 90 | 0x18,0x18,0x18,0xf8,0xf8,0x18,0x18,0x18, 91 | 0x00,0x00,0x00,0xf8,0xf8,0x18,0x18,0x18, 92 | 0x03,0x07,0x0e,0x1c,0x38,0x70,0xe0,0xc0, 93 | 0xc0,0xe0,0x70,0x38,0x1c,0x0e,0x07,0x03, 94 | 0x01,0x03,0x07,0x0f,0x1f,0x3f,0x7f,0xff, 95 | 0x00,0x00,0x00,0x00,0x0f,0x0f,0x0f,0x0f, 96 | 0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff, 97 | 0x0f,0x0f,0x0f,0x0f,0x00,0x00,0x00,0x00, 98 | 0xf0,0xf0,0xf0,0xf0,0x00,0x00,0x00,0x00, 99 | 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00, 100 | 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff, 101 | 0x00,0x00,0x00,0x00,0xf0,0xf0,0xf0,0xf0, 102 | 0x00,0x1c,0x1c,0x77,0x77,0x08,0x1c,0x00, 103 | 0x00,0x00,0x00,0x1f,0x1f,0x18,0x18,0x18, 104 | 0x00,0x00,0x00,0xff,0xff,0x00,0x00,0x00, 105 | 0x18,0x18,0x18,0xff,0xff,0x18,0x18,0x18, 106 | 0x00,0x00,0x3c,0x7e,0x7e,0x7e,0x3c,0x00, 107 | 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff, 108 | 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, 109 | 0x00,0x00,0x00,0xff,0xff,0x18,0x18,0x18, 110 | 0x18,0x18,0x18,0xff,0xff,0x00,0x00,0x00, 111 | 0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0, 112 | 0x18,0x18,0x18,0x1f,0x1f,0x00,0x00,0x00, 113 | 0x78,0x60,0x78,0x60,0x7e,0x18,0x1e,0x00, 114 | 0x00,0x18,0x3c,0x7e,0x18,0x18,0x18,0x00, 115 | 0x00,0x18,0x18,0x18,0x7e,0x3c,0x18,0x00, 116 | 0x00,0x18,0x30,0x7e,0x30,0x18,0x00,0x00, 117 | 0x00,0x18,0x0c,0x7e,0x0c,0x18,0x00,0x00, 118 | 0x00,0x18,0x3c,0x7e,0x7e,0x3c,0x18,0x00, 119 | 0x00,0x00,0x3c,0x06,0x3e,0x66,0x3e,0x00, 120 | 0x00,0x60,0x60,0x7c,0x66,0x66,0x7c,0x00, 121 | 0x00,0x00,0x3c,0x60,0x60,0x60,0x3c,0x00, 122 | 0x00,0x06,0x06,0x3e,0x66,0x66,0x3e,0x00, 123 | 0x00,0x00,0x3c,0x66,0x7e,0x60,0x3c,0x00, 124 | 0x00,0x0e,0x18,0x3e,0x18,0x18,0x18,0x00, 125 | 0x00,0x00,0x3e,0x66,0x66,0x3e,0x06,0x7c, 126 | 0x00,0x60,0x60,0x7c,0x66,0x66,0x66,0x00, 127 | 0x00,0x18,0x00,0x38,0x18,0x18,0x3c,0x00, 128 | 0x00,0x06,0x00,0x06,0x06,0x06,0x06,0x3c, 129 | 0x00,0x60,0x60,0x6c,0x78,0x6c,0x66,0x00, 130 | 0x00,0x38,0x18,0x18,0x18,0x18,0x3c,0x00, 131 | 0x00,0x00,0x66,0x7f,0x7f,0x6b,0x63,0x00, 132 | 0x00,0x00,0x7c,0x66,0x66,0x66,0x66,0x00, 133 | 0x00,0x00,0x3c,0x66,0x66,0x66,0x3c,0x00, 134 | 0x00,0x00,0x7c,0x66,0x66,0x7c,0x60,0x60, 135 | 0x00,0x00,0x3e,0x66,0x66,0x3e,0x06,0x06, 136 | 0x00,0x00,0x7c,0x66,0x60,0x60,0x60,0x00, 137 | 0x00,0x00,0x3e,0x60,0x3c,0x06,0x7c,0x00, 138 | 0x00,0x18,0x7e,0x18,0x18,0x18,0x0e,0x00, 139 | 0x00,0x00,0x66,0x66,0x66,0x66,0x3e,0x00, 140 | 0x00,0x00,0x66,0x66,0x66,0x3c,0x18,0x00, 141 | 0x00,0x00,0x63,0x6b,0x7f,0x3e,0x36,0x00, 142 | 0x00,0x00,0x66,0x3c,0x18,0x3c,0x66,0x00, 143 | 0x00,0x00,0x66,0x66,0x66,0x3e,0x0c,0x78, 144 | 0x00,0x00,0x7e,0x0c,0x18,0x30,0x7e,0x00, 145 | 0x00,0x18,0x3c,0x7e,0x7e,0x18,0x3c,0x00, 146 | 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, 147 | 0x00,0x7e,0x78,0x7c,0x6e,0x66,0x06,0x00, 148 | 0x08,0x18,0x38,0x78,0x38,0x18,0x08,0x00, 149 | 0x10,0x18,0x1c,0x1e,0x1c,0x18,0x10,0x00, 150 | 151 | 0x6c,0x00,0x02,0x48,0xa9,0x20,0x2c,0x0e, 152 | 0xe8,0xd0,0x0d,0x45,0x00,0x8d,0x0e,0xe8, 153 | 0xa5,0x00,0x8d,0x0e,0xe8,0x6c,0x10,0x02, 154 | 0x30,0x0f,0xa9,0x80,0x45,0x00,0x8d,0x0e, 155 | 0xe8,0xa5,0x00,0x8d,0x0e,0xe8,0x6c,0x0c, 156 | 0x02,0x70,0x0f,0xa9,0x40,0x45,0x00,0x8d, 157 | 0x0e,0xe8,0xa5,0x00,0x8d,0x0e,0xe8,0x6c, 158 | 0x08,0x02,0x6a,0x2c,0x0e,0xe8,0xf0,0x0d, 159 | 0x45,0x00,0x8d,0x0e,0xe8,0xa5,0x00,0x8d, 160 | 0x0e,0xe8,0x6c,0x12,0x02,0x6a,0x24,0x00, 161 | 0xf0,0x12,0x2c,0x0e,0xe8,0xd0,0x0d,0x45, 162 | 0x00,0x8d,0x0e,0xe8,0xa5,0x00,0x8d,0x0e, 163 | 0xe8,0x6c,0x14,0x02,0xa9,0x01,0x2c,0x0e, 164 | 0xe8,0xd0,0x0d,0x45,0x00,0x8d,0x0e,0xe8, 165 | 0xa5,0x00,0x8d,0x0e,0xe8,0x6c,0x16,0x02, 166 | 0x2a,0x2c,0x0e,0xe8,0xd0,0x0d,0x45,0x00, 167 | 0x8d,0x0e,0xe8,0xa5,0x00,0x8d,0x0e,0xe8, 168 | 0x6c,0x18,0x02,0x2a,0x2c,0x0e,0xe8,0xd0, 169 | 0x0d,0x45,0x00,0x8d,0x0e,0xe8,0xa5,0x00, 170 | 0x8d,0x0e,0xe8,0x6c,0x1a,0x02,0x8a,0x48, 171 | 0xba,0xbd,0x01,0x01,0x29,0x10,0xd0,0x03, 172 | 0x6c,0x0e,0x02,0x68,0xaa,0x68,0x40,0xff, 173 | 0xff,0xff,0x68,0xa8,0x68,0xaa,0x68,0x40, 174 | 0x48,0x8a,0x48,0x98,0x48,0xe6,0x02,0xd0, 175 | 0x08,0xe6,0x01,0xa5,0x04,0x30,0x02,0xe6, 176 | 0x04,0xa5,0x03,0xd0,0xe5,0xa5,0x05,0x8d, 177 | 0x02,0xd4,0xa5,0x06,0x8d,0x03,0xd4,0xa5, 178 | 0x07,0x8d,0x00,0xd4,0xa0,0x00,0x24,0x04, 179 | 0x10,0x02,0xa4,0x01,0xa2,0x08,0x98,0x55, 180 | 0x08,0x9d,0x12,0xc0,0xca,0x10,0xf7,0xa2, 181 | 0x07,0xbd,0x00,0xe8,0x95,0x11,0xca,0x10, 182 | 0xf8,0x8d,0x0b,0xe8,0x6c,0x04,0x02,0xff, 183 | 0xff,0xff,0x8a,0x48,0x98,0x48,0xad,0x09, 184 | 0xe8,0x4a,0x29,0x0f,0xaa,0xbd,0x13,0xfd, 185 | 0x6c,0x0a,0x02,0xff,0x0b,0x00,0x0a,0x0e, 186 | 0x09,0x08,0x07,0x0d,0x06,0x05,0x04,0x0c, 187 | 0x03,0x02,0x01,0x2c,0x0f,0xd4,0x8d,0x0f, 188 | 0xd4,0x10,0x03,0x6c,0x06,0x02,0x6c,0x02, 189 | 0x02,0x78,0xd8,0xa2,0xff,0x9a,0xad,0xfd, 190 | 0xbf,0xc9,0xff,0xd0,0x03,0x6c,0xfe,0xbf, 191 | 0xa2,0x00,0xa9,0x00,0x95,0x00,0x9d,0x00, 192 | 0xc0,0x9d,0x00,0xd4,0x9d,0x00,0xe8,0xe8, 193 | 0xd0,0xf2,0xa9,0xf8,0x8d,0x09,0xd4,0xa2, 194 | 0x0b,0xbd,0x95,0xfe,0x9d,0x00,0x02,0xca, 195 | 0x10,0xf7,0xa2,0x4f,0xbd,0xcd,0xfd,0x9d, 196 | 0x00,0x10,0xca,0x10,0xf7,0xa2,0x13,0xbd, 197 | 0xe8,0xbf,0x9d,0x50,0x10,0xca,0x10,0xf7, 198 | 0xa9,0x10,0x85,0x0c,0xa9,0x0f,0x85,0x0d, 199 | 0xa9,0x00,0x85,0x0e,0xa9,0x00,0x85,0x0f, 200 | 0xa9,0x00,0x85,0x10,0xa9,0x04,0x8d,0x1b, 201 | 0xc0,0xa2,0x0a,0xbd,0xc2,0xfd,0x9d,0x00, 202 | 0x20,0xca,0x10,0xf7,0xa9,0x22,0x85,0x07, 203 | 0xa9,0xc0,0x8d,0x0e,0xd4,0xa9,0x00,0x85, 204 | 0x05,0xa9,0x20,0x85,0x06,0xa9,0x02,0x8d, 205 | 0x0f,0xe8,0xa9,0xc0,0x85,0x00,0x8d,0x0e, 206 | 0xe8,0xa9,0x78,0xc5,0x02,0xd0,0xfc,0x6c, 207 | 0xfe,0xbf,0x70,0x70,0x70,0x42,0x00,0x10, 208 | 0x82,0x07,0x41,0xc2,0xfd,0x21,0x6c,0x74, 209 | 0x69,0x72,0x72,0x61,0x00,0x15,0x12,0x10, 210 | 0x10,0x00,0x32,0x2f,0x2d,0x00,0x2b,0x65, 211 | 0x72,0x6e,0x65,0x6c,0x00,0x00,0x00,0x00, 212 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 213 | 0x00,0x00,0x00,0x00,0x00,0x2e,0x6f,0x77, 214 | 0x00,0x70,0x6c,0x61,0x79,0x69,0x6e,0x67, 215 | 0x1a,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 216 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 217 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 218 | 0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff, 219 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 220 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 221 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 222 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 223 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 224 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 225 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 226 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 227 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 228 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 229 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 230 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 231 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 232 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 233 | 0xff,0xff,0xff,0xff,0xff,0x03,0xfc,0xb8, 234 | 0xfc,0xb2,0xfc,0xa1,0xfe,0x02,0xfd,0xb2, 235 | 0xfc,0x48,0xe6,0x0c,0xd0,0x04,0xa9,0x10, 236 | 0x85,0x0c,0x68,0x40,0xff,0xff,0xff,0xff, 237 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 238 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 239 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 240 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 241 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 242 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 243 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 244 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 245 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 246 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 247 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 248 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 249 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 250 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 251 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 252 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 253 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 254 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 255 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 256 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 257 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 258 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 259 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 260 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 261 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 262 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 263 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 264 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 265 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 266 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 267 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 268 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 269 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 270 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 271 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 272 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 273 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 274 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 275 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 276 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 277 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 278 | 0xff,0xff,0x23,0xfd,0x31,0xfd,0x00,0xfc 279 | }; 280 | -------------------------------------------------------------------------------- /arm9/source/emu/altirra_5200_os.h: -------------------------------------------------------------------------------- 1 | #ifndef ROMS_ALTIRRA_5200_OS_H_ 2 | #define ROMS_ALTIRRA_5200_OS_H_ 3 | 4 | extern unsigned char const ROM_altirra_5200_os[0x800]; 5 | 6 | #endif /* ROMS_ALTIRRA_5200_OS_H_ */ -------------------------------------------------------------------------------- /arm9/source/emu/antic.h: -------------------------------------------------------------------------------- 1 | #ifndef _ANTIC_H_ 2 | #define _ANTIC_H_ 3 | 4 | #include "atari.h" 5 | 6 | /* 7 | * Offset to registers in custom relative to start of antic memory addresses. 8 | */ 9 | 10 | #define _DMACTL 0x00 11 | #define _CHACTL 0x01 12 | #define _DLISTL 0x02 13 | #define _DLISTH 0x03 14 | #define _HSCROL 0x04 15 | #define _VSCROL 0x05 16 | #define _PMBASE 0x07 17 | #define _CHBASE 0x09 18 | #define _WSYNC 0x0a 19 | #define _VCOUNT 0x0b 20 | #define _PENH 0x0c 21 | #define _PENV 0x0d 22 | #define _NMIEN 0x0e 23 | #define _NMIRES 0x0f 24 | #define _NMIST 0x0f 25 | 26 | extern UBYTE CHACTL; 27 | extern UBYTE CHBASE; 28 | extern UWORD dlist; 29 | extern UBYTE DMACTL; 30 | extern UBYTE HSCROL; 31 | extern UBYTE NMIEN; 32 | extern UBYTE NMIST; 33 | extern UBYTE PMBASE; 34 | extern UBYTE VSCROL; 35 | 36 | extern int break_ypos; 37 | extern int ypos; 38 | extern UBYTE wsync_halt; 39 | 40 | #define NMIST_C 6 41 | #define NMI_C 12 42 | 43 | extern UBYTE global_artif_mode; 44 | 45 | extern UBYTE PENH_input; 46 | extern UBYTE PENV_input; 47 | 48 | void ANTIC_Initialise(void); 49 | void ANTIC_Reset(void); 50 | void ANTIC_Frame(int draw_display); 51 | UBYTE ANTIC_GetByte(UWORD addr); 52 | void ANTIC_PutByte(UWORD addr, UBYTE byte); 53 | 54 | UBYTE ANTIC_GetDLByte(UWORD *paddr); 55 | UWORD ANTIC_GetDLWord(UWORD *paddr); 56 | 57 | /* always call ANTIC_UpdateArtifacting after changing global_artif_mode */ 58 | void ANTIC_UpdateArtifacting(void); 59 | 60 | #define XPOS xpos 61 | 62 | #endif /* _ANTIC_H_ */ 63 | -------------------------------------------------------------------------------- /arm9/source/emu/atari.c: -------------------------------------------------------------------------------- 1 | /* 2 | * atari.c - main high-level routines 3 | * 4 | * Copyright (c) 1995-1998 David Firth 5 | * Copyright (c) 1998-2006 Atari800 development team (see DOC/CREDITS) 6 | * 7 | * This file is part of the Atari800 emulator project which emulates 8 | * the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers. 9 | * 10 | * Atari800 is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * Atari800 is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with Atari800; if not, write to the Free Software 22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 | */ 24 | 25 | #include "config.h" 26 | #include 27 | #include 28 | #include 29 | #include "main.h" 30 | #include "antic.h" 31 | #include "atari.h" 32 | #include "cartridge.h" 33 | #include "cpu.h" 34 | #include "gtia.h" 35 | #include "input.h" 36 | #include "memory.h" 37 | #include "pia.h" 38 | #include "platform.h" 39 | #include "pokeysnd.h" 40 | 41 | 42 | void Atari800_RunEsc(UBYTE esc_code) 43 | { 44 | Atari800_Exit(TRUE); 45 | } 46 | 47 | 48 | void Warmstart(void) 49 | { 50 | PIA_Reset(); 51 | ANTIC_Reset(); 52 | /* CPU_Reset() must be after PIA_Reset(), 53 | because Reset routine vector must be read from OS ROM */ 54 | CPU_Reset(); 55 | /* note: POKEY and GTIA have no Reset pin */ 56 | } 57 | 58 | void Coldstart(void) { 59 | PIA_Reset(); 60 | ANTIC_Reset(); 61 | /* CPU_Reset() must be after PIA_Reset(), 62 | because Reset routine vector must be read from OS ROM */ 63 | CPU_Reset(); 64 | /* note: POKEY and GTIA have no Reset pin */ 65 | 66 | /* reset cartridge to power-up state */ 67 | CART_Start(); 68 | 69 | /* set Atari OS Coldstart flag */ 70 | dPutByte(0x244, 1); 71 | 72 | consol_index = 2; 73 | consol_table[2] = 0x0f; 74 | 75 | /* hold Option during reboot */ 76 | consol_table[2] &= ~CONSOL_OPTION; 77 | 78 | consol_table[1] = consol_table[2]; 79 | } 80 | 81 | int Atari800_InitialiseMachine(void) 82 | { 83 | MEMORY_InitialiseMachine(); 84 | return TRUE; 85 | } 86 | 87 | int Atari800_DetectFileType(const char *filename) 88 | { 89 | return AFILE_CART; 90 | } 91 | 92 | int Atari800_OpenFile(const char *filename, int reboot, int diskno, int readonly) { 93 | // Remove cart if exist 94 | CART_Remove(); 95 | 96 | int type = Atari800_DetectFileType(filename); 97 | 98 | switch (type) 99 | { 100 | case AFILE_CART: 101 | case AFILE_ROM: 102 | if (CART_Insert(filename) != 0) { 103 | return AFILE_ERROR; 104 | } 105 | if (reboot) 106 | Coldstart(); 107 | break; 108 | 109 | default: 110 | break; 111 | } 112 | return type; 113 | } 114 | 115 | int Atari800_Initialise(void) 116 | { 117 | INPUT_Initialise(); 118 | 119 | // Platform Specific Initialisation 120 | Atari_Initialise(); 121 | 122 | // Initialise Custom Chips 123 | ANTIC_Initialise(); 124 | GTIA_Initialise(); 125 | PIA_Initialise(); 126 | POKEY_Initialise(); 127 | 128 | Atari800_InitialiseMachine(); 129 | 130 | return TRUE; 131 | } 132 | 133 | int Atari800_Exit(int run_monitor) { 134 | return Atari_Exit(run_monitor); 135 | } 136 | 137 | extern int gTotalAtariFrames; 138 | void Atari800_Frame(void) 139 | { 140 | INPUT_Frame(); 141 | GTIA_Frame(); 142 | ANTIC_Frame((myCart.frame_skip ? (gTotalAtariFrames & myCart.frame_skip) : TRUE)); // With frameskip, we skip every 8th frame (drawing 7 of 8). Skip is dangerous for the collision detection so we do it sparingly 143 | POKEY_Frame(); 144 | 145 | gTotalAtariFrames++; 146 | } 147 | -------------------------------------------------------------------------------- /arm9/source/emu/atari.h: -------------------------------------------------------------------------------- 1 | #ifndef _ATARI_H_ 2 | #define _ATARI_H_ 3 | 4 | #include 5 | #include "config.h" 6 | #include "printf.h" 7 | 8 | /* Fundamental declarations ---------------------------------------------- */ 9 | 10 | #ifndef FALSE 11 | #define FALSE 0 12 | #endif 13 | #ifndef TRUE 14 | #define TRUE 1 15 | #endif 16 | 17 | #define MAX_FILENAME_LEN 256 18 | 19 | // Some global sound defines 20 | #define SOUND_FREQ (15720) // 60 frames per second. 264 scanlines per frame. 1 samples per scanline. 60*264*1 = 15720 21 | #define SNDLENGTH 1024 // Must be power of 2... so we can quickly mask it 22 | 23 | /* SBYTE and UBYTE must be exactly 1 byte long. */ 24 | /* SWORD and UWORD must be exactly 2 bytes long. */ 25 | /* SLONG and ULONG must be exactly 4 bytes long. */ 26 | #define SBYTE signed char 27 | #define SWORD signed short 28 | #define SLONG signed int 29 | #define UBYTE unsigned char 30 | #define UWORD unsigned short 31 | #define ULONG unsigned int 32 | /* Note: in various parts of the emulator we assume that char is 1 byte and int is 4 bytes. */ 33 | 34 | /* Global debug registers to aid with emulation debug */ 35 | extern ULONG debug[]; 36 | 37 | /* Public interface ------------------------------------------------------ */ 38 | 39 | /* Video system. */ 40 | #define TV_PAL 312 41 | #define TV_NTSC 262 42 | 43 | /* Dimensions of atari_screen. 44 | atari_screen is ATARI_WIDTH * ATARI_HEIGHT bytes. 45 | Each byte is an Atari color code - use Palette_Get[RGB] functions 46 | to get actual RGB codes. 47 | You should never display anything outside the middle 336 columns. */ 48 | #define ATARI_WIDTH 384 49 | #define ATARI_HEIGHT 240 50 | 51 | /* Special key codes. 52 | Store in key_code. */ 53 | #define AKEY_WARMSTART -2 54 | #define AKEY_COLDSTART -3 55 | #define AKEY_EXIT -4 56 | #define AKEY_BREAK -5 57 | #define AKEY_UI -7 58 | #define AKEY_SCREENSHOT -8 59 | #define AKEY_SCREENSHOT_INTERLACE -9 60 | #define AKEY_START -10 61 | #define AKEY_SELECT -11 62 | #define AKEY_OPTION -12 63 | 64 | 65 | /* File types returned by Atari800_DetectFileType() and Atari800_OpenFile(). */ 66 | #define AFILE_ERROR 0 67 | #define AFILE_CART 9 68 | #define AFILE_ROM 10 69 | 70 | /* Initializes Atari800 emulation core. */ 71 | int Atari800_Initialise(void); 72 | 73 | /* Emulates one frame (1/50sec for PAL, 1/60sec for NTSC). */ 74 | void Atari800_Frame(void); 75 | 76 | /* Reboots the emulated Atari. */ 77 | void Coldstart(void); 78 | 79 | /* Presses the Reset key in the emulated Atari. */ 80 | void Warmstart(void); 81 | 82 | /* Reinitializes after machine_type or ram_size change. 83 | You should call Coldstart() after it. */ 84 | int Atari800_InitialiseMachine(void); 85 | 86 | /* Auto-detects file type and returns one of AFILE_* values. */ 87 | int Atari800_DetectFileType(const char *filename); 88 | 89 | /* Auto-detects file type and mounts the file in the emulator. 90 | reboot: Coldstart() for disks, cartridges and tapes 91 | diskno: drive number for disks (1-8) 92 | readonly: mount disks as read-only */ 93 | int Atari800_OpenFile(const char *filename, int reboot, int diskno, int readonly); 94 | 95 | /* Checks for "popular" filenames of ROM images in the specified directory 96 | and sets atari_*_filename to the ones found. 97 | If only_if_not_set is TRUE, then atari_*_filename is modified only when 98 | Util_filenamenotset() is TRUE for it. */ 99 | void Atari800_FindROMImages(const char *directory, int only_if_not_set); 100 | 101 | /* Shuts down Atari800 emulation core. */ 102 | int Atari800_Exit(int run_monitor); 103 | 104 | 105 | /* Private interface ----------------------------------------------------- */ 106 | /* Don't use outside the emulation core! */ 107 | 108 | 109 | /* Current clock cycle in a scanline. 110 | Normally 0 <= xpos && xpos < LINE_C, but in some cases xpos >= LINE_C, 111 | which means that we are already in line (ypos + 1). */ 112 | extern int xpos; 113 | 114 | /* xpos limit for the currently running 6502 emulation. */ 115 | extern int xpos_limit; 116 | 117 | /* Number of cycles per scanline. */ 118 | #define LINE_C 114 119 | 120 | /* STA WSYNC resumes here. */ 121 | #define WSYNC_C 106 122 | 123 | /* Number of memory refresh cycles per scanline. 124 | In the first scanline of a font mode there are actually less than DMAR 125 | memory refresh cycles. */ 126 | #define DMAR 9 127 | 128 | /* Number of scanlines per frame. */ 129 | #define max_ypos TV_NTSC 130 | 131 | #define UNALIGNED_STAT_DEF() 132 | #define UNALIGNED_STAT_DECL() 133 | #define UNALIGNED_GET_WORD(ptr) (*(const UWORD *) (ptr)) 134 | #define UNALIGNED_PUT_WORD(ptr, value) (*(UWORD *) (ptr) = (value)) 135 | #define UNALIGNED_GET_LONG(ptr) (*(const ULONG *) (ptr)) 136 | #define UNALIGNED_PUT_LONG(ptr, value) (*(ULONG *) (ptr) = (value)) 137 | 138 | /* Handles an escape sequence. */ 139 | void Atari800_RunEsc(UBYTE esc_code); 140 | 141 | /* Reads a byte from the specified special address (not RAM or ROM). */ 142 | UBYTE Atari800_GetByte(UWORD addr); 143 | 144 | /* Stores a byte at the specified special address (not RAM or ROM). */ 145 | void Atari800_PutByte(UWORD addr, UBYTE byte); 146 | 147 | #endif /* _ATARI_H_ */ 148 | -------------------------------------------------------------------------------- /arm9/source/emu/atari_nds.c: -------------------------------------------------------------------------------- 1 | /* $Id: atari_vga.c,v 1.1 2001/10/26 05:36:48 fox Exp $ */ 2 | /* -------------------------------------------------------------------------- */ 3 | 4 | /* 5 | * DJGPP - VGA Backend for David Firth's Atari 800 emulator 6 | * 7 | * by Ivo van Poorten (C)1996 See file COPYRIGHT for policy. 8 | * 9 | */ 10 | 11 | /* -------------------------------------------------------------------------- */ 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include "main.h" 19 | 20 | #include "config.h" 21 | #include "cpu.h" 22 | #include "input.h" 23 | #include "pokeysnd.h" 24 | 25 | #define DSPRATE 11025 26 | 27 | u16 trig0 = 1; 28 | u16 trig1 = 1; 29 | u16 stick0 = STICK_CENTRE; 30 | u16 stick1 = STICK_CENTRE; 31 | 32 | #define first_lno 20 /* center 320x200 window in 384x240 screen */ 33 | #define first_col 32 34 | 35 | /* -------------------------------------------------------------------------- */ 36 | /* CONFIG & INITIALISATION */ 37 | /* -------------------------------------------------------------------------- */ 38 | void Atari_Initialise(void) 39 | { 40 | Pokey_sound_init(FREQ_17_APPROX, DSPRATE, 1, 0); //SND_BIT16); 41 | 42 | trig0 = 1; // Not pressed 43 | trig1 = 1; // Not pressed 44 | stick0 = STICK_CENTRE; 45 | stick1 = STICK_CENTRE; 46 | 47 | key_consol = CONSOL_NONE; 48 | } 49 | 50 | /* -------------------------------------------------------------------------- */ 51 | /* ATARI EXIT */ 52 | /* -------------------------------------------------------------------------- */ 53 | int Atari_Exit(int run_monitor) 54 | { 55 | return 0; 56 | } 57 | 58 | -------------------------------------------------------------------------------- /arm9/source/emu/cartridge.h: -------------------------------------------------------------------------------- 1 | #ifndef _CARTRIDGE_H_ 2 | #define _CARTRIDGE_H_ 3 | 4 | #include "config.h" 5 | #include "atari.h" 6 | 7 | #define CART_NONE 0 8 | #define CART_5200_4 1 9 | #define CART_5200_8 2 10 | #define CART_5200_EE_16 3 11 | #define CART_5200_NS_16 4 12 | #define CART_5200_32 5 13 | #define CART_5200_40 6 14 | #define CART_5200_64 7 15 | #define CART_5200_64_SWAP 8 16 | #define CART_5200_128 9 17 | #define CART_5200_256 10 18 | #define CART_5200_512 11 19 | #define CART_LAST_SUPPORTED 11 20 | 21 | struct cart_t 22 | { 23 | char *md5; 24 | unsigned char type; 25 | unsigned char control; 26 | unsigned char use_analog; 27 | unsigned char analog_speed; 28 | unsigned char digital_min; 29 | unsigned char digital_max; 30 | unsigned char keys_debounced; 31 | unsigned char frame_skip; 32 | short int scale_x; 33 | short int scale_y; 34 | short int offset_x; 35 | short int offset_y; 36 | unsigned char artifacting; 37 | unsigned char x_function; 38 | }; 39 | 40 | extern struct cart_t myCart; 41 | 42 | #define CTRL_JOY 1 43 | #define CTRL_SWAP 2 44 | #define CTRL_FROG 3 45 | #define CTRL_QBERT 4 46 | #define CTRL_ROBO 5 47 | #define CTRL_SR 6 48 | 49 | #define DIGITAL 0 50 | #define ANALOG 1 51 | 52 | #define NO_FS 0 53 | #define YES_FS 3 // Only for non-DSi where we need the speed. Displays 3 of 4 frames. 54 | #define YES_FSL 7 // A lighter version of frameskip. Displays 7 of 8 frames. 55 | 56 | #define X_FIRE 0 57 | #define X_PANUP 1 58 | #define X_PANDN 2 59 | #define X_PAND2 3 60 | 61 | #define CART_MAX_SIZE (512 * 1024) 62 | 63 | #define CART_CANT_OPEN -1 /* Can't open cartridge image file */ 64 | #define CART_BAD_FORMAT -2 /* Unknown cartridge format */ 65 | #define CART_BAD_CHECKSUM -3 /* Warning: bad CART checksum */ 66 | int CART_Insert(const char *filename); 67 | void CART_Remove(void); 68 | void CART_Start(void); 69 | int Util_flen(FILE *fp); 70 | 71 | #endif /* _CARTRIDGE_H_ */ 72 | -------------------------------------------------------------------------------- /arm9/source/emu/config.h: -------------------------------------------------------------------------------- 1 | //Obsoleted file -------------------------------------------------------------------------------- /arm9/source/emu/cpu.h: -------------------------------------------------------------------------------- 1 | #ifndef _CPU_H_ 2 | #define _CPU_H_ 3 | 4 | #include "config.h" 5 | #ifdef ASAP /* external project, see http://asap.sf.net */ 6 | #include "asap_internal.h" 7 | #else 8 | #include "atari.h" 9 | #endif 10 | 11 | #define N_FLAG 0x80 12 | #define V_FLAG 0x40 13 | #define B_FLAG 0x10 14 | #define D_FLAG 0x08 15 | #define I_FLAG 0x04 16 | #define Z_FLAG 0x02 17 | #define C_FLAG 0x01 18 | 19 | void CPU_Initialise(void); /* used in the assembler version of cpu.c only */ 20 | void CPU_GetStatus(void); 21 | void CPU_PutStatus(void); 22 | void CPU_Reset(void); 23 | void NMI(void); 24 | void GO(int limit); 25 | #define GenerateIRQ() (IRQ = 1) 26 | 27 | extern ULONG regPC; 28 | extern UBYTE regA; 29 | extern UBYTE regP; 30 | extern UBYTE regS; 31 | extern UBYTE regY; 32 | extern UBYTE regX; 33 | 34 | #define SetN regP |= N_FLAG 35 | #define ClrN regP &= (~N_FLAG) 36 | #define SetV regP |= V_FLAG 37 | #define ClrV regP &= (~V_FLAG) 38 | #define SetB regP |= B_FLAG 39 | #define ClrB regP &= (~B_FLAG) 40 | #define SetD regP |= D_FLAG 41 | #define ClrD regP &= (~D_FLAG) 42 | #define SetI regP |= I_FLAG 43 | #define ClrI regP &= (~I_FLAG) 44 | #define SetZ regP |= Z_FLAG 45 | #define ClrZ regP &= (~Z_FLAG) 46 | #define SetC regP |= C_FLAG 47 | #define ClrC regP &= (~C_FLAG) 48 | 49 | extern UBYTE IRQ; 50 | 51 | extern UBYTE cim_encountered; 52 | 53 | #endif /* _CPU_H_ */ 54 | -------------------------------------------------------------------------------- /arm9/source/emu/gtia.c: -------------------------------------------------------------------------------- 1 | /* 2 | * gtia.c - GTIA chip emulation 3 | * 4 | * Copyright (C) 1995-1998 David Firth 5 | * Copyright (C) 1998-2005 Atari800 development team (see DOC/CREDITS) 6 | * 7 | * This file is part of the Atari800 emulator project which emulates 8 | * the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers. 9 | * 10 | * Atari800 is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * Atari800 is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with Atari800; if not, write to the Free Software 22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 | */ 24 | #include 25 | #include "config.h" 26 | #include "a5200utils.h" 27 | #include 28 | #include 29 | #include 30 | #include "atari.h" 31 | #include "antic.h" 32 | #include "gtia.h" 33 | #include "input.h" 34 | #include "pokeysnd.h" 35 | 36 | /* GTIA Registers ---------------------------------------------------------- */ 37 | 38 | UBYTE M0PL __attribute__((section(".dtcm"))); 39 | UBYTE M1PL __attribute__((section(".dtcm"))); 40 | UBYTE M2PL __attribute__((section(".dtcm"))); 41 | UBYTE M3PL __attribute__((section(".dtcm"))); 42 | UBYTE P0PL __attribute__((section(".dtcm"))); 43 | UBYTE P1PL __attribute__((section(".dtcm"))); 44 | UBYTE P2PL __attribute__((section(".dtcm"))); 45 | UBYTE P3PL __attribute__((section(".dtcm"))); 46 | UBYTE HPOSP0 __attribute__((section(".dtcm"))); 47 | UBYTE HPOSP1 __attribute__((section(".dtcm"))); 48 | UBYTE HPOSP2 __attribute__((section(".dtcm"))); 49 | UBYTE HPOSP3 __attribute__((section(".dtcm"))); 50 | UBYTE HPOSM0 __attribute__((section(".dtcm"))); 51 | UBYTE HPOSM1 __attribute__((section(".dtcm"))); 52 | UBYTE HPOSM2 __attribute__((section(".dtcm"))); 53 | UBYTE HPOSM3 __attribute__((section(".dtcm"))); 54 | UBYTE SIZEP0 __attribute__((section(".dtcm"))); 55 | UBYTE SIZEP1 __attribute__((section(".dtcm"))); 56 | UBYTE SIZEP2 __attribute__((section(".dtcm"))); 57 | UBYTE SIZEP3 __attribute__((section(".dtcm"))); 58 | UBYTE SIZEM __attribute__((section(".dtcm"))); 59 | UBYTE GRAFP0 __attribute__((section(".dtcm"))); 60 | UBYTE GRAFP1 __attribute__((section(".dtcm"))); 61 | UBYTE GRAFP2 __attribute__((section(".dtcm"))); 62 | UBYTE GRAFP3 __attribute__((section(".dtcm"))); 63 | UBYTE GRAFM __attribute__((section(".dtcm"))); 64 | UBYTE COLPM0 __attribute__((section(".dtcm"))); 65 | UBYTE COLPM1 __attribute__((section(".dtcm"))); 66 | UBYTE COLPM2 __attribute__((section(".dtcm"))); 67 | UBYTE COLPM3 __attribute__((section(".dtcm"))); 68 | UBYTE COLPF0 __attribute__((section(".dtcm"))); 69 | UBYTE COLPF1 __attribute__((section(".dtcm"))); 70 | UBYTE COLPF2 __attribute__((section(".dtcm"))); 71 | UBYTE COLPF3 __attribute__((section(".dtcm"))); 72 | UBYTE COLBK __attribute__((section(".dtcm"))); 73 | UBYTE PRIOR __attribute__((section(".dtcm"))); 74 | UBYTE VDELAY __attribute__((section(".dtcm"))); 75 | UBYTE GRACTL __attribute__((section(".dtcm"))); 76 | UBYTE POTENA __attribute__((section(".dtcm"))); 77 | 78 | /* Internal GTIA state ----------------------------------------------------- */ 79 | 80 | UBYTE consol_index __attribute__((section(".dtcm"))) = 0; 81 | UBYTE consol_table[3] __attribute__((section(".dtcm"))); 82 | UBYTE consol_mask __attribute__((section(".dtcm"))); 83 | UBYTE TRIG[4] __attribute__((section(".dtcm"))); 84 | UBYTE TRIG_latch[4] __attribute__((section(".dtcm"))); 85 | 86 | void set_prior(UBYTE byte); /* in antic.c */ 87 | 88 | /* Player/Missile stuff ---------------------------------------------------- */ 89 | 90 | /* change to 0x00 to disable collisions */ 91 | #define collisions_mask_missile_playfield 0x0f 92 | #define collisions_mask_player_playfield 0x0f 93 | #define collisions_mask_missile_player 0x0f 94 | #define collisions_mask_player_player 0x0f 95 | 96 | #define P1PL_T P1PL 97 | #define P2PL_T P2PL 98 | #define P3PL_T P3PL 99 | #define M0PL_T M0PL 100 | #define M1PL_T M1PL 101 | #define M2PL_T M2PL 102 | #define M3PL_T M3PL 103 | 104 | extern UBYTE player_dma_enabled; 105 | extern UBYTE missile_dma_enabled; 106 | extern UBYTE player_gra_enabled; 107 | extern UBYTE missile_gra_enabled; 108 | extern UBYTE player_flickering; 109 | extern UBYTE missile_flickering; 110 | 111 | static UBYTE *hposp_ptr[4] __attribute__((section(".dtcm"))); 112 | static UBYTE *hposm_ptr[4] __attribute__((section(".dtcm"))); 113 | static ULONG hposp_mask[4] __attribute__((section(".dtcm"))); 114 | 115 | static ULONG *grafp_ptr[4] __attribute__((section(".dtcm"))); 116 | static UBYTE global_sizem[4] __attribute__((section(".dtcm"))); 117 | static UBYTE PM_Width[4] __attribute__((section(".dtcm"))) = {1, 2, 1, 4}; 118 | 119 | ULONG *grafp_lookup = (ULONG*)0x068A0000; // Using 4K here for lookup table... ULONG[4][256] 120 | 121 | /* Meaning of bits in pm_scanline: 122 | bit 0 - Player 0 123 | bit 1 - Player 1 124 | bit 2 - Player 2 125 | bit 3 - Player 3 126 | bit 4 - Missile 0 127 | bit 5 - Missile 1 128 | bit 6 - Missile 2 129 | bit 7 - Missile 3 130 | */ 131 | 132 | UBYTE pm_scanline[ATARI_WIDTH / 2 + 8] __attribute__((section(".dtcm"))); /* there's a byte for every *pair* of pixels */ 133 | UBYTE pm_dirty __attribute__((section(".dtcm"))) = TRUE; 134 | 135 | #define C_PM0 0x01 136 | #define C_PM1 0x02 137 | #define C_PM01 0x03 138 | #define C_PM2 0x04 139 | #define C_PM3 0x05 140 | #define C_PM23 0x06 141 | #define C_PM023 0x07 142 | #define C_PM123 0x08 143 | #define C_PM0123 0x09 144 | #define C_PM25 0x0a 145 | #define C_PM35 0x0b 146 | #define C_PM235 0x0c 147 | #define C_COLLS 0x0d 148 | #define C_BAK 0x00 149 | #define C_HI2 0x20 150 | #define C_HI3 0x30 151 | #define C_PF0 0x40 152 | #define C_PF1 0x50 153 | #define C_PF2 0x60 154 | #define C_PF3 0x70 155 | 156 | extern UWORD cl_lookup[128]; 157 | 158 | #define PF0PM (*(UBYTE *) &cl_lookup[C_PF0 | C_COLLS]) 159 | #define PF1PM (*(UBYTE *) &cl_lookup[C_PF1 | C_COLLS]) 160 | #define PF2PM (*(UBYTE *) &cl_lookup[C_PF2 | C_COLLS]) 161 | #define PF3PM (*(UBYTE *) &cl_lookup[C_PF3 | C_COLLS]) 162 | 163 | /* Colours ----------------------------------------------------------------- */ 164 | 165 | extern UWORD hires_lookup_l[128]; 166 | extern ULONG lookup_gtia9[16]; 167 | extern ULONG lookup_gtia11[16]; 168 | 169 | void setup_gtia9_11(void) { 170 | int i; 171 | ULONG count9 = 0; 172 | ULONG count11 = 0; 173 | lookup_gtia11[0] = lookup_gtia9[0] & 0xf0f0f0f0; 174 | for (i = 1; i < 16; i++) { 175 | lookup_gtia9[i] = lookup_gtia9[0] | (count9 += 0x01010101); 176 | lookup_gtia11[i] = lookup_gtia9[0] | (count11 += 0x10101010); 177 | } 178 | } 179 | 180 | 181 | /* Initialization ---------------------------------------------------------- */ 182 | 183 | void GTIA_Initialise(void) 184 | { 185 | int i; 186 | for (i = 0; i < 256; i++) { 187 | int tmp = i + 0x100; 188 | ULONG grafp1 = 0; 189 | ULONG grafp2 = 0; 190 | ULONG grafp4 = 0; 191 | do { 192 | grafp1 <<= 1; 193 | grafp2 <<= 2; 194 | grafp4 <<= 4; 195 | if (tmp & 1) { 196 | grafp1++; 197 | grafp2 += 3; 198 | grafp4 += 15; 199 | } 200 | tmp >>= 1; 201 | } while (tmp != 1); 202 | grafp_lookup[2*256+i] = grafp_lookup[0*256+i] = grafp1; 203 | grafp_lookup[1*256+i] = grafp2; 204 | grafp_lookup[3*256+i] = grafp4; 205 | } 206 | memset(cl_lookup, COLOUR_BLACK, sizeof(cl_lookup)); 207 | for (i = 0; i < 32; i++) 208 | GTIA_PutByte((UWORD) i, 0); 209 | 210 | POTENA=0; 211 | } 212 | 213 | #define update_partial_pmpl_colls() 214 | 215 | /* Prepare PMG scanline ---------------------------------------------------- */ 216 | 217 | ITCM_CODE void new_pm_scanline(void) 218 | { 219 | /* Clear if necessary */ 220 | if (pm_dirty) { 221 | memset(pm_scanline, 0, ATARI_WIDTH / 2); 222 | pm_dirty = FALSE; 223 | } 224 | 225 | /* Draw Players */ 226 | 227 | #define DO_PLAYER(n) if (GRAFP##n) { \ 228 | ULONG grafp = grafp_ptr[n][GRAFP##n] & hposp_mask[n]; \ 229 | if (grafp) { \ 230 | UBYTE *ptr = hposp_ptr[n]; \ 231 | pm_dirty = TRUE; \ 232 | do { \ 233 | if (grafp & 1) \ 234 | P##n##PL_T |= *ptr |= 1 << n; \ 235 | ptr++; \ 236 | grafp >>= 1; \ 237 | } while (grafp); \ 238 | } \ 239 | } 240 | 241 | /* optimized DO_PLAYER(0): pm_scanline is clear and P0PL is unused */ 242 | if (GRAFP0) { 243 | ULONG grafp = grafp_ptr[0][GRAFP0] & hposp_mask[0]; 244 | if (grafp) { 245 | UBYTE *ptr = hposp_ptr[0]; 246 | pm_dirty = TRUE; 247 | do { 248 | if (grafp & 1) 249 | *ptr = 1; 250 | ptr++; 251 | grafp >>= 1; 252 | } while (grafp); 253 | } 254 | } 255 | 256 | DO_PLAYER(1) 257 | DO_PLAYER(2) 258 | DO_PLAYER(3) 259 | 260 | /* Draw Missiles */ 261 | 262 | #define DO_MISSILE(n,p,m,r,l) if (GRAFM & m) { \ 263 | int j = global_sizem[n]; \ 264 | UBYTE *ptr = hposm_ptr[n]; \ 265 | if (GRAFM & r) { \ 266 | if (GRAFM & l) \ 267 | j <<= 1; \ 268 | } \ 269 | else \ 270 | ptr += j; \ 271 | if (ptr < pm_scanline + 2) { \ 272 | j += ptr - pm_scanline - 2; \ 273 | ptr = pm_scanline + 2; \ 274 | } \ 275 | else if (ptr + j > pm_scanline + ATARI_WIDTH / 2 - 2) \ 276 | j = pm_scanline + ATARI_WIDTH / 2 - 2 - ptr; \ 277 | if (j > 0) \ 278 | do \ 279 | M##n##PL_T |= *ptr++ |= p; \ 280 | while (--j); \ 281 | } 282 | 283 | if (GRAFM) { 284 | pm_dirty = TRUE; 285 | DO_MISSILE(3, 0x80, 0xc0, 0x80, 0x40) 286 | DO_MISSILE(2, 0x40, 0x30, 0x20, 0x10) 287 | DO_MISSILE(1, 0x20, 0x0c, 0x08, 0x04) 288 | DO_MISSILE(0, 0x10, 0x03, 0x02, 0x01) 289 | } 290 | } 291 | 292 | /* GTIA registers ---------------------------------------------------------- */ 293 | 294 | void GTIA_Frame(void) 295 | { 296 | int consol = key_consol | 0x08; 297 | 298 | consol_table[0] = consol; 299 | consol_table[1] = consol_table[2] &= consol; 300 | 301 | if (GRACTL & 4) { 302 | TRIG_latch[0] &= TRIG[0]; 303 | TRIG_latch[1] &= TRIG[1]; 304 | TRIG_latch[2] &= TRIG[2]; 305 | TRIG_latch[3] &= TRIG[3]; 306 | } 307 | } 308 | 309 | UBYTE GTIA_GetByte(UWORD addr) 310 | { 311 | switch (addr & 0x1f) { 312 | case _M0PF: 313 | return (((PF0PM & 0x10) >> 4) 314 | + ((PF1PM & 0x10) >> 3) 315 | + ((PF2PM & 0x10) >> 2) 316 | + ((PF3PM & 0x10) >> 1)) & collisions_mask_missile_playfield; 317 | case _M1PF: 318 | return (((PF0PM & 0x20) >> 5) 319 | + ((PF1PM & 0x20) >> 4) 320 | + ((PF2PM & 0x20) >> 3) 321 | + ((PF3PM & 0x20) >> 2)) & collisions_mask_missile_playfield; 322 | case _M2PF: 323 | return (((PF0PM & 0x40) >> 6) 324 | + ((PF1PM & 0x40) >> 5) 325 | + ((PF2PM & 0x40) >> 4) 326 | + ((PF3PM & 0x40) >> 3)) & collisions_mask_missile_playfield; 327 | case _M3PF: 328 | return (((PF0PM & 0x80) >> 7) 329 | + ((PF1PM & 0x80) >> 6) 330 | + ((PF2PM & 0x80) >> 5) 331 | + ((PF3PM & 0x80) >> 4)) & collisions_mask_missile_playfield; 332 | case _P0PF: 333 | return ((PF0PM & 0x01) 334 | + ((PF1PM & 0x01) << 1) 335 | + ((PF2PM & 0x01) << 2) 336 | + ((PF3PM & 0x01) << 3)) & collisions_mask_player_playfield; 337 | case _P1PF: 338 | return (((PF0PM & 0x02) >> 1) 339 | + (PF1PM & 0x02) 340 | + ((PF2PM & 0x02) << 1) 341 | + ((PF3PM & 0x02) << 2)) & collisions_mask_player_playfield; 342 | case _P2PF: 343 | return (((PF0PM & 0x04) >> 2) 344 | + ((PF1PM & 0x04) >> 1) 345 | + (PF2PM & 0x04) 346 | + ((PF3PM & 0x04) << 1)) & collisions_mask_player_playfield; 347 | case _P3PF: 348 | return (((PF0PM & 0x08) >> 3) 349 | + ((PF1PM & 0x08) >> 2) 350 | + ((PF2PM & 0x08) >> 1) 351 | + (PF3PM & 0x08)) & collisions_mask_player_playfield; 352 | case _M0PL: 353 | update_partial_pmpl_colls(); 354 | return M0PL & collisions_mask_missile_player; 355 | case _M1PL: 356 | update_partial_pmpl_colls(); 357 | return M1PL & collisions_mask_missile_player; 358 | case _M2PL: 359 | update_partial_pmpl_colls(); 360 | return M2PL & collisions_mask_missile_player; 361 | case _M3PL: 362 | update_partial_pmpl_colls(); 363 | return M3PL & collisions_mask_missile_player; 364 | case _P0PL: 365 | update_partial_pmpl_colls(); 366 | return (((P1PL & 0x01) << 1) /* mask in player 1 */ 367 | + ((P2PL & 0x01) << 2) /* mask in player 2 */ 368 | + ((P3PL & 0x01) << 3)) /* mask in player 3 */ 369 | & collisions_mask_player_player; 370 | case _P1PL: 371 | update_partial_pmpl_colls(); 372 | return ((P1PL & 0x01) /* mask in player 0 */ 373 | + ((P2PL & 0x02) << 1) /* mask in player 2 */ 374 | + ((P3PL & 0x02) << 2)) /* mask in player 3 */ 375 | & collisions_mask_player_player; 376 | case _P2PL: 377 | update_partial_pmpl_colls(); 378 | return ((P2PL & 0x03) /* mask in player 0 and 1 */ 379 | + ((P3PL & 0x04) << 1)) /* mask in player 3 */ 380 | & collisions_mask_player_player; 381 | case _P3PL: 382 | update_partial_pmpl_colls(); 383 | return (P3PL & 0x07) /* mask in player 0,1, and 2 */ 384 | & collisions_mask_player_player; 385 | case _TRIG0: 386 | return TRIG[0] & TRIG_latch[0]; 387 | case _TRIG1: 388 | return TRIG[1] & TRIG_latch[1]; 389 | case _TRIG2: 390 | return TRIG[2] & TRIG_latch[2]; 391 | case _TRIG3: 392 | return TRIG[3] & TRIG_latch[3]; 393 | case _PAL: 394 | return 0x0f; // Force NTSC 395 | case _CONSOL: 396 | { 397 | UBYTE byte = consol_table[consol_index] & consol_mask; 398 | if (consol_index > 0) { 399 | consol_index--; 400 | } 401 | return byte; 402 | } 403 | default: 404 | break; 405 | } 406 | 407 | return 0xf; 408 | } 409 | 410 | #define UPDATE_PM_CYCLE_EXACT {} 411 | void GTIA_PutByte(UWORD addr, UBYTE byte) 412 | { 413 | UWORD cword; 414 | UWORD cword2; 415 | 416 | switch (addr & 0x1f) 417 | { 418 | case _CONSOL: 419 | consol_mask = (~byte) & 0x0f; 420 | POTENA = byte & 0x04; 421 | break; 422 | 423 | case _COLBK: 424 | COLBK = byte &= 0xfe; 425 | COLOUR_TO_WORD(cword,byte); 426 | cl_lookup[C_BAK] = cword; 427 | if (cword != (UWORD) (lookup_gtia9[0]) ) { 428 | lookup_gtia9[0] = cword + (cword << 16); 429 | if (PRIOR & 0x40) 430 | setup_gtia9_11(); 431 | } 432 | break; 433 | case _COLPF0: 434 | COLPF0 = byte &= 0xfe; 435 | COLOUR_TO_WORD(cword,byte); 436 | cl_lookup[C_PF0] = cword; 437 | if ((PRIOR & 1) == 0) { 438 | cl_lookup[C_PF0 | C_PM23] = cl_lookup[C_PF0 | C_PM3] = cl_lookup[C_PF0 | C_PM2] = cword; 439 | if ((PRIOR & 3) == 0) { 440 | if (PRIOR & 0xf) { 441 | cl_lookup[C_PF0 | C_PM01] = cl_lookup[C_PF0 | C_PM1] = cl_lookup[C_PF0 | C_PM0] = cword; 442 | if ((PRIOR & 0xf) == 0xc) 443 | cl_lookup[C_PF0 | C_PM0123] = cl_lookup[C_PF0 | C_PM123] = cl_lookup[C_PF0 | C_PM023] = cword; 444 | } 445 | else 446 | cl_lookup[C_PF0 | C_PM01] = (cl_lookup[C_PF0 | C_PM0] = cword | cl_lookup[C_PM0]) | (cl_lookup[C_PF0 | C_PM1] = cword | cl_lookup[C_PM1]); 447 | } 448 | if ((PRIOR & 0xf) >= 0xa) 449 | cl_lookup[C_PF0 | C_PM25] = cword; 450 | } 451 | break; 452 | case _COLPF1: 453 | COLPF1 = byte &= 0xfe; 454 | COLOUR_TO_WORD(cword,byte); 455 | cl_lookup[C_PF1] = cword; 456 | if ((PRIOR & 1) == 0) { 457 | cl_lookup[C_PF1 | C_PM23] = cl_lookup[C_PF1 | C_PM3] = cl_lookup[C_PF1 | C_PM2] = cword; 458 | if ((PRIOR & 3) == 0) { 459 | if (PRIOR & 0xf) { 460 | cl_lookup[C_PF1 | C_PM01] = cl_lookup[C_PF1 | C_PM1] = cl_lookup[C_PF1 | C_PM0] = cword; 461 | if ((PRIOR & 0xf) == 0xc) 462 | cl_lookup[C_PF1 | C_PM0123] = cl_lookup[C_PF1 | C_PM123] = cl_lookup[C_PF1 | C_PM023] = cword; 463 | } 464 | else 465 | cl_lookup[C_PF1 | C_PM01] = (cl_lookup[C_PF1 | C_PM0] = cword | cl_lookup[C_PM0]) | (cl_lookup[C_PF1 | C_PM1] = cword | cl_lookup[C_PM1]); 466 | } 467 | } 468 | ((UBYTE *)hires_lookup_l)[0x80] = ((UBYTE *)hires_lookup_l)[0x41] = (UBYTE) 469 | (hires_lookup_l[0x60] = cword & 0xf0f); 470 | break; 471 | case _COLPF2: 472 | COLPF2 = byte &= 0xfe; 473 | COLOUR_TO_WORD(cword,byte); 474 | cl_lookup[C_PF2] = cword; 475 | if (PRIOR & 4) 476 | cl_lookup[C_PF2 | C_PM01] = cl_lookup[C_PF2 | C_PM1] = cl_lookup[C_PF2 | C_PM0] = cword; 477 | if ((PRIOR & 9) == 0) { 478 | if (PRIOR & 0xf) 479 | cl_lookup[C_PF2 | C_PM23] = cl_lookup[C_PF2 | C_PM3] = cl_lookup[C_PF2 | C_PM2] = cword; 480 | else 481 | cl_lookup[C_PF2 | C_PM23] = (cl_lookup[C_PF2 | C_PM2] = cword | cl_lookup[C_PM2]) | (cl_lookup[C_PF2 | C_PM3] = cword | cl_lookup[C_PM3]); 482 | } 483 | break; 484 | case _COLPF3: 485 | COLPF3 = byte &= 0xfe; 486 | COLOUR_TO_WORD(cword,byte); 487 | cl_lookup[C_PF3] = cword; 488 | if (PRIOR & 4) 489 | cl_lookup[C_PF3 | C_PM01] = cl_lookup[C_PF3 | C_PM1] = cl_lookup[C_PF3 | C_PM0] = cword; 490 | if ((PRIOR & 9) == 0) { 491 | if (PRIOR & 0xf) 492 | cl_lookup[C_PF3 | C_PM23] = cl_lookup[C_PF3 | C_PM3] = cl_lookup[C_PF3 | C_PM2] = cword; 493 | else { 494 | cl_lookup[C_PF3 | C_PM25] = cl_lookup[C_PF2 | C_PM25] = cl_lookup[C_PM25] = cl_lookup[C_PF3 | C_PM2] = cword | cl_lookup[C_PM2]; 495 | cl_lookup[C_PF3 | C_PM35] = cl_lookup[C_PF2 | C_PM35] = cl_lookup[C_PM35] = cl_lookup[C_PF3 | C_PM3] = cword | cl_lookup[C_PM3]; 496 | cl_lookup[C_PF3 | C_PM235] = cl_lookup[C_PF2 | C_PM235] = cl_lookup[C_PM235] = cl_lookup[C_PF3 | C_PM23] = cl_lookup[C_PF3 | C_PM2] | cl_lookup[C_PF3 | C_PM3]; 497 | cl_lookup[C_PF0 | C_PM235] = cl_lookup[C_PF0 | C_PM35] = cl_lookup[C_PF0 | C_PM25] = 498 | cl_lookup[C_PF1 | C_PM235] = cl_lookup[C_PF1 | C_PM35] = cl_lookup[C_PF1 | C_PM25] = cword; 499 | } 500 | } 501 | break; 502 | case _COLPM0: 503 | COLPM0 = byte &= 0xfe; 504 | COLOUR_TO_WORD(cword,byte); 505 | cl_lookup[C_PM023] = cl_lookup[C_PM0] = cword; 506 | cl_lookup[C_PM0123] = cl_lookup[C_PM01] = cword2 = cword | cl_lookup[C_PM1]; 507 | if ((PRIOR & 4) == 0) { 508 | cl_lookup[C_PF2 | C_PM0] = cl_lookup[C_PF3 | C_PM0] = cword; 509 | cl_lookup[C_PF2 | C_PM01] = cl_lookup[C_PF3 | C_PM01] = cword2; 510 | if ((PRIOR & 0xc) == 0) { 511 | if (PRIOR & 3) { 512 | cl_lookup[C_PF0 | C_PM0] = cl_lookup[C_PF1 | C_PM0] = cword; 513 | cl_lookup[C_PF0 | C_PM01] = cl_lookup[C_PF1 | C_PM01] = cword2; 514 | } 515 | else { 516 | cl_lookup[C_PF0 | C_PM0] = cword | cl_lookup[C_PF0]; 517 | cl_lookup[C_PF1 | C_PM0] = cword | cl_lookup[C_PF1]; 518 | cl_lookup[C_PF0 | C_PM01] = cword2 | cl_lookup[C_PF0]; 519 | cl_lookup[C_PF1 | C_PM01] = cword2 | cl_lookup[C_PF1]; 520 | } 521 | } 522 | } 523 | break; 524 | case _COLPM1: 525 | COLPM1 = byte &= 0xfe; 526 | COLOUR_TO_WORD(cword,byte); 527 | cl_lookup[C_PM123] = cl_lookup[C_PM1] = cword; 528 | cl_lookup[C_PM0123] = cl_lookup[C_PM01] = cword2 = cword | cl_lookup[C_PM0]; 529 | if ((PRIOR & 4) == 0) { 530 | cl_lookup[C_PF2 | C_PM1] = cl_lookup[C_PF3 | C_PM1] = cword; 531 | cl_lookup[C_PF2 | C_PM01] = cl_lookup[C_PF3 | C_PM01] = cword2; 532 | if ((PRIOR & 0xc) == 0) { 533 | if (PRIOR & 3) { 534 | cl_lookup[C_PF0 | C_PM1] = cl_lookup[C_PF1 | C_PM1] = cword; 535 | cl_lookup[C_PF0 | C_PM01] = cl_lookup[C_PF1 | C_PM01] = cword2; 536 | } 537 | else { 538 | cl_lookup[C_PF0 | C_PM1] = cword | cl_lookup[C_PF0]; 539 | cl_lookup[C_PF1 | C_PM1] = cword | cl_lookup[C_PF1]; 540 | cl_lookup[C_PF0 | C_PM01] = cword2 | cl_lookup[C_PF0]; 541 | cl_lookup[C_PF1 | C_PM01] = cword2 | cl_lookup[C_PF1]; 542 | } 543 | } 544 | } 545 | break; 546 | case _COLPM2: 547 | COLPM2 = byte &= 0xfe; 548 | COLOUR_TO_WORD(cword,byte); 549 | cl_lookup[C_PM2] = cword; 550 | cl_lookup[C_PM23] = cword2 = cword | cl_lookup[C_PM3]; 551 | if (PRIOR & 1) { 552 | cl_lookup[C_PF0 | C_PM2] = cl_lookup[C_PF1 | C_PM2] = cword; 553 | cl_lookup[C_PF0 | C_PM23] = cl_lookup[C_PF1 | C_PM23] = cword2; 554 | } 555 | if ((PRIOR & 6) == 0) { 556 | if (PRIOR & 9) { 557 | cl_lookup[C_PF2 | C_PM2] = cl_lookup[C_PF3 | C_PM2] = cword; 558 | cl_lookup[C_PF2 | C_PM23] = cl_lookup[C_PF3 | C_PM23] = cword2; 559 | } 560 | else { 561 | cl_lookup[C_PF2 | C_PM2] = cword | cl_lookup[C_PF2]; 562 | cl_lookup[C_PF3 | C_PM25] = cl_lookup[C_PF2 | C_PM25] = cl_lookup[C_PM25] = cl_lookup[C_PF3 | C_PM2] = cword | cl_lookup[C_PF3]; 563 | cl_lookup[C_PF2 | C_PM23] = cword2 | cl_lookup[C_PF2]; 564 | cl_lookup[C_PF3 | C_PM235] = cl_lookup[C_PF2 | C_PM235] = cl_lookup[C_PM235] = cl_lookup[C_PF3 | C_PM23] = cword2 | cl_lookup[C_PF3]; 565 | } 566 | } 567 | break; 568 | case _COLPM3: 569 | COLPM3 = byte &= 0xfe; 570 | COLOUR_TO_WORD(cword,byte); 571 | cl_lookup[C_PM3] = cword; 572 | cl_lookup[C_PM23] = cword2 = cword | cl_lookup[C_PM2]; 573 | if (PRIOR & 1) { 574 | cl_lookup[C_PF0 | C_PM3] = cl_lookup[C_PF1 | C_PM3] = cword; 575 | cl_lookup[C_PF0 | C_PM23] = cl_lookup[C_PF1 | C_PM23] = cword2; 576 | } 577 | if ((PRIOR & 6) == 0) { 578 | if (PRIOR & 9) { 579 | cl_lookup[C_PF2 | C_PM3] = cl_lookup[C_PF3 | C_PM3] = cword; 580 | cl_lookup[C_PF2 | C_PM23] = cl_lookup[C_PF3 | C_PM23] = cword2; 581 | } 582 | else { 583 | cl_lookup[C_PF2 | C_PM3] = cword | cl_lookup[C_PF2]; 584 | cl_lookup[C_PF3 | C_PM35] = cl_lookup[C_PF2 | C_PM35] = cl_lookup[C_PM35] = cl_lookup[C_PF3 | C_PM3] = cword | cl_lookup[C_PF3]; 585 | cl_lookup[C_PF2 | C_PM23] = cword2 | cl_lookup[C_PF2]; 586 | cl_lookup[C_PF3 | C_PM235] = cl_lookup[C_PF2 | C_PM235] = cl_lookup[C_PM235] = cl_lookup[C_PF3 | C_PM23] = cword2 | cl_lookup[C_PF3]; 587 | } 588 | } 589 | break; 590 | 591 | case _GRAFM: 592 | GRAFM = byte; 593 | UPDATE_PM_CYCLE_EXACT 594 | break; 595 | 596 | #define CYCLE_EXACT_GRAFP(n) 597 | 598 | #define DO_GRAFP(n) case _GRAFP##n:\ 599 | GRAFP##n = byte;\ 600 | CYCLE_EXACT_GRAFP(n);\ 601 | break; 602 | 603 | DO_GRAFP(0) 604 | DO_GRAFP(1) 605 | DO_GRAFP(2) 606 | DO_GRAFP(3) 607 | 608 | case _HITCLR: 609 | M0PL = M1PL = M2PL = M3PL = 0; 610 | P0PL = P1PL = P2PL = P3PL = 0; 611 | PF0PM = PF1PM = PF2PM = PF3PM = 0; 612 | break; 613 | /* TODO: cycle-exact missile HPOS, GRAF, SIZE */ 614 | /* this is only an approximation */ 615 | case _HPOSM0: 616 | HPOSM0 = byte; 617 | hposm_ptr[0] = pm_scanline + byte - 0x20; 618 | UPDATE_PM_CYCLE_EXACT 619 | break; 620 | case _HPOSM1: 621 | HPOSM1 = byte; 622 | hposm_ptr[1] = pm_scanline + byte - 0x20; 623 | UPDATE_PM_CYCLE_EXACT 624 | break; 625 | case _HPOSM2: 626 | HPOSM2 = byte; 627 | hposm_ptr[2] = pm_scanline + byte - 0x20; 628 | UPDATE_PM_CYCLE_EXACT 629 | break; 630 | case _HPOSM3: 631 | HPOSM3 = byte; 632 | hposm_ptr[3] = pm_scanline + byte - 0x20; 633 | UPDATE_PM_CYCLE_EXACT 634 | break; 635 | 636 | #define CYCLE_EXACT_HPOSP(n) 637 | 638 | #define DO_HPOSP(n) case _HPOSP##n: \ 639 | hposp_ptr[n] = pm_scanline + byte - 0x20; \ 640 | if (byte >= 0x22) { \ 641 | if (byte > 0xbe) { \ 642 | if (byte >= 0xde) \ 643 | hposp_mask[n] = 0; \ 644 | else \ 645 | hposp_mask[n] = 0xffffffff >> (byte - 0xbe); \ 646 | } \ 647 | else \ 648 | hposp_mask[n] = 0xffffffff; \ 649 | } \ 650 | else if (byte > 2) \ 651 | hposp_mask[n] = 0xffffffff << (0x22 - byte); \ 652 | else \ 653 | hposp_mask[n] = 0; \ 654 | CYCLE_EXACT_HPOSP(n)\ 655 | HPOSP##n = byte; \ 656 | break; 657 | 658 | DO_HPOSP(0) 659 | DO_HPOSP(1) 660 | DO_HPOSP(2) 661 | DO_HPOSP(3) 662 | 663 | /* TODO: cycle-exact size changes */ 664 | /* this is only an approximation */ 665 | case _SIZEM: 666 | SIZEM = byte; 667 | global_sizem[0] = PM_Width[byte & 0x03]; 668 | global_sizem[1] = PM_Width[(byte & 0x0c) >> 2]; 669 | global_sizem[2] = PM_Width[(byte & 0x30) >> 4]; 670 | global_sizem[3] = PM_Width[(byte & 0xc0) >> 6]; 671 | UPDATE_PM_CYCLE_EXACT 672 | break; 673 | case _SIZEP0: 674 | SIZEP0 = byte; 675 | grafp_ptr[0] = &grafp_lookup[(byte & 3)*256]; 676 | UPDATE_PM_CYCLE_EXACT 677 | break; 678 | case _SIZEP1: 679 | SIZEP1 = byte; 680 | grafp_ptr[1] = &grafp_lookup[(byte & 3)*256]; 681 | UPDATE_PM_CYCLE_EXACT 682 | break; 683 | case _SIZEP2: 684 | SIZEP2 = byte; 685 | grafp_ptr[2] = &grafp_lookup[(byte & 3)*256]; 686 | UPDATE_PM_CYCLE_EXACT 687 | break; 688 | case _SIZEP3: 689 | SIZEP3 = byte; 690 | grafp_ptr[3] = &grafp_lookup[(byte & 3)*256]; 691 | UPDATE_PM_CYCLE_EXACT 692 | break; 693 | case _PRIOR: 694 | set_prior(byte); 695 | PRIOR = byte; 696 | if (byte & 0x40) 697 | setup_gtia9_11(); 698 | break; 699 | case _VDELAY: 700 | VDELAY = byte; 701 | break; 702 | case _GRACTL: 703 | GRACTL = byte; 704 | missile_gra_enabled = (byte & 0x01); 705 | player_gra_enabled = (byte & 0x02); 706 | player_flickering = ((player_dma_enabled | player_gra_enabled) == 0x02); 707 | missile_flickering = ((missile_dma_enabled | missile_gra_enabled) == 0x01); 708 | if ((byte & 4) == 0) 709 | TRIG_latch[0] = TRIG_latch[1] = TRIG_latch[2] = TRIG_latch[3] = 1; 710 | break; 711 | } 712 | } 713 | -------------------------------------------------------------------------------- /arm9/source/emu/gtia.h: -------------------------------------------------------------------------------- 1 | #ifndef _GTIA_H_ 2 | #define _GTIA_H_ 3 | 4 | #include "atari.h" 5 | 6 | #define _HPOSP0 0x00 7 | #define _M0PF 0x00 8 | #define _HPOSP1 0x01 9 | #define _M1PF 0x01 10 | #define _HPOSP2 0x02 11 | #define _M2PF 0x02 12 | #define _HPOSP3 0x03 13 | #define _M3PF 0x03 14 | #define _HPOSM0 0x04 15 | #define _P0PF 0x04 16 | #define _HPOSM1 0x05 17 | #define _P1PF 0x05 18 | #define _HPOSM2 0x06 19 | #define _P2PF 0x06 20 | #define _HPOSM3 0x07 21 | #define _P3PF 0x07 22 | #define _SIZEP0 0x08 23 | #define _M0PL 0x08 24 | #define _SIZEP1 0x09 25 | #define _M1PL 0x09 26 | #define _SIZEP2 0x0a 27 | #define _M2PL 0x0a 28 | #define _SIZEP3 0x0b 29 | #define _M3PL 0x0b 30 | #define _SIZEM 0x0c 31 | #define _P0PL 0x0c 32 | #define _GRAFP0 0x0d 33 | #define _P1PL 0x0d 34 | #define _GRAFP1 0x0e 35 | #define _P2PL 0x0e 36 | #define _GRAFP2 0x0f 37 | #define _P3PL 0x0f 38 | #define _GRAFP3 0x10 39 | #define _TRIG0 0x10 40 | #define _GRAFM 0x11 41 | #define _TRIG1 0x11 42 | #define _COLPM0 0x12 43 | #define _TRIG2 0x12 44 | #define _COLPM1 0x13 45 | #define _TRIG3 0x13 46 | #define _COLPM2 0x14 47 | #define _PAL 0x14 48 | #define _COLPM3 0x15 49 | #define _COLPF0 0x16 50 | #define _COLPF1 0x17 51 | #define _COLPF2 0x18 52 | #define _COLPF3 0x19 53 | #define _COLBK 0x1a 54 | #define _PRIOR 0x1b 55 | #define _VDELAY 0x1c 56 | #define _GRACTL 0x1d 57 | #define _HITCLR 0x1e 58 | #define _CONSOL 0x1f 59 | 60 | extern UBYTE GRAFM; 61 | extern UBYTE GRAFP0; 62 | extern UBYTE GRAFP1; 63 | extern UBYTE GRAFP2; 64 | extern UBYTE GRAFP3; 65 | extern UBYTE HPOSP0; 66 | extern UBYTE HPOSP1; 67 | extern UBYTE HPOSP2; 68 | extern UBYTE HPOSP3; 69 | extern UBYTE HPOSM0; 70 | extern UBYTE HPOSM1; 71 | extern UBYTE HPOSM2; 72 | extern UBYTE HPOSM3; 73 | extern UBYTE SIZEP0; 74 | extern UBYTE SIZEP1; 75 | extern UBYTE SIZEP2; 76 | extern UBYTE SIZEP3; 77 | extern UBYTE SIZEM; 78 | extern UBYTE COLPM0; 79 | extern UBYTE COLPM1; 80 | extern UBYTE COLPM2; 81 | extern UBYTE COLPM3; 82 | extern UBYTE COLPF0; 83 | extern UBYTE COLPF1; 84 | extern UBYTE COLPF2; 85 | extern UBYTE COLPF3; 86 | extern UBYTE COLBK; 87 | extern UBYTE GRACTL; 88 | extern UBYTE M0PL; 89 | extern UBYTE M1PL; 90 | extern UBYTE M2PL; 91 | extern UBYTE M3PL; 92 | extern UBYTE P0PL; 93 | extern UBYTE P1PL; 94 | extern UBYTE P2PL; 95 | extern UBYTE P3PL; 96 | extern UBYTE PRIOR; 97 | extern UBYTE VDELAY; 98 | extern UBYTE POTENA; 99 | 100 | #define COLOUR_BLACK 0 101 | #define COLOUR_TO_WORD(dest,src) dest = (((UWORD) (src)) << 8) | (src); 102 | 103 | extern UBYTE collisions_mask_missile_playfield; 104 | extern UBYTE collisions_mask_player_playfield; 105 | extern UBYTE collisions_mask_missile_player; 106 | extern UBYTE collisions_mask_player_player; 107 | 108 | extern UBYTE TRIG[4]; 109 | extern UBYTE TRIG_latch[4]; 110 | 111 | extern UBYTE consol_index; 112 | extern UBYTE consol_table[3]; 113 | 114 | void GTIA_Initialise(void); 115 | void GTIA_Frame(void); 116 | void new_pm_scanline(void); 117 | UBYTE GTIA_GetByte(UWORD addr); 118 | void GTIA_PutByte(UWORD addr, UBYTE byte); 119 | 120 | #endif /* _GTIA_H_ */ 121 | -------------------------------------------------------------------------------- /arm9/source/emu/hash.c: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // Hash.cpp 3 | // ---------------------------------------------------------------------------- 4 | #include 5 | #include "hash.h" 6 | #include "printf.h" 7 | 8 | // ---------------------------------------------------------------------------- 9 | // Step1 10 | // ---------------------------------------------------------------------------- 11 | static uint hash_Step1(uint w, uint x, uint y, uint z, uint data, uint s) { 12 | w += (z ^ (x & (y ^ z))) + data; 13 | w = w << s | w >> (32 - s); 14 | w += x; 15 | return w; 16 | } 17 | 18 | // ---------------------------------------------------------------------------- 19 | // Step2 20 | // ---------------------------------------------------------------------------- 21 | static uint hash_Step2(uint w, uint x, uint y, uint z, uint data, uint s) { 22 | w += (y ^ (z & (x ^ y))) + data; 23 | w = w << s | w >> (32 - s); 24 | w += x; 25 | return w; 26 | } 27 | 28 | // ---------------------------------------------------------------------------- 29 | // Step3 30 | // ---------------------------------------------------------------------------- 31 | static uint hash_Step3(uint w, uint x, uint y, uint z, uint data, uint s) { 32 | w += (x ^ y ^ z) + data; 33 | w = w << s | w >> (32 - s); 34 | w += x; 35 | return w; 36 | } 37 | 38 | // ---------------------------------------------------------------------------- 39 | // Step4 40 | // ---------------------------------------------------------------------------- 41 | static uint hash_Step4(uint w, uint x, uint y, uint z, uint data, uint s) { 42 | w += (y ^ (x | ~z)) + data; 43 | w = w << s | w >> (32 - s); 44 | w += x; 45 | return w; 46 | } 47 | 48 | // ---------------------------------------------------------------------------- 49 | // Transform 50 | // ---------------------------------------------------------------------------- 51 | static void hash_Transform(uint out[4], uint in[16]) { 52 | static uint a, b, c, d; 53 | 54 | a = out[0]; 55 | b = out[1]; 56 | c = out[2]; 57 | d = out[3]; 58 | 59 | a = hash_Step1(a, b, c, d, in[0] + 0xd76aa478, 7); 60 | d = hash_Step1(d, a, b, c, in[1] + 0xe8c7b756, 12); 61 | c = hash_Step1(c, d, a, b, in[2] + 0x242070db, 17); 62 | b = hash_Step1(b, c, d, a, in[3] + 0xc1bdceee, 22); 63 | a = hash_Step1(a, b, c, d, in[4] + 0xf57c0faf, 7); 64 | d = hash_Step1(d, a, b, c, in[5] + 0x4787c62a, 12); 65 | c = hash_Step1(c, d, a, b, in[6] + 0xa8304613, 17); 66 | b = hash_Step1(b, c, d, a, in[7] + 0xfd469501, 22); 67 | a = hash_Step1(a, b, c, d, in[8] + 0x698098d8, 7); 68 | d = hash_Step1(d, a, b, c, in[9] + 0x8b44f7af, 12); 69 | c = hash_Step1(c, d, a, b, in[10] + 0xffff5bb1, 17); 70 | b = hash_Step1(b, c, d, a, in[11] + 0x895cd7be, 22); 71 | a = hash_Step1(a, b, c, d, in[12] + 0x6b901122, 7); 72 | d = hash_Step1(d, a, b, c, in[13] + 0xfd987193, 12); 73 | c = hash_Step1(c, d, a, b, in[14] + 0xa679438e, 17); 74 | b = hash_Step1(b, c, d, a, in[15] + 0x49b40821, 22); 75 | 76 | a = hash_Step2(a, b, c, d, in[1] + 0xf61e2562, 5); 77 | d = hash_Step2(d, a, b, c, in[6] + 0xc040b340, 9); 78 | c = hash_Step2(c, d, a, b, in[11] + 0x265e5a51, 14); 79 | b = hash_Step2(b, c, d, a, in[0] + 0xe9b6c7aa, 20); 80 | a = hash_Step2(a, b, c, d, in[5] + 0xd62f105d, 5); 81 | d = hash_Step2(d, a, b, c, in[10] + 0x02441453, 9); 82 | c = hash_Step2(c, d, a, b, in[15] + 0xd8a1e681, 14); 83 | b = hash_Step2(b, c, d, a, in[4] + 0xe7d3fbc8, 20); 84 | a = hash_Step2(a, b, c, d, in[9] + 0x21e1cde6, 5); 85 | d = hash_Step2(d, a, b, c, in[14] + 0xc33707d6, 9); 86 | c = hash_Step2(c, d, a, b, in[3] + 0xf4d50d87, 14); 87 | b = hash_Step2(b, c, d, a, in[8] + 0x455a14ed, 20); 88 | a = hash_Step2(a, b, c, d, in[13] + 0xa9e3e905, 5); 89 | d = hash_Step2(d, a, b, c, in[2] + 0xfcefa3f8, 9); 90 | c = hash_Step2(c, d, a, b, in[7] + 0x676f02d9, 14); 91 | b = hash_Step2(b, c, d, a, in[12] + 0x8d2a4c8a, 20); 92 | 93 | a = hash_Step3(a, b, c, d, in[5] + 0xfffa3942, 4); 94 | d = hash_Step3(d, a, b, c, in[8] + 0x8771f681, 11); 95 | c = hash_Step3(c, d, a, b, in[11] + 0x6d9d6122, 16); 96 | b = hash_Step3(b, c, d, a, in[14] + 0xfde5380c, 23); 97 | a = hash_Step3(a, b, c, d, in[1] + 0xa4beea44, 4); 98 | d = hash_Step3(d, a, b, c, in[4] + 0x4bdecfa9, 11); 99 | c = hash_Step3(c, d, a, b, in[7] + 0xf6bb4b60, 16); 100 | b = hash_Step3(b, c, d, a, in[10] + 0xbebfbc70, 23); 101 | a = hash_Step3(a, b, c, d, in[13] + 0x289b7ec6, 4); 102 | d = hash_Step3(d, a, b, c, in[0] + 0xeaa127fa, 11); 103 | c = hash_Step3(c, d, a, b, in[3] + 0xd4ef3085, 16); 104 | b = hash_Step3(b, c, d, a, in[6] + 0x04881d05, 23); 105 | a = hash_Step3(a, b, c, d, in[9] + 0xd9d4d039, 4); 106 | d = hash_Step3(d, a, b, c, in[12] + 0xe6db99e5, 11); 107 | c = hash_Step3(c, d, a, b, in[15] + 0x1fa27cf8, 16); 108 | b = hash_Step3(b, c, d, a, in[2] + 0xc4ac5665, 23); 109 | 110 | a = hash_Step4(a, b, c, d, in[0] + 0xf4292244, 6); 111 | d = hash_Step4(d, a, b, c, in[7] + 0x432aff97, 10); 112 | c = hash_Step4(c, d, a, b, in[14] + 0xab9423a7, 15); 113 | b = hash_Step4(b, c, d, a, in[5] + 0xfc93a039, 21); 114 | a = hash_Step4(a, b, c, d, in[12] + 0x655b59c3, 6); 115 | d = hash_Step4(d, a, b, c, in[3] + 0x8f0ccc92, 10); 116 | c = hash_Step4(c, d, a, b, in[10] + 0xffeff47d, 15); 117 | b = hash_Step4(b, c, d, a, in[1] + 0x85845dd1, 21); 118 | a = hash_Step4(a, b, c, d, in[8] + 0x6fa87e4f, 6); 119 | d = hash_Step4(d, a, b, c, in[15] + 0xfe2ce6e0, 10); 120 | c = hash_Step4(c, d, a, b, in[6] + 0xa3014314, 15); 121 | b = hash_Step4(b, c, d, a, in[13] + 0x4e0811a1, 21); 122 | a = hash_Step4(a, b, c, d, in[4] + 0xf7537e82, 6); 123 | d = hash_Step4(d, a, b, c, in[11] + 0xbd3af235, 10); 124 | c = hash_Step4(c, d, a, b, in[2] + 0x2ad7d2bb, 15); 125 | b = hash_Step4(b, c, d, a, in[9] + 0xeb86d391, 21); 126 | 127 | out[0] += a; 128 | out[1] += b; 129 | out[2] += c; 130 | out[3] += d; 131 | } 132 | 133 | // ---------------------------------------------------------------------------- 134 | // Compute 135 | // ---------------------------------------------------------------------------- 136 | static byte __attribute__((aligned(64))) buffer3[64] = { 0 }; 137 | static uint idx = 0; 138 | 139 | void hash_Compute(const byte* source, uint length, byte * dest) { 140 | uint buffer1[4] = {0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476}; 141 | uint buffer2[2] = {0}; 142 | 143 | memset(buffer3, 0x00, sizeof(buffer3)); 144 | 145 | uint temp = buffer2[0]; 146 | if((buffer2[0] = temp + ((uint)length << 3)) < temp) { 147 | buffer2[1]++; 148 | } 149 | buffer2[1] += length >> 29; 150 | 151 | temp = (temp >> 3) & 0x3f; 152 | if(temp) { 153 | byte* ptr = (byte*)buffer3 + temp; 154 | temp = 64 - temp; 155 | if(length < temp) { 156 | for(idx = 0; idx < length; idx++) { 157 | ptr[idx] = source[idx]; 158 | } 159 | } 160 | 161 | for(idx = 0; idx < temp; idx++) { 162 | ptr[idx] = source[idx]; 163 | } 164 | 165 | hash_Transform(buffer1, (uint*)buffer3); 166 | source += temp; 167 | length -= temp; 168 | } 169 | 170 | while(length >= 64) { 171 | for(idx = 0; idx < 64; idx++) { 172 | buffer3[idx] = source[idx]; 173 | } 174 | hash_Transform(buffer1, (uint*)buffer3); 175 | source += 64; 176 | length -= 64; 177 | } 178 | 179 | for(idx = 0; idx < length; idx++) { 180 | buffer3[idx] = source[idx]; 181 | } 182 | 183 | uint count = (buffer2[0] >> 3) & 0x3f; 184 | byte* ptr = buffer3 + count; 185 | *ptr++ = 0x80; 186 | 187 | count = 63 - count; 188 | 189 | if(count < 8) { 190 | for(idx = 0; idx < count; idx++) { 191 | ptr[idx] = 0; 192 | } 193 | hash_Transform(buffer1, (uint*)buffer3); 194 | 195 | for(idx = 0; idx < 56; idx++) { 196 | buffer3[idx] = 0; 197 | } 198 | } 199 | else { 200 | for(idx = 0; idx < count - 8; idx++) { 201 | ptr[idx] = 0; 202 | } 203 | } 204 | 205 | ((uint*)buffer3)[14] = buffer2[0]; 206 | ((uint*)buffer3)[15] = buffer2[1]; 207 | 208 | hash_Transform(buffer1, (uint*)buffer3); 209 | 210 | byte digest[16]; 211 | byte* bufferptr = (byte*)buffer1; 212 | for(idx = 0; idx < 16; idx++) { 213 | digest[idx] = bufferptr[idx]; 214 | } 215 | 216 | sprintf((char*)dest, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", digest[0], digest[1], digest[2], digest[3], digest[4], digest[5], digest[6], digest[7], digest[8], digest[9], digest[10], digest[11], digest[12], digest[13], digest[14], digest[15]); 217 | } 218 | 219 | -------------------------------------------------------------------------------- /arm9/source/emu/hash.h: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // Hash.h 3 | // ---------------------------------------------------------------------------- 4 | #ifndef HASH_H 5 | #define HASH_H 6 | 7 | #include 8 | 9 | typedef unsigned int uint; 10 | typedef unsigned char byte; 11 | 12 | extern void hash_Compute(const byte* source, uint length, byte * dest); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /arm9/source/emu/input.c: -------------------------------------------------------------------------------- 1 | /* 2 | * input.c - keyboard, joysticks and mouse emulation 3 | * 4 | * Copyright (C) 2001-2002 Piotr Fusik 5 | * Copyright (C) 2001-2006 Atari800 development team (see DOC/CREDITS) 6 | * 7 | * This file is part of the Atari800 emulator project which emulates 8 | * the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers. 9 | * 10 | * Atari800 is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * Atari800 is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with Atari800; if not, write to the Free Software 22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 | */ 24 | #include 25 | 26 | #include "config.h" 27 | #include 28 | #include "antic.h" 29 | #include "atari.h" 30 | #include "cartridge.h" 31 | #include "cpu.h" 32 | #include "gtia.h" 33 | #include "input.h" 34 | #include "memory.h" 35 | #include "pia.h" 36 | #include "platform.h" 37 | #include "pokeysnd.h" 38 | 39 | #define Atari_POT(x) 228 40 | 41 | extern UBYTE PCPOT_input[8]; 42 | 43 | int key_code = AKEY_NONE; 44 | int key_shift = 0; 45 | int key_consol = CONSOL_NONE; 46 | 47 | #define joy_5200_min 6 48 | #define joy_5200_center 114 49 | #define joy_5200_max 220 50 | 51 | static UBYTE STICK[4], OLDSTICK[4]; 52 | static UBYTE TRIG_input[4] = {0,0,0,0}; 53 | 54 | void INPUT_Initialise(void) 55 | { 56 | for (int i = 0; i < 4; i++) 57 | { 58 | PCPOT_input[2 * i] = joy_5200_center; 59 | PCPOT_input[2 * i+1] = joy_5200_center; 60 | TRIG_input[i] = 1; 61 | } 62 | } 63 | 64 | extern UWORD trig0, trig1; 65 | extern UWORD stick0, stick1; 66 | 67 | UBYTE anlaog_speed_map[6][2] = 68 | { 69 | {1,1}, 70 | {1,2}, 71 | {2,2}, 72 | {2,3}, 73 | {3,3}, 74 | {3,4} 75 | }; 76 | 77 | void INPUT_Frame(void) 78 | { 79 | static UWORD input_frame=0; 80 | int i; 81 | static int last_key_code = AKEY_NONE; 82 | static int last_key_break = 0; 83 | static UBYTE last_stick[4] = {STICK_CENTRE, STICK_CENTRE, STICK_CENTRE, STICK_CENTRE}; 84 | 85 | /* handle keyboard */ 86 | 87 | input_frame++; 88 | 89 | /* In Atari 5200 joystick there's a second fire button, which acts 90 | like the Shift key in 800/XL/XE (bit 3 in SKSTAT) and generates IRQ 91 | like the Break key (bit 7 in IRQST and IRQEN). 92 | Note that in 5200 the joystick position and first fire button are 93 | separate for each port, but the keypad and 2nd button are common. 94 | That is, if you press a key in the emulator, it's like you really pressed 95 | it in all the controllers simultaneously. Normally the port to read 96 | keypad & 2nd button is selected with the CONSOL register in GTIA 97 | (this is simply not emulated). 98 | key_code is used for keypad keys and key_shift is used for 2nd button. 99 | */ 100 | i = key_shift; 101 | if (i && !last_key_break) { 102 | if (IRQEN & 0x80) { 103 | IRQST &= ~0x80; 104 | GenerateIRQ(); 105 | } 106 | } 107 | last_key_break = i; 108 | 109 | SKSTAT |= 0xc; 110 | if (key_shift) 111 | SKSTAT &= ~8; 112 | 113 | if (key_code <= 0) 114 | { 115 | last_key_code = AKEY_NONE; 116 | } 117 | 118 | if ((key_code > 0) || key_shift) 119 | { 120 | /* The 5200 has only 4 of the 6 keyboard scan lines connected */ 121 | /* Pressing one 5200 key is like pressing 4 Atari 800 keys. */ 122 | /* The LSB (bit 0) and bit 5 are the two missing lines. */ 123 | /* When debounce is enabled, multiple keys pressed generate 124 | * no results. */ 125 | /* When debounce is disabled, multiple keys pressed generate 126 | * results only when in numerical sequence. */ 127 | /* Thus the LSB being one of the missing lines is important 128 | * because that causes events to be generated. */ 129 | /* Two events are generated every 64 scan lines 130 | * but this code only does one every frame. */ 131 | /* Bit 5 is different for each keypress because it is one 132 | * of the missing lines. */ 133 | static char bit5_5200 = 0; 134 | if (bit5_5200) 135 | { 136 | key_code &= ~0x20; 137 | } 138 | 139 | if (myCart.keys_debounced) 140 | bit5_5200 = !bit5_5200; 141 | else 142 | bit5_5200 = 0; 143 | 144 | /* 5200 2nd fire button generates CTRL as well */ 145 | if (key_shift) 146 | { 147 | key_code |= AKEY_SHFTCTRL; 148 | } 149 | 150 | if (key_code >= 0) 151 | { 152 | SKSTAT &= ~4; 153 | if ((key_code ^ last_key_code) & ~AKEY_SHFTCTRL) { 154 | /* ignore if only shift or control has changed its state */ 155 | last_key_code = key_code; 156 | KBCODE = (UBYTE) key_code; 157 | if (IRQEN & 0x40) { 158 | if (IRQST & 0x40) { 159 | IRQST &= ~0x40; 160 | GenerateIRQ(); 161 | } 162 | else { 163 | /* keyboard over-run */ 164 | SKSTAT &= ~0x40; 165 | } 166 | } 167 | } 168 | } 169 | } 170 | 171 | /* handle joysticks */ 172 | i = (stick1 << 4) | stick0; 173 | OLDSTICK[0] = STICK[0];OLDSTICK[1] = STICK[1]; 174 | STICK[0] = i & 0x0f; 175 | STICK[1] = (i >> 4) & 0x0f; 176 | 177 | // We don't support the other two sticks, so this will result in both being in the CENTER position... 178 | i = (STICK_CENTRE << 4) | STICK_CENTRE; 179 | STICK[2] = i & 0x0f; 180 | STICK[3] = (i >> 4) & 0x0f; 181 | 182 | for (i = 0; i < 2; i++) 183 | { 184 | if ((STICK[i] & 0x0c) == 0) { /* right and left simultaneously */ 185 | if (last_stick[i] & 0x04) /* if wasn't left before, move left */ 186 | STICK[i] |= 0x08; 187 | else /* else move right */ 188 | STICK[i] |= 0x04; 189 | } 190 | else { 191 | last_stick[i] &= 0x03; 192 | last_stick[i] |= STICK[i] & 0x0c; 193 | } 194 | if ((STICK[i] & 0x03) == 0) { /* up and down simultaneously */ 195 | if (last_stick[i] & 0x01) /* if wasn't up before, move up */ 196 | STICK[i] |= 0x02; 197 | else /* else move down */ 198 | STICK[i] |= 0x01; 199 | } 200 | else { 201 | last_stick[i] &= 0x0c; 202 | last_stick[i] |= STICK[i] & 0x03; 203 | } 204 | TRIG_input[i] = (i==0 ? trig0 : trig1); 205 | } 206 | 207 | // handle analog joysticks in Atari 5200 208 | for (i = 0; i < 2; i++) 209 | { 210 | if ((STICK[i] & (STICK_CENTRE ^ STICK_LEFT)) == 0) 211 | { 212 | if (myCart.use_analog) 213 | { 214 | if (PCPOT_input[2 * i] >myCart.digital_min) PCPOT_input[2 * i] -= anlaog_speed_map[myCart.analog_speed][input_frame & 1]; 215 | if (PCPOT_input[2 * i] <=myCart.digital_min) PCPOT_input[2 * i]= myCart.digital_min; 216 | } 217 | else 218 | PCPOT_input[2 * i]= myCart.digital_min; 219 | } 220 | else if ((STICK[i] & (STICK_CENTRE ^ STICK_RIGHT)) == 0) 221 | { 222 | if (myCart.use_analog) 223 | { 224 | if (PCPOT_input[2 * i] =myCart.digital_max) PCPOT_input[2 * i]= myCart.digital_max; 226 | } 227 | else 228 | PCPOT_input[2 * i]= myCart.digital_max; 229 | } 230 | else 231 | { 232 | if (!myCart.use_analog) PCPOT_input[2 * i] = joy_5200_center; 233 | } 234 | 235 | 236 | if ((STICK[i] & (STICK_CENTRE ^ STICK_FORWARD)) == 0) 237 | { 238 | if (myCart.use_analog) 239 | { 240 | if (PCPOT_input[2 * i +1] >myCart.digital_min) PCPOT_input[2 * i +1] -= anlaog_speed_map[myCart.analog_speed][input_frame & 1]; 241 | if (PCPOT_input[2 * i +1] <=myCart.digital_min) PCPOT_input[2 * i +1]= myCart.digital_min; 242 | } 243 | else 244 | PCPOT_input[2 * i +1]= myCart.digital_min; 245 | } 246 | else if ((STICK[i] & (STICK_CENTRE ^ STICK_BACK)) == 0) 247 | { 248 | if (myCart.use_analog) 249 | { 250 | if (PCPOT_input[2 * i +1] =myCart.digital_max) PCPOT_input[2 * i +1]= myCart.digital_max; 252 | } 253 | else 254 | PCPOT_input[2 * i +1]= myCart.digital_max; 255 | } 256 | else 257 | { 258 | if (!myCart.use_analog) PCPOT_input[2 * i + 1] = joy_5200_center; 259 | } 260 | } 261 | 262 | TRIG[0] = TRIG_input[0]; 263 | TRIG[1] = TRIG_input[1]; 264 | TRIG[2] = TRIG_input[2]; 265 | TRIG[3] = TRIG_input[3]; 266 | PORT_input[0] = (STICK[1] << 4) | STICK[0]; 267 | PORT_input[1] = (STICK[3] << 4) | STICK[2]; 268 | } 269 | 270 | -------------------------------------------------------------------------------- /arm9/source/emu/input.h: -------------------------------------------------------------------------------- 1 | #ifndef _A5200_INPUT_H_ 2 | #define _A5200_INPUT_H_ 3 | 4 | // Analog Speed Values... 5 | #define ANA_SLOWEST 0 6 | #define ANA_SLOWER 1 7 | #define ANA_NORMAL 2 8 | #define ANA_FAST 3 9 | #define ANA_FASTER 4 10 | #define ANA_FASTEST 5 11 | 12 | 13 | /* key_code values */ 14 | #define AKEY_NONE -1 15 | 16 | #define AKEY_SHFT 0x40 17 | #define AKEY_CTRL 0x80 18 | #define AKEY_SHFTCTRL 0xc0 19 | 20 | /* 5200 key codes */ 21 | #define AKEY_5200_START 0x39 22 | #define AKEY_5200_PAUSE 0x31 23 | #define AKEY_5200_RESET 0x29 24 | #define AKEY_5200_0 0x25 25 | #define AKEY_5200_1 0x3f 26 | #define AKEY_5200_2 0x3d 27 | #define AKEY_5200_3 0x3b 28 | #define AKEY_5200_4 0x37 29 | #define AKEY_5200_5 0x35 30 | #define AKEY_5200_6 0x33 31 | #define AKEY_5200_7 0x2f 32 | #define AKEY_5200_8 0x2d 33 | #define AKEY_5200_9 0x2b 34 | #define AKEY_5200_HASH 0x23 35 | #define AKEY_5200_ASTERISK 0x27 36 | 37 | /* key_consol masks */ 38 | /* Note: key_consol should be CONSOL_NONE if no consol key is pressed. 39 | When a consol key is pressed, corresponding bit should be cleared. 40 | */ 41 | 42 | #define CONSOL_NONE 0x07 43 | #define CONSOL_START 0x01 44 | #define CONSOL_SELECT 0x02 45 | #define CONSOL_OPTION 0x04 46 | 47 | extern int key_code; /* regular Atari key code */ 48 | extern int key_shift; /* Shift key pressed */ 49 | extern int key_consol; /* Start, Select and Option keys */ 50 | 51 | /* Joysticks ----------------------------------------------------------- */ 52 | 53 | /* joystick position */ 54 | 55 | #define STICK_LL 0x09 56 | #define STICK_BACK 0x0d 57 | #define STICK_LR 0x05 58 | #define STICK_LEFT 0x0b 59 | #define STICK_CENTRE 0x0f 60 | #define STICK_RIGHT 0x07 61 | #define STICK_UL 0x0a 62 | #define STICK_FORWARD 0x0e 63 | #define STICK_UR 0x06 64 | 65 | /* joy_autofire values */ 66 | #define AUTOFIRE_OFF 0 67 | #define AUTOFIRE_FIRE 1 /* Fire dependent */ 68 | #define AUTOFIRE_CONT 2 /* Continuous */ 69 | 70 | extern int joy_autofire[4]; /* autofire mode for each Atari port */ 71 | 72 | extern int joy_block_opposite_directions; /* can't move joystick left 73 | and right simultaneously */ 74 | 75 | extern int joy_multijoy; /* emulate MultiJoy4 interface */ 76 | 77 | /* 5200 joysticks values */ 78 | extern int joy_5200_min; 79 | extern int joy_5200_center; 80 | extern int joy_5200_max; 81 | 82 | /* Mouse --------------------------------------------------------------- */ 83 | 84 | /* mouse_mode values */ 85 | #define MOUSE_OFF 0 86 | #define MOUSE_PAD 1 /* Paddles */ 87 | #define MOUSE_TOUCH 2 /* Atari touch tablet */ 88 | #define MOUSE_KOALA 3 /* Koala pad */ 89 | #define MOUSE_PEN 4 /* Light pen */ 90 | #define MOUSE_GUN 5 /* Light gun */ 91 | #define MOUSE_AMIGA 6 /* Amiga mouse */ 92 | #define MOUSE_ST 7 /* Atari ST mouse */ 93 | #define MOUSE_TRAK 8 /* Atari CX22 Trak-Ball */ 94 | #define MOUSE_JOY 9 /* Joystick */ 95 | 96 | extern int mouse_mode; /* device emulated with mouse */ 97 | extern int mouse_port; /* Atari port, to which the emulated device is attached */ 98 | extern int mouse_delta_x; /* x motion since last frame */ 99 | extern int mouse_delta_y; /* y motion since last frame */ 100 | extern int mouse_buttons; /* buttons (b0=1: first button pressed, b1=1: 2nd pressed, etc. */ 101 | extern int mouse_speed; /* how fast the mouse pointer moves */ 102 | extern int mouse_pot_min; /* min. value of POKEY's POT register */ 103 | extern int mouse_pot_max; /* max. value of POKEY's POT register */ 104 | extern int mouse_pen_ofs_h; /* light pen/gun horizontal offset (for calibration) */ 105 | extern int mouse_pen_ofs_v; /* light pen/gun vertical offset (for calibration) */ 106 | extern int mouse_joy_inertia; /* how long the mouse pointer can move (time in Atari frames) 107 | after a fast motion of mouse */ 108 | 109 | /* Functions ----------------------------------------------------------- */ 110 | 111 | void INPUT_Initialise(void); 112 | void INPUT_Frame(void); 113 | void INPUT_Scanline(void); 114 | void INPUT_SelectMultiJoy(int no); 115 | void INPUT_CenterMousePointer(void); 116 | void INPUT_DrawMousePointer(void); 117 | 118 | #endif /* __A5200_INPUT_H_ */ 119 | -------------------------------------------------------------------------------- /arm9/source/emu/memory.c: -------------------------------------------------------------------------------- 1 | /* 2 | * memory.c - memory emulation 3 | * 4 | * Copyright (C) 1995-1998 David Firth 5 | * Copyright (C) 1998-2006 Atari800 development team (see DOC/CREDITS) 6 | * 7 | * This file is part of the Atari800 emulator project which emulates 8 | * the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers. 9 | * 10 | * Atari800 is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * Atari800 is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with Atari800; if not, write to the Free Software 22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 | */ 24 | 25 | #include "config.h" 26 | #include 27 | #include 28 | #include 29 | 30 | #include "atari.h" 31 | #include "antic.h" 32 | #include "cpu.h" 33 | #include "cartridge.h" 34 | #include "gtia.h" 35 | #include "memory.h" 36 | #include "pia.h" 37 | #include "pokeysnd.h" 38 | 39 | wrfunc *writemap = (wrfunc *)0x06860000; // Slight speedup to put the write function table in VRAM... uses 256K but we have nothing else to use if for! 40 | rdfunc readmap[65536] __attribute__ ((aligned (16))); // Some areas are hotspots for peripheral reads (Antic, GTIA, Pokey, etc). 41 | UBYTE memory[65536] __attribute__ ((aligned (16))); // This is the full 64K of Atari5200 memory map. For normal cart games, this is all there is! 42 | 43 | UBYTE normal_memory[16] __attribute__((section(".dtcm"))); // A quick way to determine if we are in a region of memory that might have special handling (banked, or peripheral mapped) 44 | UBYTE *mem_map[16] __attribute__((section(".dtcm"))); // This is the magic that allows us to index into banks of memory quickly. 16 banks of 4K cover the entire 5200 memory map. 45 | 46 | void ROM_PutByte(UWORD addr, UBYTE value) 47 | { 48 | // ROM normally doesn't respond to a write... 49 | } 50 | 51 | void MEMORY_InitialiseMap(void) 52 | { 53 | // Set the memory map back to pointing to main memory 54 | for (int i=0; i<16; i++) 55 | { 56 | mem_map[i] = memory + (0x1000 * i) - (0x1000 * i); // Yes, pointless except to get across the point that we are offsetting the memory map to avoid having to mask the addr in memory.h 57 | } 58 | } 59 | 60 | UBYTE PIA_GetByte(UWORD addr) 61 | { 62 | return addr & 0xff; // Floating bus. Not accurate but good enough for games like Star Raiders who read from a non-existent PIA on the 5200 63 | } 64 | 65 | void PIA_PutByte(UWORD addr, UBYTE data) // PIA doesn't exist on the 5200... but that doesn't stop Star Raiders from writing it 66 | { 67 | (void)addr; 68 | (void)data; 69 | } 70 | 71 | void MEMORY_InitialiseMachine(void) 72 | { 73 | unsigned int i; 74 | 75 | MEMORY_InitialiseMap(); 76 | dFillMem(0x0000, 0x00, 0x4000); 77 | dFillMem(0x4000, 0xff, 0x8000); 78 | dFillMem(0xC000, 0x00, 0x4000); 79 | memcpy(memory + 0xf800, atari_os, 0x800); 80 | SetRAM(0x0000, 0x3fff); 81 | SetROM(0x4000, 0xffff); 82 | 83 | // Set entire upper 16K to write nothing... and then override with peripherals below 84 | for (i=0xc000; i <= 0xffff; i++) writemap[i] = ROM_PutByte; 85 | 86 | for (i=0xc000; i <= 0xcfff; i++) readmap[i] = GTIA_GetByte; 87 | for (i=0xc000; i <= 0xcfff; i++) writemap[i] = GTIA_PutByte; 88 | 89 | for (i=0xd300; i <= 0xd3ff; i++) readmap[i] = PIA_GetByte; 90 | for (i=0xd300; i <= 0xd3ff; i++) writemap[i] = PIA_PutByte; 91 | 92 | for (i=0xd400; i <= 0xd4ff; i++) readmap[i] = ANTIC_GetByte; 93 | for (i=0xd400; i <= 0xd4ff; i++) writemap[i] = ANTIC_PutByte; 94 | 95 | for (i=0xe800; i <= 0xefff; i++) readmap[i] = POKEY_GetByte; 96 | for (i=0xe800; i <= 0xefff; i++) writemap[i] = POKEY_PutByte; 97 | 98 | Coldstart(); 99 | } 100 | -------------------------------------------------------------------------------- /arm9/source/emu/memory.h: -------------------------------------------------------------------------------- 1 | #ifndef _MEMORY_H_ 2 | #define _MEMORY_H_ 3 | 4 | #include "config.h" 5 | #include /* memcpy, memset */ 6 | 7 | #include "atari.h" 8 | 9 | typedef UBYTE (*rdfunc)(UWORD addr); 10 | typedef void (*wrfunc)(UWORD addr, UBYTE value); 11 | 12 | extern UBYTE memory[65536]; 13 | extern rdfunc readmap[65536]; 14 | extern wrfunc *writemap; 15 | extern UBYTE *mem_map[16]; 16 | extern UBYTE normal_memory[16]; 17 | 18 | // This one has to use the mem_map[] table to handle banked carts 19 | inline UBYTE dGetByte(UWORD addr) 20 | { 21 | return mem_map[addr >> 12][addr]; 22 | } 23 | 24 | // Zero page will always be in the lower 16K which on a 5200 will never be swapped out / banked... 25 | inline UBYTE zGetByte(UWORD addr) 26 | { 27 | return memory[addr]; 28 | } 29 | 30 | // Writing RAM - we can do this directly. If there is a special write, it would already be trapped by writemap[] 31 | inline void dPutByte(UWORD addr, UBYTE data) 32 | { 33 | memory[addr] = data; 34 | } 35 | 36 | // So that Antic can know about any banking of cart space that might be going on... 37 | inline UBYTE *AnticMainMemLookup(unsigned int addr) 38 | { 39 | return (UBYTE *) mem_map[addr >> 12] + addr; 40 | } 41 | 42 | #define dGetWord(x) (dGetByte(x) + (dGetByte((x) + 1) << 8)) 43 | #define dGetWordAligned(x) dGetWord(x) 44 | 45 | inline void dCopyFromMem(unsigned int from, void* to, unsigned int size) 46 | { 47 | memcpy((UBYTE*)to, AnticMainMemLookup((unsigned int)from), size); 48 | } 49 | 50 | inline void dCopyToMem(void*from, unsigned int to, unsigned int size) 51 | { 52 | memcpy(AnticMainMemLookup((unsigned int)to), (UBYTE*)from, size); 53 | } 54 | 55 | #define dFillMem(addr1, value, length) memset(memory + (addr1), value, length) 56 | 57 | void ROM_PutByte(UWORD addr, UBYTE byte); 58 | 59 | #define GetByte(addr) ((normal_memory[(addr)>>12]) ? dGetByte(addr) : (readmap[(addr)] ? (*readmap[(addr)])(addr) : dGetByte(addr))) 60 | #define PutByte(addr,byte) ((addr & 0xC000) ? ((wrfunc*)0x06860000)[(addr)]((addr), byte) : dPutByte(addr,byte)) 61 | 62 | #define SetRAM(addr1, addr2) do { \ 63 | int i; \ 64 | for (i = (addr1); i <= (addr2); i++) { \ 65 | readmap[i] = NULL; \ 66 | writemap[i] = NULL; \ 67 | } \ 68 | } while (0) 69 | #define SetROM(addr1, addr2) do { \ 70 | int i; \ 71 | for (i = (addr1); i <= (addr2); i++) { \ 72 | readmap[i] = NULL; \ 73 | writemap[i] = ROM_PutByte; \ 74 | } \ 75 | } while (0) 76 | 77 | void MEMORY_InitialiseMachine(void); 78 | void MemStateSave(UBYTE SaveVerbose); 79 | void MemStateRead(UBYTE SaveVerbose); 80 | #define CopyROM(addr1, addr2, src) memcpy(memory + (addr1), src, (addr2) - (addr1) + 1) 81 | 82 | inline void CopyFromMem(UWORD from, UBYTE *to, int size) {while (--size >= 0) {*to++ = memory[from];from++;}} 83 | inline void CopyToMem(const UBYTE *from, UWORD to, int size) {while (--size >= 0) {memory[to++] = *from++;}} 84 | extern void MEMORY_InitialiseMap(void); 85 | #endif /* _MEMORY_H_ */ 86 | -------------------------------------------------------------------------------- /arm9/source/emu/pia.c: -------------------------------------------------------------------------------- 1 | /* 2 | * pia.c - PIA chip emulation 3 | * 4 | * Copyright (C) 1995-1998 David Firth 5 | * Copyright (C) 1998-2005 Atari800 development team (see DOC/CREDITS) 6 | * 7 | * This file is part of the Atari800 emulator project which emulates 8 | * the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers. 9 | * 10 | * Atari800 is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * Atari800 is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with Atari800; if not, write to the Free Software 22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 | */ 24 | 25 | #include "config.h" 26 | 27 | #include "atari.h" 28 | #include "cpu.h" 29 | #include "memory.h" 30 | #include "pia.h" 31 | #include "input.h" 32 | 33 | UBYTE PACTL; 34 | UBYTE PBCTL; 35 | UBYTE PORTA; 36 | UBYTE PORTB; 37 | UBYTE PORT_input[2]; 38 | 39 | UBYTE atari_os[0x800]; 40 | 41 | void PIA_Initialise(void) { 42 | PACTL = 0x3f; 43 | PBCTL = 0x3f; 44 | PORTA = 0xff; 45 | PORTB = 0xff; 46 | PORT_input[0] = 0xff; 47 | PORT_input[1] = 0xff; 48 | } 49 | 50 | void PIA_Reset(void) { 51 | PORTA = 0xff; 52 | PORTB = 0xff; 53 | } -------------------------------------------------------------------------------- /arm9/source/emu/pia.h: -------------------------------------------------------------------------------- 1 | #ifndef _PIA_H_ 2 | #define _PIA_H_ 3 | 4 | #include "atari.h" 5 | 6 | #define _PORTA 0x00 7 | #define _PORTB 0x01 8 | #define _PACTL 0x02 9 | #define _PBCTL 0x03 10 | 11 | extern UBYTE PACTL; 12 | extern UBYTE PBCTL; 13 | extern UBYTE PORTA; 14 | extern UBYTE PORTB; 15 | extern UBYTE PORT_input[2]; 16 | 17 | extern UBYTE atari_os[0x800]; 18 | 19 | extern void PIA_Initialise(void); 20 | extern void PIA_Reset(void); 21 | 22 | #endif /* _PIA_H_ */ 23 | -------------------------------------------------------------------------------- /arm9/source/emu/platform.h: -------------------------------------------------------------------------------- 1 | #ifndef _PLATFORM_H_ 2 | #define _PLATFORM_H_ 3 | 4 | #include "config.h" 5 | #include 6 | 7 | /* This include file defines prototypes for platform-specific functions. */ 8 | 9 | void Atari_Initialise(void); 10 | int Atari_Exit(int run_monitor); 11 | void Atari_DisplayScreen(void); 12 | 13 | int Atari_PORT(int num); 14 | 15 | #ifdef SUPPORTS_ATARI_CONFIGINIT 16 | /* This function sets the configuration parameters to default values */ 17 | void Atari_ConfigInit(void); 18 | #endif 19 | 20 | #endif /* _PLATFORM_H_ */ 21 | -------------------------------------------------------------------------------- /arm9/source/emu/pokey.c: -------------------------------------------------------------------------------- 1 | /* 2 | * pokey.c - POKEY sound chip emulation 3 | * 4 | * Copyright (C) 1995-1998 David Firth 5 | * Copyright (C) 1998-2005 Atari800 development team (see DOC/CREDITS) 6 | * 7 | * This file is part of the Atari800 emulator project which emulates 8 | * the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers. 9 | * 10 | * Atari800 is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * Atari800 is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with Atari800; if not, write to the Free Software 22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 | */ 24 | #include 25 | #include 26 | #include "config.h" 27 | #include "atari.h" 28 | #include "cpu.h" 29 | #include "pia.h" 30 | #include "pokey.h" 31 | #include "gtia.h" 32 | #include "input.h" 33 | #include "pokeysnd.h" 34 | #include "antic.h" 35 | 36 | unsigned short pokeyBufIdx __attribute__((section(".dtcm")))= 0; 37 | char pokey_buffer[SNDLENGTH] __attribute__((section(".dtcm"))); 38 | 39 | UBYTE KBCODE __attribute__((section(".dtcm"))); 40 | UBYTE SERIN __attribute__((section(".dtcm"))); 41 | UBYTE IRQST __attribute__((section(".dtcm"))); 42 | UBYTE IRQEN __attribute__((section(".dtcm"))); 43 | UBYTE SKSTAT __attribute__((section(".dtcm"))); 44 | UBYTE SKCTLS __attribute__((section(".dtcm"))); 45 | int DELAYED_SERIN_IRQ; 46 | int DELAYED_SEROUT_IRQ; 47 | int DELAYED_XMTDONE_IRQ; 48 | 49 | /* structures to hold the 9 pokey control bytes */ 50 | UBYTE AUDF[4 * MAXPOKEYS] __attribute__((section(".dtcm"))); /* AUDFx (D200, D202, D204, D206) */ 51 | UBYTE AUDC[4 * MAXPOKEYS] __attribute__((section(".dtcm"))); /* AUDCx (D201, D203, D205, D207) */ 52 | UBYTE AUDCTL[MAXPOKEYS] __attribute__((section(".dtcm"))); /* AUDCTL (D208) */ 53 | int DivNIRQ[4] __attribute__((section(".dtcm"))); 54 | int DivNMax[4] __attribute__((section(".dtcm"))); 55 | int Base_mult[MAXPOKEYS]; /* selects either 64Khz or 15Khz clock mult */ 56 | 57 | UBYTE POT_input[8] = {228, 228, 228, 228, 228, 228, 228, 228}; 58 | UBYTE PCPOT_input[8] = {112, 112, 112, 112, 112, 112,112, 112}; 59 | UBYTE POT_all; 60 | UBYTE pot_scanline; 61 | 62 | UBYTE poly9_lookup[511]; 63 | UBYTE poly17_lookup[16385]; 64 | static ULONG random_scanline_counter; 65 | 66 | ULONG POKEY_GetRandomCounter(void) 67 | { 68 | return random_scanline_counter; 69 | } 70 | 71 | void POKEY_SetRandomCounter(ULONG value) 72 | { 73 | random_scanline_counter = value; 74 | } 75 | 76 | ITCM_CODE UBYTE POKEY_GetByte(UWORD addr) 77 | { 78 | UBYTE byte = 0xff; 79 | 80 | addr &= 0x0f; 81 | switch (addr) { 82 | case _POT0: 83 | case _POT1: 84 | case _POT2: 85 | case _POT3: 86 | case _POT4: 87 | case _POT5: 88 | case _POT6: 89 | case _POT7: 90 | if (!POTENA) 91 | return 228; 92 | if (POT_input[addr] <= pot_scanline) { 93 | return POT_input[addr]; 94 | } 95 | return pot_scanline; 96 | break; 97 | case _ALLPOT: 98 | { 99 | unsigned int i; 100 | for (i = 0; i < 8; i++) 101 | if (POT_input[i] <= pot_scanline) 102 | byte &= ~(1 << i); // reset bit if pot value known 103 | } 104 | return byte; 105 | //return POT_all; 106 | break; 107 | case _KBCODE: 108 | //byte = KBCODE; 109 | if ( SKCTLS & 0x01 ) 110 | return 0xff; 111 | else 112 | return KBCODE | ((random_scanline_counter & 0x1)<<5); 113 | break; 114 | case _RANDOM: 115 | if ((SKCTLS & 0x03) != 0) { 116 | int i = random_scanline_counter + XPOS; 117 | if (AUDCTL[0] & POLY9) 118 | byte = poly9_lookup[i % POLY9_SIZE]; 119 | else { 120 | const UBYTE *ptr; 121 | i %= POLY17_SIZE; 122 | ptr = poly17_lookup + (i >> 3); 123 | i &= 7; 124 | byte = (UBYTE) ((ptr[0] >> i) + (ptr[1] << (8 - i))); 125 | } 126 | } 127 | break; 128 | case _SERIN: 129 | byte = SERIN; 130 | break; 131 | case _IRQST: 132 | byte = IRQST; 133 | break; 134 | case _SKSTAT: 135 | byte = SKSTAT; 136 | break; 137 | } 138 | 139 | return byte; 140 | } 141 | 142 | void Update_Counter(int chan_mask); 143 | 144 | 145 | #ifndef SOUND_GAIN /* sound gain can be pre-defined in the configure/Makefile */ 146 | #define SOUND_GAIN 4 147 | #endif 148 | 149 | ITCM_CODE void POKEY_PutByte(UWORD addr, UBYTE byte) 150 | { 151 | addr &= 0x0f; 152 | switch (addr) { 153 | case _AUDC1: 154 | AUDC[CHAN1] = byte; 155 | Update_pokey_sound(_AUDC1, byte, 0, SOUND_GAIN); 156 | break; 157 | case _AUDC2: 158 | AUDC[CHAN2] = byte; 159 | Update_pokey_sound(_AUDC2, byte, 0, SOUND_GAIN); 160 | break; 161 | case _AUDC3: 162 | AUDC[CHAN3] = byte; 163 | Update_pokey_sound(_AUDC3, byte, 0, SOUND_GAIN); 164 | break; 165 | case _AUDC4: 166 | AUDC[CHAN4] = byte; 167 | Update_pokey_sound(_AUDC4, byte, 0, SOUND_GAIN); 168 | break; 169 | case _AUDCTL: 170 | AUDCTL[0] = byte; 171 | 172 | /* determine the base multiplier for the 'div by n' calculations */ 173 | if (byte & CLOCK_15) 174 | Base_mult[0] = DIV_15; 175 | else 176 | Base_mult[0] = DIV_64; 177 | 178 | Update_Counter((1 << CHAN1) | (1 << CHAN2) | (1 << CHAN3) | (1 << CHAN4)); 179 | Update_pokey_sound(_AUDCTL, byte, 0, SOUND_GAIN); 180 | break; 181 | case _AUDF1: 182 | AUDF[CHAN1] = byte; 183 | Update_Counter((AUDCTL[0] & CH1_CH2) ? ((1 << CHAN2) | (1 << CHAN1)) : (1 << CHAN1)); 184 | Update_pokey_sound(_AUDF1, byte, 0, SOUND_GAIN); 185 | break; 186 | case _AUDF2: 187 | AUDF[CHAN2] = byte; 188 | Update_Counter(1 << CHAN2); 189 | Update_pokey_sound(_AUDF2, byte, 0, SOUND_GAIN); 190 | break; 191 | case _AUDF3: 192 | AUDF[CHAN3] = byte; 193 | Update_Counter((AUDCTL[0] & CH3_CH4) ? ((1 << CHAN4) | (1 << CHAN3)) : (1 << CHAN3)); 194 | Update_pokey_sound(_AUDF3, byte, 0, SOUND_GAIN); 195 | break; 196 | case _AUDF4: 197 | AUDF[CHAN4] = byte; 198 | Update_Counter(1 << CHAN4); 199 | Update_pokey_sound(_AUDF4, byte, 0, SOUND_GAIN); 200 | break; 201 | case _IRQEN: 202 | IRQEN = byte; 203 | IRQST |= ~byte & 0xf7; /* Reset disabled IRQs except XMTDONE */ 204 | if (IRQEN & 0x20) { 205 | SLONG delay; 206 | delay = 0; 207 | if (delay > 0) 208 | DELAYED_SERIN_IRQ = delay; 209 | } 210 | if ((~IRQST & IRQEN) == 0) 211 | IRQ = 0; 212 | break; 213 | case _SKRES: 214 | SKSTAT |= 0xe0; 215 | break; 216 | case _POTGO: 217 | if (!(SKCTLS & 4)) { 218 | pot_scanline = 0; /* slow pot mode */ 219 | } 220 | break; 221 | case _SEROUT: 222 | break; 223 | case _STIMER: 224 | DivNIRQ[CHAN1] = DivNMax[CHAN1]; 225 | DivNIRQ[CHAN2] = DivNMax[CHAN2]; 226 | DivNIRQ[CHAN4] = DivNMax[CHAN4]; 227 | Update_pokey_sound(_STIMER, byte, 0, SOUND_GAIN); 228 | break; 229 | case _SKCTLS: 230 | SKCTLS = byte; 231 | Update_pokey_sound(_SKCTLS, byte, 0, SOUND_GAIN); 232 | if (byte & 4) 233 | pot_scanline = 228; /* fast pot mode - return results immediately */ 234 | break; 235 | } 236 | } 237 | 238 | void POKEY_Initialise(void) 239 | { 240 | int i; 241 | ULONG reg; 242 | 243 | /* Initialise Serial Port Interrupts */ 244 | DELAYED_SERIN_IRQ = 0; 245 | DELAYED_SEROUT_IRQ = 0; 246 | DELAYED_XMTDONE_IRQ = 0; 247 | 248 | KBCODE = 0xff; 249 | SERIN = 0x00; /* or 0xff ? */ 250 | IRQST = 0xff; 251 | IRQEN = 0x00; 252 | SKSTAT = 0xef; 253 | SKCTLS = 0x00; 254 | 255 | for (i = 0; i < (MAXPOKEYS * 4); i++) { 256 | AUDC[i] = 0; 257 | AUDF[i] = 0; 258 | } 259 | 260 | for (i = 0; i < MAXPOKEYS; i++) { 261 | AUDCTL[i] = 0; 262 | Base_mult[i] = DIV_64; 263 | } 264 | 265 | for (i = 0; i < 4; i++) 266 | DivNIRQ[i] = DivNMax[i] = 0; 267 | 268 | pot_scanline = 0; 269 | 270 | /* initialise poly9_lookup */ 271 | reg = 0x1ff; 272 | for (i = 0; i < 511; i++) { 273 | reg = ((((reg >> 5) ^ reg) & 1) << 8) + (reg >> 1); 274 | poly9_lookup[i] = (UBYTE) reg; 275 | } 276 | /* initialise poly17_lookup */ 277 | reg = 0x1ffff; 278 | for (i = 0; i < 16385; i++) { 279 | reg = ((((reg >> 5) ^ reg) & 0xff) << 9) + (reg >> 8); 280 | poly17_lookup[i] = (UBYTE) (reg >> 1); 281 | } 282 | 283 | random_scanline_counter = rand(); 284 | } 285 | 286 | void POKEY_Frame(void) 287 | { 288 | random_scanline_counter %= (AUDCTL[0] & POLY9) ? POLY9_SIZE : POLY17_SIZE; 289 | } 290 | 291 | /*************************************************************************** 292 | ** Generate POKEY Timer IRQs if required ** 293 | ** called on a per-scanline basis, not very precise, but good enough ** 294 | ** for most applications ** 295 | ***************************************************************************/ 296 | unsigned short bPausePokey = 0; 297 | ITCM_CODE void POKEY_Scanline(void) 298 | { 299 | extern unsigned short myPokeyBufIdx; 300 | unsigned short next_pokey_idx = (pokeyBufIdx+1) & (SNDLENGTH-1); 301 | 302 | if (bPausePokey) bPausePokey--; 303 | else 304 | { 305 | if (next_pokey_idx == myPokeyBufIdx) 306 | { 307 | bPausePokey = SNDLENGTH / 3; 308 | } 309 | else 310 | { 311 | Pokey_process(&pokey_buffer[pokeyBufIdx], 1); // Each scanline, compute 1 output samples. This corresponds to a 15720Khz output sample rate if running at 60FPS (good enough) 312 | pokeyBufIdx = next_pokey_idx; 313 | } 314 | } 315 | 316 | if (pot_scanline < 228) 317 | pot_scanline++; 318 | 319 | POT_input[0] = PCPOT_input[0]; POT_input[1] = PCPOT_input[1]; POT_input[2] = PCPOT_input[2]; POT_input[3] = PCPOT_input[3]; 320 | 321 | random_scanline_counter += LINE_C; 322 | 323 | if ((DivNIRQ[CHAN1] -= LINE_C) < 0 ) { 324 | DivNIRQ[CHAN1] += DivNMax[CHAN1]; 325 | if (IRQEN & 0x01) { 326 | IRQST &= 0xfe; 327 | GenerateIRQ(); 328 | } 329 | } 330 | 331 | if ((DivNIRQ[CHAN2] -= LINE_C) < 0 ) { 332 | DivNIRQ[CHAN2] += DivNMax[CHAN2]; 333 | if (IRQEN & 0x02) { 334 | IRQST &= 0xfd; 335 | GenerateIRQ(); 336 | } 337 | } 338 | 339 | if ((DivNIRQ[CHAN4] -= LINE_C) < 0 ) { 340 | DivNIRQ[CHAN4] += DivNMax[CHAN4]; 341 | if (IRQEN & 0x04) { 342 | IRQST &= 0xfb; 343 | GenerateIRQ(); 344 | } 345 | } 346 | } 347 | 348 | /*****************************************************************************/ 349 | /* Module: Update_Counter() */ 350 | /* Purpose: To process the latest control values stored in the AUDF, AUDC, */ 351 | /* and AUDCTL registers. It pre-calculates as much information as */ 352 | /* possible for better performance. This routine has been added */ 353 | /* here again as I need the precise frequency for the pokey timers */ 354 | /* again. The pokey emulation is therefore somewhat sub-optimal */ 355 | /* since the actual pokey emulation should grab the frequency values */ 356 | /* directly from here instead of calculating them again. */ 357 | /* */ 358 | /* Author: Ron Fries,Thomas Richter */ 359 | /* Date: March 27, 1998 */ 360 | /* */ 361 | /* Inputs: chan_mask: Channel mask, one bit per channel. */ 362 | /* The channels that need to be updated */ 363 | /* */ 364 | /* Outputs: Adjusts local globals - no return value */ 365 | /* */ 366 | /*****************************************************************************/ 367 | 368 | ITCM_CODE void Update_Counter(int chan_mask) 369 | { 370 | /************************************************************/ 371 | /* As defined in the manual, the exact Div_n_cnt values are */ 372 | /* different depending on the frequency and resolution: */ 373 | /* 64 kHz or 15 kHz - AUDF + 1 */ 374 | /* 1 MHz, 8-bit - AUDF + 4 */ 375 | /* 1 MHz, 16-bit - AUDF[CHAN1]+256*AUDF[CHAN2] + 7 */ 376 | /************************************************************/ 377 | 378 | /* only reset the channels that have changed */ 379 | 380 | if (chan_mask & (1 << CHAN1)) { 381 | /* process channel 1 frequency */ 382 | if (AUDCTL[0] & CH1_179) 383 | DivNMax[CHAN1] = AUDF[CHAN1] + 4; 384 | else 385 | DivNMax[CHAN1] = (AUDF[CHAN1] + 1) * Base_mult[0]; 386 | if (DivNMax[CHAN1] < LINE_C) 387 | DivNMax[CHAN1] = LINE_C; 388 | } 389 | 390 | if (chan_mask & (1 << CHAN2)) { 391 | /* process channel 2 frequency */ 392 | if (AUDCTL[0] & CH1_CH2) { 393 | if (AUDCTL[0] & CH1_179) 394 | DivNMax[CHAN2] = AUDF[CHAN2] * 256 + AUDF[CHAN1] + 7; 395 | else 396 | DivNMax[CHAN2] = (AUDF[CHAN2] * 256 + AUDF[CHAN1] + 1) * Base_mult[0]; 397 | } 398 | else 399 | DivNMax[CHAN2] = (AUDF[CHAN2] + 1) * Base_mult[0]; 400 | if (DivNMax[CHAN2] < LINE_C) 401 | DivNMax[CHAN2] = LINE_C; 402 | } 403 | 404 | if (chan_mask & (1 << CHAN4)) { 405 | /* process channel 4 frequency */ 406 | if (AUDCTL[0] & CH3_CH4) { 407 | if (AUDCTL[0] & CH3_179) 408 | DivNMax[CHAN4] = AUDF[CHAN4] * 256 + AUDF[CHAN3] + 7; 409 | else 410 | DivNMax[CHAN4] = (AUDF[CHAN4] * 256 + AUDF[CHAN3] + 1) * Base_mult[0]; 411 | } 412 | else 413 | DivNMax[CHAN4] = (AUDF[CHAN4] + 1) * Base_mult[0]; 414 | if (DivNMax[CHAN4] < LINE_C) 415 | DivNMax[CHAN4] = LINE_C; 416 | } 417 | } 418 | 419 | void PokeyClearBuffer(void) 420 | { 421 | memset(pokey_buffer, 0x00, SNDLENGTH); 422 | pokeyBufIdx = 0; 423 | POKEY_Initialise(); 424 | Pokey_DoInit(); 425 | } 426 | 427 | -------------------------------------------------------------------------------- /arm9/source/emu/pokey.h: -------------------------------------------------------------------------------- 1 | #ifndef _POKEY_H_ 2 | #define _POKEY_H_ 3 | 4 | #ifdef ASAP /* external project, see http://asap.sf.net */ 5 | #include "asap_internal.h" 6 | #else 7 | #include "atari.h" 8 | #endif 9 | 10 | #define _AUDF1 0x00 11 | #define _AUDC1 0x01 12 | #define _AUDF2 0x02 13 | #define _AUDC2 0x03 14 | #define _AUDF3 0x04 15 | #define _AUDC3 0x05 16 | #define _AUDF4 0x06 17 | #define _AUDC4 0x07 18 | #define _AUDCTL 0x08 19 | #define _STIMER 0x09 20 | #define _SKRES 0x0a 21 | #define _POTGO 0x0b 22 | #define _SEROUT 0x0d 23 | #define _IRQEN 0x0e 24 | #define _SKCTLS 0x0f 25 | 26 | #define _POT0 0x00 27 | #define _POT1 0x01 28 | #define _POT2 0x02 29 | #define _POT3 0x03 30 | #define _POT4 0x04 31 | #define _POT5 0x05 32 | #define _POT6 0x06 33 | #define _POT7 0x07 34 | #define _ALLPOT 0x08 35 | #define _KBCODE 0x09 36 | #define _RANDOM 0x0a 37 | #define _SERIN 0x0d 38 | #define _IRQST 0x0e 39 | #define _SKSTAT 0x0f 40 | 41 | #define _POKEY2 0x10 /* offset to second pokey chip (STEREO expansion) */ 42 | 43 | #ifndef ASAP 44 | 45 | extern UBYTE KBCODE; 46 | extern UBYTE IRQST; 47 | extern UBYTE IRQEN; 48 | extern UBYTE SKSTAT; 49 | extern int DELAYED_SERIN_IRQ; 50 | extern int DELAYED_SEROUT_IRQ; 51 | extern int DELAYED_XMTDONE_IRQ; 52 | 53 | extern UBYTE POT_input[8]; 54 | 55 | ULONG POKEY_GetRandomCounter(void); 56 | void POKEY_SetRandomCounter(ULONG value); 57 | UBYTE POKEY_GetByte(UWORD addr); 58 | void POKEY_PutByte(UWORD addr, UBYTE byte); 59 | void POKEY_Initialise(void); 60 | void POKEY_Frame(void); 61 | void POKEY_Scanline(void); 62 | 63 | #endif 64 | 65 | /* CONSTANT DEFINITIONS */ 66 | 67 | /* definitions for AUDCx (D201, D203, D205, D207) */ 68 | #define NOTPOLY5 0x80 /* selects POLY5 or direct CLOCK */ 69 | #define POLY4 0x40 /* selects POLY4 or POLY17 */ 70 | #define PURETONE 0x20 /* selects POLY4/17 or PURE tone */ 71 | #define VOL_ONLY 0x10 /* selects VOLUME OUTPUT ONLY */ 72 | #define VOLUME_MASK 0x0f /* volume mask */ 73 | 74 | /* definitions for AUDCTL (D208) */ 75 | #define POLY9 0x80 /* selects POLY9 or POLY17 */ 76 | #define CH1_179 0x40 /* selects 1.78979 MHz for Ch 1 */ 77 | #define CH3_179 0x20 /* selects 1.78979 MHz for Ch 3 */ 78 | #define CH1_CH2 0x10 /* clocks channel 1 w/channel 2 */ 79 | #define CH3_CH4 0x08 /* clocks channel 3 w/channel 4 */ 80 | #define CH1_FILTER 0x04 /* selects channel 1 high pass filter */ 81 | #define CH2_FILTER 0x02 /* selects channel 2 high pass filter */ 82 | #define CLOCK_15 0x01 /* selects 15.6999kHz or 63.9210kHz */ 83 | 84 | /* for accuracy, the 64kHz and 15kHz clocks are exact divisions of 85 | the 1.79MHz clock */ 86 | #define DIV_64 28 /* divisor for 1.79MHz clock to 64 kHz */ 87 | #define DIV_15 114 /* divisor for 1.79MHz clock to 15 kHz */ 88 | 89 | /* the size (in entries) of the 4 polynomial tables */ 90 | #define POLY4_SIZE 0x000f 91 | #define POLY5_SIZE 0x001f 92 | #define POLY9_SIZE 0x01ff 93 | #define POLY17_SIZE 0x0001ffff 94 | 95 | #define MAXPOKEYS 1 /* max number of emulated chips */ 96 | 97 | /* channel/chip definitions */ 98 | #define CHAN1 0 99 | #define CHAN2 1 100 | #define CHAN3 2 101 | #define CHAN4 3 102 | #define CHIP1 0 103 | #define CHIP2 4 104 | #define CHIP3 8 105 | #define CHIP4 12 106 | #define SAMPLE 127 107 | 108 | /* structures to hold the 9 pokey control bytes */ 109 | extern UBYTE AUDF[4 * MAXPOKEYS]; /* AUDFx (D200, D202, D204, D206) */ 110 | extern UBYTE AUDC[4 * MAXPOKEYS]; /* AUDCx (D201, D203, D205, D207) */ 111 | extern UBYTE AUDCTL[MAXPOKEYS]; /* AUDCTL (D208) */ 112 | 113 | extern int DivNIRQ[4], DivNMax[4]; 114 | extern int Base_mult[MAXPOKEYS]; /* selects either 64Khz or 15Khz clock mult */ 115 | 116 | extern UBYTE poly9_lookup[POLY9_SIZE]; 117 | extern UBYTE poly17_lookup[16385]; 118 | 119 | #endif 120 | -------------------------------------------------------------------------------- /arm9/source/emu/pokeysnd.c: -------------------------------------------------------------------------------- 1 | /* 2 | * pokeysnd.c - POKEY sound chip emulation, v2.4 3 | * 4 | * Copyright (C) 1996-1998 Ron Fries 5 | * Copyright (C) 1998-2006 Atari800 development team (see DOC/CREDITS) 6 | * 7 | * This file is part of the Atari800 emulator project which emulates 8 | * the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers. 9 | * 10 | * Atari800 is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * Atari800 is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with Atari800; if not, write to the Free Software 22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 | */ 24 | #include 25 | 26 | #include "config.h" 27 | #include "atari.h" 28 | #include "pokeysnd.h" 29 | 30 | #define READ_U32(x) \ 31 | ((*(unsigned char *) (x)) | ((*((unsigned char *) (x) + 1)) << 8) | \ 32 | ((*((unsigned char *) (x) + 2)) << 16) | ((*((unsigned char *) (x) + 3)) << 24)) 33 | #define WRITE_U32(x, d) \ 34 | { \ 35 | uint32 i = d; \ 36 | (*(unsigned char *)(x)) = ((i) & 255); \ 37 | (*((unsigned char *)(x) + 1)) = (((i) >> 8) & 255); \ 38 | (*((unsigned char *)(x) + 2)) = (((i) >> 16) & 255); \ 39 | (*((unsigned char *)(x) + 3)) = (((i) >> 24) & 255); \ 40 | } 41 | 42 | /* GLOBAL VARIABLE DEFINITIONS */ 43 | 44 | /* number of pokey chips currently emulated */ 45 | static uint8 Num_pokeys; 46 | 47 | static uint8 AUDV[4 * MAXPOKEYS] __attribute__((section(".dtcm"))); /* Channel volume - derived */ 48 | 49 | static uint8 Outbit[4 * MAXPOKEYS] __attribute__((section(".dtcm"))); /* current state of the output (high or low) */ 50 | 51 | static uint8 Outvol[4 * MAXPOKEYS] __attribute__((section(".dtcm"))); /* last output volume for each channel */ 52 | 53 | /* Initialze the bit patterns for the polynomials. */ 54 | 55 | /* The 4bit and 5bit patterns are the identical ones used in the pokey chip. */ 56 | /* Though the patterns could be packed with 8 bits per byte, using only a */ 57 | /* single bit per byte keeps the math simple, which is important for */ 58 | /* efficient processing. */ 59 | 60 | static uint8 bit4[POLY4_SIZE] = 61 | {1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0}; /* new table invented by Perry */ 62 | 63 | static uint8 bit5[POLY5_SIZE] = 64 | {1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0}; 65 | 66 | static uint32 P4 = 0, /* Global position pointer for the 4-bit POLY array */ 67 | P5 = 0, /* Global position pointer for the 5-bit POLY array */ 68 | P9 = 0, /* Global position pointer for the 9-bit POLY array */ 69 | P17 = 0; /* Global position pointer for the 17-bit POLY array */ 70 | 71 | static uint32 Div_n_cnt[4 * MAXPOKEYS], /* Divide by n counter. one for each channel */ 72 | Div_n_max[4 * MAXPOKEYS]; /* Divide by n maximum, one for each channel */ 73 | 74 | static uint32 Samp_n_max, /* Sample max. For accuracy, it is *256 */ 75 | Samp_n_cnt[2] __attribute__ ((aligned (4))); /* Sample cnt. */ 76 | 77 | /* Volume only emulations declarations */ 78 | static uint32 snd_freq17 = FREQ_17_APPROX; 79 | int32 snd_playback_freq = 22050; 80 | uint8 snd_num_pokeys = 1; 81 | static int snd_flags = 0; 82 | 83 | /* multiple sound engine interface */ 84 | static void null_pokey_process(void *sndbuffer, unsigned int sndn) {} 85 | void (*Pokey_process_ptr)(void *sndbuffer, unsigned int sndn) = null_pokey_process; 86 | 87 | static void Update_pokey_sound_rf(uint16, uint8, uint8, uint8); 88 | static void null_pokey_sound(uint16 addr, uint8 val, uint8 chip, uint8 gain) {} 89 | void (*Update_pokey_sound) (uint16 addr, uint8 val, uint8 chip, uint8 gain) = null_pokey_sound; 90 | 91 | /*****************************************************************************/ 92 | /* In my routines, I treat the sample output as another divide by N counter */ 93 | /* For better accuracy, the Samp_n_cnt has a fixed binary decimal point */ 94 | /* which has 8 binary digits to the right of the decimal point. I use a two */ 95 | /* byte array to give me a minimum of 40 bits, and then use pointer math to */ 96 | /* reference either the 24.8 whole/fraction combination or the 32-bit whole */ 97 | /* only number. This is mainly used to keep the math simple for */ 98 | /* optimization. See below: */ 99 | /* */ 100 | /* Representation on little-endian machines: */ 101 | /* xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx | xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx */ 102 | /* fraction whole whole whole whole unused unused unused */ 103 | /* */ 104 | /* Samp_n_cnt[0] gives me a 32-bit int 24 whole bits with 8 fractional bits, */ 105 | /* while (uint32 *)((uint8 *)(&Samp_n_cnt[0])+1) gives me the 32-bit whole */ 106 | /* number only. */ 107 | /* */ 108 | /* Representation on big-endian machines: */ 109 | /* xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx | xxxxxxxx xxxxxxxx xxxxxxxx.xxxxxxxx */ 110 | /* unused unused unused whole whole whole whole fraction */ 111 | /* */ 112 | /* Samp_n_cnt[1] gives me a 32-bit int 24 whole bits with 8 fractional bits, */ 113 | /* while (uint32 *)((uint8 *)(&Samp_n_cnt[0])+3) gives me the 32-bit whole */ 114 | /* number only. */ 115 | /*****************************************************************************/ 116 | 117 | 118 | /*****************************************************************************/ 119 | /* Module: Pokey_sound_init() */ 120 | /* Purpose: to handle the power-up initialization functions */ 121 | /* these functions should only be executed on a cold-restart */ 122 | /* */ 123 | /* Author: Ron Fries */ 124 | /* Date: January 1, 1997 */ 125 | /* */ 126 | /* Inputs: freq17 - the value for the '1.79MHz' Pokey audio clock */ 127 | /* playback_freq - the playback frequency in samples per second */ 128 | /* num_pokeys - specifies the number of pokey chips to be emulated */ 129 | /* */ 130 | /* Outputs: Adjusts local globals - no return value */ 131 | /* */ 132 | /*****************************************************************************/ 133 | 134 | static int Pokey_sound_init_rf(uint32 freq17, uint16 playback_freq, uint8 num_pokeys, unsigned int flags) 135 | { 136 | uint8 chan; 137 | 138 | Update_pokey_sound = Update_pokey_sound_rf; 139 | 140 | /* start all of the polynomial counters at zero */ 141 | P4 = 0; 142 | P5 = 0; 143 | P9 = 0; 144 | P17 = 0; 145 | 146 | /* calculate the sample 'divide by N' value based on the playback freq. */ 147 | Samp_n_max = ((uint32) freq17 << 8) / playback_freq; 148 | 149 | Samp_n_cnt[0] = 0; /* initialize all bits of the sample */ 150 | Samp_n_cnt[1] = 0; /* 'divide by N' counter */ 151 | 152 | for (chan = 0; chan < (MAXPOKEYS * 4); chan++) { 153 | Outvol[chan] = 0; 154 | Outbit[chan] = 0; 155 | Div_n_cnt[chan] = 0; 156 | Div_n_max[chan] = 0x7fffffffL; 157 | AUDV[chan] = 0; 158 | } 159 | 160 | /* set the number of pokey chips currently emulated */ 161 | Num_pokeys = num_pokeys; 162 | 163 | return 0; /* OK */ 164 | } 165 | 166 | int Pokey_DoInit(void) 167 | { 168 | return Pokey_sound_init_rf(snd_freq17, (uint16) snd_playback_freq, snd_num_pokeys, snd_flags); 169 | } 170 | 171 | int Pokey_sound_init(uint32 freq17, uint16 playback_freq, uint8 num_pokeys, unsigned int flags) 172 | { 173 | snd_freq17 = freq17; 174 | snd_playback_freq = playback_freq; 175 | snd_num_pokeys = num_pokeys; 176 | snd_flags = flags; 177 | 178 | return Pokey_DoInit(); 179 | } 180 | 181 | /*****************************************************************************/ 182 | /* Module: Update_pokey_sound() */ 183 | /* Purpose: To process the latest control values stored in the AUDF, AUDC, */ 184 | /* and AUDCTL registers. It pre-calculates as much information as */ 185 | /* possible for better performance. This routine has not been */ 186 | /* optimized. */ 187 | /* */ 188 | /* Author: Ron Fries */ 189 | /* Date: January 1, 1997 */ 190 | /* */ 191 | /* Inputs: addr - the address of the parameter to be changed */ 192 | /* val - the new value to be placed in the specified address */ 193 | /* gain - specified as an 8-bit fixed point number - use 1 for no */ 194 | /* amplification (output is multiplied by gain) */ 195 | /* */ 196 | /* Outputs: Adjusts local globals - no return value */ 197 | /* */ 198 | /*****************************************************************************/ 199 | 200 | static void Update_pokey_sound_rf(uint16 addr, uint8 val, uint8 chip, uint8 gain) 201 | { 202 | uint32 new_val = 0; 203 | uint8 chan; 204 | uint8 chan_mask; 205 | 206 | /* determine which address was changed */ 207 | switch (addr & 0x0f) { 208 | case _AUDF1: 209 | chan_mask = 1 << CHAN1; 210 | if (AUDCTL[0] & CH1_CH2) /* if ch 1&2 tied together */ 211 | chan_mask |= 1 << CHAN2; /* then also change on ch2 */ 212 | break; 213 | case _AUDC1: 214 | AUDV[CHAN1] = (val & VOLUME_MASK) * gain; 215 | chan_mask = 1 << CHAN1; 216 | break; 217 | case _AUDF2: 218 | chan_mask = 1 << CHAN2; 219 | break; 220 | case _AUDC2: 221 | AUDV[CHAN2] = (val & VOLUME_MASK) * gain; 222 | chan_mask = 1 << CHAN2; 223 | break; 224 | case _AUDF3: 225 | chan_mask = 1 << CHAN3; 226 | if (AUDCTL[0] & CH3_CH4) /* if ch 3&4 tied together */ 227 | chan_mask |= 1 << CHAN4; /* then also change on ch4 */ 228 | break; 229 | case _AUDC3: 230 | AUDV[CHAN3] = (val & VOLUME_MASK) * gain; 231 | chan_mask = 1 << CHAN3; 232 | break; 233 | case _AUDF4: 234 | chan_mask = 1 << CHAN4; 235 | break; 236 | case _AUDC4: 237 | AUDV[CHAN4] = (val & VOLUME_MASK) * gain; 238 | chan_mask = 1 << CHAN4; 239 | break; 240 | case _AUDCTL: 241 | chan_mask = 15; /* all channels */ 242 | break; 243 | default: 244 | chan_mask = 0; 245 | break; 246 | } 247 | 248 | /************************************************************/ 249 | /* As defined in the manual, the exact Div_n_cnt values are */ 250 | /* different depending on the frequency and resolution: */ 251 | /* 64 kHz or 15 kHz - AUDF + 1 */ 252 | /* 1 MHz, 8-bit - AUDF + 4 */ 253 | /* 1 MHz, 16-bit - AUDF[CHAN1]+256*AUDF[CHAN2] + 7 */ 254 | /************************************************************/ 255 | 256 | /* only reset the channels that have changed */ 257 | 258 | if (chan_mask & (1 << CHAN1)) { 259 | /* process channel 1 frequency */ 260 | if (AUDCTL[0] & CH1_179) 261 | new_val = AUDF[CHAN1] + 4; 262 | else 263 | new_val = (AUDF[CHAN1] + 1) * Base_mult[0]; 264 | 265 | if (new_val != Div_n_max[CHAN1]) { 266 | Div_n_max[CHAN1] = new_val; 267 | 268 | if (Div_n_cnt[CHAN1] > new_val) { 269 | Div_n_cnt[CHAN1] = new_val; 270 | } 271 | } 272 | } 273 | 274 | if (chan_mask & (1 << CHAN2)) { 275 | /* process channel 2 frequency */ 276 | if (AUDCTL[0] & CH1_CH2) { 277 | if (AUDCTL[0] & CH1_179) 278 | new_val = AUDF[CHAN2] * 256 + 279 | AUDF[CHAN1] + 7; 280 | else 281 | new_val = (AUDF[CHAN2] * 256 + 282 | AUDF[CHAN1] + 1) * Base_mult[0]; 283 | } 284 | else 285 | new_val = (AUDF[CHAN2] + 1) * Base_mult[0]; 286 | 287 | if (new_val != Div_n_max[CHAN2]) { 288 | Div_n_max[CHAN2] = new_val; 289 | 290 | if (Div_n_cnt[CHAN2] > new_val) { 291 | Div_n_cnt[CHAN2] = new_val; 292 | } 293 | } 294 | } 295 | 296 | if (chan_mask & (1 << CHAN3)) { 297 | /* process channel 3 frequency */ 298 | if (AUDCTL[0] & CH3_179) 299 | new_val = AUDF[CHAN3] + 4; 300 | else 301 | new_val = (AUDF[CHAN3] + 1) * Base_mult[0]; 302 | 303 | if (new_val != Div_n_max[CHAN3]) { 304 | Div_n_max[CHAN3] = new_val; 305 | 306 | if (Div_n_cnt[CHAN3] > new_val) { 307 | Div_n_cnt[CHAN3] = new_val; 308 | } 309 | } 310 | } 311 | 312 | if (chan_mask & (1 << CHAN4)) { 313 | /* process channel 4 frequency */ 314 | if (AUDCTL[0] & CH3_CH4) { 315 | if (AUDCTL[0] & CH3_179) 316 | new_val = AUDF[CHAN4] * 256 + 317 | AUDF[CHAN3] + 7; 318 | else 319 | new_val = (AUDF[CHAN4] * 256 + 320 | AUDF[CHAN3] + 1) * Base_mult[0]; 321 | } 322 | else 323 | new_val = (AUDF[CHAN4] + 1) * Base_mult[0]; 324 | 325 | if (new_val != Div_n_max[CHAN4]) { 326 | Div_n_max[CHAN4] = new_val; 327 | 328 | if (Div_n_cnt[CHAN4] > new_val) { 329 | Div_n_cnt[CHAN4] = new_val; 330 | } 331 | } 332 | } 333 | 334 | /* if channel is volume only, set current output */ 335 | for (chan = CHAN1; chan <= CHAN4; chan++) 336 | { 337 | if (chan_mask & (1 << chan)) 338 | { 339 | /* I've disabled any frequencies that exceed the sampling 340 | frequency. There isn't much point in processing frequencies 341 | that the hardware can't reproduce. I've also disabled 342 | processing if the volume is zero. */ 343 | if ((AUDC[chan] & VOL_ONLY) || ((AUDC[chan] & VOLUME_MASK) == 0) || (Div_n_max[chan] < (Samp_n_max >> 8))) 344 | { 345 | /* indicate the channel is 'on' */ 346 | Outvol[chan] = 1; 347 | /* and set channel freq to max to reduce processing */ 348 | Div_n_max[chan] = 0x7fffffffL; 349 | Div_n_cnt[chan] = 0x7fffffffL; 350 | } 351 | } 352 | } 353 | } 354 | 355 | 356 | /*****************************************************************************/ 357 | /* Module: Pokey_process() */ 358 | /* Purpose: To fill the output buffer with the sound output based on the */ 359 | /* pokey chip parameters. */ 360 | /* */ 361 | /* Author: Ron Fries */ 362 | /* Date: January 1, 1997 */ 363 | /* */ 364 | /* Inputs: *buffer - pointer to the buffer where the audio output will */ 365 | /* be placed */ 366 | /* n - size of the playback buffer */ 367 | /* */ 368 | /* Outputs: the buffer will be filled with n bytes of audio - no return val */ 369 | /* */ 370 | /*****************************************************************************/ 371 | ITCM_CODE void Pokey_process(void *sndbuffer, unsigned sndn) 372 | { 373 | register char *buffer = (char *) sndbuffer; 374 | register uint16 n = sndn; 375 | 376 | register uint32 *div_n_ptr; 377 | register uint8 *samp_cnt_w_ptr; 378 | register uint32 event_min; 379 | register uint8 next_event; 380 | register unsigned char cur_val; /* otherwise we'll simplify as 8-bit unsigned */ 381 | register uint8 *out_ptr; 382 | register uint8 audc; 383 | register uint8 toggle; 384 | register uint8 *vol_ptr; 385 | 386 | /* set a pointer to the whole portion of the samp_n_cnt */ 387 | samp_cnt_w_ptr = ((uint8 *) (&Samp_n_cnt[0]) + 1); 388 | 389 | /* set a pointer for optimization */ 390 | out_ptr = Outvol; 391 | vol_ptr = AUDV; 392 | 393 | /* The current output is pre-determined and then adjusted based on each */ 394 | /* output change for increased performance (less over-all math). */ 395 | /* add the output values of all 4 channels */ 396 | cur_val = SAMP_MIN; 397 | if (*out_ptr++) cur_val += *vol_ptr; 398 | vol_ptr++; 399 | 400 | if (*out_ptr++) cur_val += *vol_ptr; 401 | vol_ptr++; 402 | 403 | if (*out_ptr++) cur_val += *vol_ptr; 404 | vol_ptr++; 405 | 406 | if (*out_ptr++) cur_val += *vol_ptr; 407 | vol_ptr++; 408 | 409 | /* loop until the buffer is filled */ 410 | while (n) 411 | { 412 | /* Normally the routine would simply decrement the 'div by N' */ 413 | /* counters and react when they reach zero. Since we normally */ 414 | /* won't be processing except once every 80 or so counts, */ 415 | /* I've optimized by finding the smallest count and then */ 416 | /* 'accelerated' time by adjusting all pointers by that amount. */ 417 | 418 | /* find next smallest event (either sample or chan 1-4) */ 419 | next_event = SAMPLE; 420 | event_min = READ_U32(samp_cnt_w_ptr); 421 | 422 | div_n_ptr = Div_n_cnt; 423 | 424 | /* Though I could have used a loop here, this is faster */ 425 | if (*div_n_ptr <= event_min) { 426 | event_min = *div_n_ptr; 427 | next_event = CHAN1; 428 | } 429 | div_n_ptr++; 430 | if (*div_n_ptr <= event_min) { 431 | event_min = *div_n_ptr; 432 | next_event = CHAN2; 433 | } 434 | div_n_ptr++; 435 | if (*div_n_ptr <= event_min) { 436 | event_min = *div_n_ptr; 437 | next_event = CHAN3; 438 | } 439 | div_n_ptr++; 440 | if (*div_n_ptr <= event_min) { 441 | event_min = *div_n_ptr; 442 | next_event = CHAN4; 443 | } 444 | div_n_ptr++; 445 | 446 | /* if the next event is a channel change */ 447 | if (next_event != SAMPLE) { 448 | /* shift the polynomial counters */ 449 | 450 | /* decrement all counters by the smallest count found */ 451 | /* again, no loop for efficiency */ 452 | div_n_ptr--; 453 | *div_n_ptr -= event_min; 454 | div_n_ptr--; 455 | *div_n_ptr -= event_min; 456 | div_n_ptr--; 457 | *div_n_ptr -= event_min; 458 | div_n_ptr--; 459 | *div_n_ptr -= event_min; 460 | 461 | WRITE_U32(samp_cnt_w_ptr, READ_U32(samp_cnt_w_ptr) - event_min); 462 | 463 | /* since the polynomials require a mod (%) function which is 464 | division, I don't adjust the polynomials on the SAMPLE events, 465 | only the CHAN events. I have to keep track of the change, 466 | though. */ 467 | 468 | P4 = (P4 + event_min) % POLY4_SIZE; 469 | P5 = (P5 + event_min) % POLY5_SIZE; 470 | P9 = (P9 + event_min) % POLY9_SIZE; 471 | P17 = (P17 + event_min) % POLY17_SIZE; 472 | 473 | /* adjust channel counter */ 474 | Div_n_cnt[next_event] += Div_n_max[next_event]; 475 | 476 | /* get the current AUDC into a register (for optimization) */ 477 | audc = AUDC[next_event]; 478 | 479 | /* set a pointer to the current output (for opt...) */ 480 | out_ptr = &Outvol[next_event]; 481 | 482 | /* assume no changes to the output */ 483 | toggle = FALSE; 484 | 485 | /* From here, a good understanding of the hardware is required */ 486 | /* to understand what is happening. I won't be able to provide */ 487 | /* much description to explain it here. */ 488 | 489 | /* if VOLUME only then nothing to process */ 490 | if (!(audc & VOL_ONLY)) { 491 | /* if the output is pure or the output is poly5 and the poly5 bit */ 492 | /* is set */ 493 | if ((audc & NOTPOLY5) || bit5[P5]) { 494 | /* if the PURETONE bit is set */ 495 | if (audc & PURETONE) { 496 | /* then simply toggle the output */ 497 | toggle = TRUE; 498 | } 499 | /* otherwise if POLY4 is selected */ 500 | else if (audc & POLY4) { 501 | /* then compare to the poly4 bit */ 502 | toggle = (bit4[P4] == !(*out_ptr)); 503 | } 504 | else { 505 | /* if 9-bit poly is selected on this chip */ 506 | if (AUDCTL[next_event >> 2] & POLY9) { 507 | /* compare to the poly9 bit */ 508 | toggle = ((poly9_lookup[P9] & 1) == !(*out_ptr)); 509 | } 510 | else { 511 | /* otherwise compare to the poly17 bit */ 512 | toggle = (((poly17_lookup[P17 >> 3] >> (P17 & 7)) & 1) == !(*out_ptr)); 513 | } 514 | } 515 | } 516 | } 517 | 518 | /* check channel 1 filter (clocked by channel 3) */ 519 | if ( AUDCTL[next_event >> 2] & CH1_FILTER) { 520 | /* if we're processing channel 3 */ 521 | if ((next_event & 0x03) == CHAN3) { 522 | /* check output of channel 1 on same chip */ 523 | if (Outvol[next_event & 0xfd]) { 524 | /* if on, turn it off */ 525 | Outvol[next_event & 0xfd] = 0; 526 | cur_val -= AUDV[next_event & 0xfd]; 527 | } 528 | } 529 | } 530 | 531 | /* check channel 2 filter (clocked by channel 4) */ 532 | if ( AUDCTL[next_event >> 2] & CH2_FILTER) { 533 | /* if we're processing channel 4 */ 534 | if ((next_event & 0x03) == CHAN4) { 535 | /* check output of channel 2 on same chip */ 536 | if (Outvol[next_event & 0xfd]) { 537 | /* if on, turn it off */ 538 | Outvol[next_event & 0xfd] = 0; 539 | cur_val -= AUDV[next_event & 0xfd]; 540 | } 541 | } 542 | } 543 | 544 | /* if the current output bit has changed */ 545 | if (toggle) { 546 | if (*out_ptr) { 547 | /* remove this channel from the signal */ 548 | cur_val -= AUDV[next_event]; 549 | 550 | /* and turn the output off */ 551 | *out_ptr = 0; 552 | } 553 | else { 554 | /* turn the output on */ 555 | *out_ptr = 1; 556 | 557 | /* and add it to the output signal */ 558 | cur_val += AUDV[next_event]; 559 | } 560 | } 561 | } 562 | else { /* otherwise we're processing a sample */ 563 | /* adjust the sample counter - note we're using the 24.8 integer 564 | which includes an 8 bit fraction for accuracy */ 565 | int iout; 566 | iout = cur_val; 567 | *buffer++ = (char) ((iout))+128; 568 | *Samp_n_cnt += Samp_n_max; 569 | /* and indicate one less byte in the buffer */ 570 | n--; 571 | } 572 | } 573 | } 574 | 575 | -------------------------------------------------------------------------------- /arm9/source/emu/pokeysnd.h: -------------------------------------------------------------------------------- 1 | /*****************************************************************************/ 2 | /* */ 3 | /* Module: POKEY Chip Simulator Includes, V2.3 */ 4 | /* Purpose: To emulate the sound generation hardware of the Atari POKEY chip. */ 5 | /* Author: Ron Fries */ 6 | /* */ 7 | /* Revision History: */ 8 | /* */ 9 | /* 09/22/96 - Ron Fries - Initial Release */ 10 | /* 04/06/97 - Brad Oliver - Some cross-platform modifications. Added */ 11 | /* big/little endian #defines, removed , */ 12 | /* conditional defines for TRUE/FALSE */ 13 | /* 01/19/98 - Ron Fries - Changed signed/unsigned sample support to a */ 14 | /* compile-time option. Defaults to unsigned - */ 15 | /* define SIGNED_SAMPLES to create signed. */ 16 | /* */ 17 | /*****************************************************************************/ 18 | /* */ 19 | /* License Information and Copyright Notice */ 20 | /* ======================================== */ 21 | /* */ 22 | /* PokeySound is Copyright(c) 1996-1998 by Ron Fries */ 23 | /* */ 24 | /* This library is free software; you can redistribute it and/or modify it */ 25 | /* under the terms of version 2 of the GNU Library General Public License */ 26 | /* as published by the Free Software Foundation. */ 27 | /* */ 28 | /* This library is distributed in the hope that it will be useful, but */ 29 | /* WITHOUT ANY WARRANTY; without even the implied warranty of */ 30 | /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library */ 31 | /* General Public License for more details. */ 32 | /* To obtain a copy of the GNU Library General Public License, write to the */ 33 | /* Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ 34 | /* */ 35 | /* Any permitted reproduction of these routines, in whole or in part, must */ 36 | /* bear this legend. */ 37 | /* */ 38 | /*****************************************************************************/ 39 | 40 | #ifndef _POKEYSOUND_H 41 | #define _POKEYSOUND_H 42 | 43 | #include "config.h" 44 | #include "pokey.h" 45 | 46 | #ifndef _TYPEDEF_H 47 | #define _TYPEDEF_H 48 | 49 | /* define some data types to keep it platform independent */ 50 | #ifdef COMP16 /* if 16-bit compiler defined */ 51 | #define int8 char 52 | #define int16 int 53 | #define int32 long 54 | #else /* else default to 32-bit compiler */ 55 | #define int8 char 56 | #define int16 short 57 | #define int32 int 58 | #endif 59 | 60 | #define uint8 unsigned int8 61 | #define uint16 unsigned int16 62 | #define uint32 unsigned int32 63 | 64 | #endif 65 | 66 | /* CONSTANT DEFINITIONS */ 67 | 68 | /* As an alternative to using the exact frequencies, selecting a playback 69 | frequency that is an exact division of the main clock provides a higher 70 | quality output due to less aliasing. For best results, a value of 71 | 1787520 MHz is used for the main clock. With this value, both the 72 | 64 kHz and 15 kHz clocks are evenly divisible. Selecting a playback 73 | frequency that is also a division of the clock provides the best 74 | results. The best options are FREQ_64 divided by either 2, 3, or 4. 75 | The best selection is based on a trade off between performance and 76 | sound quality. 77 | 78 | Of course, using a main clock frequency that is not exact will affect 79 | the pitch of the output. With these numbers, the pitch will be low 80 | by 0.127%. (More than likely, an actual unit will vary by this much!) */ 81 | 82 | #define FREQ_17_EXACT 1789790 /* exact 1.79 MHz clock freq */ 83 | #define FREQ_17_APPROX 1787520 /* approximate 1.79 MHz clock freq */ 84 | 85 | #ifdef __cplusplus 86 | extern "C" { 87 | #endif 88 | 89 | //#define SIGNED_SAMPLES /* define for signed output */ 90 | 91 | #ifdef SIGNED_SAMPLES /* if signed output selected */ 92 | #define SAMP_MAX 127 /* then set signed 8-bit clipping ranges */ 93 | #define SAMP_MIN -128 94 | #define SAMP_MID 0 95 | #else 96 | #define SAMP_MAX 255 /* else set unsigned 8-bit clip ranges */ 97 | #define SAMP_MIN 0 98 | #define SAMP_MID 128 99 | #endif 100 | 101 | /* init flags */ 102 | #define SND_BIT16 1 103 | #define SND_STEREO 2 104 | 105 | extern int32 snd_playback_freq; 106 | extern uint8 snd_num_pokeys; 107 | 108 | extern int enable_new_pokey; 109 | extern int stereo_enabled; 110 | extern int serio_sound_enabled; 111 | extern int console_sound_enabled; 112 | 113 | extern void (*Pokey_process_ptr)(void *sndbuffer, unsigned int sndn); 114 | extern void (*Update_pokey_sound)(uint16 addr, uint8 val, uint8 /*chip*/, uint8 gain); 115 | extern void (*Update_serio_sound)(int out, UBYTE data); 116 | extern void (*Update_consol_sound)(int set); 117 | 118 | int Pokey_sound_init(uint32 freq17, uint16 playback_freq, uint8 num_pokeys, 119 | unsigned int flags 120 | ); 121 | void Pokey_process(void *sndbuffer, unsigned int sndn); 122 | int Pokey_DoInit(void); 123 | void Pokey_set_mzquality(int quality); 124 | 125 | #ifdef __cplusplus 126 | } 127 | 128 | #endif 129 | #endif 130 | -------------------------------------------------------------------------------- /arm9/source/highscore.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "a5200utils.h" 7 | #include "highscore.h" 8 | #include "cartridge.h" 9 | #include "bgHighScore.h" 10 | #include "bgBottom.h" 11 | #include "printf.h" 12 | 13 | #define MAX_HS_GAMES 500 14 | #define HS_VERSION 0x0001 15 | 16 | #define HS_OPT_SORTMASK 0x0003 17 | #define HS_OPT_SORTLOW 0x0001 18 | #define HS_OPT_SORTTIME 0x0002 19 | #define HS_OPT_SORTASCII 0x0003 20 | 21 | #pragma pack(1) 22 | 23 | struct score_t 24 | { 25 | char initials[4]; 26 | char score[7]; 27 | char reserved[5]; 28 | uint16 year; 29 | uint8 month; 30 | uint8 day; 31 | }; 32 | 33 | struct highscore_t 34 | { 35 | char md5sum[33]; 36 | char notes[21]; 37 | uint16 options; 38 | struct score_t scores[10]; 39 | }; 40 | 41 | struct highscore_full_t 42 | { 43 | uint16 version; 44 | char last_initials[4]; 45 | struct highscore_t highscore_table[MAX_HS_GAMES]; 46 | uint32 checksum; 47 | } highscores; 48 | 49 | 50 | extern int bg0, bg0b,bg1b; 51 | 52 | 53 | uint32 highscore_checksum(void) 54 | { 55 | char *ptr = (char *)&highscores; 56 | uint32 sum = 0; 57 | 58 | for (int i=0; i<(int)sizeof(highscores) - 4; i++) 59 | { 60 | sum = *ptr++; 61 | } 62 | return sum; 63 | } 64 | 65 | void highscore_init(void) 66 | { 67 | bool create_defaults = 0; 68 | FILE *fp; 69 | 70 | strcpy(highscores.last_initials, " "); 71 | 72 | // -------------------------------------------------------------- 73 | // See if the a5200 high score file exists... if so, read it! 74 | // -------------------------------------------------------------- 75 | fp = fopen("/data/a5200.hi", "rb"); 76 | if (fp != NULL) 77 | { 78 | fread(&highscores, sizeof(highscores), 1, fp); 79 | fclose(fp); 80 | 81 | if (highscores.version != HS_VERSION) create_defaults = 1; 82 | if (highscore_checksum() != highscores.checksum) create_defaults = 1; 83 | } 84 | else 85 | { 86 | create_defaults = 1; 87 | } 88 | 89 | if (create_defaults) // Doesn't exist yet or is invalid... create defaults and save it... 90 | { 91 | strcpy(highscores.last_initials, " "); 92 | 93 | for (int i=0; i 0) 234 | { 235 | // Swap... 236 | memcpy(&score_entry, &highscores.highscore_table[foundIdx].scores[j], sizeof(score_entry)); 237 | memcpy(&highscores.highscore_table[foundIdx].scores[j], &highscores.highscore_table[foundIdx].scores[j+1], sizeof(score_entry)); 238 | memcpy(&highscores.highscore_table[foundIdx].scores[j+1], &score_entry, sizeof(score_entry)); 239 | } 240 | } 241 | else 242 | { 243 | if (strcmp(highscores.highscore_table[foundIdx].scores[j+1].score, highscores.highscore_table[foundIdx].scores[j].score) > 0) 244 | { 245 | // Swap... 246 | memcpy(&score_entry, &highscores.highscore_table[foundIdx].scores[j], sizeof(score_entry)); 247 | memcpy(&highscores.highscore_table[foundIdx].scores[j], &highscores.highscore_table[foundIdx].scores[j+1], sizeof(score_entry)); 248 | memcpy(&highscores.highscore_table[foundIdx].scores[j+1], &score_entry, sizeof(score_entry)); 249 | } 250 | } 251 | } 252 | } 253 | } 254 | 255 | void highscore_entry(short foundIdx) 256 | { 257 | char bEntryDone = 0; 258 | char blink=0; 259 | unsigned short entry_idx=0; 260 | char dampen=0; 261 | time_t unixTime = time(NULL); 262 | struct tm* timeStruct = gmtime((const time_t *)&unixTime); 263 | 264 | dsPrintValue(3,20,0, (char*)"UP/DN/LEFT/RIGHT ENTER SCORE"); 265 | dsPrintValue(3,21,0, (char*)"PRESS START TO SAVE SCORE "); 266 | dsPrintValue(3,22,0, (char*)"PRESS SELECT TO CANCEL "); 267 | dsPrintValue(3,23,0, (char*)" "); 268 | 269 | strcpy(score_entry.score, "000000"); 270 | strcpy(score_entry.initials, highscores.last_initials); 271 | score_entry.year = timeStruct->tm_year +1900; 272 | score_entry.month = timeStruct->tm_mon+1; 273 | score_entry.day = timeStruct->tm_mday; 274 | while (!bEntryDone) 275 | { 276 | swiWaitForVBlank(); 277 | if (keysCurrent() & KEY_SELECT) {bEntryDone=1;} 278 | 279 | if (keysCurrent() & KEY_START) 280 | { 281 | strcpy(highscores.last_initials, score_entry.initials); 282 | memcpy(&highscores.highscore_table[foundIdx].scores[9], &score_entry, sizeof(score_entry)); 283 | strcpy(highscores.highscore_table[foundIdx].md5sum, md5); 284 | highscore_sort(foundIdx); 285 | highscore_save(); 286 | bEntryDone=1; 287 | } 288 | 289 | if (dampen == 0) 290 | { 291 | if ((keysCurrent() & KEY_RIGHT) || (keysCurrent() & KEY_A)) 292 | { 293 | if (entry_idx < 8) entry_idx++; 294 | blink=25; 295 | dampen=15; 296 | } 297 | 298 | if (keysCurrent() & KEY_LEFT) 299 | { 300 | if (entry_idx > 0) entry_idx--; 301 | blink=25; 302 | dampen=15; 303 | } 304 | 305 | if (keysCurrent() & KEY_UP) 306 | { 307 | if (entry_idx < 3) // This is the initials 308 | { 309 | if (score_entry.initials[entry_idx] == ' ') 310 | score_entry.initials[entry_idx] = 'A'; 311 | else if (score_entry.initials[entry_idx] == 'Z') 312 | score_entry.initials[entry_idx] = ' '; 313 | else score_entry.initials[entry_idx]++; 314 | } 315 | else // This is the score... 316 | { 317 | if ((highscores.highscore_table[foundIdx].options & HS_OPT_SORTMASK) == HS_OPT_SORTASCII) 318 | { 319 | if (score_entry.score[entry_idx-3] == ' ') 320 | score_entry.score[entry_idx-3] = 'A'; 321 | else if (score_entry.score[entry_idx-3] == 'Z') 322 | score_entry.score[entry_idx-3] = '0'; 323 | else if (score_entry.score[entry_idx-3] == '9') 324 | score_entry.score[entry_idx-3] = ' '; 325 | else score_entry.score[entry_idx-3]++; 326 | } 327 | else 328 | { 329 | score_entry.score[entry_idx-3]++; 330 | if (score_entry.score[entry_idx-3] > '9') score_entry.score[entry_idx-3] = '0'; 331 | } 332 | } 333 | blink=0; 334 | dampen=10; 335 | } 336 | 337 | if (keysCurrent() & KEY_DOWN) 338 | { 339 | if (entry_idx < 3) // // This is the initials 340 | { 341 | if (score_entry.initials[entry_idx] == ' ') 342 | score_entry.initials[entry_idx] = 'Z'; 343 | else if (score_entry.initials[entry_idx] == 'A') 344 | score_entry.initials[entry_idx] = ' '; 345 | else score_entry.initials[entry_idx]--; 346 | } 347 | else // This is the score... 348 | { 349 | if ((highscores.highscore_table[foundIdx].options & HS_OPT_SORTMASK) == HS_OPT_SORTASCII) 350 | { 351 | if (score_entry.score[entry_idx-3] == ' ') 352 | score_entry.score[entry_idx-3] = '9'; 353 | else if (score_entry.score[entry_idx-3] == '0') 354 | score_entry.score[entry_idx-3] = 'Z'; 355 | else if (score_entry.score[entry_idx-3] == 'A') 356 | score_entry.score[entry_idx-3] = ' '; 357 | else score_entry.score[entry_idx-3]--; 358 | } 359 | else 360 | { 361 | score_entry.score[entry_idx-3]--; 362 | if (score_entry.score[entry_idx-3] < '0') score_entry.score[entry_idx-3] = '9'; 363 | } 364 | } 365 | blink=0; 366 | dampen=10; 367 | } 368 | } 369 | else 370 | { 371 | dampen--; 372 | } 373 | 374 | sprintf(hs_line, "%04d-%02d-%02d %-3s %-6s", score_entry.year, score_entry.month, score_entry.day, score_entry.initials, score_entry.score); 375 | if ((++blink % 60) > 30) 376 | { 377 | if (entry_idx < 3) 378 | hs_line[13+entry_idx] = '_'; 379 | else 380 | hs_line[16+entry_idx] = '_'; 381 | } 382 | dsPrintValue(3,17, 0, (char*)hs_line); 383 | } 384 | 385 | show_scores(foundIdx, true); 386 | } 387 | 388 | void highscore_options(short foundIdx, char *md5) 389 | { 390 | uint16 options = 0x0000; 391 | static char notes[21]; 392 | char bEntryDone = 0; 393 | char blink=0; 394 | unsigned short entry_idx=0; 395 | char dampen=0; 396 | 397 | dsPrintValue(3,20,0, (char*)"UP/DN/LEFT/RIGHT ENTER NOTES"); 398 | dsPrintValue(3,21,0, (char*)"X=TOGGLE SORT, L+R=CLR SCORE"); 399 | dsPrintValue(3,22,0, (char*)"PRESS START TO SAVE OPTIONS "); 400 | dsPrintValue(3,23,0, (char*)"PRESS SELECT TO CANCEL "); 401 | dsPrintValue(3,17,0, (char*)"NOTE: "); 402 | 403 | strcpy(notes, highscores.highscore_table[foundIdx].notes); 404 | options = highscores.highscore_table[foundIdx].options; 405 | 406 | while (!bEntryDone) 407 | { 408 | swiWaitForVBlank(); 409 | if (keysCurrent() & KEY_SELECT) {bEntryDone=1;} 410 | 411 | if (keysCurrent() & KEY_START) 412 | { 413 | strcpy(highscores.highscore_table[foundIdx].notes, notes); 414 | highscores.highscore_table[foundIdx].options = options; 415 | strcpy(highscores.highscore_table[foundIdx].md5sum, md5); 416 | highscore_sort(foundIdx); 417 | highscore_save(); 418 | bEntryDone=1; 419 | } 420 | 421 | if (dampen == 0) 422 | { 423 | if ((keysCurrent() & KEY_RIGHT) || (keysCurrent() & KEY_A)) 424 | { 425 | if (entry_idx < 19) entry_idx++; 426 | blink=25; 427 | dampen=15; 428 | } 429 | 430 | if (keysCurrent() & KEY_LEFT) 431 | { 432 | if (entry_idx > 0) entry_idx--; 433 | blink=25; 434 | dampen=15; 435 | } 436 | 437 | if (keysCurrent() & KEY_UP) 438 | { 439 | if (notes[entry_idx] == ' ') 440 | notes[entry_idx] = 'A'; 441 | else if (notes[entry_idx] == 'Z') 442 | notes[entry_idx] = '0'; 443 | else if (notes[entry_idx] == '9') 444 | notes[entry_idx] = ' '; 445 | else notes[entry_idx]++; 446 | blink=0; 447 | dampen=10; 448 | } 449 | 450 | if (keysCurrent() & KEY_DOWN) 451 | { 452 | if (notes[entry_idx] == ' ') 453 | notes[entry_idx] = '9'; 454 | else if (notes[entry_idx] == '0') 455 | notes[entry_idx] = 'Z'; 456 | else if (notes[entry_idx] == 'A') 457 | notes[entry_idx] = ' '; 458 | else notes[entry_idx]--; 459 | blink=0; 460 | dampen=10; 461 | } 462 | 463 | if (keysCurrent() & KEY_X) 464 | { 465 | if ((options & HS_OPT_SORTMASK) == HS_OPT_SORTLOW) 466 | { 467 | options &= (uint16)~HS_OPT_SORTMASK; 468 | options |= HS_OPT_SORTTIME; 469 | } 470 | else if ((options & HS_OPT_SORTMASK) == HS_OPT_SORTTIME) 471 | { 472 | options &= (uint16)~HS_OPT_SORTMASK; 473 | options |= HS_OPT_SORTASCII; 474 | } 475 | else if ((options & HS_OPT_SORTMASK) == HS_OPT_SORTASCII) 476 | { 477 | options &= (uint16)~HS_OPT_SORTMASK; 478 | } 479 | else 480 | { 481 | options |= (uint16)HS_OPT_SORTLOW; 482 | } 483 | highscore_showoptions(options); 484 | dampen=15; 485 | } 486 | 487 | // Clear the entire game of scores... 488 | if ((keysCurrent() & KEY_L) && (keysCurrent() & KEY_R)) 489 | { 490 | strcpy(highscores.highscore_table[foundIdx].md5sum, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"); 491 | highscores.highscore_table[foundIdx].options = 0x0000; 492 | strcpy(highscores.highscore_table[foundIdx].notes, " "); 493 | strcpy(notes, " "); 494 | for (int j=0; j<10; j++) 495 | { 496 | strcpy(highscores.highscore_table[foundIdx].scores[j].score, "000000"); 497 | strcpy(highscores.highscore_table[foundIdx].scores[j].initials, " "); 498 | strcpy(highscores.highscore_table[foundIdx].scores[j].reserved, " "); 499 | highscores.highscore_table[foundIdx].scores[j].year = 0; 500 | highscores.highscore_table[foundIdx].scores[j].month = 0; 501 | highscores.highscore_table[foundIdx].scores[j].day = 0; 502 | } 503 | show_scores(foundIdx, false); 504 | highscore_save(); 505 | } 506 | } 507 | else 508 | { 509 | dampen--; 510 | } 511 | 512 | sprintf(hs_line, "%-20s", notes); 513 | if ((++blink % 60) > 30) 514 | { 515 | hs_line[entry_idx] = '_'; 516 | } 517 | dsPrintValue(9,17, 0, (char*)hs_line); 518 | } 519 | 520 | show_scores(foundIdx, true); 521 | } 522 | 523 | void highscore_display(void) 524 | { 525 | short foundIdx = -1; 526 | short firstBlank = -1; 527 | char bDone = 0; 528 | 529 | decompress(bgHighScoreTiles, bgGetGfxPtr(bg0b), LZ77Vram); 530 | decompress(bgHighScoreMap, (void*) bgGetMapPtr(bg0b), LZ77Vram); 531 | dmaCopy((void *) bgHighScorePal,(u16*) BG_PALETTE_SUB,256*2); 532 | unsigned short dmaVal = *(bgGetMapPtr(bg1b) +31*32); 533 | dmaFillWords(dmaVal | (dmaVal<<16),(void*) bgGetMapPtr(bg1b),32*24*2); 534 | swiWaitForVBlank(); 535 | 536 | // --------------------------------------------------------------------------------- 537 | // Get the current CART md5 so we can search for it in our High Score database... 538 | // --------------------------------------------------------------------------------- 539 | strcpy(md5, myCart.md5); 540 | for (int i=0; i 5 | 6 | #include "cartridge.h" 7 | 8 | extern void highscore_init(void); 9 | extern void highscore_save(void); 10 | extern void highscore_display(void); 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /arm9/source/intro.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "a5200utils.h" 5 | 6 | #include "mus_intro_wav.h" 7 | #include "pdev_tbg0.h" 8 | #include "pdev_bg0.h" 9 | 10 | volatile u16 vusCptVBL; 11 | 12 | void vblankIntro() 13 | { 14 | vusCptVBL++; 15 | } 16 | 17 | // Intro with portabledev logo 18 | void intro_logo(void) { 19 | int soundId=-1; 20 | char bOK; 21 | 22 | // Init graphics 23 | videoSetMode(MODE_0_2D | DISPLAY_BG0_ACTIVE ); 24 | videoSetModeSub(MODE_0_2D | DISPLAY_BG0_ACTIVE ); 25 | vramSetBankA(VRAM_A_MAIN_BG); vramSetBankC(VRAM_C_SUB_BG); 26 | irqSet(IRQ_VBLANK, vblankIntro); 27 | irqEnable(IRQ_VBLANK); 28 | 29 | // Init BG 30 | int bg1 = bgInit(0, BgType_Text8bpp, BgSize_T_256x256, 31,0); 31 | 32 | // Init sub BG 33 | int bg1s = bgInitSub(0, BgType_Text8bpp, BgSize_T_256x256, 31,0); 34 | 35 | REG_BLDCNT = BLEND_FADE_BLACK | BLEND_SRC_BG0 | BLEND_DST_BG0; REG_BLDY = 16; 36 | REG_BLDCNT_SUB = BLEND_FADE_BLACK | BLEND_SRC_BG0 | BLEND_DST_BG0; REG_BLDY_SUB = 16; 37 | 38 | // Show portabledev 39 | decompress(pdev_tbg0Tiles, bgGetGfxPtr(bg1), LZ77Vram); 40 | decompress(pdev_tbg0Map, (void*) bgGetMapPtr(bg1), LZ77Vram); 41 | dmaCopy((void *) pdev_tbg0Pal,(u16*) BG_PALETTE,256*2); 42 | 43 | decompress(pdev_bg0Tiles, bgGetGfxPtr(bg1s), LZ77Vram); 44 | decompress(pdev_bg0Map, (void*) bgGetMapPtr(bg1s), LZ77Vram); 45 | dmaCopy((void *) pdev_bg0Pal,(u16*) BG_PALETTE_SUB,256*2); 46 | 47 | FadeToColor(0,BLEND_FADE_BLACK | BLEND_SRC_BG0 | BLEND_DST_BG0,3,0,3); 48 | 49 | soundId = soundPlaySample((const void *) mus_intro_wav, SoundFormat_ADPCM, mus_intro_wav_size, 22050, 127, 64, false, 0); 50 | 51 | bOK=false; 52 | while (!bOK) { if ( !(keysCurrent() & 0x1FFF) ) bOK=true; } // 0x1FFF = key or pen 53 | vusCptVBL=0;bOK=false; 54 | while (!bOK && (vusCptVBL<3*60)) { if (keysCurrent() & 0x1FFF ) bOK=true; } 55 | bOK=false; 56 | while (!bOK) { if ( !(keysCurrent() & 0x1FFF) ) bOK=true; } 57 | 58 | FadeToColor(1,BLEND_FADE_WHITE | BLEND_SRC_BG0 | BLEND_DST_BG0,3,16,3); 59 | if (soundId!=-1) soundKill(soundId); 60 | } 61 | -------------------------------------------------------------------------------- /arm9/source/intro.h: -------------------------------------------------------------------------------- 1 | #ifndef _INTRO_H 2 | #define _INTRO_H 3 | 4 | extern void intro_logo(void); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /arm9/source/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "main.h" 8 | #include "intro.h" 9 | #include "atari.h" 10 | #include "a5200utils.h" 11 | #include "highscore.h" 12 | #include "printf.h" 13 | 14 | extern int bg0, bg1; 15 | 16 | extern int load_os(); 17 | 18 | // Program entry point 19 | int main(int argc, char **argv) 20 | { 21 | extern void MEMORY_InitialiseMap(void); 22 | MEMORY_InitialiseMap(); 23 | 24 | // Init sound 25 | consoleDemoInit(); 26 | soundEnable(); 27 | lcdMainOnTop(); 28 | 29 | // Init Fat 30 | if (!fatInitDefault()) { 31 | iprintf("Unable to initialize libfat!\n"); 32 | return -1; 33 | } 34 | 35 | // Init Timer 36 | dsInitTimer(); 37 | dsInstallSoundEmuFIFO(); 38 | highscore_init(); 39 | 40 | // Intro and main screen 41 | intro_logo(); 42 | dsInitScreenMain(); 43 | etatEmu = A5200_MENUINIT; 44 | 45 | srand(time(NULL)); 46 | 47 | if (!load_os()) // Should never fail as we have fallback Altira BIOS 48 | { 49 | //load rom file via args if a rom path is supplied 50 | if(argc > 1) 51 | { 52 | dsShowScreenMain(); 53 | dsLoadGame(argv[1]); 54 | Atari800_Initialise(); 55 | etatEmu = A5200_PLAYINIT; 56 | } 57 | else 58 | { 59 | chdir("/roms"); // Try to start in roms area... doesn't matter if it fails 60 | chdir("a5200"); // And try to start in the subdir /a5200... doesn't matter if it fails. 61 | } 62 | // Main loop of emulation 63 | dsMainLoop(); 64 | } 65 | else { 66 | dsShowScreenMain(); 67 | dsPrintValue(0,0,0, "Can't find 5200.rom BIOS"); 68 | dsReadPad(); 69 | } 70 | 71 | // Free memory to be correct 72 | dsFreeEmu(); 73 | 74 | return(0); 75 | } 76 | -------------------------------------------------------------------------------- /arm9/source/main.h: -------------------------------------------------------------------------------- 1 | #ifndef _MAIN_H 2 | #define _MAIN_H 3 | 4 | #include 5 | 6 | #define EMU_INIT 1 7 | #define EMU_END 2 8 | 9 | extern int bg0, bg1, bg2, bg3; // BG pointers 10 | extern int bg0s, bg1s, bg2s, bg3s; // sub BG pointers 11 | 12 | extern volatile u16 vusCptVBL; // VBL test 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /arm9/source/printf.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // \author (c) Marco Paland (info@paland.com) 3 | // 2014-2019, PALANDesign Hannover, Germany 4 | // 5 | // \license The MIT License (MIT) 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | // THE SOFTWARE. 24 | // 25 | // \brief Tiny printf, sprintf and snprintf implementation, optimized for speed on 26 | // embedded systems with a very limited resources. 27 | // Use this instead of bloated standard/newlib printf. 28 | // These routines are thread safe and reentrant. 29 | // 30 | /////////////////////////////////////////////////////////////////////////////// 31 | 32 | #ifndef _PRINTF_H_ 33 | #define _PRINTF_H_ 34 | 35 | #include 36 | #include 37 | 38 | 39 | #ifdef __cplusplus 40 | extern "C" { 41 | #endif 42 | 43 | #define PRINTF_DISABLE_SUPPORT_FLOAT 44 | #define PRINTF_DISABLE_SUPPORT_EXPONENTIAL 45 | #define PRINTF_DISABLE_SUPPORT_LONG_LONG 46 | #define PRINTF_DISABLE_SUPPORT_PTRDIFF_T 47 | 48 | /** 49 | * Output a character to a custom device like UART, used by the printf() function 50 | * This function is declared here only. You have to write your custom implementation somewhere 51 | * \param character Character to output 52 | */ 53 | void _putchar(char character); 54 | 55 | 56 | /** 57 | * Tiny printf implementation 58 | * You have to implement _putchar if you use printf() 59 | * To avoid conflicts with the regular printf() API it is overridden by macro defines 60 | * and internal underscore-appended functions like printf_() are used 61 | * \param format A string that specifies the format of the output 62 | * \return The number of characters that are written into the array, not counting the terminating null character 63 | */ 64 | #define printf printf_ 65 | int printf_(const char* format, ...); 66 | 67 | 68 | /** 69 | * Tiny sprintf implementation 70 | * Due to security reasons (buffer overflow) YOU SHOULD CONSIDER USING (V)SNPRINTF INSTEAD! 71 | * \param buffer A pointer to the buffer where to store the formatted string. MUST be big enough to store the output! 72 | * \param format A string that specifies the format of the output 73 | * \return The number of characters that are WRITTEN into the buffer, not counting the terminating null character 74 | */ 75 | #define sprintf sprintf_ 76 | int sprintf_(char* buffer, const char* format, ...); 77 | 78 | 79 | /** 80 | * Tiny snprintf/vsnprintf implementation 81 | * \param buffer A pointer to the buffer where to store the formatted string 82 | * \param count The maximum number of characters to store in the buffer, including a terminating null character 83 | * \param format A string that specifies the format of the output 84 | * \param va A value identifying a variable arguments list 85 | * \return The number of characters that COULD have been written into the buffer, not counting the terminating 86 | * null character. A value equal or larger than count indicates truncation. Only when the returned value 87 | * is non-negative and less than count, the string has been completely written. 88 | */ 89 | #define snprintf snprintf_ 90 | #define vsnprintf vsnprintf_ 91 | int snprintf_(char* buffer, size_t count, const char* format, ...); 92 | int vsnprintf_(char* buffer, size_t count, const char* format, va_list va); 93 | 94 | 95 | /** 96 | * Tiny vprintf implementation 97 | * \param format A string that specifies the format of the output 98 | * \param va A value identifying a variable arguments list 99 | * \return The number of characters that are WRITTEN into the buffer, not counting the terminating null character 100 | */ 101 | #define vprintf vprintf_ 102 | int vprintf_(const char* format, va_list va); 103 | 104 | 105 | /** 106 | * printf with output function 107 | * You may use this as dynamic alternative to printf() with its fixed _putchar() output 108 | * \param out An output function which takes one character and an argument pointer 109 | * \param arg An argument pointer for user data passed to output function 110 | * \param format A string that specifies the format of the output 111 | * \return The number of characters that are sent to the output function, not counting the terminating null character 112 | */ 113 | int fctprintf(void (*out)(char character, void* arg), void* arg, const char* format, ...); 114 | 115 | 116 | #ifdef __cplusplus 117 | } 118 | #endif 119 | 120 | 121 | #endif // _PRINTF_H_ 122 | -------------------------------------------------------------------------------- /logo.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wavemotion-dave/A5200DS/8f6e3bb302fcedf0cd6a1d19f2b32fb4a53d656d/logo.bmp -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # a5200ds 2 | 3 | a5200ds is an Atari 5200 emulator for the Nintendo DS/DSi/XL/LL 4 | 5 | To use this emulator, you must use NTSC compatible roms with a52/bin format. 6 | You also need the 5200.rom rom bios in the same folder as A5200DS.NDS (alternate 7 | locations it can be: /roms/bios or /data/bios) to use this emulator properly 8 | (there is a built-in open-source replacement BIOS which will work for some 9 | games but doesn't have full compatibilty so it is still strongly recommended 10 | you use 5200.bin). A quick search on google will help you about that. 11 | Do not ask me about such files - you will be ignored. 12 | 13 | ![Atari5200](https://github.com/wavemotion-dave/A5200DS/blob/main/arm9/gfx/bgTop.png) 14 | 15 | Copyright : 16 | ----------------------- 17 | a5200ds is Copyright (c) 2021-2025 Dave Bernazzani (wavemotion-dave) 18 | 19 | This program is built upon alekmaul's magnificent efforts from circa 2011. He was 20 | kind enough to grant me permission to update this emulator for the modern era. 21 | 22 | As long as there is no commercial use (i.e. no profit is made), copying and distribution 23 | of this emulator, its source code and associated readme files, with or without modification, 24 | are permitted in any medium without royalty provided this copyright notice is used 25 | and both alekmaul and wavemotion-dave are thanked profusely. 26 | 27 | The a5200ds emulator is offered as-is, without any warranty. 28 | 29 | Features : 30 | ---------- 31 | * Support for the original 69 commercial releases plus a couple hundred homebrews, hacks and prototypes. 32 | * All games run at full speed on a DSi or above. Most games will run at full speed on the older DS-Lite/Phat (some of the more complex conversions will lag). 33 | * Bankswitching carts up to 512K are supported. Bounty Bob Strikes Back is supported. 34 | * Games like Frogger and Q-Bert auto-patch so the button does not need to be pressed to move/hop. 35 | * Games like Robotron will auto configure twin-sticks so you can use the ABXY buttons to shoot while the d-pad moves. 36 | * 10 high-scores per game is saved to the SD card. 37 | 38 | Known Issues : 39 | --------- 40 | Most things are playing fine on a DSi. Most of the original commercial games (like Missile Command, Space Invaders, Centipede) will generally 41 | run fine on the older DS-LITE or DS-PHAT. 42 | 43 | Check updates on my web site : https://github.com/wavemotion-dave/A5200DS 44 | 45 | History : 46 | -------------------------------------------------------------------------------- 47 | V3.8 : 02-Feb-2025 by wavemotion-dave 48 | * Fixed banking so games like Dropzone properly render lower screen graphics (moonscape). 49 | * Improved 64K banking for games that only sparingly swap banks - these can now use the faster CPU core driver (renders Dropzone and Laser Hawk full speed on older DS-Lite hardware) 50 | * More CPU optimizations to improve speed slightly. 51 | * More games are now running full speed on the DS-Lite - Vanguard is now playable! 52 | * Latest hacks from the A5200 forums on Atariage have been added to the internal database. 53 | 54 | V3.7 : 30-Jan-2025 by wavemotion-dave 55 | * New banking handling so we only move pointers - not blocks of memory. Renders all 5200 Super Banked games playable. 56 | * New NTSC palette from Trebor's Pro Palette (NTSC_LUM1_HOT 5200). 57 | * Added 5200 512K Super Cart banking. 58 | * Improved Pokey emulation (around the random scanline start value - fixes one Acid800 test). 59 | * Improved keypad debounce for Star Raiders. 60 | * Improved sound handling to reduce pops/clicks. Increased the sample rate on the DSi for improved fidelity. 61 | 62 | V3.6 : 08-Jan-2024 by wavemotion-dave 63 | * Internal database updated to include known prototypes, hacks and other sundry 5200 games. 64 | * Codebase cleanup across the board. 65 | * Improved key debounce to fix lots of games including Star Raiders (which has a new overlay). 66 | * Color Artifacting added for the few games that utilize it (Choplifter, etc.) 67 | 68 | V3.5 : 05-Jan-2024 by wavemotion-dave 69 | * Major cleanup across the board - a few more frames of performance and many games on the older DS-Lite will now run full speed without frameskip. 70 | * Touch of paint on the main emulation screen to make the console buttons a bit more prominent. 71 | * New X button handling on the games that utilize more than 192 vertical pixels to smooth scroll upper/lower areas of the screen (usually just status/score in those areas so pressing the X button to bring them momentarily into view works fine). 72 | * About 50 new homebrews and hacks added to the internal database (up to 240 games now). 73 | * Version 3.5a fixes the Star Raiders game and adds a new overlay for it! Fixes for Phobos. A few screen tweaks. Sound pops improved. 74 | 75 | V3.4 : 01-May-2023 by wavemotion-dave 76 | * Another frame or two of performance from memory optmizations. 77 | * Removed lots of obsoleted code to streamline the build. 78 | * Added a new DSi special build that will finally run Bosconian at full speed with speech as long as you are in DSi (2x CPU) mode. 79 | * Added tweaks and support for latest homebrew carts like Rob-N-Banks. 80 | 81 | V3.3 : 30-Apr-2023 by wavemotion-dave 82 | * Improved screen blend so it leaves less visible artifacts. 83 | * Improved sound mute so it eliminates most of the little pops. 84 | * Built with latest libnds to keep things fresh. 85 | * v3.3a hotfix for sound pops. Sorry! 86 | 87 | V3.2 : 12-Dec-2021 by wavemotion-dave 88 | * Reverted back to ARM7 SoundLib (a few games missing key sounds) 89 | 90 | V3.1 : 30-Nov-2021 by wavemotion-dave 91 | * Switched to maxmod audio library for improved sound. 92 | * Try to start in /roms or /roms/a5200 if possible 93 | 94 | V3.0 : 04-Nov-2021 by wavemotion-dave 95 | * New sound core to eliminate zingers. 96 | * 5200.rom bios can be in /roms/bios or /data/bios 97 | 98 | V2.9 : 22-July-2021 by wavemotion-dave 99 | * High Score support added! 100 | * Added swap LCD functionality with L+R+A (hold for 1 sec) 101 | 102 | V2.8 : 20-Mar-2021 by wavemotion-dave 103 | * A fresh coat of paint for the logo and file selection. 104 | * A few minor bugs fixed and cleanup as time permitted. 105 | 106 | V2.7 : 10-Feb-2021 by wavemotion-dave 107 | * Improved FPS timing. 108 | * Added screen scaling (using L/R Shoulder Buttons) from XEGS 109 | * Added Frame Skip for DS-LITE/PHAT to gain speed! 110 | 111 | V2.6 : 23-Jan-2021 by wavemotion-dave 112 | * Squeezed another 2% speedup across the board from memory tweaks. 113 | * Added a few more XL conversions to the compatibility list. 114 | 115 | V2.5 : 12-Jan-2021 by wavemotion-dave 116 | * Hundreds of small pixel tweaks to get all games looking as good as possible. 117 | 118 | V2.4 : 09-Jan-2021 by wavemotion-dave 119 | * More XL Conversions added to the comatibility table. 120 | * More speed tweaks especially in bank switching rendering virtually all games playable at full speed. 121 | 122 | V2.3 : 03-Jan-2021 by wavemotion-dave 123 | * New and imprmoved DTCM and VRAM usage for faster moving of data around the system... 124 | this results in a 10-15% speed improvement and Bounty Bob Strikes Back is finally playable at 60FPS! 125 | 126 | V2.2 : 02-Jan-2021 by wavemotion-dave 127 | * Fixed launching via command line (so TWL++ integration will work now) 128 | * Added support for 64k Super Carts (Laswer Hawk, Dropzone, MULE, Berks4, etc) 129 | * Added support for 512k Super Carts (Bosconian... though it runs really slowly) 130 | * New memory map scheme for slight improvement in stubbon games like Bounty Bob Strikes Back 131 | 132 | V2.1 : 30-Dec-2020 by wavemotion-dave 133 | * Pokey Emulation buffers completely re-written. It now sounds passably good! 134 | You can hear the voices in Berzerk clearly. 'Nuff said. 135 | 136 | V2.0 : 30-Dec-2020 by wavemotion-dave 137 | * Fixed background noise bug on Pokey emulation - all sounds now available in 138 | all games (fixes Wizard of Wor sound, Blueprint sound, etc). 139 | * Tons of minor screen adjustments for various games to make them look as good as possible. 140 | * More games run properly - Bounty Bob Strikes Back is playable (but not yet full speed) 141 | 142 | V1.9 : 27-Dec-2020 by wavemotion-dave 143 | * New virtual keypad layout. 144 | * Improved Analog vs Digital auto-selection. 145 | * Improved speed in ANTIC and CPU cores. 146 | * Corrected NTSC color palett. 147 | * More games run properly - Montezuma's Revenge is playable. 148 | 149 | V1.8 : 25-Dec-2020 by wavemotion-dave 150 | * Improved collision detection by removing some of the speedup hacks of the past. 151 | * More games run more correctly - better screen usage and improved control support. 152 | * Robotron 2084 now works with ABXY buttons as shooting buttons. 153 | 154 | V1.7 : 24-Dec-2020 by wavemotion-dave 155 | * Ressurected from the ashes... Improved cart detection. Better analog support. 156 | Patched working controls for QBERT, FROGGER and Wizard of Wor 157 | Better screen handling started 158 | Now using Altirra-3.20-test4 replacement BIOS if 5200.rom isn't around. 159 | 160 | V1.6 : 28/06/2011 161 | * Add Analog managment with icon on screen, just click on it to activate/desactivate 162 | -> this will fix pb with lot's of game like breakout, missile command, and so on 163 | 164 | V1.5 : 26/06/2011 165 | * Fix bug in GTIA/POKEY for enabling pot management, analog jostick works now 166 | * Compiled with new devkitpro (r33), win 1 fps since previous version 167 | 168 | V1.4 : 13/06/2011 169 | * Add automatic chip detection for 16k roms (but you can change it) 170 | * Button L to display/hide FPS 171 | * Add R & L to change Rom 172 | * Really fix flickering pb, alphalerp is back and screen is smoother 173 | * Better sound (not so much ...) 174 | 175 | V1.3 : 12/06/2011 176 | * Fix pb with iEvo (hangs on menu) 177 | 178 | V1.2 : 11/06/2011 179 | * Fix pb with B button (now you can use bombs in HERO) 180 | * Remove argc/argv management (for Another World test with his ievo) 181 | * Fix flickering pb (remove alphalerp for now) 182 | 183 | V1.1 : 23/05/2011 184 | * Quick fix about bios problem 185 | * change screen height to 256 186 | * Add more easy understanding message when no game in current diretory (Thx 187 | Another World for the tip) 188 | * Fix name in makefile (was 7800 and not 5200) 189 | 190 | V1.0 : 22/05/2011 191 | * Initial release 192 | * Compiled with last version of Devkitpro/libnds, so DSi compatible \o/ 193 | 194 | -------------------------------------------------------------------------------- 195 | How to use a5200DS : 196 | -------------------------------------------------------------------------------- 197 | 198 | Put the a52/bin files where you want on your card. 199 | 200 | That's all, a5200DS can be used now :) ! 201 | 202 | When the emulator starts, click on the cartridge slot to choose a file. you are use Up/Down 203 | to select a file, then use A to load it. 204 | 205 | Controls : 206 | * Direction pad : the joystick ... 207 | * A : Fire button 1 208 | * B : Shift button (Fire button 2) 209 | * X : FPS Display Toggle 210 | * Y : Full Speed Toggle 211 | * R : * button (often starts game) 212 | * L : # button (often changes game selection) 213 | * START : START button 214 | * SELECT : Pause button 215 | * L/R + UP/DN used for scaling 216 | * L+R+A hold for 1 sec - swap LCD screens 217 | 218 | Use stylus on buttons for other actions on bottom screen. 219 | 220 | -------------------------------------------------------------------------------- 221 | Supported Games (with MD5SUM so you can find the right rom) 222 | -------------------------------------------------------------------------------- 223 | 224 | 72a91c53bfaa558d863610e3e6d50213 Ant Eater.a52 225 | c8e90376b7e1b00dcbd4042f50bffb75 Atari 5200 Calibration Cart 226 | 45f8841269313736489180c8ec3e9588 Activision Decathlon, The (USA).a52 227 | 4b1aecab0e2f9c90e514cb0a506e3a5f Adventure II-a.a52 228 | e2f6085028eb8cf24ad7b50ca4ef640f Adventure II-b.a52 229 | 9e6d04dc20cbd6d3cdb722e420dea203 ANALOG Multicart (XL Conversion).a52 230 | 737717ff4f8402ed5b02e4bf866bbbe3 ANALOG Multicart V2 (XL Conversion).a52 231 | 77c6b647746bb1413c5566378ef25eec Archon (XL Conversion).a52 232 | bae7c1e5eb04e19ef8d0d0b5ce134332 Astro Chase (USA).a52 233 | d31a3bbb4c99f539f0d2c4e02bec516e Atlantis (XL Conversion).a52 234 | ec65389cc604b279d69a889725c723e7 Attack of the Mutant Camels (XL Conversion).a52 235 | f5cd178cbea0ae7d8cf65b30cfd04225 Ballblazer (USA).a52 236 | 96b424d0bb0339f4edfe8095fe275d62 Batty Builders (XL Conversion).a52 237 | 8123393ae9635f6bc15ddc3380b04328 Blueprint (1982) (CBS).a52 238 | 17e5c03b4fcada48d4c2529afcfe3a70 BCs Quest For Tires (XL Conversion).a52 239 | 315e0bb45f28bb227e92b8c9e00ee8eb Blaster.a52 240 | 1913310b1e44ad7f3b90aeb16790a850 Beamrider (USA).a52 241 | f8973db8dc272c2e5eb7b8dbb5c0cc3b BerZerk (USA).a52 242 | 139229eed18032fdea735fa5360bd551 Beef Drop Ultimate SD Edition.a52 243 | d9499b29559f8c3bf27391f0b9682ae8 Bosconian (512k conversion).a52 244 | 81790daff7f7646a6c371c056622be9c Bounty Bob Strikes Back (Merged) (Big Five Software) (U).a52 245 | a074a1ff0a16d1e034ee314b85fa41e9 Buck Rogers - Planet of Zoom (USA).a52 246 | 713feccd8f2722f2e9bdcab98e25a35f Buried Bucks (XL Conversion).a52 247 | 3147ad22f8d5f46b1ef40a39da3a3de1 Captain Beeble (XL Conversion).a52 248 | 79335deb06a1ef532fea8eee8012ecde Capture the Flag.a52 249 | 01b978c3faf5d516f300f98c00377532 Carol Shaw's River Raid (USA).a52 250 | 4965b4c8acca64c4fac39a7c0763f611 Castle Blast (USA) (Unl).a52 251 | 8f4c07a9e0ef2ded720b403810220aaf Castle Crisis (USA) (Unl).a52 252 | d64a175672b6dba0c0b244c949799e64 Caverns of Mars (Conv).a52 253 | 1db260d6769bed6bf4731744213097b8 Caverns Of Mars 2 (Conv).a52 254 | c4a14a88a4257970223b1ef9bf95da5b Caverns Of Mars 3 (Conv).a52 255 | 261702e8d9acbf45d44bb61fd8fa3e17 Centipede (USA).a52 256 | df283efab9d36a15603283ee2a7bdb71 Chess (XL Conversion).a52 257 | 21b722b9c93076a3605ec157ac3aa4b8 Chop Suey.a52 258 | 3ff7707e25359c9bcb2326a5d8539852 Choplifter! (USA).a52 259 | 701dd2903b55a5b6734afa120e141334 Chicken (XL Conversion).a52 260 | e60a98edcc5cad98170772ea8d8c118d Claim Jumper (XL Conversion).a52 261 | f21a0fb1653215bbeea87dd80249015e Claim Jumper (XL Converion Alternate).a52 262 | 4a754460e43bebd08b943c8dba31d581 Clowns & Balloons (XL Conversion).a52 263 | dc382809b4ba707d8a9084421c7a4976 Cloudburst.a52 264 | 5720423ebd7575941a1586466ba9beaf Congo Bongo (USA).a52 265 | 1a64edff521608f9f4fa9d7bdb355087 Countermeasure (USA).a52 266 | 4c034f3db0489726abd401550a402c32 COSMI (XL Conversion).a52 267 | 195c23a894c7ac8631757eec661ab1e6 Crossfire (XL Conversion).a52 268 | cd64cc0b348a634080078206e3111f9a Crystal Castles (Final Conversion).a52 269 | 7c27d225a13e178610babf331a0759c0 David Crane's Pitfall II - Lost Caverns (USA).a52 270 | 27d5f32b0d46d3d80773a2b505f95046 Defender (1982) (Atari).a52 271 | b4af8b555278dec6e2c2329881dc0a15 Demon Attack (XL Conversion).a52 272 | 32b2bb28213dbb01b69e003c4b35bb57 Desmonds Dungeon (XL Conversion).a52 273 | 6049d5ef7eddb1bb3a643151ff506219 Diamond Mine (XL Conversion).a52 274 | 3abd0c057474bad46e45f3d4e96eecee Dig Dug (1983) (Atari).a52 275 | 1d1eab4067fc0aaf2b2b880fb8f72e40 Donkey Kong Arcade.a52 276 | 4dcca2e6a88d57e54bc7b2377cc2e5b5 Donkey Kong Jr Enhanded.a52 277 | 0c393d2b04afae8a8f8827d30794b29a Donkey Kong (XL Conversion).a52 278 | ae5b9bbe91983ab111fd7cf3d29d6b11 Donkey Kong Jr (XL Conversion).a52 279 | 159ccaa564fc2472afd1f06665ec6d19 Dreadnaught Factor, The (USA).a52 280 | b7fafc8ae6bb0801e53d5756b14dbe31 Drelbs.a52 281 | c4ea4997cf906dd20ae474eebe1d2a04 Dropzone (64k conversion).a52 282 | e9b7d19c573a30e6503f35c886666358 Encounter.a52 283 | 5789a45479d9769d4662a15f349d83ed Fairy Force (homebrew).a52 284 | 4b6c878758f4d4de7f9650296db76d2e Fast Eddie (XL Conversion).a52 285 | 14bd9a0423eafc3090333af916cfbce6 Frisky Tom (USA) (Proto).a52 286 | 05a086fe4cc3ad16d39c3bc45eb9c26f Fort Apocalypse (XL Conversion).a52 287 | 2c89c9444f99fd7ac83f88278e6772c6 Frogger (1983) (Parker Bros).a52 288 | d8636222c993ca71ca0904c8d89c4411 Frogger II - Threeedeep! (USA).a52 289 | 3ace7c591a88af22bac0c559bbb08f03 Galaxian (1982) (Atari).a52 290 | 4012282da62c0d72300294447ef6b9a2 Gateway to Apshai (XL Conversion).a52 291 | 0fdce0dd4014f3188d0ca289f53387d0 Gebelli (XL Conversion).a52 292 | 85fe2492e2945015000272a9fefc06e3 Gorf (1982) (CBS).a52 293 | a21c545a52d488bfdaf078d786bf4916 Gorf Converted (1982) (CBS).a52 294 | dc271e475b4766e80151f1da5b764e52 Gremlins (USA).a52 295 | dacc0a82e8ee0c086971f9d9bac14127 Gyruss (USA).a52 296 | b7617ac90462ef13f8350e32b8198873 Gyruss (Autofire Hack).a52 297 | f8f0e0a6dc2ffee41b2a2dd736cba4cd H.E.R.O. (USA).a52 298 | d824f6ee24f8bc412468268395a76159 Ixion (XL Conversion).a52 299 | 936db7c08e6b4b902c585a529cb15fc5 James Bond 007 (USA).a52 300 | 082846d3a43aab4672fe98252eb1b6f9 Jawbreaker (XL Conversion).a52 301 | 25cfdef5bf9b126166d5394ae74a32e7 Joust (USA).a52 302 | bc748804f35728e98847da6cdaf241a7 Jr. Pac-Man (USA) (Proto).a52 303 | 40f3fca978058da46cd3e63ea8d2412f Jr Pac-Man (1984) (Atari) (U).a52 304 | a0d407ab5f0c63e1e17604682894d1a9 Jumpman Jr (Conv).a52 305 | 27140302a715694401319568a83971a1 Jumpman Jr (XL Conversion).a52 306 | 1a6ccf1152d2bcebd16f0989b8257108 Jumpman Jr (XL Conversion).a52 307 | 834067fdce5d09b86741e41e7e491d6c Jungle Hunt (USA).a52 308 | 92fd2f43bc0adf2f704666b5244fadf1 Kaboom! (USA).a52 309 | 796d2c22f8205fb0ce8f1ee67c8eb2ca Kangaroo (USA).a52 310 | f25a084754ea4d37c2fb1dc8ca6dc51b Keystone Kapers (USA).a52 311 | 3b03e3cda8e8aa3beed4c9617010b010 Koffi - Yellow Kopter (USA) (Unl).a52 312 | 03d0d59c5382b0a34a158e74e9bfce58 Kid Grid.a52 313 | b99f405de8e7700619bcd18524ba0e0e K-Razy Shoot-Out (USA).a52 314 | 66977296ff8c095b8cb755de3472b821 K-Razy Shoot-Out (1982) (CBS) [h1] (Two Port).a52 315 | 5154dc468c00e5a343f5a8843a14f8ce K-Star Patrol (XL Conversion).a52 316 | c4931be078e2b16dc45e9537ebce836b Laser Gates (Conversion).a52 317 | 4e16903c352c8ed75ed9377e72ebe333 Laser Hawk (64k conversion).a52 318 | 46264c86edf30666e28553bd08369b83 Last Starfighter, The (USA) (Proto).a52 319 | ff785ce12ad6f4ca67f662598025c367 Megamania (1983) (Activision).a52 320 | 8311263811e366bf5ef07977d0f5a5ae MajorBlink_5200_V2 (XL Conversion).a52 321 | d00dff571bfa57c7ff7880c3ce03b178 Mario Brothers (1983) (Atari).a52 322 | 1cd67468d123219201702eadaffd0275 Meteorites (USA).a52 323 | bc33c07415b42646cc813845b979d85a Meebzork (1983) (Atari).a52 324 | 84d88bcdeffee1ab880a5575c6aca45e Millipede (USA) (Proto).a52 325 | d859bff796625e980db1840f15dec4b5 Miner 2049er Starring Bounty Bob (USA).a52 326 | 69d472a79f404e49ad2278df3c8a266e Miniature Golf (1983) (Atari).a52 327 | 972b6c0dbf5501cacfdc6665e86a796c Missile Command (USA).a52 328 | 694897cc0d98fcf2f59eef788881f67d Montezuma's Revenge featuring Panama Joe (USA).a52 329 | 296e5a3a9efd4f89531e9cf0259c903d Moon Patrol (USA).a52 330 | 2d8e6aa095bf2aee75406ade8b035a50 Moon Patrol Sprite Hack (USA).a52 331 | 627dbb2f84daef11229a165a69d84e09 Moon Patrol Redux.a52 332 | 618e3eb7ae2810768e1aefed1bfdcec4 Mountain King (USA).a52 333 | 23296829e0e1316541aa6b5540b9ba2e Mountain King (1984) (Sunrise Software) [h1] (Two Port).a52 334 | a6ed56ea679e6279d0baca2e5cafab78 M.U.L.E. (64k conversion).a52 335 | fc3ab610323cc34e7984f4bd599b871f Mr Cool (XL Conversion).a52 336 | d1873645fee21e84b25dc5e939d93e9b Mr. Do!'s Castle (USA).a52 337 | ef9a920ffdf592546499738ee911fc1e Ms. Pac-Man (USA).a52 338 | 8341c9a660280292664bcaccd1bc5279 Necromancer.a52 339 | 6c661ed6f14d635482f1d35c5249c788 Oils Well (XL Conversion).a52 340 | 5781071d4e3760dd7cd46e1061a32046 O'Riley's Mine (XL Conversion).a52 341 | f1a4d62d9ba965335fa13354a6264623 Pac-Man (USA).a52 342 | 43e9af8d8c648515de46b9f4bcd024d7 Pacific Coast Hwy (XL Conversion).a52 343 | 57c5b010ec9b5f6313e691bdda94e185 Pastfinder (XL Conversion).a52 344 | a301a449fc20ad345b04932d3ca3ef54 Pengo (USA).a52 345 | b9e727eaef3463d5979ec06fc5bd5048 Pinhead.a52 346 | ecbd6dd2ab105dd43f98476966bbf26c Pitfall! (USA).a52 (use classics fix instead) 347 | 2be3529c33fdf6b76fa7528ba43cdd7f Pitfall (classics fix).a52 348 | fd0cbea6ad18194be0538844e3d7fdc9 Pole Position (USA).a52 349 | c3fc21b6fa55c0473b8347d0e2d2bee0 Pooyan.a52 350 | dd4ae6add63452aafe7d4fa752cd78ca Popeye (USA).a52 351 | 66057fd4b37be2a45bd8c8e6aa12498d Popeye Arcade Final (Hack).a52 352 | 894959d9c5a88c8e1744f7fcbb930065 Preppie (XL Conversion).a52 353 | ce44d14341fcc5e7e4fb7a04f77ffec9 Q-bert (USA).a52 354 | 9b7d9d874a93332582f34d1420e0f574 QIX (USA).a52 355 | 099706cedd068aced7313ffa371d7ec3 Quest for Quintana Roo (USA).a52 356 | 80e0ad043da9a7564fec75c1346dbc6e RainbowWalker.a52 357 | 150ff18392c270001f10e7934b2af546 Rally (XL Conversion).a52 358 | 88fa71fc34e81e616bdffc30e013330b Ratcatcher.a52 359 | 2bb928d7516e451c6b0159ac413407de RealSports Baseball (USA).a52 360 | e056001d304db597bdd21b2968fcc3e6 RealSports Basketball (USA).a52 361 | 022c47b525b058796841134bb5c75a18 RealSports Football (USA).a52 362 | 3074fad290298d56c67f82e8588c5a8b RealSports Soccer (USA).a52 363 | 7e683e571cbe7c77f76a1648f906b932 RealSports Tennis (USA).a52 364 | 0dc44c5bf0829649b7fec37cb0a8186b Rescue on Fractalus! (USA).a52 365 | ddf7834a420f1eaae20a7a6255f80a99 Road Runner (USA) (Proto).a52 366 | 5dba5b478b7da9fd2c617e41fb5ccd31 Robotron 2084 (USA).a52 367 | 950aa1075eaf4ee2b2c2cfcf8f6c25b4 Satans Hollow (Conv).a52 368 | b610a576cbf26a259da4ec5e38c33f09 Savage Pond (XL Conversion).a52 369 | 467e72c97db63eb59011dd062c965ec9 Scramble.a52 370 | 3748e136c451471cdf58c94b251d925f Sea Chase.a52 371 | bd4bb4dd468601a2241233778f328267 Sea Dragon 64.a52 372 | 1aadd70705d84299085845989ec614ef Sea Dragon.a52 373 | 54aa9130fa0a50ab8a74ed5b9076ff81 Shamus (XL Conversion).a52 374 | 37ec5b9d35ae681934698fea36e99aba Shamus Case II (XL Conversion).a52 375 | be75afc33f5da12974900317d824f9b9 Sinistar.a52 376 | 6e24e3519458c5cb95a7fd7711131f8d Space Dungeon (USA).a52 377 | 58430368d2c9190083f95ce923f4c996 Space Invaders (USA).a52 378 | 802a11dfcba6229cc2f93f0f3aaeb3aa Space Shuttle - A Journey Into Space (USA).a52 379 | 88d286e4b5fbbe7fd1694d98af9ef538 SpeedAce5200.a52 380 | cd1c3f732c3432c4a642732182b1ea30 Spitfire (1984) (Atari) (Prototype).a52 381 | 6208110dc3c0bf7b15b33246f2971b6e Spy Hunter (XL Conversion).a52 382 | 8378e0f92e9365a6ad42efc9b973724a Star Island.a52 383 | e2d3a3e52bb4e3f7e489acd9974d68e2 Star Raiders (USA).a52 384 | feacc7a44f9e92d245b2cb2485b48bb6 Star Rider.a52 385 | c959b65be720a03b5479650a3af5a511 Star Trek - Strategic Operations Simulator (USA).a52 386 | 00beaa8405c7fb90d86be5bb1b01ea66 Star Wars - The Arcade Game (USA).a52 387 | a2831487ab0b0b647aa590fb2b834dd9 Star Wars - ROTJ - Death Star Battle (1983) (Parker Bros).a52 388 | 865570ff9052c1704f673e6222192336 Super Breakout (USA).a52 389 | dfcd77aec94b532728c3d1fef1da9d85 Super Cobra (USA).a52 390 | d89669f026c34de7f0da2bcb75356e27 Super Pac Man Final (5200).a52 391 | 1569b7869bf9e46abd2c991c3b90caa6 Superfly (XL Conversion).a52 392 | c098a0ce6c7e059264511e650ce47b35 Tapper (XL Conversion).a52 393 | 496b6a002bc7d749c02014f7ec6c303c Tempest (1983) (Atari) (Prototype) [!].a52 394 | 6836a07ea7b2a4c071e9e86c5695b4a1 Timeslip_5200 (XL Conversion).a52 395 | bb3761de48d39218744d7dbb94553528 Time Runner (XL Conversion).a52 396 | bf4f25d64b364dd53fbd63562ea1bcda Turmoil (XL Conversion).a52 397 | 3649bfd2008161b9825f386dbaff88da Up'n Down (XL Conversion).a52 398 | 556a66d6737f0f793821e702547bc051 Vanguard (USA).a52 399 | 560b68b7f83077444a57ebe9f932905a Wizard of Wor (USA).a52 400 | 8e2ac7b944c30af9fae5f10c3a40f7a4 Worm War I (XL Conversion).a52 401 | 677e4fd5bba70f5983d2c2bbfba36b7e Xagon (XL Conversion).a52 402 | 4f6c58c28c41f31e3a1515fe1e5d15af Xari Arena (USA) (Proto).a52 403 | f35f9e5699079e2634c4bfed0c5ef2f0 Yars Strike (XL Conversion).a52 404 | 9fee054e7d4ba2392f4ba0cb73fc99a5 Zaxxon (USA).a52 405 | 433d3a2fc9896aa8294271a0204dc7e3 Zaxxon 32k_final.a52 406 | 77beee345b4647563e20fd896231bd47 Zenji (USA).a52 407 | dc45af8b0996cb6a94188b0be3be2e17 Zone Ranger (USA).a52 408 | 409 | 410 | 411 | Original AlekMaul Credits: 412 | -------------------------------------------------------------------------------- 413 | Thanks Wintermute for devkitpro and libnds (http://www.devkitpro.org). 414 | Atari800 team for source code (http://atari800.sourceforge.net/) 415 | zx81 (http://zx81.zx81.free.fr/serendipity_fr/) for GP2X-Atari version (that helped 416 | me a lot to understand Atari 5200). 417 | 418 | Original Author: 419 | Alekmaul 420 | alekmaul@portabledev.com 421 | http://www.portabledev.com 422 | -------------------------------------------------------------------------------- 423 | --------------------------------------------------------------------------------