From 71fbc3a2cac7d6c7a732de13bf08d48ef3296531 Mon Sep 17 00:00:00 2001 From: wavemotion-dave <75039837+wavemotion-dave@users.noreply.github.com> Date: Fri, 25 Apr 2025 14:34:33 -0400 Subject: [PATCH] Add files via upload --- C64_icon.bmp | Bin 0 -> 630 bytes Makefile | 47 + arm7/Makefile | 130 ++ arm7/source/arm7main.c | 106 ++ arm9/Makefile | 148 +++ arm9/data/floppy.wav | Bin 0 -> 69158 bytes arm9/data/keyclick.wav | Bin 0 -> 20744 bytes arm9/data/mus_intro.wav | Bin 0 -> 253586 bytes arm9/data/soundbank.bin | Bin 0 -> 333120 bytes arm9/gfx_data/diskmenu_bg.png | Bin 0 -> 24699 bytes arm9/gfx_data/intro.png | Bin 0 -> 39273 bytes arm9/gfx_data/keyboard.png | Bin 0 -> 43100 bytes arm9/gfx_data/mainmenu_bg.png | Bin 0 -> 24219 bytes arm9/source/1541d64.cpp | 2176 ++++++++++++++++++++++++++++++ arm9/source/1541d64.h | 170 +++ arm9/source/1541fs.cpp | 506 +++++++ arm9/source/1541fs.h | 74 ++ arm9/source/1541job.cpp | 493 +++++++ arm9/source/1541job.h | 151 +++ arm9/source/C64.cpp | 1203 +++++++++++++++++ arm9/source/C64.h | 110 ++ arm9/source/CIA.cpp | 595 +++++++++ arm9/source/CIA.h | 199 +++ arm9/source/CPU1541.cpp | 756 +++++++++++ arm9/source/CPU1541.h | 288 ++++ arm9/source/CPUC64.cpp | 640 +++++++++ arm9/source/CPUC64.h | 190 +++ arm9/source/CPU_emulline.h | 1387 ++++++++++++++++++++ arm9/source/Display.cpp | 870 ++++++++++++ arm9/source/Display.h | 76 ++ arm9/source/FixPoint.h | 433 ++++++ arm9/source/IEC.cpp | 989 ++++++++++++++ arm9/source/IEC.h | 275 ++++ arm9/source/Prefs.cpp | 53 + arm9/source/Prefs.h | 58 + arm9/source/SID.cpp | 1331 +++++++++++++++++++ arm9/source/SID.h | 178 +++ arm9/source/VIC.cpp | 1675 ++++++++++++++++++++++++ arm9/source/VIC.h | 250 ++++ arm9/source/diskmenu.cpp | 686 ++++++++++ arm9/source/diskmenu.h | 21 + arm9/source/lzav.h | 2324 +++++++++++++++++++++++++++++++++ arm9/source/main.cpp | 283 ++++ arm9/source/main.h | 58 + arm9/source/mainmenu.cpp | 661 ++++++++++ arm9/source/mainmenu.h | 48 + arm9/source/soundbank.h | 6 + arm9/source/sysconfig.h | 129 ++ arm9/source/sysdeps.h | 200 +++ 49 files changed, 19973 insertions(+) create mode 100644 C64_icon.bmp create mode 100644 Makefile create mode 100644 arm7/Makefile create mode 100644 arm7/source/arm7main.c create mode 100644 arm9/Makefile create mode 100644 arm9/data/floppy.wav create mode 100644 arm9/data/keyclick.wav create mode 100644 arm9/data/mus_intro.wav create mode 100644 arm9/data/soundbank.bin create mode 100644 arm9/gfx_data/diskmenu_bg.png create mode 100644 arm9/gfx_data/intro.png create mode 100644 arm9/gfx_data/keyboard.png create mode 100644 arm9/gfx_data/mainmenu_bg.png create mode 100644 arm9/source/1541d64.cpp create mode 100644 arm9/source/1541d64.h create mode 100644 arm9/source/1541fs.cpp create mode 100644 arm9/source/1541fs.h create mode 100644 arm9/source/1541job.cpp create mode 100644 arm9/source/1541job.h create mode 100644 arm9/source/C64.cpp create mode 100644 arm9/source/C64.h create mode 100644 arm9/source/CIA.cpp create mode 100644 arm9/source/CIA.h create mode 100644 arm9/source/CPU1541.cpp create mode 100644 arm9/source/CPU1541.h create mode 100644 arm9/source/CPUC64.cpp create mode 100644 arm9/source/CPUC64.h create mode 100644 arm9/source/CPU_emulline.h create mode 100644 arm9/source/Display.cpp create mode 100644 arm9/source/Display.h create mode 100644 arm9/source/FixPoint.h create mode 100644 arm9/source/IEC.cpp create mode 100644 arm9/source/IEC.h create mode 100644 arm9/source/Prefs.cpp create mode 100644 arm9/source/Prefs.h create mode 100644 arm9/source/SID.cpp create mode 100644 arm9/source/SID.h create mode 100644 arm9/source/VIC.cpp create mode 100644 arm9/source/VIC.h create mode 100644 arm9/source/diskmenu.cpp create mode 100644 arm9/source/diskmenu.h create mode 100644 arm9/source/lzav.h create mode 100644 arm9/source/main.cpp create mode 100644 arm9/source/main.h create mode 100644 arm9/source/mainmenu.cpp create mode 100644 arm9/source/mainmenu.h create mode 100644 arm9/source/soundbank.h create mode 100644 arm9/source/sysconfig.h create mode 100644 arm9/source/sysdeps.h diff --git a/C64_icon.bmp b/C64_icon.bmp new file mode 100644 index 0000000000000000000000000000000000000000..c9343e89c1031b717ddc5d4a88d6db8265054d00 GIT binary patch literal 630 zcmZvZF%rTc5Jl0kc07Wm=dkw>HkghsZKxQnEY-@Zr0`6PR_p(}BxIr+cH!|CSi=6$ zE}dG7xPxztFWd?v81&cLd;_GLMd#35jMgE>BQd(Z?;(gbC&CdNAEyxf%mOASmjCj( z_5P|^sweJYiDbpfZ>keLDOTNZdevkitARM) +endif + +include $(DEVKITARM)/ds_rules + +export TARGET := GimliDS +export TOPDIR := $(CURDIR) +export VERSION := 0.6 + +ICON := -b $(CURDIR)/C64_icon.bmp "GimliDS $(VERSION);wavemotion-dave;https://github.com/wavemotion-dave/GimliDS" + +#--------------------------------------------------------------------------------- +# path to tools - this can be deleted if you set the path in windows +#--------------------------------------------------------------------------------- +export PATH := $(DEVKITARM)/bin:$(PATH) + +.PHONY: checkarm7 checkarm9 clean + +#--------------------------------------------------------------------------------- +# main targets +#--------------------------------------------------------------------------------- +all: checkarm7 checkarm9 $(TARGET).nds + +# $(TARGET).ds.gba : $(TARGET).nds + +#--------------------------------------------------------------------------------- +$(TARGET).nds : checkarm7 checkarm9 + ndstool -c $(TARGET).nds -7 arm7/$(TARGET).arm7.elf -9 arm9/$(TARGET).arm9.elf $(ICON) + +#--------------------------------------------------------------------------------- +checkarm7: + $(MAKE) -C arm7 + +#--------------------------------------------------------------------------------- +checkarm9: + $(MAKE) -C arm9 + +#--------------------------------------------------------------------------------- +clean: + $(MAKE) -C arm9 clean + $(MAKE) -C arm7 clean + rm -f $(TARGET).nds + #rm -f $(TARGET).ds.gba $(TARGET).arm7 $(TARGET).arm9 diff --git a/arm7/Makefile b/arm7/Makefile new file mode 100644 index 0000000..9f6bdb8 --- /dev/null +++ b/arm7/Makefile @@ -0,0 +1,130 @@ +#--------------------------------------------------------------------------------- +.SUFFIXES: +#--------------------------------------------------------------------------------- +ifeq ($(strip $(DEVKITARM)),) +$(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM) +endif + +include $(DEVKITARM)/ds_rules + +#--------------------------------------------------------------------------------- +# BUILD is the directory where object files & intermediate files will be placed +# SOURCES is a list of directories containing source code +# INCLUDES is a list of directories containing extra header files +# DATA is a list of directories containing binary files +# all directories are relative to this makefile +#--------------------------------------------------------------------------------- +BUILD := build +SOURCES := source +INCLUDES := include build +DATA := + +#--------------------------------------------------------------------------------- +# options for code generation +#--------------------------------------------------------------------------------- +ARCH := -mthumb-interwork + +CFLAGS := -g -Wall -O2\ + -mcpu=arm7tdmi -mtune=arm7tdmi -fomit-frame-pointer\ + -ffast-math \ + $(ARCH) + +CFLAGS += $(INCLUDE) -DARM7 +CXXFLAGS := $(CFLAGS) + +ASFLAGS := -g $(ARCH) +LDFLAGS = -specs=ds_arm7.specs -g $(ARCH) -Wl,--nmagic -Wl,-Map,$(notdir $*).map + +LIBS := -lmm7 -lnds7 + +#--------------------------------------------------------------------------------- +# list of directories containing libraries, this must be the top level containing +# include and lib +#--------------------------------------------------------------------------------- +LIBDIRS := $(LIBNDS) + + +#--------------------------------------------------------------------------------- +# no real need to edit anything past this point unless you need to add additional +# rules for different file extensions +#--------------------------------------------------------------------------------- +ifneq ($(BUILD),$(notdir $(CURDIR))) +#--------------------------------------------------------------------------------- + +export ARM7ELF := $(CURDIR)/$(TARGET).arm7.elf +export DEPSDIR := $(CURDIR)/$(BUILD) + +export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) + +export CC := $(PREFIX)gcc +export CXX := $(PREFIX)g++ +export AR := $(PREFIX)ar +export OBJCOPY := $(PREFIX)objcopy + +CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) +CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) +SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) +BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) + +export OFILES := $(addsuffix .o,$(BINFILES)) \ + $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) + +export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ + $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ + -I$(CURDIR)/$(BUILD) + +export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) + +#--------------------------------------------------------------------------------- +# use CXX for linking C++ projects, CC for standard C +#--------------------------------------------------------------------------------- +ifeq ($(strip $(CPPFILES)),) +#--------------------------------------------------------------------------------- + export LD := $(CC) +#--------------------------------------------------------------------------------- +else +#--------------------------------------------------------------------------------- + export LD := $(CXX) +#--------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------- + +.PHONY: $(BUILD) clean + +#--------------------------------------------------------------------------------- +$(BUILD): + @[ -d $@ ] || mkdir -p $@ + @make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile + +#--------------------------------------------------------------------------------- +clean: + @echo clean ... + @rm -fr $(BUILD) *.elf + + +#--------------------------------------------------------------------------------- +else + +DEPENDS := $(OFILES:.o=.d) + +#--------------------------------------------------------------------------------- +# main targets +#--------------------------------------------------------------------------------- +$(ARM7ELF) : $(OFILES) + @echo linking $(notdir $@) + @$(LD) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@ + + +#--------------------------------------------------------------------------------- +# you need a rule like this for each extension you use as binary data +#--------------------------------------------------------------------------------- +%.bin.o : %.bin +#--------------------------------------------------------------------------------- + @echo $(notdir $<) + @$(bin2o) + +-include $(DEPENDS) + +#--------------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------------- diff --git a/arm7/source/arm7main.c b/arm7/source/arm7main.c new file mode 100644 index 0000000..a53828a --- /dev/null +++ b/arm7/source/arm7main.c @@ -0,0 +1,106 @@ +/*--------------------------------------------------------------------------------- + + Derived from the default ARM7 core + + Copyright (C) 2005 - 2010 + Michael Noland (joat) + Jason Rogers (dovoto) + Dave Murphy (WinterMute) + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any + damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it and + redistribute it freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you + must not claim that you wrote the original software. If you use + this software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + +---------------------------------------------------------------------------------*/ +#include +#include +#include + +//--------------------------------------------------------------------------------- +void VcountHandler() { +//--------------------------------------------------------------------------------- + inputGetAndSend(); +} + +//--------------------------------------------------------------------------------- +void VblankHandler(void) { +//--------------------------------------------------------------------------------- + +} + +volatile bool exitflag = false; + +//--------------------------------------------------------------------------------- +void powerButtonCB() { +//--------------------------------------------------------------------------------- + exitflag = true; +} + +//--------------------------------------------------------------------------------- +int main(int argc, char ** argv) { +//--------------------------------------------------------------------------------- + // clear sound registers + dmaFillWords(0, (void*)0x04000400, 0x100); + + REG_SOUNDCNT |= SOUND_ENABLE; + writePowerManagement(PM_CONTROL_REG, ( readPowerManagement(PM_CONTROL_REG) & ~PM_SOUND_MUTE ) | PM_SOUND_AMP ); + powerOn(POWER_SOUND); + + readUserSettings(); + ledBlink(0); + + irqInit(); + // Start the RTC tracking IRQ + initClockIRQ(); + fifoInit(); + touchInit(); + + mmInstall(FIFO_MAXMOD); + + SetYtrigger(80); + + installSoundFIFO(); + + installSystemFIFO(); + + /* + REG_IPC_FIFO_CR = IPC_FIFO_ENABLE | IPC_FIFO_SEND_CLEAR | IPC_FIFO_RECV_IRQ; + irqSet(IRQ_FIFO_NOT_EMPTY, FiFoHandler); + irqEnable(IRQ_VBLANK | IRQ_VCOUNT|IRQ_FIFO_NOT_EMPTY); + + SoundSetTimer(0); + */ + + irqSet(IRQ_VCOUNT, VcountHandler); + irqSet(IRQ_VBLANK, VblankHandler); + + irqEnable(IRQ_VBLANK | IRQ_VCOUNT | IRQ_NETWORK); + + setPowerButtonCB(powerButtonCB); + + // Keep the ARM7 mostly idle + while (!exitflag) { + if ( 0 == (REG_KEYINPUT & (KEY_SELECT | KEY_START | KEY_L | KEY_R))) { + exitflag = true; + } + swiWaitForVBlank(); + } + return 0; +} + + diff --git a/arm9/Makefile b/arm9/Makefile new file mode 100644 index 0000000..a11c807 --- /dev/null +++ b/arm9/Makefile @@ -0,0 +1,148 @@ +#--------------------------------------------------------------------------------- +.SUFFIXES: +#--------------------------------------------------------------------------------- +ifeq ($(strip $(DEVKITARM)),) +$(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") +endif + +include $(DEVKITARM)/ds_rules + +#--------------------------------------------------------------------------------- +# BUILD is the directory where object files & intermediate files will be placed +# SOURCES is a list of directories containing source code +# INCLUDES is a list of directories containing extra header files +# DATA is a list of directories containing binary files +# all directories are relative to this makefile +#--------------------------------------------------------------------------------- +BUILD := build +SOURCES := source +INCLUDES := source +DATA := data +GRAPHICS := gfx +BACKGRD := gfx_data + +#--------------------------------------------------------------------------------- +# options for code generation +#--------------------------------------------------------------------------------- +ARCH := -marm -mthumb-interwork + +CFLAGS := -g -O3 -flto -Wall -Wformat=0 -Wno-sequence-point -Wno-delete-non-virtual-dtor -Wno-pointer-arith -Wno-register -Wno-narrowing -march=armv5te -mtune=arm946e-s -fomit-frame-pointer -ffast-math $(ARCH) -falign-functions=4 -frename-registers -finline-functions $(ARCH) + +CFLAGS += $(INCLUDE) -DARM9 -D__NDS__=1 -DPRECISE_CPU_CYCLES=1 -DPRECISE_CIA_CYCLES=0 -DGLOBAL_VARS=1 +CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions + +ASFLAGS := -g $(ARCH) -march=armv5te -mtune=arm946e-s + +LDFLAGS = -specs=ds_arm9.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) + +#--------------------------------------------------------------------------------- +# any extra libraries we wish to link with the project +#--------------------------------------------------------------------------------- +LIBS := -lmm9 -lfat -lnds9 + +#--------------------------------------------------------------------------------- +# list of directories containing libraries, this must be the top level containing +# include and lib +#--------------------------------------------------------------------------------- +LIBDIRS := $(LIBNDS) + +#--------------------------------------------------------------------------------- +# no real need to edit anything past this point unless you need to add additional +# rules for different file extensions +#--------------------------------------------------------------------------------- +ifneq ($(BUILD),$(notdir $(CURDIR))) +#--------------------------------------------------------------------------------- + +export ARM9ELF := $(CURDIR)/$(TARGET).arm9.elf +export DEPSDIR := $(CURDIR)/$(BUILD) + +export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ + $(foreach dir,$(DATA),$(CURDIR)/$(dir)) \ + $(foreach dir,$(GRAPHICS),$(CURDIR)/$(dir)) \ + $(foreach dir,$(BACKGRD),$(CURDIR)/$(dir)) + +CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) +CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) +SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) +BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) +PNGFILES := $(foreach dir,$(GRAPHICS),$(notdir $(wildcard $(dir)/*.png))) + +OSPECIALS := keyboard.o mainmenu_bg.o diskmenu_bg.o intro.o + +#--------------------------------------------------------------------------------- +# use CXX for linking C++ projects, CC for standard C +#--------------------------------------------------------------------------------- +ifeq ($(strip $(CPPFILES)),) +#--------------------------------------------------------------------------------- + export LD := $(CC) +#--------------------------------------------------------------------------------- +else +#--------------------------------------------------------------------------------- + export LD := $(CXX) +#--------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------- + +export OFILES := $(OSPECIALS) $(addsuffix .o,$(BINFILES)) \ + $(PNGFILES:.png=.o) $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) + +export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ + $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ + -I$(CURDIR)/$(BUILD) + +export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) + +.PHONY: $(BUILD) clean + +#--------------------------------------------------------------------------------- +$(BUILD): + @[ -d $@ ] || mkdir -p $@ + @make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile + +#--------------------------------------------------------------------------------- +clean: + @echo clean ... + @rm -fr $(BUILD) *.elf *.nds* *.bin + + +#--------------------------------------------------------------------------------- +else + +DEPENDS := $(OFILES:.o=.d) + +#--------------------------------------------------------------------------------- +# main targets +#--------------------------------------------------------------------------------- +$(ARM9ELF) : $(OFILES) + @echo linking $(notdir $@) + @$(LD) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@ + +#--------------------------------------------------------------------------------- +# you need a rule like this for each extension you use as binary data +#--------------------------------------------------------------------------------- + +%.bin.o : %.bin + @echo $(notdir $<) + @$(bin2o) + +%.wav.o : %.wav + @echo $(notdir $<) + @$(bin2o) + +keyboard.s keyboard.h : keyboard.png + grit $^ -o $@ -gt -mrt -mR8 -mLs -gzl -mzl + +mainmenu_bg.s mainmenu_bg.h : mainmenu_bg.png + grit $^ -o $@ -gt -mrt -mR8 -mLs -gzl -mzl + +diskmenu_bg.s diskmenu_bg.h : diskmenu_bg.png + grit $^ -o $@ -gt -mrt -mR8 -mLs -gzl -mzl + +intro.s intro.h : intro.png + grit $^ -o $@ -gt -mrt -mR8 -mLs -gzl -mzl + +-include $(DEPENDS) + +#--------------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------------- diff --git a/arm9/data/floppy.wav b/arm9/data/floppy.wav new file mode 100644 index 0000000000000000000000000000000000000000..5326f06a0d26b5377df5d3e1cacb01aec5053a15 GIT binary patch literal 69158 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 qL3Xj?1d&$6!~-j}W*Xjr!?YgIM%Xy6 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≤b>#F^bOz@*jMwo<2zD>YW_dH6VV_xRNZ51Z5v_l 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

UECdCy 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�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

ZTpfsijSJ+F@L8Q@L+?=?AyxuOHzW*c_0 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

  • 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

    0_kzp96iodYrbKtb^Xs*AIgRoqCR0S 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

    vCaK#K7sMTMy>}eIzN`$krHOHMiryaa z4U(p&1XE|HC4rKbpR_BXt*LB%rA+c2&ym>~z_;}RnACE`EDmG)Lf4#O5l zEg_fd#CD-IqAxg23zhWP$IylV8z>q)5pFD1)2dltP@}nX;wewl_?}5h%H6cj=?NK) z)90n8CT~q>=lj*$+_TsHpZkXAp*IwF8%nRu@wei+gp>q7o+WqU8hQ`9tGH&1^92Xj zjIKrS<}tOs)IL%%v=?MN;`wZ^;^)*XZsT3 z4tc73wjoug6$mG75^E*bOZ}9#GQDN`jkNA?*4#{aljKdPj42T7oC%)k8|tuq+!&^k zQf7EcaDJe5aB=u$EMA*uy`chJU9pgRt9OF$G8|c4Vk}`_!e5~4&i4H1VoI<^L~81snM| zTUSVQIz6M%_cV_m>D%P}!QIaJo#QPZZ{|QZI?ImaYG!zLwfYr-gp;m&q%VdoFhqa;6@Id&IKjAGDfgS)vr3#g>C^Y#vf7 zsyN_QXR1J?t+xu~jb2v>t5%uhG zRyAul=8%W&(}Y3hW4dHeXQ_EeGnk0Y$u(lEon%!v?m(5?INB@J#y>7M16rjOS!c7~ z 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

    Sn zHr}c(hADu6)|f*-Dk7UkssD;S9i5!LmyuLosd5>82i%*RS(sn6(G}*SPiT=%2q~v{ zKoOQHkNf#g@#!tp`B?pZ)_&|Yg>JeO3;aRL%RqI!OjPM69M#Dg zBFpT8NMsKAcNx+jLz`>me9c24Q?btk1Tzhrd_z~-#((dmQ+?}qPxHQoM0JlU%}+|T zC{Z_8Q&x_rq_@8BT3JPj^9{lHZ^299w912gS_dEc0lFW0kpw%=uWKTbnm; zV1?>E#!h`d)#BqDiN!sMg+`;4NjPP+Hty^lC6oQ6wjGcY1+;#5Qa(re>y%%c&4%?Nbz1I0f{JJ_4>@DYRu*l^r^t2IjANv>=#VBO!)O#>$ zYD4eqrL|{LEz^lewvwgyvN+*zuOVWTL6KGD%jHOaUVl#3BDaVd&M@L0G(u}884dM~ z*2X+sD>H_m{7EvYzA$@R?DdIbrgr#^MqE$td~ObsN&RalvEXK6lMU&kRb8Ws-Om#;6OweEHg6n78&>3&`&>mwp;p_`|;7xS<_Wz;NG z`GLuN;~Agt!!Et3Zg1o9MMl;^s}=sB%Ku1h8}BczoU>GNH^x&3rn?({!=C57Ynu@` z!Dt`mT_c=vuz6-rwxOYXtSjVCtVA7y`O{o!zhi(UbdjCvnTKxGp3R$1iCclYmYGj~ zWZwH6?rO%vw&r<9@tn(1*?zpZm5rGpTX%wYeLW!$yt<-f;&{c)PxgXOi8? zw%)_z)>7vir6_F2q=WdCJFrJ}|M#M<%*A;BprJwtt2Q0%0sgeTvbNU}&(rh1*MH~v z{|pqwZR*<3`BTzX(aCzDjaxh)=p4-xoy?m$W)gzRcIyhuFex8R(7Gv-kIH!;H$cN!KYp*Xb?WeweOQGBD*h)YA3UR)P zmU=5?E7bWQb?p`8w_a=fmwFk_ihU|R)g%2~t&`r2=lQh91+OLA-{%ybg}CQ4$9%lB z8{glm^@bS{=j6#%#@r>vr_Lo~WVV_PrFyhMndNcff5ze`Sf(X4>@qszc4}AT2>v4K zd6eFlNBx^73=+E>2a6xzpF(N8+GuHtT1HUUW*NJa)%8igsg0#eQEm#OtfFYLs+^_< zdcT2oXiU$&&-Zop-F4z`Ta^3_jMG7D)}xZ$uD=RV$8N%<)v#N4C7Yp6f2CfoPGz+3 z-9B4G#Icm)c6Dg$E*WS9_eU@-U8@M{_!q^kQmZ$$SPSDIuQeeD6ZLH`T`Hs4adoO? zFJpJI7F(xIr*M5KC41bNMp|7tR_jHMd^2M=GZyiwU20?@lw;zHw(SqRqW$K2--3ZB(iU>9CiH!^cxeS75A7_R&d? zQakIxlU9cIbB6~@TxWLF4%>`IH`CbI5v)^lxg0q>>tqw6nX07Et9?)9Zl|m@-DlA* z`Q4rA(#|5bt=eI!ep^BDJgkJ-wR#yX*czn`bT_|hya(5hH&VYrFl$)JpV-Qe_2ppY z= zlUU&uh$MDtf0chMD(dh(+wipWmv)z3!+I1p3MzY*WovFRY6>JXwr9-0e=s9IW$ScMko#{~1Wsd(SVAqM*Ri#VR!Bj=47e9-r_F;AI6bZiC?BxI(zTX`F zZ+7h(KB*%U=rrZFNvhUnDY4CjKZ< z#r87LF3_)f;l?ZIP)ji3t4h;Hq~0&kT=&TgA1X$AEneuHuv24k!D7j3 zf+b4$Bo-*1WbW^9{moVaY(m99D(_mo_$zOn30<~!jvuYzC?O|rV6q-`1j?yojmMAl zt={OVu~|YbSyqSn!TS{ku+kUxSMyd;K9~ zI0>6>k%JXkcNx*spZIAerK&#)dQp$eM7Teq?3D=lUG;C|lUeA&KP&Ha*PHCBU%Ap= zEtzJ8&siL~$yf~aEOI16f9`=*_gjfkRs6Xx(i?}{-qN~nVaQKJGdGCVZWQmFjpgd5 z|Bss27-i2F&8&unQfOPbFiTslyHJf{1x{DJH46_PkU3V0);UN<<@)r;t?f;p;W%Y= zsrczrb`i;y{x{04_Bgz>@qKx^i`pqKwXUIaKkMvo zdkyyYhW=hc`&Ge(_4Qm++G*ss-R&s~1&!XE<_kIWS5+I=4I7q6GY{aD^z))KA0<<8z? z?onCK&(l{0jHnj4xuy2HUG(`X+QbdrHsUd(s1t8_wfXV|xiJY8?R z)RmWO>#k_ehCbt}ADbVZODoP&4;P0%?4B=Y7SWuhe}|GD(Zj>Fe>suQzi4esS;^^m za6B77pS|5n0ZdcgYiUQh&|-?kc^Bx8xsoR%RH7+WbPr!|hs+G_$IR^Q)rjQ=T45eh zf%9z7kK$Wn5nNx~_z*8!i-j-A@)h6-?snI{=&#dx=XcG22P=DbH3;^5maUGT`+3hp ztZ-P%jH0T)Vv|*rswEgLcKTS%gDmFbBAb-Krm z{O?VU8qRpH-&SWk@+Yy<*l+7kpZ$WruWd)CKde5TDSkHsRSlCt{(_vaXJz@nM@!m$ zF}uiES9w0M>w6LBenFe9#K6C)?;M;PDWj=f{mveMMy&q_mZ*kgw!Oax zR?mTTkIT6K9j|SbT^21lUhDOsD?LH~8AEHDCc6Cr9p_V;&{FUDHCbz0Nc+^lT8%Me z7Yx)%RJD|H2KjBoBC$8$4_;rGQO5k z&6ZHVLiszJnxFUSgl`_6J>{8-=f9viYLStYsDT^`g|$=#C+L!CEbcc|Bg zRLVBSRqSMUg(IsK#znMT2lI+Ajq5_nHx0R5M+xr0uRTQ@>V(xQx>K{cYpFxe9!%XkVWR+$MWqkqdEmOwK?*8hI z$SrG*QEIXfxA@&v=piSokuBLrY%aU>h?XmghRRdwpHt_(R;X5#4fiB<<_+0hukgUJ z%Do~zFf^`tm~67P7>)Rbqq9kf>05VP#C>a<{f@&(DLCdCRx)-%_>iq{Nr}0btSOw& zYpvpskML!uy)Pr3Co|qTWOf{D23PUY+xT)SLO(Hi+vzv+j8E(z%q1 zeBNT-yA0jnL0U!u(XEvtI?vKY>hXx>dF_18|1Sbq&ANVuC#E{bOeNUq?B&FG#)~TM zPvU*4a`m@SeBKmex`(gHknRAT=pRwna#XBwZ2qQXmy-SXWu3#s=Xs5Z+9RT8L+r}h1Rq2hbEs*oQ_Y(A$n&my z(v?&Ez94<-e%^8jT`8V-zW^b8jmbWs)AZpdYoeTzw9IO9?gsenT9MsYp&G}3GNSg< z!&WQh7MjR$HT+$DBbV-OY_v@8b}&K;^A$Jn9kIK?6l%p$-oF|>XdIuu$r=7lR!W?3 zwtuZ{j2$U5T1^@eQQ+8>>-D6R^R>>8O8JHCxF>kilys}Da~x<69Wmr? zyxdf=zW-8+Cw#fou4-3`p~iDAA5PziO4T7*1AArq9io~&w0^4g98D{&fwRlt;SO>T z=jhXu+VwgsQ*Y!wFB1X(o%h}&`gT4ghtXEa7-&YlY_Ip8SC_A;h8ZYAjp%HH(b3y7 zz9QRihK#Sb&|epd({*z4Hqb~vLS*yx^6yCXGTfUTTl}jPzfjX2&e{+aR?^$~^-#p3 zhZyxm+*zsEJcm-YG)_0AB=gyVhT?c8~t$F8#^fw$K$; z`+l?h%60C{HD2GCFHEFg_1B9JnKyLD_w%)T4%B|hi)A4-ASy%B-&fd$v*J8QFOIfIgp>N%ZKmUnj?N}WN$|PTh(K} z_YcrZw_&7z#0f62$2E=3vGlo(#{WMo(*YwaY|%GK=E+7^kEh#h^}8=!slU7B8kr#z zuvA5B0Wz7#Udx8w&4xaUqh=<1QhdZVzG3DZQJ?2f;d|!Jp-#n)CqM85!;xVppLmGM z(g8E}HG_VUM^@X5q9BFS{uC#D8tvSatY2JgUBCp#WZ7XGC>+-&IYptURI|(0?Yv@LszX1z z;COMqNi>(2Xe$qhBvqt_6yVoNI9GdW%PijfcZL)`FEdKRvWouuOp4sVo=v1tDYjXYpEecc%ZhlkcjUzSA)C#T-*Om)u3Hc z)4O@7%hP^G1*6bdQSr*9^16DVqDnHuO2`enLvC1O*RrWyn693J2?&Tt&o9Qn5u~2%gRM^>SYnc|j zdsA&xM@y9u<4b2xiq-gWhFZdvDe6*xNHiQDCuwL4D?{ULq^Nxo8z8Xp2t~@`;QR{DA!Tr_|#0rD%2ymL;?!K6T z_EiS0HpI9u(z*^}qH45~hmFoq>IzvSaSmZ0Lt5uk<5`Ngm_IZ%e*0nUp-H@~gOyA%W%OKEbC99tZm*)S!PKVbD3dR`uj1N6{4HiRUD1DO*FWeSi(PY_D0LBcPAI~E z%Dm4*%_*LcRXJ8Drwoo=<_KSDrRiAaeM;USbG4d??kZgN>+s}9m$@pp=+FBi&H2o`&sr$EZ|+reS*dK(R*Xf_tVMUUrSrpNYqL#8NZq){7<#=WEU0oJ!GK-gu z+VPl3*bJPo2QQqYRqT@AHAk-Y2*lEbjlU(`QRf_}WGVJCAFu77z@1(6$XiNz%06-r zP@m?}w{r4Z?abNVXWwHLWp#7u?mT=?YQkN7;9tn;d74+2bnE$yUhI5TN>nA5JD#Cb zQ`EMtdHFD2XQ!A^V-Z)o=h`e={txHdrw4Z6l315Hi$3&pon3FIm>d{CEs473R@XZzZ@tuDir)AUKW}sXU1}RU(S3#n-crV>-)sIK zu4l)ln;@?DNfP5-LV;YVe&6BmMaby~t-jV-mg~RC-aSC=V!!^Tu3yiUDyU~(G@tfA zsy?T7nG@EzKABydFhX`{gYA0xe9BcyTplUaq2<-Y-j&c-1!uWUsc%N=*^IBPC}FI5 zTVu-E&8RO8LHr}ScEr~c|H~q(V&2sqb&S`dvBSj$`I0fui5X2E=eTGrY{p^}!~h?2 zzubdvD;fLoG~!0)UhVN!S7#XLPMRS9^$TNW4my7uuMKsl#1l4K(|bE%_P(w&*!?p) zA)i;o9AnSv5nivkd!Ca^(b?Hr8Y{c- zF{Q6zu6SkgT$Rlmz*INLtT));Z?uKieVTqIK!FDp`Fk^Ay4yt|elB>zH{o z(!OD}|8njRowcfn)>8S`4b9Ngc==Oks2H~CE!wkyqHvjLKzlarLpJ><9%Lme|1Ex- zm&9HNy8c}}(^bglsCS1N5!%;0udn!@4OEN6B7G<1Bmd?9^pvi<`KS-H<3+YQ$TYl>H@_c6VorlCe3-c^(v`Bw( z#2!9h8H1je_xB6h*}}JO!5TmCmT#lGUOYXa^%Sdo6q~^q z;urmp+ox~Te%Cr;Z_|T*yAU~!!Ee3Pu9q^r_`h7P7e$NvS_|1($vXMlGf4G)b^Qdd z&Za9(bG+yEp%n*_9d{Vf9M)HBT5Lt>C%q*`(bQ%Kuc~gsy?D)bylvDDD+ypZ(N61^Wph?2sHZh zKBeogHDZT|Q?iq;6WhE4vo#gHYiEqa45OiQry5@qy|a;eT}K(b%(*VNhBdd9orTr3 zwfOYs+Tp7~@E;$f+=>lcEZg$@vaSu#4hU=PVY%sDO*O%qR(~Bxa19cl?d1O+n3fieJh3;!5J8xIp3g%$_+~d<(txtTN%pSE@+OzDza5cZ($oX4|)}qZ{ z#K?0{>pHS2-;0>ufG!%Nu18qL+Di7f`Bp@w?{g>RNxPtrzSZu-tjc+uO8BDhH!9T~ z%Kd>%&K&6JQL(?+arRP7@MHFO5NrIPzm%om-IQo;`Q+qeq}1(WLE{O!&*+P~`njYd zpW_BcG2d5m<|@WgQ|EtKoM0U$E6QdKX7Rtpa6t{<`~F4kc&puq7MoLc(SnurRBaYu zAex*{3EVI4THMU{1$K8oUlxA$2}JRnI8#SHEf0$v&lEXTXQ)7N(F3zmu$@ z%ErrYdV9M0bf}C=c#ypI`WQhQxQc&&(dX9Lq2e6HD;%%;&S078M@1KNSEg_5G2#~D^Bt6gGWzWuz4muXZUphL&%8@F`dLQVKh`B2 zk&X4e8b6Qria5s+tr7GQyDVQ)K95mT?xHeHM?=S`ZD+;bepJ(UP|)*qoDLMNdmUA^ zUqMmET>NZC4R8@*Tth8uq6S0hUGF2kDHObkxM?bK{FZ+8vul4v|NB7g=HjLma^*IA z{ebt!SV_`W8`Ra`)p1Wngjkvv&+oX2o>oz9nyCB3XtuL)&{tm#RJ&J=i}yu1XFA7B z>^a@FV~?|LRLh4G^{s>VKdPr6(%)6+oj2jAX!HA%H39?l<7>_l#P_PUe@+{>L~fz2 z9mm^0>cw|a&vSU@b>r<@BRiwN)=YN2=udh5QLE-R7idTWzEghOW$FLWZ|^HZ7w@S; zBfMy4vm9^F^!f1^>Um7i8f7&=3J>bTel(<6w62ROw_DM0=?S8xDTQs!RGxRlb6SVV zg?rKph7w|cbJ6Q-CMQtj54OY?R%2Z=j?TXiUdavM6O~tyqbkRaVcG^0f#a zzDiy~Jon@WO47JQhbn_iu5e_f>)$4evz7BcW1Nq2Z^e`E)|!9BdXPNHEap*ny)156TpnWzg&zo4M50BR#zdg!F4C7@Mv#0yeUwYY#`LSE5&~H*7 zcUk401-EBnYYtH5zQw=8mG(Y*-Zl8~C_A-5T=e@S8!l9~XLzmtX5TOJ5g)J?8_li% zGrPWt%`7fza-+ED3BQeF&^WXem4qiAfz3&DzQAk;@1wSJ!AlgxFOo>#RyA4Rr&#U!AhoeH?d(6fV_(}#*$yJb?V;O2{B)iu z*ykg&XxsUVne4K0ISRYXI?BK8 zZnBQ1_mQg%!dLh<}2HkdYwDH+C z$#+j`^&wj56+Qc!H4US@V!rSOY8^tl{ZCHu`(BDkaP~)@p&rwa1O>8&7y! zBg(v6yQkQ}t*Gm?(kid%r}^G_!r4k2^X+{)vI`z^4_u%24?_D9JugS6zoU?=Xo2xm z*EU$GxB1^#%G?xl!S@lsSQhPN7Ni?yZiWVHJ3~?D$YLHA`g^Q5x(`DQp{;+5qV^!7 zJ?z8}ewt<`H;qE~t(?$}NFwH)TYb0PEc7_ija_+*VwOADx_Fj*ZIPxRxtm3FVotgn zxh^#Ko1zRO=#C>OeQzW>`&-I2&hds4&Ty@Lp5GfQ^B+fq!+4vqUc=eNSkdqd-!s6` z&v#FlnRmc5wakyRQ6qmr%yX3T9p#)X6L2B>wx3tY?QE6J$lG}TAZsRPQn&We2(RG{ zO4BHAr&mhd*k)cF zJ|+cx19#0qLW{h24}uHkJB(50;G&**sE+=sjG-f^ zEJ|8Nuib}~o}uf#OF5hDOyj+Gbi&&s@y$#n+JGAmh?E|d;{B; z%=p^u*n$6I7v8u|nrP@jBYh=h`x}I}8Ydl2iJhrSQ~w^soR8z>rdmACaMV0%jd!kd z|7=A|TfBZm8uN_VnQ|WIV(<+iTm_IN)GK<9Q##P`%1o+*W#s}r-;_dmyF=c(;dNs zOYzbecVT(~HdMSooZcC2RzLsYT8o0(F#Px$&#x?q?E?#b+hwn7*Z^6wM zwa{+0`$7B9!eTEd*L~*8*T^INm4-Dl;h%^!euirPPG-ZcQQ%N@coS<6W(6Lm@6}O` z+p%6bcCn1>7EzWfSgOr*{^@Mg7!>s;>o=ZNoQ8R}_O`e_3;<$g2J>dKsttpPVOkN;7+RY^ScWmFvArg%leM8{+{y}#dM;6u?T07jGM3g!w*+f0H&%=IG zL%-z1wUMR$D=$5n+IBD1=Nz({C!RQte)qnJ@?1ZCPrHjJQyjxR7wD-uT&pC7stxvd z55X-Pl#% zvKo~{kXciYiP8Ru@V@qSC*sPEt;+j*4OCMdf7GK)HB-}je6A|$sqH##@X#QHG>W3v z7f03i?oy7j36r(eCQl>6!RRS=@gME`r&?HG3fQO z>;6FFm&;bmgQBviWpLyk$5!w78D(t}mp-koC6zd`{T`B~R|}WscZFQO-bQQetOir4 z(JN?(Tk-oEjP;q8ABD(zq4Ty@aG zNboc@Hv_dOcF6lKq5WYA7e^b7PxRl#M$uY--D2GDbr+?j<}sg%xPD*v#u#)o*8i_# zvmmE;SdS_0@hQl1lo?Amv#)Y=#RKLV6O73ouKcL+5$lvWjQQ#@& zvD>UOxR$=t!fZ9>%e`36duf&NbgTnrY)i}n-(X7~Gq<|SD2`ohv!`98P)5Gt(WFi} z%*861z4c(n7SM>UU^SYX)xOFSe#C-*#d@t^v)1q}3;g^FOInXzPQ`;8S%;q}_z@jg z%O>t+N&jJMQq4Itn`>UlGGtShusjQq;t-LH*n24QJf6j|W7U0*ziboJbruDz9{NB#hQkn-O6h%q<)T6>IX1uG0~ap*uC4> ztom$Wn?&Cj!fH+DVRrLw`FXc`qBY$_3}ctJ(bjTKmtFQ9J!qXM+zx(yujt`6#~MHF z7STK}@^^vv--|@P;0*^SEYp@pY?nlQ>SB(&__jNEx*~jA@J&@@)0qE$3DK+&drWWF zvl4b_z29ob$7Dox_w{kFR#yJiloM6Xkyo7ZH&n35RX)W`^N`ba`FYtzi}NK}Q@LcH zT~MOEO14D_cPs4yXa8I2&dcyRlP)tAFe4Qx{+$-TKI*;uMJ5j-v4g$~y=y+Uco{Es z_v)in#~`Zju~j^M@(wyuFIna9SeNjwtgXTF>02fHXIz~=qTx$0UXW8AHO+<~FN%L< z!W{Ye_0JnMp4*`&eFnJAGUt7K3=`SP9~?d z(at1i?S17Lfc`oub4OGid%?Wv8XqUo(;v0rTE|jtGTS(qpm!q%{=9yB)_b2)h9`Xb zNhNv-AHPF;TBtvFsM{IYan~hJt0>_~XII^w*T@E9VpS|ZpSA2|>D2F~Sr~1bZ z9(&xO|53KCH6y9anshQ#8}062lF;B8vytl&a(N@VC`yiX&d1Q&3U}&gob-?xPBl~( z3e&abR~ac&dt}H?;Hx_#f+ps&q0q+;knxn2!>r6XR^ke_A-}t|rqaYyykh?I79DLO zl8ijpSG7xX=Z%=jT-KvEzG#!g<@%a|#@SZ0D}RbOr&+a~&9(C>!)-XJq&aI&n)eQK z$aw1DEh0ag+0fa1-n-`c6WQ-rDR&LK_dI?5XxjCxUP~m^6|?nJmi~#>`kq|6nMoe& zNTungJZ-Vo-R5(J%;NrH^~STUcOsZw;&E^AsgLt4{rL822xn7jia1n9^Y*RI-$ISP z(rU2}}O7(t}+uh)aH>9IT)SZJ?qYm+O^N#?#F>stl|D5Ly~-PCXADEp^U?*mn|YeOB*0 zlIV6dF-~2)7klV7rlZxvTcw>hi03Sd`!%7pDcWozh2&FO*H1j%M)ix=I#=Du@BONU ze-~x?Jz49J4!>QY)lZ9VZKbMw#;1*?ZO%_ zwNYK3wByS7sc7;5tk6IlIO2$Tyb9otstBSjohag@Q`K^IQp*LRi9agM2{GJ?+Nme9 zjC`ffQTbe>dm_*J0)N&}AD>p{DbC$AS*;jPpI;yXxtfD+6M~3!C0W(@7wz+c^X2gjiUqO`JK(hZcJa;RiKExq<+i0&By+Lq zjjlLGOWvRr$Mfjv&A6(WPt-B)%J8Kr=zal0X^I~9$YmRdnktK$X0$Hz5Zc`;PjEeM z`a|B|W%R_dSg)(roT%S7xXV)Mvw10|1-v3p^o%*idK^4cd%x&xy>Rf;l)0gFvbTL| z7CmvX`!n{cIZPAGp;l$pv5vc=y*7Uysf={Lyr#z=$Lm#%)rgCqHdfbZ&rgk-DaOou z&i9W0Kk%E-iBBj;WZN}o5gyf_-HnmQSd_ZjHJ>x2hTFUF#nH!i;sEx#rjG z-;!j`6FC{*iQaDU>60vL9<#M76s?C5;lRYd^kjXinv-TpIb}Y%#WmNv>TkYJ_3om0 zt{v+(8r?x!ZxuA2|jrO*P;TZ@s62Pw^ZH$|TVy=yuZ z;L_f?+mYEJ3dMQ)#1(Xh%+#?9vc`_%wXJ;0Pdw4D-g7}7&IQ*x=yxmlo42g9Xl@>x zOGZ(|$(N|>=jyr8Yn^#%(Z(WFnP0_)W7C>`Y=I!0vw{3{1dI*>Jv+4<(1FkB`1Xf4q~PoBRs z{%GpV)p^?+X@HR%y$ug969HcCO1~s3M+RC(ae7;OobV=JzgVu`c7%2aF>S?h)9_3i zrMn{CUrBwJP;5dyS>s%XwN5r#Q%yWJ5{Vqd74dxc2N6wYjMyptqX?`G!l{oSbD^+r z`Ts}h9apFOTWf4cw4d*^?jG%)mA@{TFm8h+TG>erI^d4xNo?~rzPw;k!-mQlyLK!< zNhducwh}h$XH2cvay_WPZ? zgmsFs;`k>@(nM`O)aV;Q)0{@}_=a+IHl;X%8;w3Mq$_Kc!|R?&|D~&ZYM+niWJXr9 z&fo;~>l2*R9ov*Z8)x*+r995n+UbOt@@@3Ej@o!sLSnIJ@HizIMEz@tP_Eba2lVg? zub=qZ6DirLdZo2{MeSRHI#djuUs^FzKT*g!xmJv$j!6Ci37o{ zN16{*G}3mVwYTX^v9h-fB8xrkUZQ?YG-^LJ=laR0+T||%gTi%MWIHF;E}>5=_CZVgkGR0#DV)(Ti{HfvCFC zjXI*nM(lj-jh>IXl#R9&5ypRc);}=JYTkJf=2*k(XXhb$vF|@7y4N+R^13Acaf}6; zhb?-DlNOe@^9NruUu^6xKI}EK^l|*nT-36i-^j}H*LBr_NaPZaMBdB&{QixJpE}IX z{DzbE@-#brA{c5d54FS3e=1cLWh{mhV%OBzRV>akoX>j=;SAt`9+A^sgD<-Q=S8ga zob&zR91#(G2^&2iHdmkG6Pi*}H1P-~eU-|!gnvqp?e614C#vCZw91=|k4t*ty+%g? zGxpuQ{V3(F#asWQZDymk{?wHFo$YptNEO;jJeB-mT+>g+)M)z0lqAc29;#b|X=2~k zOj^1aHi=ye8uF6&>4W=en~lVq@8=O8;DsMjzn1>mfOoCn-8b`@+12PYU%g+Q{!Mb< z3hTG3j@yw|&V-qkpoG^k#{D?tRuq?;Qj|+v@digJYEG=+ctW{8!l^s;=@q5wTJ|B9|}LUj9RQ`ODuo8znRGYeW&BL@Wcf z_3OCyQ~5)GrRG9lEsUITTJ|fPIM@H95JoFKb&Fb^Q=5a{x6f5}x#kM0(tK_EB{k_c zVBr!UP33gP!hQ?j( zS`bDHaIL|PF!9cGk{!b6d%82eoOtbW1l2aSnSMnz;9=E6F+>W6!cy4Uf^retT0 zQtq$@?!DN>qP!e}bnfWol&hictXNrG2ydP;c2{H758VZ$U2U>VxYfqw1@}Thb*gJ- z5p$c~?#G_$@qjXx!F92h(E%mcsw`Wy^KBcA(=R*U_C z;@N(&uj6?;Qt?RT$Suc?@JzT7IGzDTf-W%$-efWkZxUsCbaCW^O5#w)Y z?eDo(qXaLUUA%EW#crY4 zL9D5LKwIb6hx=Ii*kNzHHj9YL8|pb#pZ=ummuZz6`aDYd0$&x`-(#pGQ_$*MjQ5SR zE#d1|@>N^W>lSL@a(|h_kG?DN^QL!?HrF1+Z*@0@+9KnY@{3x^eu`Z+!-qFAwp;UX zJrZJ$XJPaeSLsWQ9N>y0aA|PkRNBcTXB^Adz2JZfDqWxUgG z)R%Z7L+s8PPgHMf_hLPi=;b?31=!%DE{B1YTI8Jpq6$bq|7jQ&sD{IgMViD1s8 z9v3@QfW&O4TGTL-<}-&lFuI9Z_Gf{~6Qq|B~d$|sv(zlR+UI?qF14`bMlN*FBI%}>qLqykpF z%KYUYGnD;4zbETp60T86t5(&bcN-`7nZdMo{mw~SwboV@#IMuz`Wm(P#C`LwQ8p6y zykmUNcHU6?_9@q2zV1zC0-L>elm6X?Ab-=#vG(Ge(Rg0%&wAfK)Vt6ILmiClvJ{Mc zLfw8bD~jEH7UHUpjpKKX&rz(w+rFFXYEz8vH~l=&eer-%TG=f1R(7ixy{)dFA9Dp6FMAJw0c<$1}6uK~H_y z>DDxyyV?Gd{7ya|Cg$u{(_pT2wOq*K4qo9&)@Qagr?HmpOP20!tJMau={D@x_6o~8(C@+uzQSrv=1=B2Lp%d;rfW~-VcupfUsA))ymRd7c0F%-9#Q;; z`+juH#R0Q;%f%@0Fb=qezr0gfI`Z)z)f$u+JaR>3J_wd&_ zK$F0I@c^|(K^c8!M#FM_VQaz6O^m;_H&=I?r zeBt#?qTX!e!~aGHxp?`qh@=XoseFon*vhp+uk`D5?oj}jJq+qK6c;)sk* zpyGYvjNkbC0^If?jc00-ZT2btnM<#k@6*e$R^(kpo_iL3a=BJY?`vvmy0pjy`~x%X zz$~E-u2<7V{Q5-N&JYwffPOSkUe`-B!eQtmo;w~&<0Z9ml#&eb`#}i!WxN*pW2}T& zpsveN-Y!HID~Dr0tO^OIH090fYN?{e$K`3U5+U;Kf^DWa`v}+Ri?JhicvrGcq884s zk2oVAF0%gGiLMTGovE&|Osj6km%$#Hv{?ysb~hG^r+74UR5ep5sK&8=`9GwY$#>V| z`WuxeYX1)s{uiHRaA)LDp6gNF^(ZZmF?_vu~mz^Q%V@*NHwVrH70A zzqp<+i0p3hb7`Y1vgS*fjl_Fz_S@3#iMx{g&&Fzgx4KvG*WyNNVSkG|CiY4z>Nht# za?3S~ImZ#?7W=`j@!D+O5<3#+#aHFAT^%g^fYI5((GGEU@_$c6*AKlsjba~iFO*Qn z4BGdodtrw*-jIyJwOVYOv2aYCE;l-J;JHgRzgamdm@C|C1h;bj7FzKh$DL{u`d~$E z+S>g%EZJi(W}Cr1`%zHLC}aNl18$v<%_m@t7u?m4vI(`cMj@?vjq7AH@-Fj#>~(#U ztJQSRwsYUdPInU#Z|upoox&D79Mt5Wn>*?uw%l~JU1(*l_q>h#o?}TKQ@(qhyRtT~ zsGl3S>*86YZ?O!Kfp-*<$w}!=1iX5g(|<64pTvH62w^i}5U^ z;KEp^S-_b?4c)>Af1_4k(o<(T-cz^W@u##-wA3qFXNvm8v&vRbL3ZntH0)H|7274+ z<5ZE%FGNw7Ca(olry2b3Fy6NjB2AxeCqF++dkw+2-Su3=z1kUP{m}p9L|-|kwF{}m zLrVX;*yShUnaf2re{kN<#5BiH#rn8f^Z#k08PlCo?q%BlRp)H2ckA-Yu@i1b{W%Gv9Eu=X|n@o4S<9H3n#&Zj5X@`vI_EEs58(V{rZ(rqn881v$=FonA zvq~X*(gP*+(rxNpPJUaRgh3ym8io>ihn~xi-7+WRBxvoR*J0!LPyKY**KK+~c505C zxnKP?gOPr{I+wJ{v1g zeqtYXxR2KQKC*1%nWphHnsvzJHSE%u%`33- z*tE#NZDC&4#YpUJ6h5w9TC#_Cv4XKbNmlCKuRbx&Y`QxeUz-;wpZKv_Jix=$u&1$7 z(AQ#dlz%-vA=YLzbH;~hv-Q}YoXL~4W?{5PCdpy ztrt^oqPlcqt3O~Xx3JV_#l)^KPfca}kBB($H7^aNa#gZF$pnf_?EF}iH#VHS+p9}I6g7ozv>q?T^EKir zL%$|Owi%VJL}iOydp5F~j`-fiNw3q%UhsO=C#S0YdY`$Bmo1DUV#QxU^pP9wq@uoK ziSD)o-EB+V?X0`?!W!+h7#)6&9w)2WTfR>6{g?V^9a`Ar-QOoM;)oJ|hP77v%@G8d z9qAN8s-+VqsHk5Gx>A1L{U-Wh-v4Q)f4j;C-2H{p#v0+5)O-LP_jUDLq)rEo+;jRX zEn%|we0jX~AQ~7*Z5hMQN33~}xkYQfy@G3G)&IxU=65V~5Y_yHThmZXdUcGwiL<+M zF+31YFniwYA=XuY;q?LC=2dLa&iTvXtn1B9vTB+1$oyn-_bgMtP?|?-*Eh7oToL#~ zdihp&S!1)L&bX?#8A|Bh@dUScQbQNtb<@|6;Evc^u&B0Amv(|48u@Fnie!&=KTn^F z)y0L-P9dec5#QxUgt1=vHZ=~8d(8dyynE+Guh4xi?NJj^=zFkYO?Pxeq3=?b;>b0d za-TMjIqBSyzZty{yQp+fl2~IM>)1Q_xpPv&*vI5mn&~8J&jJ?cha?ud&0Vq6{q?J_ zyAthfuitECT~@M6p@Kc-4Al~X%%as(T`4_=%Vu=N%A69)Qqv6QAtfJ65Bo)i$SsKI zA@=3PWd0nA&;XXE87p&}IczSvcSd)38b$m(GP~eTKg*V!W~Hv7K-FhYdzsq~V>ibp z-na{!bvwSvB8%pvY?jlMyv%G>R%gm2&p*ZMlrtP)Eq1uaS0~42s^3Yw%f)jI!bUxU zetIa$GtNAMg`QyMJ%?}klxp#w7)n<@v;-~kJiBwijP?-gbCy<_hT2kaXI2Vf!9=%g z$dmN87uj)N@c>ht?;ZXs_GFvwb;%cvaP8R7zDes7L zMnra&Gi??({>$?`Pug|lujIK*8}0k?l}PeYx9x%VuM49xjTV{)ZZs{gLYcciel% z_6Fz6ssEa}_5gK_^(@_-`9ZB(SE=uGo^o31I&Bqu!F^{$j5aIi?p|qwGGfl~xRLfE zRd%vg{1S@hBuPWPc zGoJ|wW5zR5ze8O+jNjvC2WRxppU%JBXI~TXywCh5zj;+QGpqbq;|_OEO$>9V@5;Nc zE3zpKu}5!r^>73hYeUDmLtdLgj5nvux_j&3u39xX1ID) z&nJhXaXqVDiMM%>Z|KRB#nWv@@i)VGo#$EccoI!Kb)gF1bTefnecE4q>@Rp>4Q(b? zACBW8-$o!`W16F>p+uCU3e@JEVo#4J_{V1)y?MoEY80{43~A?h*I!W0Oj^+({=c8& zb^6gvG_f8Z{KI$WRmylOLlx&M;rr5ls-r$_9HDANEGr^*g%aO)kcsLuJkP zkl)_{t#$VQZU5hXlCSJ{iN_9@*Vto1u0iXFp( zRX!EH`;PbD#*ZIJNaGLhif4W;r)PbNzTQ@sp^kX=_sh8EdB@Y#vEHs7JNQ21Ypjd> zKrNT46h&EF6E?ct=gHz~z()D=%;_&fD7{=TOA_b?`g zP(X+3w|+FA#(MIS%6Y;kPpDf4J(h!_mnki3w^g5gt2UqFm>K$R24(P*M0fl~U;c#b z)_KoPS3H{t{s_R`~AFK8^un}+x_mJ z)a=e5&y?$CT#lme&Nfq8gD?K&ld~g%oV@ZGKQEE>IT#t%GhSkZXH)-N=;~Hwt7X(Y zNe7yP`M05iqwbR$@e+w2jXZryoPU;h-gC~; z%313=djsc>y>DW7x$ziv5hmLv8|wsaxtQej=VgP+I71^m)s9t;wMH@f%GWr? zP&|Dkv-Zft#zcIeD!zzZ{CbW$xT&&iv>TJWj}!QACwuihZElIzYWC}Q7A2kY#p=xF z=5ZZSQp}dyt62-SE7mr}Q{x}-*Ea0u!+sz7SZH36{aadGqO@z&Wn&*lBe9lYEbBXr zMUEAxt$enHPq)<)-Eqs{B+fC;J4R6&o-q?`p|p3ho$zC$frL-b{{xXJYgu5vI{9! zBCg=Jpsm|^)O&d6*bS@+{~FI$2xTNox|7bkkVg!k^s;ij#!F3ij@U2mB#)nw;*}BU z3H)NOEZCw1hG~gAUcge3{q-sWXzzE$G1+-#+Kw7ymB?}o5qd@JKQ|xG&Q``xWu`Ck z`|U~|k*`up(t;lKBueXtBc4PSosu%fGc==&@r?Rd-S`ud7_SFoXNHKl_Dy21y2M{{^QOSyEA80j@T(I)XxK`IyA)f+G&|an^-}PjQ zD;3m_O_KQR(@6$l3neP4<|(cix%hjXA)<6YYm*&*+UIwB{2cqMu2t(Fe2vwd2NLZw zqc+Z~4!2;@o6&Sc)C=h2>qXOYsY`mJC3ZYqtvu24U!k4vjF8pNf9X1#Ty3kLw)k!A zbN0Q~n~i8<#6M?l^O!s70e4XocW8tEaY7G&nV=72N7#&5^A<-jS1xIkmes1|v16=w zsiZ#(A+{`9_pnmLUe%M0r{PBXK=*B1_d#9sQPEu)YdLSCV&}jJSNgxOyXijn$`i`a zUrs>e!?kk%-Qy07XkR6NuS}n=?hLiudo{3DZDoudmF{PO9`^o@EJH`752ost*o&a2 z*m>u2!}k!&x|0Rl!7gt_L@QXz&v=5^h4O9Ib+(^ZVWyaE9za6}+2W&Y*k$Hcx4BXa zV{WkeOiyStT5W<>d(PGFW627!`KkCPtXRxZx8txacx)}du+DFGI$x}=k5%9KMc<3D zCGm{1+CClDt1}DLN6o`ZjbXJvG_pSwK^-OYpeqYfm7PpyMa4QEEOy@bh}Vhrj`Mh) zV74W6q{WVJFkC#9<`+bEm_IqG1{cj<)BAKbwzQy@tgSAcwD2HG-s{NxRkm-S7VC&G zYbaH2_WC4_i~7g2v42&ocmnG$N$qy3+bR}17;zHKVw9QtOOF1I*e&D%KIs8W^aSFI z=hG};(^s)DI;^{9c(!Y)kT)nR37jXt^bjqh9JuacnCBbR#r#eEN3i()rFa4kma?W@^(?Y$Y~pl(55C?Qn4>o>;iF|CK%6W%;$Oq z9l7w#NrbR1A%jgyvk!AdKH&xLjO_0dK6B8q%ip%*w4F4eL;ik-YLnTSu1CR_I3=?7 zGo~F=~+bQ8~~*nogy<>D@N$f$0`aC5X- zYpvMQtEscrLBQoub1}6qjAQa8G00q)E^@!lps&qJ9#3l>;aYFe(7twsT`2J%e~lgH zepQm6{C1K0#m>01F#AmPd{3k_)=-X2dU=xHFVnxV3OOUzDynyz7#n@e1zr*lkF2AP zNvVRzL$``ZXf~yeNO9!p?a|`9u-jp0xL}Or^tYRmcb0dySOa;ZpRafBVo1J*u@iHS zE{LwHQQTQOK8V_CI(rEtrm$B$t0LB2Jdnf}@AHW|{$9t(x?hX8MoZn4s;{y=f$Q2k zVhv42`czGyij@Wo+IwaENnngcXe$xu_-GRIY_Y+dF)V8m_582`JHwTZ*Xsa z>VBVwB)4fzZ0pROlC@c(B|Pgjh}C>H`EIc9hoY*;i+PLf z9LJJIHe2M2^=0oKRjbyCa?nJb>#J22EmAgVmGa7dXEJXunPjuXP8~Psg?MgE5!82w zR%qh0kxld(5}D0+uHmcq^Yi<>wqvxPu)tRsXATaV>OGNl7NrQK;dAv5HjFstdaup@ zBZc+OvV@n8=T}ARL}pLyBRAPk5mEXAokh%OQNm6idDk4RxfBFMoqKQ4qwaK;CCls+vnZM8QmkC9 zh!pR~E|1F%dydvL6z{!kMdToy){Dj#no$LWliTM`C2g=;*=9R?#Fbt{6tDPyjM{vt z+>wvBNvUJyN5qRl8~T{4GZh!k(mG%H`v$ETD@HCTOBUoA<;jZDVvp7fRKye7d#|&s z^Z9Qv_H1>CHF?kI|EG+F0sPp&B;!3|&=vID)qH4rt{V?TyHHi)nHv-@G+X>0YnqpkV z&ScZ|$Lu72H`ADkIQct{m)x&$cQtnI*z4jBcXJJQc(6%t_s=lp7^7rEecw+FySp2E zItC_p-!oeOnMCm&=a{Y_W-$hBtZ+sUpL``|pT4)?GaMG~F;G+Nq62j9aUo)rTu z;4k%Eua%=Y+Yry9YNUnRxxx$PZSOc^*p4Ckx+iPU2`fI~|Je7pyQ72mwqem?HrUXa zs;fmQHsn_JrIs_WsHLq5bdG)Ve0Y+gKp<__&p z)%_o@V9|RVO|(=*7TbG;O=<3PEm2(Tjq#i|cu9*q;ayeCd^6#;Lu~djV=xzcQptJh zC1;2ohgvCjWOwvYuP2jwwRY~v04asm;+c0joFVM|1^gJ#gfHu}v0mdnBD!Nx+#7t=3`92% z?S19z=O{3CHyA{7=}d=fg2QU_rZxG~7O3S}UOgyqDT@8c`M%@h7W(>??7Ml+9s5;{ zNpz)0`Q>d{ z7rUMu$35Spzwt=~`RQbTklvW>S#iHO!yMf7vC_Sve6P^=2KZYq=kJf|UQyQZ^6wVn ztlda1Nb@qBnv!-d(cFHbu}!B4K4W!AJO@2*@)X#UR&btjii+X{?$3o zVc2xIDuX!WMRhw$1^bC=H$mjQznz8Ki*L8~ihYLrQW=Mfq|QNiYiMPMX?N+hX&$V5 zos6nXsQw>3c81n?Dc|yDy^tHZU2v6OuxP}3Cp*JS=)5!HZJ?C3d~GI1-&Y(tqR5|_ z6>Qc<=Ta|6eZ{n41N_wqxpg5cMAbDg}eh}mvN?6C{p_r7k!?iaK`WZRX~+oc_`GN+Oec4=Kp=;HAV z-`kVF1TO~J$JlIW%tq|=W!YozA;4)Oz5iF!dBE#jzJL529X}&VvXktQ%#e|FA|hF3 zheWcnGBUC^*~iY_^Oz~CBgw3YLb4U2VHeK-{l1_6zOU!;oagy|?|om_=f0+BZU#Hz z6VU7+e$y_r4J)7u&tzw;l5;(HlmdBdW)P~9=7yll-kg|5^PJJvW*|A7&FO0ayKX5v zWD{q>1WtlxU`XJ^NZ37i_uRG^ncb^2S9S7k;_|DuVs>`P8} ze;~6<6J%(jME$(vDcbyg0wwMNr8B2ZvXBGob9VPacK2d>wgEkM0x0w-6y^-{_Py?U)7c7RfB-S^ytg1136%R72}*QO`a&>l`R*JK9>F7Ubh9#;3Y)fNoId zF|=h7?NHWpG-%(FAVDz}RWUG)F-r3UEtb(qm%zO`2Ht4wIU|KeG{A9ir5ThnleR2@ zzi$Ie{fwkWZ`TNdDuSG(0J51#+<$eK|MKfiBx}Ed(5|9Y`U6`b<#?x%t{e_htfTyO zD=ImXp4>e9B5ipY8H+JQO7Pe7T((llk8#s7Q??qiYskIM(2p|#joyw*334ic?5R3h z(RV>>k+^7Yqo1o3q&9gdL+#p=$c)Sw^*!Tf6l1*`7V>Ea=<@HVw4lJ((U0~2FjnD1_)867N9^z4pqJS}d)JVEZ3Mlz-r6$f`ecaL5@_jFaBf=KUlpzG z0Bq=X5NYENVq+vD8e4KAAm1R8$1Z#shSAQ~7^O_n_d%6E27JDiwXy+8?dPDduNm(n zwE8^bZFCE>j6EOZSY^<2=Hj^+p1jJlY7|d`Jhk#aL?5-c-%KyJvdWB%qbKuaM!~py zMUaJ70~^=jRTs^#eh&HzKS5c)g2fYf@>5p+V30^F)^i!oPPti~MZpR+S^M4C51(?+ z9$Kc>J2_=$K+2biInT=2WZ|!;SewcsuQ2Whxl=qhf>qg!eWpyT4yg2fcHBr-=W-C< z7qnFwsr~()kv+g{t7D(Sp6m>QsY%@h!NyN=>J$$sw@(TGF9yi!MmGggwrkXWgnlL<*ION=X&sQ{Gyo;l0w>i69d$&aFd9jkS?|AMWY2Jx zxyS5iXYwyt?-V1n2}#@p`qLQ+#+y*~Sg5+u%Cr+#-}Eehm4v@EMpo2^5g5l zN{dJOwuRRQ{$5N?qv%6>q#19*&#J=Dih)Vw&%Ys4(I?Wp3O|Dj^j^IWe@}_VGk@T~ zA0pwH0}uFuo-6S?7;FhQ2W}^qYXXl{T9Xp~s^9E4=>NXr^(~)I2l?6~cyfB$t6sPW zeGnmK3kX43TZ+U)xbWW~kPEcp2ngdVq(oc6I$yxk#T%EgIMV(-A0=oTXpD_gyk6p) zg6MEF!rT7`miY$+a*NA2cY1kl4X8*d)chb_Tn5UD2gPg$g&jf;bqZ&Kh&wK+?+t1Uk%oD6pJv_~x@IS^PH**zBds+sMgVC&e zrD)5M!WqBC)5UuBfc}PkXl)%@ukD*zukJCQSLv6l{C2S3dm^C4BFw!qz*bzwHR{AT zHKn~Zz>np4T3;G{%b(;jCtNyqUO~!z6$ICk9`ptCO#~~=W>+j?M{fkFeFH)}9<-~c zk++{^M_*!}pJV?V4X3v6`0WU?K<(akv)4DWPZvVFl)X>jrJtletY*>L#S_xsv(Od& z9&TavkpxPZo|B{&Vg)%>mgO{84T`OYp_V2spvh`a-s8PB|9c*70di^v=FtPOEGO1n zNWxO1Lx>??O)~VmPeRj_(wW&I58SIb)V&T*_kvp(16`e*)-wm;I7Xu|GJ)vC2&Jo# zjf@8Cb)YV7UX*=ShdRDY+X_;ixo@I_?Oal1flqLP&JA~b1*&c&;W)6~SIBIB1wEO; zC^h^rGrCMQduB3fIW5Ic(-$)b#eklSc9sMFUIdi$3No=b!8#4FN2>&a z$cD!Bc92)?0V%|TedmB%jc#Rrh^dq}FG%*xs3_vgj&86%vbEvFiHpZW;CteQoa4F@ zVz!+niikN@KO^qg6ttzr56cY>(5gvU;K3kM{E2b-6MU2o)M*~}*TG0_Ky2Dr4FzeL zM`|)QU*>U`#rtHgQJ}DX)cZm3(rk+k_C0#h1ngJ^>>?g6iY%}!{i}sXWCsx2XuLz` zhwPv$uu(HI@upyrwi;{xsnpPm(wZ|4RcWJo>}NqNMjC#ccWtqZuWKxhis0Jn!9St} zt?bD)l(NUsrccl-55Q`z9rDLU)N8ch!j$w3Xeb?6DlKR&HSZ~q5B`st&?n?^zJH22 zNyE2BJoDdU(GR0yK;7oO(q}^(z6z9AKSV-_MEkI%Z_o;JWEEf*vZ51C!;?|b*BQ-I zjO=#--LGMtc+yzSWt`k)Na)t_zM1!3tQzII=fR6N!NmVW=_#Y`{ApVBY*?YWD7zq9 z(~@A!%3MZa*0Zw&t;#}gl0=*5;Sjhgo*goUwf<4qlkcz_+pt} z-%b%^J=xjQ8H06O6xOiHhAx0*j6$1;C2S_}i&kU}*)l6YfSN zOY5jjy~-j=84NA2k94RANGB8cBR!nV+(xx1uM2Xg=}_0T0oUw-21}Vwa~-86YGXF@ z+X67(7;sfrTJk1*v=q1?H{9K*W|o$XS5A0oUid>%kb_=e+UraP(QX3!?F(peH?7+O zc3cccn!;F3;C&MOVmw@MH2iM_{T)i*Mufl3`8Xh4W(G4u)ywdov`AR4gBSFW{DJFC zuEBlt4A_9Xd%;g9G2-fwm%}%VK{^ririW@5_+`By4aq~>p8(n1MT2<}?z$fY zunL|%861ZH%qNyI^_%=_!$>@oVa?s-ppe`jbNfU3Qi8Q{3F&>VB ztG03HV+=-;WI=jq^Opl`so$(f)e zb!2Dc9|u7tK8oi3DOQ3$mW{cqJJ0oI?RN&%=*RdP_@nB7h}+B(G1%$<29o)K5&1TZ z#&PiX?_7zGQZS}^b{JKx6>F|5NUIwq_MsJ%nM-W}j-or%I&?eh(}*|&SaG72x2Y)> z43!NGWzGRTEw>@%+Q!)J1*JOX7s1gFA8GSgnI5(SiH%@=PiIZe1-r~=%`B$W#q6#{ zteqLGr6I_ay08bE(~H`Sbq#8%$|^FdbOBmx2CJm3gXkcORG#<%O#5$;!s%C>mXXTC zt}DT~Ri}*|*>@3&a4_`aK#&ZJebj}K_Uy`2#0=W;RHEqjbF`}#*s%xYPYrrK z;}D#JGoB0FR4K~OaH$LMEoES4DK#>JapUzJXoZALtGtGcL=$?eyx<*>qPcj~zV@fp z^WeA#K$h3xwb8*FG!0lQRrG@>GsfPeWMeQ~;nQt6aT0Jq4APQ2fjcV0G1t`DfJaZ! zw*By}P4M&CaK<6XnK~nJdWU+=(*6M)cN}uDFW~MMDKiNuBQvtW;^4h{;3T7F%nWfe z7V$nAEopaBnOe6~&z!)6$HL*&5-tWSD>*ztd+&o$GJq2F zkEn}22TL}Zh?!-)4!o@SLylF z;IGnPmd0Sp4{6U>dOH=l;AF;NDA=td^0s>5IirR>4F;MzF4@)1vvT`4!-}EzG=rw)S@et7<9o zPxI)l;ykdEm3o?0a|dm767b+7*6S5U$H;}7z=1Q_AMVRmtW>j?Xqn%TUcO6huKw|0 zppA^5lEc5kO1uM7yFgD5FtTeoO_*gsUx2~1Sp938u=Yhg>KI>R&(#5ysbBOg)|8hL zKJE6kbJaf2JJpuH9r~)*O*hI?iq)A`bYwJo(8`hQX|u0r7cqf-J)G7J;OfnN9a!gY zLA}aAgUnO^I~u}Wpc*5an$Nm#z!_tpwrU+#fmpVKsJ@0Of5$0POO!`=umtpXhrO;<(efzogg0yyk zh89EV)f;MsWPH;iaIRe7ii~i`%%F}!pq^St8G3+|7ICgW45hu!nKuT?nv~k_fmm;# ziMT=wPEoEpl4X=?wuV8VDfw?xxOF9XPhJo~T4Y`N!in1SQc!DH2OiRwcB}#M{fegA zSZP(6^QQFFC?s0#JjZERyXTA4k^q;P0mAA^yXwNt%EOP;MOH^*^cJ9T`DwwyV=lb(=+l zTuG~_nt_it3)W#DFoGQdMpj2^6t?Q2MP)+&v_&t?D8>d^Mo;Eu1}*p;%)AfT#8zsH zqqSY&rPV3_SvdGzP>6`|7qHqd;Duj6MQ6c9*Wu@n1-VBqxPA%7Piw0@VBaSh(T5-x z?deYjjCYbJ&VuXy0AHHf@-gsH3J{XE`}vsHmuTTDw5kqh(l#5bq%vH+5as5fRAqd| zwupF<8V%##qo_n>QHMc}`T`sT+nfO5{04Ho1^#;U$hj4lSEHPEVO9sQ@|2=X;x&eq zW>l@$8A~GsrsHm7L1?wFcZxC5j6oL*u4u|=b^~t>VuuU^`}AZTHvscEKB*G*Z#YFO z^ol(V0ylqD7M`t2*{wiHy}94GwQ=l(1+4px%&j}>0Iyx_fYp4r7-Y2w&E5jg)@;^^ zzPs(Hw;KJ=3t}>U%pFGWHt#9;y8!D@w8fa|ii}MSX4n&i8LjHDQ<~t} zV3q)Dwyt%oeEkFTaJouwjFD@Wl^7)9G0>R@(4s%VZP9PJ$)X3Du5 zNgs^aGbZf+0nCDHz|)mhtbM6XeQd9Q&&?ke`Am7&1qzIFD>eN zQSSScVnon)xU?2jnzhMlG|o-5(D(T8#W;J2JPE0r?~c z$7F~1t251s%tTMneQ?Q1)ZB)Vs7@KBklht$giF$9Z71b@_EF!BN$|F1aP$P8l5bxJ z8Qg;3My@-2eh9uw0v9(&)_pkg4RGiQc=2}l{(>Nt(`IcHZ4;O2d-^pP^IX7~PlK^u z08hOP{xCmkH7w)GfnKKOD5XpYrF;&))O#`+D6k;Nt0u^% z4bjkgfaUrlnd`&nwgEAkv&fuf|I#v}5?`d;Q^*F7)1RL~t!H@G6Z16Ro#pRyynf`; z^TC%m<9Ay7fF7nmo|GOem7USl2P7w#K9CP6`y80}8}N-f&`km7s5#ebL`%l&;GIXv z%bq|6mJMm0*|Ws2siGh9?QKTxD)*eGZAYp92S(^eo<7O@PXRd^p=={)Y$9vTD2?@4 z3rd=`GJOjy)0EjX){E9ltHD9v^6W*<1D8SxU(vEHNJ}?@uj0XITB}V5Cuz$$jZ(EA zSP61l%r%#5HuF9`%-DGDn851v%wjGDQG5ql;8|xBb$uEzpC_A%0VkT@(=~1kv68IQ z-0UVZWM*YIxMbHqzchTqo$aR*1X7i0ioKf+)wZ20L+o1x`n) z*wI%5wcP_9+7_t$J~;VL(5Jt^CPuz3#Ez)J-f9;txhByQEg@IZ?^V1np|&ZMs6N!# zy@kR_FFhqc4xM`d^)pw)L!xhIXXm@yJJQcdJhOn)k!QG({B3mN%A5zYL2Dj?i%!DN z*T79iLf1M5WS~aEll>anc$_q&YjjAEiwWb70)JNzfl@Tora;dMMYgP+<{? z8ALy#wB~S%w|FBM{tU<;K;>{z#i&88|>1|a2f+`ybovk9m(P)u3sqYr=aEd z4ve-tpfn?!uLgU_2emL!TdA~cbKsDB!6iGP?;H76L@8RG4yB((?`CqT9T88NL17Xl zETe~JJk#%#$$*F7xeS5XMTl;V5S7J!a}v5NYAi*TMm7nfbw(_|1@|v}82e!377x1;q6?n8L^xX=!UQ&`A^S?a!E) zZ*2iMVKy((?D%(<(5C#%%FN;^0a zEMtuubF~Zmt1&pR5~V$dR4pp;cWN|Z%1h+RyiqB>X2k$HNP)5ELuRJ>XnEY_S=(H{AsF{t}6TkeCA>;x@6 zXR@M|Q0tS?obygBBbb*Ne3I1=1?G-KPf5k!Sy;Kx)8ALPt1WXkksfWKEk~gY#wESN zIyI)w0VMTnXwN8WQ=V9cotPcHtTEv1Z8Rr|l&p}9)Kic))@D3DqDAxn(}3=wcUoWU zXU*^BGK!J8ia!c#wF)y)kQscAb@m)3c!pFaTaEE=&&W@L=4@qL&IIJ9bg&o_Ep4J- z`QHRuW(*G!EREsyOUYi4o%v{U;4mq<1cMt53}>mvy1=boSmLhihzBL)!hb3hnko9 z@X-xHR%8CfrO^NBNIJ%W_mnI2g=+WWGQzJGcKyQlM&$nlnr?ob(c$;^(KWS%e>H_q zzYfna_hLCPoc^t5LN$l0mTnusOA(3QIe4}i9N<_8Fp!$N z(}w?#_-0fvZRl&kV_MLI0rX%lPi)6B=_g9MgADI+^myrzgc)Zf1(LnHpc>_d`#=V3 zLhpKkAsT}zw1+qHomj9D<#ngOW+v22Z#R7U5;*S>$S($M-anLb9+a`0QJN2;?h9^h zKu;^e|6hWuRfJd8rwnB`GeIF=fw-;)Yrah2s9Z?D@`0vu@HritNA-($z*~{%Tt@>g z_!>!60=mHMpsKB0TKaEdJU-`}y#eW(&D;Lv1Lsx&N4||D%^U{P(5Eionu9!T1mC@j z=C%Y{!6ebwkT>Zov4Wn9Nk5~GA3%V&gO)cFCVW>9 z-Dz!5t8qwLBSq_kRLyK!ZICM(Z$nSpg2)mxg7{K1+E4OQi<*{R8tWxPus;(6nj1A0 zzo}cjNB!rSFC|%Kc@S3_Q*0GIPT>3V^wU^sM#w9S46-;c?JD(a&dZga@}tqo{vBk% z=b2q&)O^dOXUrwW{V!%q`S2OO)BAS?<;SsRhcRzGz;2#Vl!j|jrC+sv+C2*ctjLdB~cNt$yFY*fPYpo8lU~!;iK05HuEZ`tBeO5-!(||o8 zlI+E59n6l4ME?;FibwU?nGNzB%Gzs9Ybx_xHl#t($ewP14a7Eb`ODy(+w6Jm>YnGc z)d;j`T;k;cRc>cyH?Vh&#@7MNTpp^CB1%8hJx~VopRD290M(H)d=J$)Pg#!=wZ70Z zsXcPP(V^$=>51X9`~3rUbpz11UKi=<-(R$34<#AXwmm$jUeJiW3CEM)o2OtED9K3Z zx3L>Z!`U(y)KA&oE7Veh6JupYtQfLFsn~t6##wO8URt&q93|#aCu z(Iy~RIdGS7_Sb^RcvZFFFs0yJSt%=dkYObvXVOAD6IUKMh>^_lz)La()Z(vq;s45< z{zAhh3etionpUOd&Vq1Ot$~_=cisy+Imb%R&AM>LB5)cyMIAeb{u)q zUbJ+dp{-ntwlW@_-Ck^|j5KC!SfiAfS*m2f6Yns;of*@QnN{t^_0sLdH%;hKY1(17 z@RZ1q9x^gFslf=o*N|3S$;9>73gX$|8K-9Zzm;3VuM^qa+QLyH=lYFu*)D&gIaUZ{}_6#hV@<6 zOATsOE1wf&@>I~s-eGL@={?W8aXxPHS)Jr#^w`L+>A+}OPU`7fgmzV-wJoV(05!~F zt?PZgk^LxAnMZw}FwTRiuLmeeyMb2BZfojx)oa74JzGy!)`!fwmT|^E({@aWm(gr% z(L(X}JKWieI^saG@gRU*pdszU^xXLkigFhm;Q1*fC%P!KiPympKL->iZt_f{7x*TS z)p~G`6eFJhSMk5ro{PEE+OFVzJ?~rjbq71%D31v|e}KA-MR)2kF&)VwyyA znn;7DGBdR888A$?Krx?$3Mgs+n>&A|g?p%Z4K>VU4)pIH%GD2wAUZOZ&op`!Ps@%% z3lkGF!E-G}=h^=whG-ec_dSRR;yAQ;EnZ>Vbn= zP_rlC;hce|2AlYmP-@TC6F?6A_*L67vn}UmBvJ)xf14AW=W?~XPf=STe%B7WKR8Q% zv=;=UebAq9JuS{}z~e5!n~uPlw8owR)$R?w*3+;U^!gb_+&FSxj&gD+ZU#o)sKBwb z^&L>zFxs;i4!jE~(=mA6HPF~U)bN1UZP3(Zo=aK|jhVH%@n)CA+$c0y*+n(O#hE1tX*nu|BKok+yAT)QmHtm!^?4jJ!(o-oeIO4ij3 z+M(CzC|)C2Wuth>JM~vpD?SX|IuSf0*4@eYona(nKtcIHFy*ln6K6F;*Vz!MT{Un` zQM9mWk&qb+&-f=tfi7*MOQzS6wSw-XdIjUn+T4OWz4>rd@+R;_7={ zResxx9c5gb@yx4oL^0bES`^Q?Y^Fu)nT?2#>ZkN)3hf=riKH7NrFO3(a^}43ge>g4 zEJ*LOvI8?AQ!(QV2MW-lJ2NepzVR=B#q>0KfoIIt7m0jr#`+TMAafLyqr`IITxH41 z^p!y$}QtG+>+mjl}Q4AfI!sw>cSZGsZu3o8S*G6MQwa92+_moeG9f_grHOLYsM zI`hf=h}t-H2&hiYRcBruxy#&I=3rNMG8w!!6D}AB-<<%iQ$8>P%0CDM(ia}^A$NA? z$q(R%ZNXLA>on)3<&*YeHR0ctkVEN#mlG6|7Sy4Y)&GM2&3LWZKp;iH9F+rV(5~l$ z&=PrSciLjy24jAxDb}+s59sDTavk$Etp_*E#bRw5c5BnI@SlfwV?4I&MnF9Y(zy%Q z&jN}l0~R!cPYcRwPw&jyqkUlqN>=8g@2WnZqO@nh5#mAp5l&Oeevr;S(AbY4lWWwg ze}Njw82XSJRAgV0^GX7)dq|DMiWP?wQ0CRq&- zoOnDbEjmwojNQ8t8zb}!2s|m+>P7BnUGIU>?(nqOItt{fU#n6eW4-BT>5BN6wWn5cKI5fz{Z6or{*c>vY40D; zFZu!XW6iXr-Bsv!ae7gNS*^(2HwCr1q9-B4S&2k-AN%SeavFWFQ^AAP*%{mILeTSX z;jS4Vzlc_JEak?9nvHq07pcuj_HiT{$G@B_^{F-nf13Yvet)x9jqqWH%k8vm6Ma|j zz8&e6@z1n2y8;TkiPk{-D)C-KJD3w)MR6#K+58GaQ;I=D)Z*!*9?SWxGM`IBgI)le zWQ0OJ0+n2&&1XPRdS>eVorIobf^L<72GxO{>KCb`s0S3YE7(VG06oKAqx2U!4QGdr zNC%&VQkj{cBz0?lQZLAHv>}$CcZB+C#nKqvq46?m^6r`ORj^hpSJZ}AvKd9LE}HJW4ro9dZ*u`1r1Z`3l7)eLjG*ixpa>-dQ;`aoH+nfde>prS z!T~pM_f`o(CdF2YZb1gX*Iv}_5y?-NGYm^1@!gRcQYPr zxte}OyoU$Ct=lvI&1pw%RnN`-&@_zX`n5M2@1* zgXu}XfMG0m77;~uvRX95o2k^5IM(1;^!(KY{Xix&ASxmRn~{GdDZczgo@vQ8lDQLYx#pd zqMnYG-^+IwK-;CqUxJr@1Xtb0ZZ`wyt{5XzkzTw)FUs&&0b21iG&Y*@Jbzy2QlobU z`fa{bEmk60oc+-B6Ht65fj0tOH#*xLO1=w?zXMhNljm;0Z9GRBz3CrH{2TuBGkj<} z{Aezm@sohAJ^^c~M~m1duYyx;q@}yz8{dNPj>38L8dC@2nfx=bgC6>kQ~5wn;va`I z`5X~95%;A(akQ#bZVi(qdGuMogMa)W2#g|6QC`M1!s~2LN3W3qJ-zybbZ~aKt!l*>kgh%as>h6-~R#hR;IH6 literal 0 HcmV?d00001 diff --git a/arm9/gfx_data/diskmenu_bg.png b/arm9/gfx_data/diskmenu_bg.png new file mode 100644 index 0000000000000000000000000000000000000000..d0010c5efa1132ec993d2083f3bb09bb49830585 GIT binary patch literal 24699 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℘d+y9L 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 PWeQM|Q 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 literal 0 HcmV?d00001 diff --git a/arm9/gfx_data/mainmenu_bg.png b/arm9/gfx_data/mainmenu_bg.png new file mode 100644 index 0000000000000000000000000000000000000000..e5ace4b58e5058303934b2643647cbd9988acc52 GIT binary patch literal 24219 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 Ad;kCd literal 0 HcmV?d00001 diff --git a/arm9/source/1541d64.cpp b/arm9/source/1541d64.cpp new file mode 100644 index 0000000..0fe762a --- /dev/null +++ b/arm9/source/1541d64.cpp @@ -0,0 +1,2176 @@ +/* + * 1541d64.cpp - 1541 emulation in disk image files (.d64/.x64/zipcode) + * + * Frodo Copyright (C) Christian Bauer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Incompatibilities: + * - No support for relative files + * - Unimplemented commands: P + * - Impossible to implement: B-E, M-E + */ + +#include "sysdeps.h" + +#include "1541d64.h" +#include "IEC.h" +#include "Prefs.h" +#include "C64.h" +#include "main.h" + +// Channel modes (IRC users listen up :-) +enum { + CHMOD_FREE, // Channel free + CHMOD_COMMAND, // Command/error channel + CHMOD_DIRECTORY, // Reading directory, using large allocated buffer + CHMOD_FILE, // Sequential file open, using buffer in 1541 RAM + CHMOD_REL, // Relative file open, using buffer in 1541 RAM + CHMOD_DIRECT // Direct buffer access ('#'), using buffer in 1541 RAM +}; + +// Directory track +const int DIR_TRACK = 18; + +// BAM structure +enum { + BAM_DIR_TRACK = 0, // Track... + BAM_DIR_SECTOR = 1, // ...and sector of first directory block (unused) + BAM_FMT_TYPE = 2, // Format type + BAM_BITMAP = 4, // Sector allocation map + BAM_DISK_NAME = 144, // Disk name + BAM_DISK_ID = 162, // Disk ID + BAM_FMT_CHAR = 165 // Format characters +}; + +// Directory structure +enum { + DIR_NEXT_TRACK = 0, // Track... + DIR_NEXT_SECTOR = 1, // ... and sector of next directory block + DIR_ENTRIES = 2, // Start of directory entries (8) + + DE_TYPE = 0, // File type/flags + DE_TRACK = 1, // Track... + DE_SECTOR = 2, // ...and sector of first data block + DE_NAME = 3, // File name + DE_SIDE_TRACK = 19, // Track... + DE_SIDE_SECTOR = 20, // ...and sector of first side sector + DE_REC_LEN = 21, // Record length + DE_OVR_TRACK = 26, // Track... + DE_OVR_SECTOR = 27, // ...and sector on overwrite (@) + DE_NUM_BLOCKS_L = 28, // Number of blocks, LSB + DE_NUM_BLOCKS_H = 29, // Number of blocks, MSB + + SIZEOF_DE = 32 // Size of directory entry +}; + +// Interleave of directory and data blocks +const int DIR_INTERLEAVE = 3; +const int DATA_INTERLEAVE = 10; + +// Number of sectors per track, for all tracks +const int num_sectors[41] = { + 0, + 21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21, + 19,19,19,19,19,19,19, + 18,18,18,18,18,18, + 17,17,17,17,17, + 17,17,17,17,17 // Tracks 36..40 +}; + +// Accumulated number of sectors +const int accum_num_sectors[41] = { + 0, + 0,21,42,63,84,105,126,147,168,189,210,231,252,273,294,315,336, + 357,376,395,414,433,452,471, + 490,508,526,544,562,580, + 598,615,632,649,666, + 683,700,717,734,751 // Tracks 36..40 +}; + +// Prototypes +static bool match(const uint8 *p, int p_len, const uint8 *n); +static FILE *open_image_file(const char *path, bool write_mode); +static bool parse_image_file(FILE *f, image_file_desc &desc); + + +/* + * Constructor: Prepare emulation, open image file + */ + +ImageDrive::ImageDrive(IEC *iec, const char *filepath) : Drive(iec), the_file(NULL), bam(ram + 0x700), bam_dirty(false) +{ + for (int i=0; i<18; i++) { + ch[i].mode = CHMOD_FREE; + ch[i].buf = NULL; + } + ch[15].mode = CHMOD_COMMAND; + + Reset(); + + // Open image file + if (change_image(filepath)) + Ready = true; +} + + +/* + * Destructor + */ + +ImageDrive::~ImageDrive() +{ + close_image(); +} + + +/* + * Close the image file + */ + +void ImageDrive::close_image(void) +{ + if (the_file) { + close_all_channels(); + if (bam_dirty) { + write_sector(DIR_TRACK, 0, bam); + bam_dirty = false; + } + fclose(the_file); + the_file = NULL; + } +} + + +/* + * Open the image file + */ + +bool ImageDrive::change_image(const char *path) +{ + // Close old image file + close_image(); + + // Open new image file (try write access first, then read-only) + write_protected = false; + the_file = open_image_file(path, true); + if (the_file == NULL) { + write_protected = true; + the_file = open_image_file(path, false); + } + if (the_file) { + + // Determine file type and fill in image_file_desc structure + if (!parse_image_file(the_file, desc)) { + fclose(the_file); + the_file = NULL; + return false; + } + + // Read BAM + read_sector(DIR_TRACK, 0, bam); + bam_dirty = false; + return true; + } else + return false; +} + + +/* + * Open channel + */ + +uint8 ImageDrive::Open(int channel, const uint8 *name, int name_len) +{ + //sprintf(a,"ImageDrive::Open channel %d, file %s\n", channel, name);printdbg(a); + + set_error(ERR_OK); + + // Channel 15: execute file name as command + if (channel == 15) { + execute_cmd(name, name_len); + return ST_OK; + } + + if (ch[channel].mode != CHMOD_FREE) + { + // Gauntlet... sigh... +#if 0 + set_error(ERR_NOCHANNEL); + return ST_OK; +#endif + } + + if (name[0] == '$') { + if (channel) + return open_file_ts(channel, DIR_TRACK, 0); + else + return open_directory(name + 1, name_len - 1); + } + + if (name[0] == '#') { + return open_direct(channel, name); + } + + return open_file(channel, name, name_len); +} + + +/* + * Open file + */ + +uint8 ImageDrive::open_file(int channel, const uint8 *name, int name_len) +{ + //sprintf(a,"ImageDrive::open_file , file %s %d\n", name, name_len);printdbg(a); + uint8 plain_name[NAMEBUF_LENGTH]; + int plain_name_len; + int mode = FMODE_READ; + int type = FTYPE_DEL; + int rec_len = 0; + parse_file_name(name, name_len, plain_name, plain_name_len, mode, type, rec_len); + if (plain_name_len > 16) + plain_name_len = 16; + + //sprintf(a," plain name %s, type %d, mode %d\n", plain_name, type, mode);printdbg(a); + + // Channel 0 is READ, channel 1 is WRITE + if (channel == 0 || channel == 1) { + mode = channel ? FMODE_WRITE : FMODE_READ; + if (type == FTYPE_DEL) + type = FTYPE_PRG; + } + + ch[channel].writing = (mode == FMODE_WRITE || mode == FMODE_APPEND); + + // Wildcards are only allowed on reading + if (ch[channel].writing && (strchr((const char *)plain_name, '*') || strchr((const char *)plain_name, '?'))) { + set_error(ERR_SYNTAX33); + return ST_OK; + } + + // Check for write-protection if writing + if (ch[channel].writing && write_protected) { + set_error(ERR_WRITEPROTECT); + return ST_OK; + } + + // Relative files are not supported + if (type == FTYPE_REL) { + set_error(ERR_UNIMPLEMENTED); + return ST_OK; + } + + // Find file in directory + int dir_track, dir_sector, entry; + if (find_first_file(plain_name, plain_name_len, dir_track, dir_sector, entry)) { + + // File exists + //sprintf(a," file exists, dir track %d, sector %d, entry %d\n", dir_track, dir_sector, entry);printdbg(a); + ch[channel].dir_track = dir_track; + ch[channel].dir_sector = dir_sector; + ch[channel].entry = entry; + uint8 *de = dir + DIR_ENTRIES + entry * SIZEOF_DE; + + // Get file type from existing file if not specified in file name + if (type == FTYPE_DEL) + type = de[DE_TYPE] & 7; + + if ((de[DE_TYPE] & 7) != type) { + + // File type doesn't match + set_error(ERR_FILETYPE); + + } else if (mode == FMODE_WRITE) { + + if (name[0] == '@') { + + // Open old file for overwriting (save-replace) + return create_file(channel, plain_name, plain_name_len, type, true); + + } else { + + // File to be written already exists, error + set_error(ERR_FILEEXISTS); + } + + } else if (mode == FMODE_APPEND) { + + // Open old file for appending + open_file_ts(channel, de[DE_TRACK], de[DE_SECTOR]); + + // Seek to end of file + int track = 0, sector = 0, num_blocks = 0; + while (ch[channel].buf[0]) { + if (!read_sector(track = ch[channel].buf[0], sector = ch[channel].buf[1], ch[channel].buf)) + return ST_OK; + num_blocks++; + } + + // Change channel mode to writing, adjust buffer pointer + ch[channel].writing = true; + ch[channel].buf_len = ch[channel].buf[1] + 1; + ch[channel].buf_ptr = ch[channel].buf + ch[channel].buf_len; + ch[channel].track = track; + ch[channel].sector = sector; + ch[channel].num_blocks = num_blocks; + + } else if (mode == FMODE_M) { + + // Open old file for reading, even if it is not closed + return open_file_ts(channel, de[DE_TRACK], de[DE_SECTOR]); + + } else { + + // Open old file for reading, error if file is open + if (de[DE_TYPE] & 0x80) + return open_file_ts(channel, de[DE_TRACK], de[DE_SECTOR]); + else + set_error(ERR_WRITEFILEOPEN); + } + + } else { + + // File doesn't exist + //sprintf(a," file not found\n");printdbg(a); + + // Set file type to SEQ if not specified in file name + if (type == FTYPE_DEL) + type = FTYPE_SEQ; + + if (mode == FMODE_WRITE) { + + // Create new file for writing + return create_file(channel, plain_name, plain_name_len, type); + + } else + set_error(ERR_FILENOTFOUND); + } + return ST_OK; +} + + +/* + * Open channel for reading from file given track/sector of first block + */ + +uint8 ImageDrive::open_file_ts(int channel, int track, int sector) +{ + //sprintf(a,"open_file_ts track %d, sector %d\n", track, sector);printdbg(a); + + // Allocate buffer and set channel mode + int buf = alloc_buffer(-1); + if (buf == -1) { + set_error(ERR_NOCHANNEL); + return ST_OK; + } + ch[channel].buf_num = buf; + ch[channel].buf = ram + 0x300 + buf * 0x100; + ch[channel].mode = CHMOD_FILE; + + // On the next call to Read, the first block will be read + ch[channel].buf[0] = track; + ch[channel].buf[1] = sector; + ch[channel].buf_len = 0; + + return ST_OK; +} + + +/* + * Create file and open channel for writing to file + */ + +uint8 ImageDrive::create_file(int channel, const uint8 *name, int name_len, int type, bool overwrite) +{ + //sprintf(a,"create_file %s, type %d\n", name, type);printdbg(a); + + // Allocate buffer + int buf = alloc_buffer(-1); + if (buf == -1) { + set_error(ERR_NOCHANNEL); + return ST_OK; + } + ch[channel].buf_num = buf; + ch[channel].buf = ram + 0x300 + buf * 0x100; + + // Allocate new directory entry if not overwriting + if (!overwrite) { + if (!alloc_dir_entry(ch[channel].dir_track, ch[channel].dir_sector, ch[channel].entry)) { + free_buffer(buf); + return ST_OK; + } + } + uint8 *de = dir + DIR_ENTRIES + ch[channel].entry * SIZEOF_DE; + + // Allocate first data block + ch[channel].track = DIR_TRACK - 1; + ch[channel].sector = -DATA_INTERLEAVE; + if (!alloc_next_block(ch[channel].track, ch[channel].sector, DATA_INTERLEAVE)) { + free_buffer(buf); + return ST_OK; + } + ch[channel].num_blocks = 1; + //sprintf(a," first data block on track %d, sector %d\n", ch[channel].track, ch[channel].sector);printdbg(a); + + // Write directory entry + memset(de, 0, SIZEOF_DE); + de[DE_TYPE] = type; // bit 7 not set -> open file + if (overwrite) { + de[DE_OVR_TRACK] = ch[channel].track; + de[DE_OVR_SECTOR] = ch[channel].sector; + } else { + de[DE_TRACK] = ch[channel].track; + de[DE_SECTOR] = ch[channel].sector; + } + memset(de + DE_NAME, 0xa0, 16); + memcpy(de + DE_NAME, name, name_len); + write_sector(ch[channel].dir_track, ch[channel].dir_sector, dir); + + // Set channel descriptor + ch[channel].mode = CHMOD_FILE; + ch[channel].writing = true; + ch[channel].buf_ptr = ch[channel].buf + 2; + ch[channel].buf_len = 2; + return ST_OK; +} + + +/* + * Prepare directory as BASIC program (channel 0) + */ + +const char type_char_1[] = "DSPUREER"; +const char type_char_2[] = "EERSELQG"; +const char type_char_3[] = "LQGRL???"; + +uint8 ImageDrive::open_directory(const uint8 *pattern, int pattern_len) +{ + // Special treatment for "$0" + if (pattern[0] == '0' && pattern_len == 1) { + pattern++; + pattern_len--; + } + + // Skip everything before the ':' in the pattern + uint8 *t = (uint8 *)memchr(pattern, ':', pattern_len); + if (t) { + t++; + pattern_len -= t - pattern; + pattern = t; + } + + ch[0].mode = CHMOD_DIRECTORY; + uint8 *p = ch[0].buf_ptr = ch[0].buf = new uint8[8192]; + + // Create directory title with disk name, ID and format type + *p++ = 0x01; // Load address $0401 (from PET days :-) + *p++ = 0x04; + *p++ = 0x01; // Dummy line link + *p++ = 0x01; + *p++ = 0; // Drive number (0) as line number + *p++ = 0; + *p++ = 0x12; // RVS ON + *p++ = '\"'; + + uint8 *q = bam + BAM_DISK_NAME; + for (int i=0; i<23; i++) { + int c; + if ((c = *q++) == 0xa0) + *p++ = ' '; // Replace 0xa0 by space + else + *p++ = c; + } + *(p-7) = '\"'; + *p++ = 0; + + // Scan all directory blocks + dir[DIR_NEXT_TRACK] = DIR_TRACK; + dir[DIR_NEXT_SECTOR] = 1; + + int num_dir_blocks = 0; + while (dir[DIR_NEXT_TRACK] && num_dir_blocks < num_sectors[DIR_TRACK]) { + if (!read_sector(dir[DIR_NEXT_TRACK], dir[DIR_NEXT_SECTOR], dir)) + return ST_OK; + num_dir_blocks++; + + // Scan all 8 entries of a block + uint8 *de = dir + DIR_ENTRIES; + for (int j=0; j<8; j++, de+=SIZEOF_DE) { + if (de[DE_TYPE] && (pattern_len == 0 || match(pattern, pattern_len, de + DE_NAME))) { + + // Dummy line link + *p++ = 0x01; + *p++ = 0x01; + + // Line number = number of blocks + *p++ = de[DE_NUM_BLOCKS_L]; + *p++ = de[DE_NUM_BLOCKS_H]; + + // Appropriate number of spaces to align file names + *p++ = ' '; + int n = (de[DE_NUM_BLOCKS_H] << 8) + de[DE_NUM_BLOCKS_L]; + if (n<10) *p++ = ' '; + if (n<100) *p++ = ' '; + + // File name enclosed in quotes + *p++ = '\"'; + q = de + DE_NAME; + uint8 c; + bool m = false; + for (int i=0; i<16; i++) { + if ((c = *q++) == 0xa0) { + if (m) + *p++ = ' '; // Replace all 0xa0 by spaces + else + m = (*p++ = '\"'); // But the first by a '"' + } else + *p++ = c; + } + if (m) + *p++ = ' '; + else + *p++ = '\"'; // No 0xa0, then append a space + + // Open files are marked by '*' + if (de[DE_TYPE] & 0x80) + *p++ = ' '; + else + *p++ = '*'; + + // File type + *p++ = type_char_1[de[DE_TYPE] & 7]; + *p++ = type_char_2[de[DE_TYPE] & 7]; + *p++ = type_char_3[de[DE_TYPE] & 7]; + + // Protected files are marked by '<' + if (de[DE_TYPE] & 0x40) + *p++ = '<'; + else + *p++ = ' '; + + // Appropriate number of spaces at the end + *p++ = ' '; + if (n >= 10) *p++ = ' '; + if (n >= 100) *p++ = ' '; + *p++ = 0; + } + } + } + + // Final line, count number of free blocks + int n = 0; + for (int i=1; i<=35; i++) { + if (i != DIR_TRACK) // exclude track 18 + n += num_free_blocks(i); + } + + *p++ = 0x01; // Dummy line link + *p++ = 0x01; + *p++ = n & 0xff; // Number of free blocks as line number + *p++ = (n >> 8) & 0xff; + + *p++ = 'B'; + *p++ = 'L'; + *p++ = 'O'; + *p++ = 'C'; + *p++ = 'K'; + *p++ = 'S'; + *p++ = ' '; + *p++ = 'F'; + *p++ = 'R'; + *p++ = 'E'; + *p++ = 'E'; + *p++ = '.'; + + memset(p, ' ', 13); + p += 13; + + *p++ = 0; + *p++ = 0; + *p++ = 0; + + ch[0].buf_len = p - ch[0].buf; + return ST_OK; +} + + +/* + * Open channel for direct buffer access + */ + +uint8 ImageDrive::open_direct(int channel, const uint8 *name) +{ + int buf = -1; + + if (name[1] == 0) + buf = alloc_buffer(-1); + else + if ((name[1] >= '0') && (name[1] <= '3') && (name[2] == 0)) + buf = alloc_buffer(name[1] - '0'); + + if (buf == -1) { + set_error(ERR_NOCHANNEL); + return ST_OK; + } + + // The buffers are in the 1541 RAM at $300 and are 256 bytes each + ch[channel].mode = CHMOD_DIRECT; + ch[channel].buf = ram + 0x300 + buf * 0x100; + ch[channel].buf_num = buf; + + // Store actual buffer number in buffer + ch[channel].buf[1] = buf + '0'; + ch[channel].buf_len = 1; + ch[channel].buf_ptr = ch[channel].buf + 1; + + return ST_OK; +} + + +/* + * Close channel + */ + +uint8 ImageDrive::Close(int channel) +{ + //sprintf(a,"ImageDrive::Close channel %d\n", channel);printdbg(a); + + switch (ch[channel].mode) { + case CHMOD_FREE: + break; + + case CHMOD_COMMAND: + close_all_channels(); + break; + + case CHMOD_DIRECT: + free_buffer(ch[channel].buf_num); + ch[channel].buf = NULL; + ch[channel].mode = CHMOD_FREE; + break; + + case CHMOD_FILE: + if (ch[channel].writing) { + + // Current block empty? Then write CR character + if (ch[channel].buf_len == 2) { + ch[channel].buf[2] = 0x0d; + ch[channel].buf_len++; + } + + // Write last data block + ch[channel].buf[0] = 0; + ch[channel].buf[1] = ch[channel].buf_len - 1; + //sprintf(a," writing last data block\n");printdbg(a); + if (!write_sector(ch[channel].track, ch[channel].sector, ch[channel].buf)) + goto free; + + // Close write file in directory + read_sector(ch[channel].dir_track, ch[channel].dir_sector, dir); + uint8 *de = dir + DIR_ENTRIES + ch[channel].entry * SIZEOF_DE; + de[DE_TYPE] |= 0x80; + de[DE_NUM_BLOCKS_L] = ch[channel].num_blocks & 0xff; + de[DE_NUM_BLOCKS_H] = ch[channel].num_blocks >> 8; + if (de[DE_OVR_TRACK]) { + // Overwriting, free old data blocks and set pointer to new ones + free_block_chain(de[DE_TRACK], de[DE_SECTOR]); + de[DE_TRACK] = de[DE_OVR_TRACK]; + de[DE_SECTOR] = de[DE_OVR_SECTOR]; + de[DE_OVR_TRACK] = de[DE_OVR_SECTOR] = 0; + } + write_sector(ch[channel].dir_track, ch[channel].dir_sector, dir); + //sprintf(a," directory entry updated\n");printdbg(a); + } +free: free_buffer(ch[channel].buf_num); + ch[channel].buf = NULL; + ch[channel].mode = CHMOD_FREE; + break; + + case CHMOD_DIRECTORY: + delete[] ch[channel].buf; + ch[channel].buf = NULL; + ch[channel].mode = CHMOD_FREE; + break; + } + + return ST_OK; +} + + +/* + * Close all channels + */ + +void ImageDrive::close_all_channels() +{ + for (int i=0; i<15; i++) + Close(i); + Close(16); + Close(17); + + cmd_len = 0; +} + + +/* + * Read from channel + */ + +uint8 ImageDrive::Read(int channel, uint8 &byte) +{ + //sprintf(a,"ImageDrive::Read channel %d\n", channel);printdbg(a); + + switch (ch[channel].mode) { + case CHMOD_FREE: + if (current_error == ERR_OK) + set_error(ERR_FILENOTOPEN); + break; + + case CHMOD_COMMAND: + // Read error channel + byte = *error_ptr++; + if (--error_len) + return ST_OK; + else { + set_error(ERR_OK); + return ST_EOF; + } + break; + + case CHMOD_FILE: + if (ch[channel].writing) + return ST_READ_TIMEOUT; + if (current_error != ERR_OK) + return ST_READ_TIMEOUT; + + // Read next block if necessary + if (ch[channel].buf_len == 0 && ch[channel].buf[0]) { + //sprintf(a," reading next data block track %d, sector %d\n", ch[channel].buf[0], ch[channel].buf[1]);printdbg(a); + if (!read_sector(ch[channel].buf[0], ch[channel].buf[1], ch[channel].buf)) + return ST_READ_TIMEOUT; + ch[channel].buf_ptr = ch[channel].buf + 2; + + // Determine block length + ch[channel].buf_len = ch[channel].buf[0] ? 254 : ch[channel].buf[1] - 1; + } + + if (ch[channel].buf_len > 0) { + byte = *(ch[channel].buf_ptr)++; + if (--(ch[channel].buf_len) == 0 && ch[channel].buf[0] == 0) + return ST_EOF; + else + return ST_OK; + } else + return ST_READ_TIMEOUT; + break; + + case CHMOD_DIRECTORY: + case CHMOD_DIRECT: + if (ch[channel].buf_len > 0) { + byte = *(ch[channel].buf_ptr)++; + if (--(ch[channel].buf_len)) + return ST_OK; + else + return ST_EOF; + } else + return ST_READ_TIMEOUT; + break; + } + return ST_READ_TIMEOUT; +} + + +/* + * Write byte to channel + */ + +uint8 ImageDrive::Write(int channel, uint8 byte, bool eoi) +{ + //sprintf(a,"ImageDrive::Write channel %d, byte %02x, eoi %d\n", channel, byte, eoi);printdbg(a); + + switch (ch[channel].mode) { + case CHMOD_FREE: + if (current_error == ERR_OK) + set_error(ERR_FILENOTOPEN); + break; + + case CHMOD_COMMAND: + // Collect characters and execute command on EOI + if (cmd_len > 58) { + set_error(ERR_SYNTAX32); + return ST_TIMEOUT; + } + + cmd_buf[cmd_len++] = byte; + + if (eoi) { + execute_cmd(cmd_buf, cmd_len); + cmd_len = 0; + } + return ST_OK; + + case CHMOD_DIRECTORY: + set_error(ERR_WRITEFILEOPEN); + break; + + case CHMOD_FILE: + if (!ch[channel].writing) + return ST_TIMEOUT; + if (current_error != ERR_OK) + return ST_TIMEOUT; + + // Buffer full? + if (ch[channel].buf_len >= 256) { + + // Yes, allocate new block + int track = ch[channel].track, sector = ch[channel].sector; + if (!alloc_next_block(track, sector, DATA_INTERLEAVE)) + return ST_TIMEOUT; + ch[channel].num_blocks++; + //sprintf(a,"next data block on track %d, sector %d\n", track, sector);printdbg(a); + + // Write buffer with link to new block + ch[channel].buf[0] = track; + ch[channel].buf[1] = sector; + write_sector(ch[channel].track, ch[channel].sector, ch[channel].buf); + + // Reset buffer + ch[channel].buf_ptr = ch[channel].buf + 2; + ch[channel].buf_len = 2; + ch[channel].track = track; + ch[channel].sector = sector; + } + *(ch[channel].buf_ptr)++ = byte; + ch[channel].buf_len++; + return ST_OK; + + case CHMOD_DIRECT: + if (ch[channel].buf_len < 256) { + *(ch[channel].buf_ptr)++ = byte; + ch[channel].buf_len++; + return ST_OK; + } else + return ST_TIMEOUT; + break; + } + return ST_TIMEOUT; +} + + +/* + * Reset drive + */ + +void ImageDrive::Reset(void) +{ + close_all_channels(); + + cmd_len = 0; + for (int i=0; i<4; i++) + buf_free[i] = true; + + if (bam_dirty) { + write_sector(DIR_TRACK, 0, bam); + bam_dirty = false; + } + + memset(ram, 0, sizeof(ram)); + + read_sector(DIR_TRACK, 0, bam); + + set_error(ERR_STARTUP); +} + + +/* + * Allocate floppy buffer + * -> Desired buffer number or -1 + * <- Allocated buffer number or -1 + */ + +int ImageDrive::alloc_buffer(int want) +{ + if (want == -1) { + for (want=3; want>=0; want--) + if (buf_free[want]) { + buf_free[want] = false; + return want; + } + return -1; + } + + if (want < 4) + if (buf_free[want]) { + buf_free[want] = false; + return want; + } else + return -1; + else + return -1; +} + + +/* + * Free floppy buffer + */ + +void ImageDrive::free_buffer(int buf) +{ + buf_free[buf] = true; +} + + +/* + * Search file in directory, return directory track/sector and entry number + * false: not found, true: found + */ + +// Return true if name 'n' matches pattern 'p' +static bool match(const uint8 *p, int p_len, const uint8 *n) +{ + if (p_len > 16) + p_len = 16; + + int c = 0; + while (p_len-- > 0) { + if (*p == '*') // Wildcard '*' matches all following characters + return true; + if ((*p != *n) && (*p != '?')) // Wildcard '?' matches single character + return false; + p++; n++; c++; + } + + return *n == 0xa0 || c == 16; +} + +bool ImageDrive::find_file(const uint8 *pattern, int pattern_len, int &dir_track, int &dir_sector, int &entry, bool cont) +{ + // Counter to prevent cyclic directories from resulting in an infinite loop + int num_dir_blocks = 0; + + // Pointer to current directory entry + uint8 *de = NULL; + if (cont) + de = dir + DIR_ENTRIES + entry * SIZEOF_DE; + else { + dir[DIR_NEXT_TRACK] = DIR_TRACK; + dir[DIR_NEXT_SECTOR] = 1; + entry = 8; + } + + while (num_dir_blocks < num_sectors[DIR_TRACK]) { + + // Goto next entry + entry++; de += SIZEOF_DE; + if (entry >= 8) { + + // Read next directory block + if (dir[DIR_NEXT_TRACK] == 0) + return false; + if (!read_sector(dir_track = dir[DIR_NEXT_TRACK], dir_sector = dir[DIR_NEXT_SECTOR], dir)) + return false; + num_dir_blocks++; + entry = 0; + de = dir + DIR_ENTRIES; + } + + // Does entry match pattern? + if ((de[DE_TYPE] & 0x3f) != FTYPE_DEL && match(pattern, pattern_len, de + DE_NAME)) + return true; + } + return false; +} + +bool ImageDrive::find_first_file(const uint8 *pattern, int pattern_len, int &dir_track, int &dir_sector, int &entry) +{ + return find_file(pattern, pattern_len, dir_track, dir_sector, entry, false); +} + +bool ImageDrive::find_next_file(const uint8 *pattern, int pattern_len, int &dir_track, int &dir_sector, int &entry) +{ + return find_file(pattern, pattern_len, dir_track, dir_sector, entry, true); +} + + +/* + * Allocate new entry in directory, returns false on error (usually when + * all sectors of track 18 are allocated) + * The track/sector and entry numbers are returned + */ + +bool ImageDrive::alloc_dir_entry(int &track, int §or, int &entry) +{ + // First look for free entry in existing directory blocks + dir[DIR_NEXT_TRACK] = DIR_TRACK; + dir[DIR_NEXT_SECTOR] = 1; + while (dir[DIR_NEXT_TRACK]) { + if (!read_sector(track = dir[DIR_NEXT_TRACK], sector = dir[DIR_NEXT_SECTOR], dir)) + return false; + + uint8 *de = dir + DIR_ENTRIES; + for (entry=0; entry<8; entry++, de+=SIZEOF_DE) { + if (de[DE_TYPE] == 0) { + //sprintf(a," allocated entry %d in dir track %d, sector %d\n", entry, track, sector);printdbg(a); + return true; + } + } + } + + // No free entry found, allocate new directory block + int last_track = track, last_sector = sector; + if (!alloc_next_block(track, sector, DIR_INTERLEAVE)) + return false; + //sprintf(a," new directory block track %d, sector %d\n", track, sector);printdbg(a); + + // Write link to new block to last block + dir[DIR_NEXT_TRACK] = track; + dir[DIR_NEXT_SECTOR] = sector; + write_sector(last_track, last_sector, dir); + + // Write new empty directory block and return first entry + memset(dir, 0, 256); + dir[DIR_NEXT_SECTOR] = 0xff; + write_sector(track, sector, dir); + entry = 0; + return true; +} + +/* + * Test if block is free in BAM (track/sector are not checked for validity) + */ + +bool ImageDrive::is_block_free(int track, int sector) +{ + uint8 *p = bam + BAM_BITMAP + (track - 1) * 4; + int byte = sector / 8 + 1; + int bit = sector & 7; + return p[byte] & (1 << bit); +} + + +/* + * Get number of free blocks on a track + */ + +int ImageDrive::num_free_blocks(int track) +{ + return bam[BAM_BITMAP + (track - 1) * 4]; +} + + +/* + * Clear BAM, mark all blocks as free + */ + +static void clear_bam(uint8 *bam) +{ + for (int track=1; track<=35; track++) { + static const uint8 num2bits[8] = {0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff}; + (bam + BAM_BITMAP)[(track-1) * 4 + 0] = num_sectors[track]; + (bam + BAM_BITMAP)[(track-1) * 4 + 1] = 0xff; + (bam + BAM_BITMAP)[(track-1) * 4 + 2] = 0xff; + (bam + BAM_BITMAP)[(track-1) * 4 + 3] = num2bits[num_sectors[track] - 16]; + } +} + + +/* + * Allocate block in BAM, returns error code + */ + +int ImageDrive::alloc_block(int track, int sector) +{ + if (track < 1 || track > 35 || sector < 0 || sector >= num_sectors[track]) + return ERR_ILLEGALTS; + + uint8 *p = bam + BAM_BITMAP + (track - 1) * 4; + int byte = sector / 8 + 1; + int bit = sector & 7; + + // Block free? + if (p[byte] & (1 << bit)) { + + // Yes, allocate and decrement free block count + //sprintf(a,"allocating block at track %d, sector %d\n", track, sector);printdbg(a); + p[byte] &= ~(1 << bit); + p[0]--; + bam_dirty = true; + return ERR_OK; + + } else + return ERR_NOBLOCK; +} + + +/* + * Free block in BAM, returns error code + */ + +int ImageDrive::free_block(int track, int sector) +{ + if (track < 1 || track > 35 || sector < 0 || sector >= num_sectors[track]) + return ERR_ILLEGALTS; + + uint8 *p = bam + BAM_BITMAP + (track - 1) * 4; + int byte = sector / 8 + 1; + int bit = sector & 7; + + // Block allocated? + if (!(p[byte] & (1 << bit))) { + + // Yes, free and increment free block count + //sprintf(a,"freeing block at track %d, sector %d\n", track, sector);printdbg(a); + p[byte] |= (1 << bit); + p[0]++; + bam_dirty = true; + } + return ERR_OK; +} + + +/* + * Allocate chain of data blocks in BAM + */ + +bool ImageDrive::alloc_block_chain(int track, int sector) +{ + uint8 buf[256]; + while (alloc_block(track, sector) == ERR_OK) { + if (!read_sector(track, sector, buf)) + return false; + track = buf[0]; + sector = buf[1]; + } + return true; +} + + +/* + * Free chain of data blocks in BAM + */ + +bool ImageDrive::free_block_chain(int track, int sector) +{ + uint8 buf[256]; + while (free_block(track, sector) == ERR_OK) { + if (!read_sector(track, sector, buf)) + return false; + track = buf[0]; + sector = buf[1]; + } + return true; +} + + +/* + * Search and allocate next free block, returns false if no more blocks + * are free (ERR_DISKFULL is also set in this case) + * "track" and "sector" must be set to the block where the search should + * begin + */ + +bool ImageDrive::alloc_next_block(int &track, int §or, int interleave) +{ + // Find track with free blocks + bool side_changed = false; + while (num_free_blocks(track) == 0) { + if (track == DIR_TRACK) { // Directory doesn't grow to other tracks +full: track = sector = 0; + set_error(ERR_DISKFULL); + return false; + } else if (track > DIR_TRACK) { + track++; + if (track > 35) { + if (!side_changed) + side_changed = true; + else + goto full; + track = DIR_TRACK - 1; + sector = 0; + } + } else { + track--; + if (track < 1) { + if (!side_changed) + side_changed = true; + else + goto full; + track = DIR_TRACK + 1; + sector = 0; + } + } + } + + // Find next free block on track + int num = num_sectors[track]; + sector = sector + interleave; + if (sector >= num) { + sector -= num; + if (sector) + sector--; + } + while (!is_block_free(track, sector)) { + sector++; + if (sector >= num_sectors[track]) { + sector = 0; + while (!is_block_free(track, sector)) { + sector++; + if (sector >= num_sectors[track]) { + // Something is wrong: the BAM free block count for this + // track was >0, but we found no free blocks + track = sector = 0; + set_error(ERR_DIRERROR); + return false; + } + } + } + } + + alloc_block(track, sector); + return true; +} + + +/* + * Sector reading/writing routines + */ + +static long offset_from_ts(const image_file_desc &desc, int track, int sector) +{ + if ((track < 1) || (track > desc.num_tracks) + || (sector < 0) || (sector >= num_sectors[track])) + return -1; + + return ((accum_num_sectors[track] + sector) << 8) + desc.header_size; +} + +// Get number of sectors per given track +int sectors_per_track(const image_file_desc &desc, int track) +{ + return num_sectors[track]; +} + +// Get reference to error info byte of given track/sector +uint8 &error_info_for_sector(image_file_desc &desc, int track, int sector) +{ + return desc.error_info[accum_num_sectors[track] + sector]; +} + +static inline const uint8 &error_info_for_sector(const image_file_desc &desc, int track, int sector) +{ + return desc.error_info[accum_num_sectors[track] + sector]; +} + +const int conv_job_error[16] = { + ERR_OK, // 0 -> 00 OK + ERR_OK, // 1 -> 00 OK + ERR_READ20, // 2 -> 20 READ ERROR + ERR_READ21, // 3 -> 21 READ ERROR + ERR_READ22, // 4 -> 22 READ ERROR + ERR_READ23, // 5 -> 23 READ ERROR + ERR_READ24, // 6 -> 24 READ ERROR (undetected by 1541) + ERR_WRITE25, // 7 -> 25 WRITE ERROR + ERR_WRITEPROTECT, // 8 -> 26 WRITE PROTECT ON + ERR_READ27, // 9 -> 27 READ ERROR + ERR_WRITE28, // 10 -> 28 WRITE ERROR + ERR_DISKID, // 11 -> 29 DISK ID MISMATCH + ERR_OK, // 12 -> 00 OK + ERR_OK, // 13 -> 00 OK + ERR_OK, // 14 -> 00 OK + ERR_NOTREADY // 15 -> 74 DRIVE NOT READY +}; + +// Read sector, return error code +static int read_sector(FILE *f, const image_file_desc &desc, int track, int sector, uint8 *buffer) +{ + floppy_soundfx(); // Play floppy SFX if needed + + // Convert track/sector to byte offset in file + long offset = offset_from_ts(desc, track, sector); + if (offset < 0) + return ERR_ILLEGALTS; + + if (f == NULL) + return ERR_NOTREADY; + + fseek(f, offset, SEEK_SET); + if (fread(buffer, 1, 256, f) != 256) + return ERR_READ22; + else { + unsigned int error = error_info_for_sector(desc, track, sector); + return conv_job_error[error & 0x0f]; + } +} + +// Write sector, return error code +static int write_sector(FILE *f, const image_file_desc &desc, int track, int sector, uint8 *buffer) +{ + floppy_soundfx(); // Play floppy SFX if needed + + // Convert track/sector to byte offset in file + long offset = offset_from_ts(desc, track, sector); + if (offset < 0) + return ERR_ILLEGALTS; + + if (f == NULL) + return ERR_NOTREADY; + + fseek(f, offset, SEEK_SET); + if (fwrite(buffer, 1, 256, f) != 256) + return ERR_WRITE25; + else + return ERR_OK; +} + +// Read sector and set error message, returns false on error +bool ImageDrive::read_sector(int track, int sector, uint8 *buffer) +{ + int error = ::read_sector(the_file, desc, track, sector, buffer); + if (error) + set_error(error, track, sector); + return error == ERR_OK; +} + +// Write sector and set error message, returns false on error +bool ImageDrive::write_sector(int track, int sector, uint8 *buffer) +{ + int error = ::write_sector(the_file, desc, track, sector, buffer); + if (error) + set_error(error, track, sector); + return error == ERR_OK; +} + +// Write error info back to image file +static void write_back_error_info(FILE *f, const image_file_desc &desc) +{ + if (desc.type == TYPE_D64 && desc.has_error_info) { + int num_sectors = desc.num_tracks == 40 ? NUM_SECTORS_40 : NUM_SECTORS_35; + fseek(f, num_sectors * 256, SEEK_SET); + fwrite(desc.error_info, num_sectors, 1, f); + } +} + +// Format disk image +static bool format_image(FILE *f, image_file_desc &desc, bool lowlevel, uint8 id1, uint8 id2, const uint8 *disk_name, int disk_name_len) +{ + uint8 p[256]; + + if (lowlevel) { + + // Fill buffer with 1541 empty sector pattern (4b 01 01 ..., + // except on track 1 where it's 01 01 01 ...) + memset(p, 1, 256); + + // Overwrite all blocks + for (int track=1; track<=35; track++) { + if (track == 2) + p[0] = 0x4b; + for (int sector=0; sector 16) + disk_name_len = 16; + memcpy(p + BAM_DISK_NAME, disk_name, disk_name_len); + p[BAM_DISK_ID] = id1; + p[BAM_DISK_ID + 1] = id2; + p[BAM_FMT_CHAR] = '2'; + p[BAM_FMT_CHAR + 1] = 'A'; + if (write_sector(f, desc, DIR_TRACK, 0, p) != ERR_OK) + return false; + + // Create and write empty directory + memset(p, 0, 256); + p[1] = 255; + return write_sector(f, desc, DIR_TRACK, 1, p) == ERR_OK; +} + + +/* + * Execute drive commands + */ + +// BLOCK-READ:channel,0,track,sector +void ImageDrive::block_read_cmd(int channel, int track, int sector, bool user_cmd) +{ + if (channel >= 16 || ch[channel].mode != CHMOD_DIRECT) { + set_error(ERR_NOCHANNEL); + return; + } + if (!read_sector(track, sector, ch[channel].buf)) + return; + if (user_cmd) { + ch[channel].buf_len = 256; + ch[channel].buf_ptr = ch[channel].buf; + } else { + ch[channel].buf_len = ch[channel].buf[0]; + ch[channel].buf_ptr = ch[channel].buf + 1; + } +} + +// BLOCK-WRITE:channel,0,track,sector +void ImageDrive::block_write_cmd(int channel, int track, int sector, bool user_cmd) +{ + if (write_protected) { + set_error(ERR_WRITEPROTECT); + return; + } + if (channel >= 16 || ch[channel].mode != CHMOD_DIRECT) { + set_error(ERR_NOCHANNEL); + return; + } + if (!user_cmd) + ch[channel].buf[0] = ch[channel].buf_len ? ch[channel].buf_len - 1 : 1; + if (!write_sector(track, sector, ch[channel].buf)) + return; + if (!user_cmd) { + ch[channel].buf_len = 1; + ch[channel].buf_ptr = ch[channel].buf + 1; + } +} + +// BLOCK-ALLOCATE:0,track,sector +void ImageDrive::block_allocate_cmd(int track, int sector) +{ + int err = alloc_block(track, sector); + if (err) { + if (err == ERR_NOBLOCK) { + // Find next free block and return its track/sector address in the + // error message (only look on higher tracks) + for (;;) { + sector++; + if (sector >= num_sectors[track]) { + track++; + sector = 0; + if (track > 35) { + set_error(ERR_NOBLOCK, 0, 0); + return; + } + } + if (is_block_free(track, sector)) { + set_error(ERR_NOBLOCK, track, sector); + return; + } + } + } else + set_error(err, track, sector); + } +} + +// BLOCK-FREE:0,track,sector +void ImageDrive::block_free_cmd(int track, int sector) +{ + int err = free_block(track, sector); + if (err) + set_error(err, track, sector); +} + +// BUFFER-POINTER:channel,pos +void ImageDrive::buffer_pointer_cmd(int channel, int pos) +{ + if (channel >= 16 || ch[channel].mode != CHMOD_DIRECT) { + set_error(ERR_NOCHANNEL); + return; + } + ch[channel].buf_ptr = ch[channel].buf + pos; + ch[channel].buf_len = 256 - pos; +} + +// M-R[] +void ImageDrive::mem_read_cmd(uint16 adr, uint8 len) +{ + error_len = len; + if (adr >= 0x300 && adr < 0x1000) { + // Read from RAM + error_ptr = (char *)ram + (adr & 0x7ff); + } else if (adr >= 0xc000) { + // Read from ROM + error_ptr = (char *)(TheC64->ROM1541) + (adr - 0xc000); + } else { + unsupp_cmd(); + memset(error_buf, 0, len); + error_ptr = error_buf; + } +} + +// M-W +void ImageDrive::mem_write_cmd(uint16 adr, uint8 len, uint8 *p) +{ + while (len) { + if (adr >= 0x300 && adr < 0x1000) { + // Write to RAM + ram[adr & 0x7ff] = *p; + } else if (adr < 0xc000) { + unsupp_cmd(); + return; + } + len--; adr++; p++; + } +} + +// COPY:new=file1,file2,... +// ^ ^ +// new_file old_files +void ImageDrive::copy_cmd(const uint8 *new_file, int new_file_len, const uint8 *old_files, int old_files_len) +{ + // Check if destination file is already present + int dir_track, dir_sector, entry; + if (find_first_file(new_file, new_file_len, dir_track, dir_sector, entry)) { + set_error(ERR_FILEEXISTS); + return; + } + + // Loop for all source files + bool first = true; + while (old_files_len > 0) { + uint8 *comma = (uint8 *)memchr(old_files, ',', old_files_len); + int name_len = comma ? comma - old_files : old_files_len; + + // Check if source file is present + if (!find_first_file(old_files, name_len, dir_track, dir_sector, entry)) { + set_error(ERR_FILENOTFOUND); + Close(17); + return; + } + uint8 *de = dir + DIR_ENTRIES + entry * SIZEOF_DE; + uint8 type = de[DE_TYPE] & 7, track = de[DE_TRACK], sector = de[DE_SECTOR]; + + // If this is the first source file, open internal write channel for destination file + if (first) { + create_file(17, new_file, new_file_len, type, false); + if (ch[17].mode == CHMOD_FREE) + return; + first = false; + } + + // Open internal read channel for source file + open_file_ts(16, track, sector); + if (ch[16].mode == CHMOD_FREE) { + Close(17); + return; + } + + // Copy file + uint8 byte, st; + do { + st = Read(16, byte); + Write(17, byte, false); + } while (st == ST_OK); + Close(16); + if (st != ST_EOF) { + Close(17); + return; + } + + if (comma) { + old_files_len -= name_len + 1; + old_files = comma + 1; + } else + old_files_len = 0; + } + Close(17); +} + +// RENAME:new=old +// ^ ^ +// new_file old_file +void ImageDrive::rename_cmd(const uint8 *new_file, int new_file_len, const uint8 *old_file, int old_file_len) +{ + // Check if destination file is already present + int dir_track, dir_sector, entry; + if (find_first_file(new_file, new_file_len, dir_track, dir_sector, entry)) { + set_error(ERR_FILEEXISTS); + return; + } + + // Check if source file is present + if (!find_first_file(old_file, old_file_len, dir_track, dir_sector, entry)) { + set_error(ERR_FILENOTFOUND); + return; + } + + // Check for write-protection + if (write_protected) { + set_error(ERR_WRITEPROTECT); + return; + } + + // Rename file in directory entry + uint8 *p = dir + DIR_ENTRIES + entry * SIZEOF_DE; + memset(p + DE_NAME, 0xa0, 16); + memcpy(p + DE_NAME, new_file, new_file_len); + write_sector(dir_track, dir_sector, dir); +} + +// SCRATCH:file1,file2,... +// ^ +// files +void ImageDrive::scratch_cmd(const uint8 *files, int files_len) +{ + // Check for write-protection + if (write_protected) { + set_error(ERR_WRITEPROTECT); + return; + } + + // Loop for all files + int num_files = 0; + while (files_len > 0) { + uint8 *comma = (uint8 *)memchr(files, ',', files_len); + int name_len = comma ? comma - files : files_len; + + int dir_track, dir_sector, entry; + if (find_first_file(files, name_len, dir_track, dir_sector, entry)) { + do { + uint8 *de = dir + DIR_ENTRIES + entry * SIZEOF_DE; + + // File protected? Then skip + if (de[DE_TYPE] & 0x40) + continue; + + // Free allocated data blocks and side sectors + free_block_chain(de[DE_TRACK], de[DE_SECTOR]); + free_block_chain(de[DE_SIDE_TRACK], de[DE_SIDE_SECTOR]); + + // Clear file type + de[DE_TYPE] = 0; + + // Write directory block back + write_sector(dir_track, dir_sector, dir); + num_files++; + } while (find_next_file(files, name_len, dir_track, dir_sector, entry)); + } + + if (comma) { + files_len -= name_len + 1; + files = comma + 1; + } else + files_len = 0; + } + + // Report number of files scratched + set_error(ERR_SCRATCHED, num_files); +} + +// INITIALIZE +void ImageDrive::initialize_cmd(void) +{ + // Close all channels and re-read BAM + close_all_channels(); + if (bam_dirty) { + write_sector(DIR_TRACK, 0, bam); + bam_dirty = false; + } + read_sector(DIR_TRACK, 0, bam); +} + +// NEW:name,id +// ^ ^ +// name comma (or NULL) +void ImageDrive::new_cmd(const uint8 *name, int name_len, const uint8 *comma) +{ + // Check for write-protection + if (write_protected) { + set_error(ERR_WRITEPROTECT); + return; + } + + // Remember current ID + uint8 id1 = bam[BAM_DISK_ID], id2 = bam[BAM_DISK_ID + 1]; + + // Formatting with ID? + if (comma) { + + close_all_channels(); + + // Clear BAM buffer + memset(bam, 0, 256); + + // Get ID from command + if (comma[1]) { + id1 = comma[1]; + id2 = comma[2] ? comma[2] : ' '; + } else { + id1 = id2 = ' '; + } + } + + // Format disk image + format_image(the_file, desc, comma, id1, id2, name, name_len); + + // Re-read BAM + read_sector(DIR_TRACK, 0, bam); + bam_dirty = false; +} + +// VALIDATE +void ImageDrive::validate_cmd(void) +{ + // Backup of old BAM in case something goes amiss + uint8 old_bam[256]; + memcpy(old_bam, bam, 256); + + // Clear BAM + clear_bam(bam); + bam_dirty = true; + + // Allocate BAM and directory + if (!alloc_block_chain(DIR_TRACK, 0)) { + memcpy(bam, old_bam, 256); + return; + } + + // Allocate all file data and side sector blocks + int dir_track, dir_sector, entry; + if (find_first_file((uint8 *)"*", 1, dir_track, dir_sector, entry)) { + do { + uint8 *de = dir + DIR_ENTRIES + entry * SIZEOF_DE; + + if (de[DE_TYPE] & 0x80) { + // Closed file, allocate all file data and side sector blocks + if (!alloc_block_chain(de[DE_TRACK], de[DE_SECTOR]) || !alloc_block_chain(de[DE_SIDE_TRACK], de[DE_SIDE_SECTOR])) { + memcpy(bam, old_bam, 256); + return; + } + } else { + // Open file, delete it + de[DE_TYPE] = 0; + write_sector(dir_track, dir_sector, dir); + } + } while (find_next_file((uint8 *)"*", 1, dir_track, dir_sector, entry)); + } +} + + +/* + * Check whether file with given header (64 bytes) and size looks like one + * of the file types supported by this module + */ + +static bool is_d64_file(const uint8 *header, long size) +{ + return size == NUM_SECTORS_35 * 256 || size == NUM_SECTORS_35 * 257 + || size == NUM_SECTORS_40 * 256 || size == NUM_SECTORS_40 * 257; +} + +static bool is_ed64_file(const uint8 *header, long size) +{ + // 35-track d64 file with header ID at the end (only used internally for + // converted zipcode files) + return size == NUM_SECTORS_35 * 256 + 2; +} + +static bool is_x64_file(const uint8 *header, long size) +{ + return memcmp(header, "C\x15\x41\x64\x01\x02", 6) == 0; +} + +static bool is_zipcode_file(const char *path) +{ +#if 0 + string base, part; + SplitPath(path, base, part); + return part.length() > 2 && part[0] >= '1' && part[0] <= '4' && part[1] == '!'; +#else + return false; +#endif +} + +bool IsImageFile(const char *path, const uint8 *header, long size) +{ + return is_d64_file(header, size) || is_x64_file(header, size) || is_zipcode_file(path); +} + + +#if 0 +/* + * Convert zipcode file to extended d64 file (d64 file with header ID) + */ + +static FILE *open_zipcode_file(FILE *old, int num, const string &base, string &part, uint8 &id1, uint8 &id2) +{ + if (old) + fclose(old); + part[0] = num + '1'; + FILE *f = fopen(AddToPath(base, part).c_str(), "rb"); + if (f == NULL) + return NULL; + if (fseek(f, 2, SEEK_SET) < 0) { + fclose(f); + return NULL; + } + if (num == 0) { + id1 = getc(f); + id2 = getc(f); + } + return f; +} + +static FILE *convert_zipcode_to_ed64(const string &path) +{ + FILE *in = NULL, *out = NULL; + uint8 id1, id2; + + // Split input file name + string base, part; + SplitPath(path, base, part); + + // Open output file + out = NULL;//fopen("ramdiskfs:/ram/test3.txt","wb"); + if (out == NULL) + goto error; + + // Decode all tracks + for (int track=1; track<=35; track++) { + int max_sect = 17 + ((track < 31) ? 1 : 0) + ((track < 25) ? 1 : 0) + ((track < 18) ? 2 : 0); + + // Select appropriate input file + switch (track) { + case 1: + if ((in = open_zipcode_file(NULL, 0, base, part, id1, id2)) == NULL) + goto error; + break; + case 9: + if ((in = open_zipcode_file(in, 1, base, part, id1, id2)) == NULL) + goto error; + break; + case 17: + if ((in = open_zipcode_file(in, 2, base, part, id1, id2)) == NULL) + goto error; + break; + case 26: + if ((in = open_zipcode_file(in, 3, base, part, id1, id2)) == NULL) + goto error; + break; + } + + // Clear "sector read" flags + bool sect_flag[21]; + for (int i=0; i= max_sect || sect_flag[s] || feof(in)) + goto error; + sect_flag[s] = true; + uint8 *p = act_track + s * 256; + + // Uncompress sector + if (t & 0x80) { + // Run-length encoded sector + uint8 len = getc(in); + uint8 rep = getc(in); + int count = 0; + for (int j=0; j 40) + return false; + + // Read header ID from BAM (use error_info as buffer) + fseek(f, desc.header_size + accum_num_sectors[18] * 256, SEEK_SET); + fread(desc.error_info, 1, 256, f); + desc.id1 = desc.error_info[BAM_DISK_ID]; + desc.id2 = desc.error_info[BAM_DISK_ID + 1]; + + // .x64 files have no error info + memset(desc.error_info, 1, sizeof(desc.error_info)); + desc.has_error_info = false; + return true; +} + +static bool parse_image_file(FILE *f, image_file_desc &desc) +{ + // Read header + uint8 header[64]; + fread(header, 1, sizeof(header), f); + + // Determine file size + fseek(f, 0, SEEK_END); + long size = ftell(f); + + // Determine file type and fill in image_file_desc structure + if (is_x64_file(header, size)) + return parse_x64_file(f, desc); + else if (is_d64_file(header, size)) + return parse_d64_file(f, desc, false); + else if (is_ed64_file(header, size)) + return parse_d64_file(f, desc, true); + else + return false; +} + + +/* + * Read directory of disk image file into (empty) c64_dir_entry vector, + * returns false on error + */ + +bool ReadImageDirectory(const char *path, vector &vec) +{ + bool result = false; + + // Open file + FILE *f = open_image_file(path, false); + if (f) { + int num_dir_blocks = 0; + + // Determine file type and fill in image_file_desc structure + image_file_desc desc; + if (!parse_image_file(f, desc)) + goto done; + + // Scan all directory blocks + uint8 dir[256]; + dir[DIR_NEXT_TRACK] = DIR_TRACK; + dir[DIR_NEXT_SECTOR] = 1; + + while (dir[DIR_NEXT_TRACK] && num_dir_blocks < num_sectors[DIR_TRACK]) { + if (read_sector(f, desc, dir[DIR_NEXT_TRACK], dir[DIR_NEXT_SECTOR], dir) != ERR_OK) + break; + num_dir_blocks++; + + // Scan all 8 entries of a block + uint8 *de = dir + DIR_ENTRIES; + for (int j=0; j<8; j++, de+=SIZEOF_DE) { + + // Skip empty entries + if (de[DE_TYPE] == 0) + continue; + + // Convert file name (strip everything after and including the first trailing space) + uint8 name_buf[17]; + memcpy(name_buf, de + DE_NAME, 16); + name_buf[16] = 0; + uint8 *p = (uint8 *)memchr(name_buf, 0xa0, 16); + if (p) + *p = 0; + + // Convert file type + int type = de[DE_TYPE] & 7; + if (type > 4) + type = FTYPE_UNKNOWN; + + // Read start address + uint8 sa_lo = 0, sa_hi = 0; + uint8 buf[256]; + if (read_sector(f, desc, de[DE_TRACK], de[DE_SECTOR], buf) == ERR_OK) { + sa_lo = buf[2]; + sa_hi = buf[3]; + } + + // Add entry + vec.push_back(c64_dir_entry(name_buf, type, !(de[DE_TYPE] & 0x80), de[DE_TYPE] & 0x40, ((de[DE_NUM_BLOCKS_H] << 8) + de[DE_NUM_BLOCKS_L]) * 254, 0, sa_lo, sa_hi)); + } + } + + result = true; +done: fclose(f); + } + return result; +} + + +/* + * Create new blank disk image file, returns false on error + */ + +bool CreateImageFile(const char *path) +{ + // Open file for writing + FILE *f = fopen(path, "wb"); + if (f == NULL) + return false; + + // Create descriptor + image_file_desc desc; + desc.type = TYPE_D64; + desc.header_size = 0; + desc.num_tracks = 35; + desc.id1 = 'F'; + desc.id1 = 'R'; + memset(desc.error_info, 1, sizeof(desc.error_info)); + desc.has_error_info = false; + + // Format image file + if (!format_image(f, desc, true, 'F', 'R', (uint8 *)"D64 FILE", 8)) { + fclose(f); + remove(path); + return false; + } + + // Close file + fclose(f); + return true; +} diff --git a/arm9/source/1541d64.h b/arm9/source/1541d64.h new file mode 100644 index 0000000..d22ce2b --- /dev/null +++ b/arm9/source/1541d64.h @@ -0,0 +1,170 @@ +// ===================================================================================== +// GimliDS Copyright (c) 2025 Dave Bernazzani (wavemotion-dave) +// +// As GimliDS is a port of the Frodo emulator for the DS/DSi/XL/LL handhelds, +// any copying or distribution of this emulator, its source code and associated +// readme files, with or without modification, are permitted per the original +// Frodo emulator license shown below. Hugest thanks to Christian Bauer for his +// efforts to provide a clean open-source emulation base for the C64. +// +// Numerous hacks and 'unsafe' optimizations have been performed on the original +// Frodo emulator codebase to get it running on the small handheld system. You +// are strongly encouraged to seek out the official Frodo sources if you're at +// all interested in this emulator code. +// +// The GimliDS emulator is offered as-is, without any warranty. Please see readme.md +// ===================================================================================== + +/* + * 1541d64.h - 1541 emulation in disk image files (.d64/.x64/zipcode) + * + * Frodo Copyright (C) Christian Bauer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _1541D64_H +#define _1541D64_H +#include "sysdeps.h" + +#include "IEC.h" + + +/* + * Definitions + */ + +// Constants +const int NUM_SECTORS_35 = 683; // Number of sectors in a 35-track image +const int NUM_SECTORS_40 = 768; // Number of sectors in a 40-track image + +// Disk image types +enum { + TYPE_D64, // D64 file + TYPE_ED64, // Converted zipcode file (D64 with header ID) + TYPE_X64 // x64 file +}; + +// Channel descriptor +struct channel_desc { + int mode; // Channel mode + bool writing; // Flag: writing to file (for file channels) + int buf_num; // Buffer number for direct access and file channels + uint8 *buf; // Pointer to start of buffer + uint8 *buf_ptr; // Pointer to current position in buffer + int buf_len; // Remaining bytes in buffer + int track, sector; // Track and sector the buffer will be written to (for writing to file channels) + int num_blocks; // Number of blocks in file (for writing to file channels) + int dir_track; // Track... + int dir_sector; // ...and sector of directory block containing file entry + int entry; // Number of entry in directory block +}; + +// Disk image file descriptor +struct image_file_desc { + int type; // See definitions above + int header_size; // Size of file header + int num_tracks; // Number of tracks + uint8 id1, id2; // Block header ID (as opposed to BAM ID) + uint8 error_info[NUM_SECTORS_40]; // Sector error information (1 byte/sector) + bool has_error_info; // Flag: error info present in file +}; + +// Disk image drive class +class ImageDrive : public Drive { +public: + ImageDrive(IEC *iec, const char *filepath); + virtual ~ImageDrive(); + + virtual uint8 Open(int channel, const uint8 *name, int name_len); + virtual uint8 Close(int channel); + virtual uint8 Read(int channel, uint8 &byte); + virtual uint8 Write(int channel, uint8 byte, bool eoi); + virtual void Reset(void); + +private: + void close_image(void); + bool change_image(const char *path); + + uint8 open_file(int channel, const uint8 *name, int name_len); + uint8 open_file_ts(int channel, int track, int sector); + uint8 create_file(int channel, const uint8 *name, int name_len, int type, bool overwrite = false); + uint8 open_directory(const uint8 *pattern, int pattern_len); + uint8 open_direct(int channel, const uint8 *filename); + void close_all_channels(void); + + int alloc_buffer(int want); + void free_buffer(int buf); + + bool find_file(const uint8 *pattern, int pattern_len, int &dir_track, int &dir_sector, int &entry, bool cont); + bool find_first_file(const uint8 *pattern, int pattern_len, int &dir_track, int &dir_sector, int &entry); + bool find_next_file(const uint8 *pattern, int pattern_len, int &dir_track, int &dir_sector, int &entry); + bool alloc_dir_entry(int &track, int §or, int &entry); + + bool is_block_free(int track, int sector); + int num_free_blocks(int track); + int alloc_block(int track, int sector); + int free_block(int track, int sector); + bool alloc_block_chain(int track, int sector); + bool free_block_chain(int track, int sector); + bool alloc_next_block(int &track, int §or, int interleave); + + bool read_sector(int track, int sector, uint8 *buffer); + bool write_sector(int track, int sector, uint8 *buffer); + void write_error_info(void); + + virtual void block_read_cmd(int channel, int track, int sector, bool user_cmd = false); + virtual void block_write_cmd(int channel, int track, int sector, bool user_cmd = false); + virtual void block_allocate_cmd(int track, int sector); + virtual void block_free_cmd(int track, int sector); + virtual void buffer_pointer_cmd(int channel, int pos); + virtual void mem_read_cmd(uint16 adr, uint8 len); + virtual void mem_write_cmd(uint16 adr, uint8 len, uint8 *p); + virtual void copy_cmd(const uint8 *new_file, int new_file_len, const uint8 *old_files, int old_files_len); + virtual void rename_cmd(const uint8 *new_file, int new_file_len, const uint8 *old_file, int old_file_len); + virtual void scratch_cmd(const uint8 *files, int files_len); + virtual void initialize_cmd(void); + virtual void new_cmd(const uint8 *name, int name_len, const uint8 *comma); + virtual void validate_cmd(void); + + FILE *the_file; // File pointer for image file + image_file_desc desc; // Image file descriptor + bool write_protected; // Flag: image file write-protected + + uint8 ram[0x800]; // 2k 1541 RAM + uint8 dir[258]; // Buffer for directory blocks + uint8 *bam; // Pointer to BAM in 1541 RAM (buffer 4, upper 256 bytes) + bool bam_dirty; // Flag: BAM modified, needs to be written back + + channel_desc ch[18]; // Descriptors for channels 0..17 (16 = internal read, 17 = internal write) + bool buf_free[4]; // Flags: buffer 0..3 free? +}; + + +/* + * Functions + */ + +// Check whether file with given header (64 bytes) and size looks like one +// of the file types supported by this module +extern bool IsImageFile(const char *path, const uint8 *header, long size); + +// Read directory of disk image file into (empty) c64_dir_entry vector +extern bool ReadImageDirectory(const char *path, vector &vec); + +// Create new blank disk image file +extern bool CreateImageFile(const char *path); + +#endif diff --git a/arm9/source/1541fs.cpp b/arm9/source/1541fs.cpp new file mode 100644 index 0000000..88bbe28 --- /dev/null +++ b/arm9/source/1541fs.cpp @@ -0,0 +1,506 @@ +// ===================================================================================== +// GimliDS Copyright (c) 2025 Dave Bernazzani (wavemotion-dave) +// +// As GimliDS is a port of the Frodo emulator for the DS/DSi/XL/LL handhelds, +// any copying or distribution of this emulator, its source code and associated +// readme files, with or without modification, are permitted per the original +// Frodo emulator license shown below. Hugest thanks to Christian Bauer for his +// efforts to provide a clean open-source emulation base for the C64. +// +// Numerous hacks and 'unsafe' optimizations have been performed on the original +// Frodo emulator codebase to get it running on the small handheld system. You +// are strongly encouraged to seek out the official Frodo sources if you're at +// all interested in this emulator code. +// +// The GimliDS emulator is offered as-is, without any warranty. Please see readme.md +// ===================================================================================== + +/* + * 1541fs.cpp - 1541 emulation in host file system + * + * Frodo Copyright (C) Christian Bauer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Notes: + * ------ + * + * - If the directory is opened (file name "$"), a temporary file + * with the structure of a 1541 directory file is created and + * opened. It can then be accessed in the same way as all other + * files. + * + * Incompatibilities: + * ------------------ + * + * - No "raw" directory reading + * - No relative/sequential/user files + * - Only "I" and "UJ" commands implemented + */ + +#include "sysdeps.h" + +#include "1541fs.h" +#include "IEC.h" +#include "main.h" +#include "Prefs.h" + +// Prototypes +static bool match(const char *p, const char *n); + +/* + * Constructor: Prepare emulation + */ + +FSDrive::FSDrive(IEC *iec, const char *path) : Drive(iec) +{ + strcpy(orig_dir_path, path); + dir_path[0] = 0; + + if (change_dir(orig_dir_path)) { + for (int i=0; i<16; i++) + file[i] = NULL; + + Reset(); + + Ready = true; + } +} + + +/* + * Destructor + */ + +FSDrive::~FSDrive() +{ + if (Ready) { + close_all_channels(); + Ready = false; + } +} + + +/* + * Change emulation directory + */ + +bool FSDrive::change_dir(char *dirpath) +{ + DIR *dir; + + if ((dir = opendir(dirpath)) != NULL) { + closedir(dir); + strcpy(dir_path, dirpath); + strncpy(dir_title, dir_path, 16); + return true; + } else + return false; +} + + +/* + * Open channel + */ + +uint8 FSDrive::Open(int channel, const uint8 *name, int name_len) +{ + set_error(ERR_OK); + + // Channel 15: Execute file name as command + if (channel == 15) { + execute_cmd(name, name_len); + return ST_OK; + } + + // Close previous file if still open + if (file[channel]) { + fclose(file[channel]); + file[channel] = NULL; + } + + if (name[0] == '#') { + set_error(ERR_NOCHANNEL); + return ST_OK; + } + + if (name[0] == '$') + return open_directory(channel, name + 1, name_len - 1); + + return open_file(channel, name, name_len); +} + + +/* + * Open file + */ + +uint8 FSDrive::open_file(int channel, const uint8 *name, int name_len) +{ + char plain_name[NAMEBUF_LENGTH]; + int plain_name_len; + int mode = FMODE_READ; + int type = FTYPE_PRG; + int rec_len = 0; + parse_file_name(name, name_len, (uint8 *)plain_name, plain_name_len, mode, type, rec_len, true); + + // Channel 0 is READ, channel 1 is WRITE + if (channel == 0 || channel == 1) { + mode = channel ? FMODE_WRITE : FMODE_READ; + if (type == FTYPE_DEL) + type = FTYPE_PRG; + } + + bool writing = (mode == FMODE_WRITE || mode == FMODE_APPEND); + + // Expand wildcards (only allowed on reading) + if (strchr(plain_name, '*') || strchr(plain_name, '?')) { + if (writing) { + set_error(ERR_SYNTAX33); + return ST_OK; + } else + find_first_file(plain_name); + } + + // Relative files are not supported + if (type == FTYPE_REL) { + set_error(ERR_UNIMPLEMENTED); + return ST_OK; + } + + // Select fopen() mode according to file mode + const char *mode_str = "rb"; + switch (mode) { + case FMODE_WRITE: + mode_str = "wb"; + break; + case FMODE_APPEND: + mode_str = "ab"; + break; + } + + // Open file + if (chdir(dir_path)) + set_error(ERR_NOTREADY); + else if ((file[channel] = fopen(plain_name, mode_str)) != NULL) { + if (mode == FMODE_READ || mode == FMODE_M) // Read and buffer first byte + read_char[channel] = fgetc(file[channel]); + } else + set_error(ERR_FILENOTFOUND); + + return ST_OK; +} + + +/* + * Find first file matching wildcard pattern and get its real name + */ + +// Return true if name 'n' matches pattern 'p' +static bool match(const char *p, const char *n) +{ + if (!*p) // Null pattern matches everything + return true; + + do { + if (*p == '*') // Wildcard '*' matches all following characters + return true; + if ((*p != *n) && (*p != '?')) // Wildcard '?' matches single character + return false; + p++; n++; + } while (*p); + + return !*n; +} + +void FSDrive::find_first_file(char *pattern) +{ + DIR *dir; + struct dirent *de; + + // Open directory for reading and skip '.' and '..' + if ((dir = opendir(dir_path)) == NULL) + return; + de = readdir(dir); + while (de && (0 == strcmp(".", de->d_name) || 0 == strcmp("..", de->d_name))) + de = readdir(dir); + + while (de) { + + // Match found? Then copy real file name + if (match(pattern, de->d_name)) { + strncpy(pattern, de->d_name, NAMEBUF_LENGTH); + closedir(dir); + return; + } + + // Get next directory entry + de = readdir(dir); + } + + closedir(dir); +} + + +/* + * Open directory, create temporary file + */ + +uint8 FSDrive::open_directory(int channel, const uint8 *pattern, int pattern_len) +{ + char buf[] = "\001\004\001\001\0\0\022\042 \042 00 2A"; + char str[NAMEBUF_LENGTH]; + char *p, *q; + int i; + + DIR *dir; + struct dirent *de; + struct stat statbuf; + + // Special treatment for "$0" + if (pattern[0] == '0' && pattern[1] == 0) { + pattern++; + pattern_len--; + } + + // Skip everything before the ':' in the pattern + uint8 *t = (uint8 *)memchr(pattern, ':', pattern_len); + if (t) + pattern = t + 1; + + // Convert pattern to ASCII + char ascii_pattern[NAMEBUF_LENGTH]; + petscii2ascii(ascii_pattern, pattern, NAMEBUF_LENGTH); + + // Open directory for reading and skip '.' and '..' + if ((dir = opendir(dir_path)) == NULL) { + set_error(ERR_NOTREADY); + return ST_OK; + } + de = readdir(dir); + while (de && (0 == strcmp(".", de->d_name) || 0 == strcmp("..", de->d_name))) + de = readdir(dir); + + // Create temporary file + if ((file[channel] = fopen("ramdiskfs:/ram/test4.txt","wb")) == NULL) { + closedir(dir); + return ST_OK; + } + + // Create directory title + p = &buf[8]; + for (i=0; i<16 && dir_title[i]; i++) + *p++ = ascii2petscii(dir_title[i]); + fwrite(buf, 1, 32, file[channel]); + + // Create and write one line for every directory entry + while (de) { + + // Include only files matching the ascii_pattern + if (match(ascii_pattern, de->d_name)) { + + // Get file statistics + chdir(dir_path); + stat(de->d_name, &statbuf); + + // Clear line with spaces and terminate with null byte + memset(buf, ' ', 31); + buf[31] = 0; + + p = buf; + *p++ = 0x01; // Dummy line link + *p++ = 0x01; + + // Calculate size in blocks (254 bytes each) + i = (statbuf.st_size + 254) / 254; + *p++ = i & 0xff; + *p++ = (i >> 8) & 0xff; + + p++; + if (i < 10) p++; // Less than 10: add one space + if (i < 100) p++; // Less than 100: add another space + + // Convert and insert file name + strcpy(str, de->d_name); + *p++ = '\"'; + q = p; + for (i=0; i<16 && str[i]; i++) + *q++ = ascii2petscii(str[i]); + *q++ = '\"'; + p += 18; + + // File type + if (S_ISDIR(statbuf.st_mode)) { + *p++ = 'D'; + *p++ = 'I'; + *p++ = 'R'; + } else { + *p++ = 'P'; + *p++ = 'R'; + *p++ = 'G'; + } + + // Write line + fwrite(buf, 1, 32, file[channel]); + } + + // Get next directory entry + de = readdir(dir); + } + + // Final line + fwrite("\001\001\0\0BLOCKS FREE. \0\0", 1, 32, file[channel]); + + // Rewind file for reading and read first byte + rewind(file[channel]); + read_char[channel] = fgetc(file[channel]); + +#ifndef __riscos + // Close directory + closedir(dir); +#endif + return ST_OK; +} + + +/* + * Close channel + */ + +uint8 FSDrive::Close(int channel) +{ + if (channel == 15) { + close_all_channels(); + return ST_OK; + } + + if (file[channel]) { + fclose(file[channel]); + file[channel] = NULL; + } + + return ST_OK; +} + + +/* + * Close all channels + */ + +void FSDrive::close_all_channels(void) +{ + for (int i=0; i<15; i++) + Close(i); + + cmd_len = 0; +} + + +/* + * Read from channel + */ + +uint8 FSDrive::Read(int channel, uint8 &byte) +{ + int c; + + // Channel 15: Error channel + if (channel == 15) { + byte = *error_ptr++; + + if (byte != '\r') + return ST_OK; + else { // End of message + set_error(ERR_OK); + return ST_EOF; + } + } + + if (!file[channel]) return ST_READ_TIMEOUT; + + // Read one byte + byte = read_char[channel]; + c = fgetc(file[channel]); + if (c == EOF) + return ST_EOF; + else { + read_char[channel] = c; + return ST_OK; + } +} + + +/* + * Write to channel + */ + +uint8 FSDrive::Write(int channel, uint8 byte, bool eoi) +{ + // Channel 15: Collect chars and execute command on EOI + if (channel == 15) { + if (cmd_len >= 58) + return ST_TIMEOUT; + + cmd_buf[cmd_len++] = byte; + + if (eoi) { + execute_cmd(cmd_buf, cmd_len); + cmd_len = 0; + } + return ST_OK; + } + + if (!file[channel]) { + set_error(ERR_FILENOTOPEN); + return ST_TIMEOUT; + } + + if (putc(byte, file[channel]) == EOF) { + set_error(ERR_WRITE25); + return ST_TIMEOUT; + } + + return ST_OK; +} + + +/* + * Execute drive commands + */ + +// INITIALIZE +void FSDrive::initialize_cmd(void) +{ + close_all_channels(); +} + +// VALIDATE +void FSDrive::validate_cmd(void) +{ +} + + +/* + * Reset drive + */ + +void FSDrive::Reset(void) +{ + close_all_channels(); + cmd_len = 0; + set_error(ERR_STARTUP); +} diff --git a/arm9/source/1541fs.h b/arm9/source/1541fs.h new file mode 100644 index 0000000..278e4e0 --- /dev/null +++ b/arm9/source/1541fs.h @@ -0,0 +1,74 @@ +// ===================================================================================== +// GimliDS Copyright (c) 2025 Dave Bernazzani (wavemotion-dave) +// +// As GimliDS is a port of the Frodo emulator for the DS/DSi/XL/LL handhelds, +// any copying or distribution of this emulator, its source code and associated +// readme files, with or without modification, are permitted per the original +// Frodo emulator license shown below. Hugest thanks to Christian Bauer for his +// efforts to provide a clean open-source emulation base for the C64. +// +// Numerous hacks and 'unsafe' optimizations have been performed on the original +// Frodo emulator codebase to get it running on the small handheld system. You +// are strongly encouraged to seek out the official Frodo sources if you're at +// all interested in this emulator code. +// +// The GimliDS emulator is offered as-is, without any warranty. Please see readme.md +// ===================================================================================== + +/* + * 1541fs.h - 1541 emulation in host file system + * + * Frodo Copyright (C) Christian Bauer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _1541FS_H +#define _1541FS_H +#include "sysdeps.h" +#include "IEC.h" + + +class FSDrive : public Drive { +public: + FSDrive(IEC *iec, const char *path); + virtual ~FSDrive(); + + virtual uint8 Open(int channel, const uint8 *name, int name_len); + virtual uint8 Close(int channel); + virtual uint8 Read(int channel, uint8 &byte); + virtual uint8 Write(int channel, uint8 byte, bool eoi); + virtual void Reset(void); + +private: + bool change_dir(char *dirpath); + + uint8 open_file(int channel, const uint8 *name, int name_len); + uint8 open_directory(int channel, const uint8 *pattern, int pattern_len); + void find_first_file(char *pattern); + void close_all_channels(void); + + virtual void initialize_cmd(void); + virtual void validate_cmd(void); + + char dir_path[256]; // Path to directory + char orig_dir_path[256]; // Original directory path + char dir_title[16]; // Directory title + FILE *file[16]; // File pointers for each of the 16 channels + + uint8 read_char[16]; // Buffers for one-byte read-ahead +}; + +#endif diff --git a/arm9/source/1541job.cpp b/arm9/source/1541job.cpp new file mode 100644 index 0000000..bc9da5f --- /dev/null +++ b/arm9/source/1541job.cpp @@ -0,0 +1,493 @@ +/* + * 1541job.cpp - Emulation of 1541 GCR disk reading/writing + * + * Frodo Copyright (C) Christian Bauer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Notes: + * ------ + * + * - This is only used for processor-level 1541 emulation. + * It simulates the 1541 disk controller hardware (R/W head, + * GCR reading/writing). + * - The preferences settings for drive 8 are used to + * specify the .d64 file + * + * Incompatibilities: + * ------------------ + * + * - No GCR writing possible (WriteSector is a ROM patch) + * - Programs depending on the exact timing of head movement/disk + * rotation don't work + * - The .d64 error info is unused + */ +#include +#include "sysdeps.h" + +#include "1541job.h" +#include "CPU1541.h" +#include "Prefs.h" + +// Number of tracks/sectors +const int NUM_TRACKS = 35; +const int NUM_SECTORS = 683; + +// Size of GCR encoded data +const int GCR_SECTOR_SIZE = 5 + 10 + 9 + 5 + 325 + 12; // SYNC + Header + Gap + SYNC + Data + Gap + +const int GCR_TRACK_SIZE = GCR_SECTOR_SIZE * 21; // Each track in gcr_data has 21 sectors +const int GCR_DISK_SIZE = GCR_TRACK_SIZE * NUM_TRACKS; + +// Job return codes +const int RET_OK = 1; // No error +const int RET_NOT_FOUND = 2; // Block not found +const int RET_NOT_READY = 15; // Drive not ready + + +// Number of sectors of each track +const int num_sectors[36] = { + 0, + 21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21, + 19,19,19,19,19,19,19, + 18,18,18,18,18,18, + 17,17,17,17,17 +}; + +// Sector offset of start of track in .d64 file +const int sector_offset[36] = { + 0, + 0,21,42,63,84,105,126,147,168,189,210,231,252,273,294,315,336, + 357,376,395,414,433,452,471, + 490,508,526,544,562,580, + 598,615,632,649,666 +}; + + +/* + * Constructor: Open .d64 file if processor-level 1541 + * emulation is enabled + */ + +Job1541::Job1541(uint8 *ram1541) : ram(ram1541) +{ + the_file = NULL; + + gcr_data = gcr_ptr = gcr_track_start = new uint8[GCR_DISK_SIZE]; + gcr_track_end = gcr_track_start + GCR_TRACK_SIZE; + current_halftrack = 2; + + disk_changed = true; + motor_on = false; + + if (ThePrefs.TrueDrive) + open_d64_file(ThePrefs.DrivePath[0]); +} + + +/* + * Destructor: Close .d64 file + */ + +Job1541::~Job1541() +{ + close_d64_file(); + delete[] gcr_data; +} + + +/* + * Preferences may have changed + */ + +void Job1541::NewPrefs(Prefs *prefs) +{ + // 1541 emulation turned off? + if (!prefs->TrueDrive) + close_d64_file(); + + // 1541 emulation turned on? + else if (!ThePrefs.TrueDrive && prefs->TrueDrive) + open_d64_file(prefs->DrivePath[0]); + + // .d64 file name changed? + else + { + if (strcmp(ThePrefs.DrivePath[0], prefs->DrivePath[0])) + { + close_d64_file(); + open_d64_file(prefs->DrivePath[0]); + disk_changed = true; + } + } +} + + +/* + * Open .d64 file + */ + +void Job1541::open_d64_file(char *filepath) +{ + long size; + uint8 magic[4]; + static uint8 bam[256]; + //printdbg(filepath); + // Clear GCR buffer + memset(gcr_data, 0x55, GCR_DISK_SIZE); + + // Try opening the file for reading/writing first, then for reading only + write_protected = false; + the_file = fopen(filepath, "rb+"); + if (the_file == NULL) { + write_protected = true; + the_file = fopen(filepath, "rb"); + } + if (the_file != NULL) { + + // Check length + fseek(the_file, 0, SEEK_END); + if ((size = ftell(the_file)) < NUM_SECTORS * 256) { + fclose(the_file); + the_file = NULL; + return; + } + + // x64 image? + fseek(the_file, 0, SEEK_SET); + fread(&magic, 4, 1, the_file); + if (magic[0] == 0x43 && magic[1] == 0x15 && magic[2] == 0x41 && magic[3] == 0x64) + image_header = 64; + else + image_header = 0; + + // Preset error info (all sectors no error) + memset(error_info, 1, NUM_SECTORS); + + // Load sector error info from .d64 file, if present + if (!image_header && size == NUM_SECTORS * 257) { + fseek(the_file, NUM_SECTORS * 256, SEEK_SET); + fread(&error_info, NUM_SECTORS, 1, the_file); + }; + + // Read BAM and get ID + read_sector(18, 0, bam); + id1 = bam[162]; + id2 = bam[163]; + + // Create GCR encoded disk data from image + disk2gcr(); + } +} + + +/* + * Close .d64 file + */ + +void Job1541::close_d64_file(void) +{ + if (the_file != NULL) { + fclose(the_file); + the_file = NULL; + } +} + +void Job1541::Reset(void) +{ + current_halftrack = 2; + disk_changed = true; + motor_on = false; +} + + +/* + * Write sector to disk (1541 ROM patch) + */ + +void Job1541::WriteSector(void) +{ + int track = ram[0x18]; + int sector = ram[0x19]; + uint16 buf = ram[0x30] | (ram[0x31] << 8); + + if (buf <= 0x0700) + if (write_sector(track, sector, ram + buf)) + sector2gcr(track, sector); +} + + +/* + * Format one track (1541 ROM patch) + */ + +void Job1541::FormatTrack(void) +{ + int track = ram[0x51]; + + // Get new ID + uint8 bufnum = ram[0x3d]; + id1 = ram[0x12 + bufnum]; + id2 = ram[0x13 + bufnum]; + + // Create empty block + uint8 buf[256]; + memset(buf, 1, 256); + buf[0] = 0x4b; + + // Write block to all sectors on track + for(int sector=0; sector GCR + * true: success, false: error + */ + +bool Job1541::write_sector(int track, int sector, uint8 *buffer) +{ + int offset; + + floppy_soundfx(); // Play floppy SFX if needed + + // Convert track/sector to byte offset in file + if ((offset = offset_from_ts(track, sector)) < 0) + return false; + + fseek(the_file, offset + image_header, SEEK_SET); + fwrite(buffer, 256, 1, the_file); + return true; +} + + +/* + * Convert track/sector to offset + */ + +int Job1541::secnum_from_ts(int track, int sector) +{ + return sector_offset[track] + sector; +} + +int Job1541::offset_from_ts(int track, int sector) +{ + if ((track < 1) || (track > NUM_TRACKS) || + (sector < 0) || (sector >= num_sectors[track])) + return -1; + + return (sector_offset[track] + sector) << 8; +} + + +/* + * Convert 4 bytes to 5 GCR encoded bytes + */ + +const uint16 gcr_table[16] = { + 0x0a, 0x0b, 0x12, 0x13, 0x0e, 0x0f, 0x16, 0x17, + 0x09, 0x19, 0x1a, 0x1b, 0x0d, 0x1d, 0x1e, 0x15 +}; + +void Job1541::gcr_conv4(uint8 *from, uint8 *to) +{ + uint16 g; + + g = (gcr_table[*from >> 4] << 5) | gcr_table[*from & 15]; + *to++ = g >> 2; + *to = (g << 6) & 0xc0; + from++; + + g = (gcr_table[*from >> 4] << 5) | gcr_table[*from & 15]; + *to++ |= (g >> 4) & 0x3f; + *to = (g << 4) & 0xf0; + from++; + + g = (gcr_table[*from >> 4] << 5) | gcr_table[*from & 15]; + *to++ |= (g >> 6) & 0x0f; + *to = (g << 2) & 0xfc; + from++; + + g = (gcr_table[*from >> 4] << 5) | gcr_table[*from & 15]; + *to++ |= (g >> 8) & 0x03; + *to = g; +} + + +/* + * Create GCR encoded disk data from image + */ + +void Job1541::sector2gcr(int track, int sector) +{ + uint8 block[256]; + uint8 buf[4]; + uint8 *p = gcr_data + (track-1) * GCR_TRACK_SIZE + sector * GCR_SECTOR_SIZE; + + read_sector(track, sector, block); + + // Create GCR header + *p++ = 0xff;*p++ = 0xff;*p++ = 0xff;*p++ = 0xff;*p++ = 0xff; // SYNC + buf[0] = 0x08; // Header mark + buf[1] = sector ^ track ^ id2 ^ id1; // Checksum + buf[2] = sector; + buf[3] = track; + gcr_conv4(buf, p); + buf[0] = id2; + buf[1] = id1; + buf[2] = 0x0f; + buf[3] = 0x0f; + gcr_conv4(buf, p+5); + p += 10; + memset(p, 0x55, 9); // Gap + p += 9; + + // Create GCR data + uint8 sum; + *p++ = 0xff;*p++ = 0xff;*p++ = 0xff;*p++ = 0xff;*p++ = 0xff; // SYNC + buf[0] = 0x07; // Data mark + sum = buf[1] = block[0]; + sum ^= buf[2] = block[1]; + sum ^= buf[3] = block[2]; + gcr_conv4(buf, p); + p += 5; + for (int i=3; i<255; i+=4) { + sum ^= buf[0] = block[i]; + sum ^= buf[1] = block[i+1]; + sum ^= buf[2] = block[i+2]; + sum ^= buf[3] = block[i+3]; + gcr_conv4(buf, p); + p += 5; + } + sum ^= buf[0] = block[255]; + buf[1] = sum; // Checksum + buf[2] = 0; + buf[3] = 0; + gcr_conv4(buf, p); + p += 5; + memset(p, 0x55, 12); // Gap +} + +void Job1541::disk2gcr(void) +{ + // Convert all tracks and sectors + for (int track=1; track<=NUM_TRACKS; track++) + for(int sector=0; sector> 1) - 1) * GCR_TRACK_SIZE; + gcr_track_end = gcr_track_start + num_sectors[current_halftrack >> 1] * GCR_SECTOR_SIZE; +} + +/* + * Control spindle motor + */ + +void Job1541::SetMotor(bool on) +{ + motor_on = on; +} + + +bool Job1541::ByteReady(void) +{ + return motor_on; +} + + +/* + * Move R/W head in (higher track numbers) + */ + +void Job1541::MoveHeadIn(void) +{ + if (current_halftrack == NUM_TRACKS*2) + return; + current_halftrack++; + + gcr_ptr = gcr_track_start = gcr_data + ((current_halftrack >> 1) - 1) * GCR_TRACK_SIZE; + gcr_track_end = gcr_track_start + num_sectors[current_halftrack >> 1] * GCR_SECTOR_SIZE; +} + + +/* + * Get state + */ + +void Job1541::GetState(Job1541State *state) +{ + state->current_halftrack = current_halftrack; + state->gcr_ptr = gcr_ptr - gcr_data; + state->write_protected = write_protected; + state->disk_changed = disk_changed; +} + + +/* + * Set state + */ + +void Job1541::SetState(Job1541State *state) +{ + current_halftrack = state->current_halftrack; + gcr_ptr = gcr_data + state->gcr_ptr; + gcr_track_start = gcr_data + ((current_halftrack >> 1) - 1) * GCR_TRACK_SIZE; + gcr_track_end = gcr_track_start + num_sectors[current_halftrack >> 1] * GCR_SECTOR_SIZE; + write_protected = state->write_protected; + disk_changed = state->disk_changed; +} diff --git a/arm9/source/1541job.h b/arm9/source/1541job.h new file mode 100644 index 0000000..c34a279 --- /dev/null +++ b/arm9/source/1541job.h @@ -0,0 +1,151 @@ +// ===================================================================================== +// GimliDS Copyright (c) 2025 Dave Bernazzani (wavemotion-dave) +// +// As GimliDS is a port of the Frodo emulator for the DS/DSi/XL/LL handhelds, +// any copying or distribution of this emulator, its source code and associated +// readme files, with or without modification, are permitted per the original +// Frodo emulator license shown below. Hugest thanks to Christian Bauer for his +// efforts to provide a clean open-source emulation base for the C64. +// +// Numerous hacks and 'unsafe' optimizations have been performed on the original +// Frodo emulator codebase to get it running on the small handheld system. You +// are strongly encouraged to seek out the official Frodo sources if you're at +// all interested in this emulator code. +// +// The GimliDS emulator is offered as-is, without any warranty. Please see readme.md +// ===================================================================================== + +/* + * 1541job.h - Emulation of 1541 GCR disk reading/writing + * + * Frodo Copyright (C) Christian Bauer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _1541JOB_H +#define _1541JOB_H +#include +#include "sysdeps.h" + +class MOS6502_1541; +class Prefs; +struct Job1541State; + +class Job1541 { +public: + Job1541(uint8 *ram1541); + ~Job1541(); + + void GetState(Job1541State *state); + void SetState(Job1541State *state); + void NewPrefs(Prefs *prefs); + void MoveHeadOut(void); + void MoveHeadIn(void); + bool SyncFound(void); + bool ByteReady(void); + uint8 ReadGCRByte(void); + uint8 WPState(void); + void WriteSector(void); + void FormatTrack(void); + void Reset(void); + void SetMotor(bool on); + +private: + void open_d64_file(char *filepath); + void close_d64_file(void); + bool read_sector(int track, int sector, uint8 *buffer); + bool write_sector(int track, int sector, uint8 *buffer); + void format_disk(void); + int secnum_from_ts(int track, int sector); + int offset_from_ts(int track, int sector); + void gcr_conv4(uint8 *from, uint8 *to); + void sector2gcr(int track, int sector); + void disk2gcr(void); + + uint8 *ram; // Pointer to 1541 RAM + FILE *the_file; // File pointer for .d64 file + int image_header; // Length of .d64/.x64 file header + + uint8 id1, id2; // ID of disk + uint8 error_info[683]; // Sector error information (1 byte/sector) + + uint8 *gcr_data; // Pointer to GCR encoded disk data + uint8 *gcr_ptr; // Pointer to GCR data under R/W head + uint8 *gcr_track_start; // Pointer to start of GCR data of current track + uint8 *gcr_track_end; // Pointer to end of GCR data of current track + int current_halftrack; // Current halftrack number (2..70) + + bool write_protected; // Flag: Disk write-protected + bool disk_changed; // Flag: Disk changed (WP sensor strobe control) + bool motor_on; +}; + +// 1541 GCR state +struct Job1541State { + int current_halftrack; + uint32 gcr_ptr; + bool write_protected; + bool disk_changed; +}; + + +/* + * Check if R/W head is over SYNC + */ + +inline bool Job1541::SyncFound(void) +{ + if (*gcr_ptr == 0xff && gcr_ptr[1] != 0xff) + return true; + else { + gcr_ptr++; // Rotate disk + if (gcr_ptr == gcr_track_end) + gcr_ptr = gcr_track_start; + return false; + } +} + + +/* + * Read one GCR byte from disk + */ + +inline uint8 Job1541::ReadGCRByte(void) +{ + extern void floppy_soundfx(void); + floppy_soundfx(); // Play floppy SFX if needed + + uint8 byte = *gcr_ptr++; // Rotate disk + if (gcr_ptr == gcr_track_end) + gcr_ptr = gcr_track_start; + return byte; +} + + +/* + * Return state of write protect sensor + */ + +inline uint8 Job1541::WPState(void) +{ + if (disk_changed) { // Disk change -> WP sensor strobe + disk_changed = false; + return write_protected ? 0x10 : 0; + } else + return write_protected ? 0 : 0x10; +} + +#endif diff --git a/arm9/source/C64.cpp b/arm9/source/C64.cpp new file mode 100644 index 0000000..cb59a87 --- /dev/null +++ b/arm9/source/C64.cpp @@ -0,0 +1,1203 @@ +// ===================================================================================== +// GimliDS Copyright (c) 2025 Dave Bernazzani (wavemotion-dave) +// +// As GimliDS is a port of the Frodo emulator for the DS/DSi/XL/LL handhelds, +// any copying or distribution of this emulator, its source code and associated +// readme files, with or without modification, are permitted per the original +// Frodo emulator license shown below. Hugest thanks to Christian Bauer for his +// efforts to provide a clean open-source emulation base for the C64. +// +// Numerous hacks and 'unsafe' optimizations have been performed on the original +// Frodo emulator codebase to get it running on the small handheld system. You +// are strongly encouraged to seek out the official Frodo sources if you're at +// all interested in this emulator code. +// +// The GimliDS emulator is offered as-is, without any warranty. Please see readme.md +// ===================================================================================== + +/* + * C64.cpp - Put the pieces together + * + * Frodo Copyright (C) Christian Bauer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "sysdeps.h" + +#include "C64.h" +#include "CPUC64.h" +#include "CPU1541.h" +#include "VIC.h" +#include "SID.h" +#include "CIA.h" +#include "IEC.h" +#include "1541job.h" +#include "Display.h" +#include "Prefs.h" +#include "mainmenu.h" +#include "lzav.h" +#include +#include "soundbank.h" + + +uint8 myRAM[C64_RAM_SIZE]; +uint8 myKERNAL[KERNAL_ROM_SIZE]; +uint8 myRAM1541[DRIVE_RAM_SIZE] __attribute__((section(".dtcm"))); + +#define SNAPSHOT_VERSION 1 + +/* + * Constructor: Allocate objects and memory + */ + +C64::C64() +{ + uint8 *p; + + // The thread is not yet running + thread_running = false; + quit_thyself = false; + have_a_break = false; + + // System-dependent things + c64_ctor1(); + + // Open display + TheDisplay = new C64Display(this); + + // Allocate RAM/ROM memory + RAM = myRAM; + Basic = new uint8[BASIC_ROM_SIZE]; + Kernal = myKERNAL; + Char = new uint8[CHAR_ROM_SIZE]; + Color = new uint8[COLOR_RAM_SIZE]; + RAM1541 = myRAM1541; + ROM1541 = new uint8[DRIVE_ROM_SIZE]; + + // Create the chips + TheCPU = new MOS6510(this, RAM, Basic, Kernal, Char, Color); + + TheJob1541 = new Job1541(RAM1541); + TheCPU1541 = new MOS6502_1541(this, TheJob1541, TheDisplay, RAM1541, ROM1541); + + TheVIC = TheCPU->TheVIC = new MOS6569(this, TheDisplay, TheCPU, RAM, Char, Color); + TheSID = TheCPU->TheSID = new MOS6581(this); + TheCIA1 = TheCPU->TheCIA1 = new MOS6526_1(TheCPU, TheVIC); + TheCIA2 = TheCPU->TheCIA2 = TheCPU1541->TheCIA2 = new MOS6526_2(TheCPU, TheVIC, TheCPU1541); + TheIEC = TheCPU->TheIEC = new IEC(TheDisplay); + + // Initialize RAM with powerup pattern + p = RAM; + for (unsigned i=0; i<512; i++) { + for (unsigned j=0; j<64; j++) + *p++ = 0; + for (unsigned j=0; j<64; j++) + *p++ = 0xff; + } + + // Initialize color RAM with random values + p = Color; + for (unsigned i=0; iAsyncReset(); + TheCPU1541->AsyncReset(); + TheSID->Reset(); + TheCIA1->Reset(); + TheCIA2->Reset(); + TheIEC->Reset(); +} + + +/* + * NMI C64 + */ + +void C64::NMI(void) +{ + TheCPU->AsyncNMI(); +} + + +/* + * The preferences have changed. prefs is a pointer to the new + * preferences, ThePrefs still holds the previous ones. + * The emulation must be in the paused state! + */ + +void C64::NewPrefs(Prefs *prefs) +{ + PatchKernal(prefs->FastReset, prefs->TrueDrive); + TheDisplay->NewPrefs(prefs); + +#ifdef __NDS__ + // Changed order of calls. If 1541 mode hasn't changed the order is insignificant. + if (prefs->TrueDrive) { + // New prefs have 1541 enabled ==> if old prefs had disabled free drives FIRST + TheIEC->NewPrefs(prefs); + TheJob1541->NewPrefs(prefs); + } else { + // New prefs has 1541 disabled ==> if old prefs had enabled free job FIRST + TheJob1541->NewPrefs(prefs); + TheIEC->NewPrefs(prefs); + } +#else + TheIEC->NewPrefs(prefs); + TheJob1541->NewPrefs(prefs); +#endif + + TheSID->NewPrefs(prefs); + + // Reset 1541 processor if turned on + if (!ThePrefs.TrueDrive && prefs->TrueDrive) + TheCPU1541->AsyncReset(); +} + + +/* + * Patch kernal IEC routines + */ + +void C64::PatchKernal(bool fast_reset, bool true_drive) +{ + if (fast_reset) { + Kernal[0x1d84] = 0xa0; + Kernal[0x1d85] = 0x00; + } else { + Kernal[0x1d84] = orig_kernal_1d84; + Kernal[0x1d85] = orig_kernal_1d85; + } + + if (true_drive) { + Kernal[0x0d40] = 0x78; + Kernal[0x0d41] = 0x20; + Kernal[0x0d23] = 0x78; + Kernal[0x0d24] = 0x20; + Kernal[0x0d36] = 0x78; + Kernal[0x0d37] = 0x20; + Kernal[0x0e13] = 0x78; + Kernal[0x0e14] = 0xa9; + Kernal[0x0def] = 0x78; + Kernal[0x0df0] = 0x20; + Kernal[0x0dbe] = 0xad; + Kernal[0x0dbf] = 0x00; + Kernal[0x0dcc] = 0x78; + Kernal[0x0dcd] = 0x20; + Kernal[0x0e03] = 0x20; + Kernal[0x0e04] = 0xbe; + } else { + Kernal[0x0d40] = 0xf2; // IECOut + Kernal[0x0d41] = 0x00; + Kernal[0x0d23] = 0xf2; // IECOutATN + Kernal[0x0d24] = 0x01; + Kernal[0x0d36] = 0xf2; // IECOutSec + Kernal[0x0d37] = 0x02; + Kernal[0x0e13] = 0xf2; // IECIn + Kernal[0x0e14] = 0x03; + Kernal[0x0def] = 0xf2; // IECSetATN + Kernal[0x0df0] = 0x04; + Kernal[0x0dbe] = 0xf2; // IECRelATN + Kernal[0x0dbf] = 0x05; + Kernal[0x0dcc] = 0xf2; // IECTurnaround + Kernal[0x0dcd] = 0x06; + Kernal[0x0e03] = 0xf2; // IECRelease + Kernal[0x0e04] = 0x07; + } + + // 1541 - Fast Reset + ROM1541[0x2ab1] = 0xfb; // Skip zero page test, just clear + ROM1541[0x2ab2] = 0x4c; // Skip zero page test, just clear + ROM1541[0x2ab3] = 0xc9; // Skip zero page test, just clear + ROM1541[0x2ab4] = 0xea; // Skip zero page test, just clear + + ROM1541[0x2ad1] = 0x4c; // Skip ROM test + ROM1541[0x2ad2] = 0xea; // Skip ROM test + ROM1541[0x2ad3] = 0xea; // Skip ROM test + + ROM1541[0x2b00] = 0x4c; // Skip RAM test + ROM1541[0x2b01] = 0x22; // Skip RAM test + ROM1541[0x2b02] = 0xeb; // Skip RAM test + + ROM1541[0x2af2] = 0xea; // ... Just clear + ROM1541[0x2af3] = 0xea; // ... Just clear + ROM1541[0x2af4] = 0xa9; // ... Just clear + ROM1541[0x2af5] = 0x00; // ... Just clear + + + // 1541 + ROM1541[0x2ae4] = 0xea; // Don't check ROM checksum + ROM1541[0x2ae5] = 0xea; + ROM1541[0x2ae8] = 0xea; + ROM1541[0x2ae9] = 0xea; + ROM1541[0x2c9b] = 0xf2; // DOS idle loop + ROM1541[0x2c9c] = 0x00; + ROM1541[0x3594] = 0x20; // Write sector + ROM1541[0x3595] = 0xf2; + ROM1541[0x3596] = 0xf5; + ROM1541[0x3597] = 0xf2; + ROM1541[0x3598] = 0x01; + ROM1541[0x3b0c] = 0xf2; // Format track + ROM1541[0x3b0d] = 0x02; +} + + +/* + * Save CPU state to snapshot + * + * 0: Error + * 1: OK + * -1: Instruction not completed + */ + +u8 CompressBuffer[0x20000]; //128K more than enough + +int C64::SaveCPUState(FILE *f) +{ + MOS6510State state; + TheCPU->GetState(&state); + + if (!state.instruction_complete) + return -1; + + // --------------------------------------------------------- + // Compress the RAM data using 'high' compression ratio... + // --------------------------------------------------------- + int max_len = lzav_compress_bound_hi(0x10000); + int comp_len = lzav_compress_hi(RAM, CompressBuffer, 0x10000, max_len); + + int i = 0; + i += fwrite(&comp_len, sizeof(comp_len), 1, f); + i += fwrite(&CompressBuffer, comp_len, 1, f); + i += fwrite(Color, 0x400, 1, f); + i += fwrite((void*)&state, sizeof(state), 1, f); + + return i == 4; +} + + +/* + * Load CPU state from snapshot + */ + +bool C64::LoadCPUState(FILE *f) +{ + MOS6510State state; + + int comp_len = 0; + int i = 0; + i += fread(&comp_len, sizeof(comp_len), 1, f); + i += fread(CompressBuffer, comp_len, 1, f); + i += fread(Color, 0x400, 1, f); + i += fread((void*)&state, sizeof(state), 1, f); + + if (i == 4) + { + // ------------------------------------------------------------------ + // Decompress the previously compressed RAM and put it back into the + // right memory location... this is quite fast all things considered. + // ------------------------------------------------------------------ + (void)lzav_decompress( CompressBuffer, RAM, comp_len, 0x10000 ); + + TheCPU->SetState(&state); + return true; + } + else + { iprintf("LoadCPUState Failed"); return false;} +} + + +/* + * Save 1541 state to snapshot + * + * 0: Error + * 1: OK + * -1: Instruction not completed + */ + +int C64::Save1541State(FILE *f) +{ + MOS6502State state; + TheCPU1541->GetState(&state); + + if (!state.idle && !state.instruction_complete) + return -1; + + int i = fwrite(RAM1541, 0x800, 1, f); + i += fwrite((void*)&state, sizeof(state), 1, f); + + return i == 2; +} + + +/* + * Load 1541 state from snapshot + */ + +bool C64::Load1541State(FILE *f) +{ + MOS6502State state; + + int i = fread(RAM1541, 0x800, 1, f); + i += fread((void*)&state, sizeof(state), 1, f); + if (i == 2) + { + TheCPU1541->SetState(&state); + return true; + } else + { iprintf("Load1541State\n"); return false;} +} + + +/* + * Save VIC state to snapshot + */ + +bool C64::SaveVICState(FILE *f) +{ + MOS6569State state; + TheVIC->GetState(&state); + return fwrite((void*)&state, sizeof(state), 1, f) == 1; +} + + +/* + * Load VIC state from snapshot + */ + +bool C64::LoadVICState(FILE *f) +{ + MOS6569State state; + + int k = fread((void*)&state, sizeof(state), 1, f); + if (k == 1) + { + TheVIC->SetState(&state); + return true; + } else + { iprintf("LoadVICState %d\n",k); return false;} +} + + +/* + * Save SID state to snapshot + */ + +bool C64::SaveSIDState(FILE *f) +{ + MOS6581State state; + TheSID->GetState(&state); + return fwrite((void*)&state, sizeof(state), 1, f) == 1; +} + + +/* + * Load SID state from snapshot + */ + +bool C64::LoadSIDState(FILE *f) +{ + MOS6581State state; + + if (fread((void*)&state, sizeof(state), 1, f) == 1) + { + TheSID->SetState(&state); + return true; + } else + { iprintf("LoadSIDState\n"); return false;} +} + + +/* + * Save CIA states to snapshot + */ + +bool C64::SaveCIAState(FILE *f) +{ + MOS6526State state; + TheCIA1->GetState(&state); + + if (fwrite((void*)&state, sizeof(state), 1, f) == 1) + { + TheCIA2->GetState(&state); + return fwrite((void*)&state, sizeof(state), 1, f) == 1; + } + else + { + return false; + } +} + + +/* + * Load CIA states from snapshot + */ + +bool C64::LoadCIAState(FILE *f) +{ + MOS6526State state; + + if (fread((void*)&state, sizeof(state), 1, f) == 1) + { + TheCIA1->SetState(&state); + if (fread((void*)&state, sizeof(state), 1, f) == 1) + { + TheCIA2->SetState(&state); + return true; + } else { iprintf("LoadCIAState1\n"); return false;} + } else { iprintf("LoadCIAState2\n"); return false;} +} + + +/* + * Save 1541 GCR state to snapshot + */ + +bool C64::Save1541JobState(FILE *f) +{ + Job1541State state; + TheJob1541->GetState(&state); + return fwrite((void*)&state, sizeof(state), 1, f) == 1; +} + + +/* + * Load 1541 GCR state from snapshot + */ + +bool C64::Load1541JobState(FILE *f) +{ + Job1541State state; + + if (fread((void*)&state, sizeof(state), 1, f) == 1) + { + TheJob1541->SetState(&state); + return true; + } else { iprintf("Load1541JobState\n"); return false;} +} + + +#define SNAPSHOT_HEADER "GimliSnapshot" +#define SNAPSHOT_1541 1 + +/* + * Save snapshot (emulation must be paused and in VBlank) + * + * To be able to use SC snapshots with SL, SC snapshots are made thus that no + * partially dealt with instructions are saved. Instead all devices are advanced + * cycle by cycle until the current instruction has been finished. The number of + * cycles this takes is saved in the snapshot and will be reconstructed if the + * snapshot is loaded into FrodoSC again. + */ + +bool C64::SaveSnapshot(char *filename) +{ + FILE *f; + uint8 flags; + + if (strlen(filename) < 5) return false; + + if ((f = fopen(filename, "wb")) == NULL) + { + //ShowRequester("Unable to open snapshot file", "OK", NULL); + return false; + } + + fprintf(f, "%s%c", SNAPSHOT_HEADER, 10); + fputc(SNAPSHOT_VERSION, f); // Version number + flags = 0; + if (ThePrefs.TrueDrive) flags |= SNAPSHOT_1541; + fputc(flags, f); + bool bVICSave = SaveVICState(f); + bool bSIDSave = SaveSIDState(f); + bool bCIASave = SaveCIAState(f); + bool bCPUSave = SaveCPUState(f); + fputc(0, f); // No delay + + if (ThePrefs.TrueDrive) + { + fwrite(ThePrefs.DrivePath[0], 256, 1, f); + Save1541State(f); + fputc(0, f); // No delay + Save1541JobState(f); + } + fclose(f); + + if (bVICSave && bSIDSave && bCIASave && bCPUSave) return true; + return false; +} + + +/* + * Load snapshot (emulation must be paused and in VBlank) + */ + +bool C64::LoadSnapshot(char *filename) +{ + uint8 delay; + FILE *f; + + if ((f = fopen(filename, "rb")) != NULL) { + char Header[] = SNAPSHOT_HEADER; + char *b = Header, c = 0; + + // For some reason memcmp()/strcmp() and so forth utterly fail here. + while (*b > 32) { + if ((c = fgetc(f)) != *b++) { + b = NULL; + break; + } + } + if (b != NULL) { + uint8 flags; + bool error = false; + long vicptr; // File offset of VIC data + + while (c != 10) + c = fgetc(f); // Shouldn't be necessary + if (fgetc(f) != SNAPSHOT_VERSION) { + ShowRequester("Unknown snapshot format", "OK", NULL); + fclose(f); + return false; + } + flags = fgetc(f); + vicptr = ftell(f); + + error |= !LoadVICState(f); + error |= !LoadSIDState(f); + error |= !LoadCIAState(f); + error |= !LoadCPUState(f); + + delay = fgetc(f); // Number of cycles the 6510 is ahead of the previous chips + (void)delay; + + if ((flags & SNAPSHOT_1541) != 0) + { + Prefs *prefs = new Prefs(ThePrefs); + + // First switch on emulation + int k=fread(prefs->DrivePath[0], 256, 1, f); + if (k==1) + { + error |=0; + } + else + { + error |=1; + iprintf("flags & SNAPSHOT_1541\n"); + } + prefs->TrueDrive = true; + NewPrefs(prefs); + ThePrefs = *prefs; + delete prefs; + + // Then read the context + error |= !Load1541State(f); + + delay = fgetc(f); // Number of cycles the 6502 is ahead of the previous chips + Load1541JobState(f); + } else if (ThePrefs.TrueDrive) { // No emulation in snapshot, but currently active? + Prefs *prefs = new Prefs(ThePrefs); + prefs->TrueDrive = false; + NewPrefs(prefs); + ThePrefs = *prefs; + delete prefs; + } + + fseek(f, vicptr, SEEK_SET); + LoadVICState(f); // Load VIC data twice in SL (is REALLY necessary sometimes!) + fclose(f); + + if (error) { + ShowRequester("Error reading snapshot file", "OK", NULL); + Reset(); + return false; + } else + return true; + } else { + fclose(f); + ShowRequester("Not a Frodo snapshot file", "OK", NULL); + return false; + } + } else { + ShowRequester("Can't open snapshot file", "OK", NULL); + return false; + } +} + +/* + * C64_GP32.i by Mike Dawson, adapted from: + * C64_x.i - Put the pieces together, X specific stuff + *f + * Frodo (C) 1994-1997,2002 Christian Bauer + * Unix stuff by Bernd Schmidt/Lutz Vieweg + */ + +#include "Prefs.h" +#include "main.h" +extern "C" { + +//#include "menu.h" +//#include "ui.h" +//#include "input.h" +//#include "gpmisc.h" +} + +#include +#include "nds/arm9/console.h" +#include + +#define MATRIX(a,b) (((a) << 3) | (b)) + +#define timers2ms(tlow,thigh) ((uint32_t)tlow | ((uint32_t)thigh<<16)) +#define TICKS_PER_SEC (BUS_CLOCK >> 6) + +void StartTimers(void) +{ + TIMER0_CR=0; + TIMER1_CR=0; + TIMER0_DATA=0; + TIMER1_DATA=0; + TIMER0_CR=TIMER_DIV_64|TIMER_ENABLE; + TIMER1_CR=TIMER_CASCADE|TIMER_ENABLE; +} + +inline uint32 GetTicks(void) +{ + return timers2ms(TIMER0_DATA, TIMER1_DATA); +} + +void Pause(uint32 ms) +{ + uint32 now; + now=timers2ms(TIMER0_DATA, TIMER1_DATA); + while((uint32)timers2ms(TIMER0_DATA, TIMER1_DATA)Reset(); + + // Patch kernal IEC routines + orig_kernal_1d84 = Kernal[0x1d84]; + orig_kernal_1d85 = Kernal[0x1d85]; + PatchKernal(ThePrefs.FastReset, ThePrefs.TrueDrive); + + current_joystick = 0; + + quit_thyself = false; + thread_func(); +} + +char kbd_feedbuf[256]; +int kbd_feedbuf_pos; + +void kbd_buf_feed(const char *s) { + strncat(kbd_feedbuf, s, 255); +} + +void kbd_buf_reset(void) { + kbd_feedbuf[0] = 0; + kbd_feedbuf[255] = 0; + kbd_feedbuf_pos=0; +} + +void kbd_buf_update(C64 *TheC64) +{ + if((kbd_feedbuf[kbd_feedbuf_pos]!=0) && TheC64->RAM[198]==0) + { + TheC64->RAM[631]=kbd_feedbuf[kbd_feedbuf_pos]; + TheC64->RAM[198]=1; + kbd_feedbuf_pos++; + } + else + { + if (TheC64->RAM[198] == 0) + { + kbd_feedbuf_pos = 0; + kbd_feedbuf[0] = 0; + } + } +} + +void load_prg(C64 *TheC64, uint8 *prg, int prg_size) { + uint8 start_hi, start_lo; + uint16 start; + int i; + + start_lo=*prg++; + start_hi=*prg++; + start=(start_hi<<8)+start_lo; + + for(i=0; i<(prg_size-2); i++) { + TheC64->RAM[start+i]=prg[i]; + } +} + +/* + * Vertical blank: Poll keyboard and joysticks, update window + */ + +ITCM_CODE void C64::VBlank(bool draw_frame) +{ + static int speed_index=0; + static int frames=0; + + scanKeys(); + kbd_buf_update(this); + + TheDisplay->PollKeyboard(TheCIA1->KeyMatrix, TheCIA1->RevMatrix, &joykey); + + TheCIA1->Joystick1 = poll_joystick(0); + TheCIA1->Joystick2 = poll_joystick(1); + + if (draw_frame) + { + TheDisplay->Update(); + + frames++; + while (GetTicks() < (((unsigned int)TICKS_PER_SEC/(unsigned int)50) * (unsigned int)frames)) + { + if (ThePrefs.TrueDrive && TheDisplay->led_state[0]) break; // If reading the drive in 'true drive' mode, just plow along... + asm("nop"); + break; + } + + frames_per_sec++; + + if (GetTicks() >= ((TICKS_PER_SEC/50) * 50)) + { + if (!speed_index) speed_index = frames_per_sec; + } + + if (frames == 50) + { + frames = 0; + speed_index = TICKS_PER_SEC - GetTicks(); // How much left-over time? Positive is good... Negative bad. + StartTimers(); + TheDisplay->Speedometer((int)speed_index); + speed_index=0; + frames_per_sec = 0; + } + } +} + + +/* + * Poll joystick port, return CIA mask + */ +u8 space=0; +u8 retkey=0; +u16 dampen=0; +extern s16 temp_offset; +extern u16 slide_dampen; +uint8 C64::poll_joystick(int port) +{ + uint8 j = 0xff; + + if (space == 1) + { + TheDisplay->KeyRelease(MATRIX(7,4), TheCIA1->KeyMatrix, TheCIA1->RevMatrix); + space=0; + } + if (retkey == 1) + { + TheDisplay->KeyRelease(MATRIX(0,1), TheCIA1->KeyMatrix, TheCIA1->RevMatrix); + retkey=0; + } + + u32 keys= keysHeld(); + + u8 joy_up = 0; + u8 joy_dn = 0; + u8 joy_fire = 0; + + if(keys & KEY_B) + { + switch (myConfig.key_B) + { + case KEY_MAP_RETURN: + TheDisplay->KeyPress(MATRIX(0,1), TheCIA1->KeyMatrix, TheCIA1->RevMatrix); + retkey=1; + break; + case KEY_MAP_SPACE: + TheDisplay->KeyPress(MATRIX(7,4), TheCIA1->KeyMatrix, TheCIA1->RevMatrix); + space=1; + break; + case KEY_MAP_PAN_UP: + temp_offset = -16; + slide_dampen = 15; + break; + case KEY_MAP_PAN_DN: + temp_offset = 16; + slide_dampen = 15; + break; + case KEY_MAP_JOY_UP: + joy_up = 1; + break; + case KEY_MAP_JOY_DN: + joy_dn = 1; + break; + case KEY_MAP_JOY_FIRE: + joy_fire = 1; + break; + } + } + + if(keys & KEY_A) + { + switch (myConfig.key_A) + { + case KEY_MAP_RETURN: + TheDisplay->KeyPress(MATRIX(0,1), TheCIA1->KeyMatrix, TheCIA1->RevMatrix); + retkey=1; + break; + case KEY_MAP_SPACE: + TheDisplay->KeyPress(MATRIX(7,4), TheCIA1->KeyMatrix, TheCIA1->RevMatrix); + space=1; + break; + case KEY_MAP_PAN_UP: + temp_offset = -16; + slide_dampen = 15; + break; + case KEY_MAP_PAN_DN: + temp_offset = 16; + slide_dampen = 15; + break; + case KEY_MAP_JOY_UP: + joy_up = 1; + break; + case KEY_MAP_JOY_DN: + joy_dn = 1; + break; + case KEY_MAP_JOY_FIRE: + joy_fire = 1; + break; + } + } + + if(keys & KEY_X) + { + switch (myConfig.key_X) + { + case KEY_MAP_RETURN: + TheDisplay->KeyPress(MATRIX(0,1), TheCIA1->KeyMatrix, TheCIA1->RevMatrix); + retkey=1; + break; + case KEY_MAP_SPACE: + TheDisplay->KeyPress(MATRIX(7,4), TheCIA1->KeyMatrix, TheCIA1->RevMatrix); + space=1; + break; + case KEY_MAP_PAN_UP: + temp_offset = -16; + slide_dampen = 15; + break; + case KEY_MAP_PAN_DN: + temp_offset = 16; + slide_dampen = 15; + break; + case KEY_MAP_JOY_UP: + joy_up = 1; + break; + case KEY_MAP_JOY_DN: + joy_dn = 1; + break; + case KEY_MAP_JOY_FIRE: + joy_fire = 1; + break; + } + } + + if(keys & KEY_Y) + { + switch (myConfig.key_Y) + { + case KEY_MAP_RETURN: + TheDisplay->KeyPress(MATRIX(0,1), TheCIA1->KeyMatrix, TheCIA1->RevMatrix); + retkey=1; + break; + case KEY_MAP_SPACE: + TheDisplay->KeyPress(MATRIX(7,4), TheCIA1->KeyMatrix, TheCIA1->RevMatrix); + space=1; + break; + case KEY_MAP_PAN_UP: + temp_offset = -16; + slide_dampen = 15; + break; + case KEY_MAP_PAN_DN: + temp_offset = 16; + slide_dampen = 15; + break; + case KEY_MAP_JOY_UP: + joy_up = 1; + break; + case KEY_MAP_JOY_DN: + joy_dn = 1; + break; + case KEY_MAP_JOY_FIRE: + joy_fire = 1; + break; + } + } + + static u32 auto_fire_dampen=0; + if ((myConfig.autoFire) && joy_fire) + { + if (++auto_fire_dampen & 0x08) joy_fire=0; + } else auto_fire_dampen=0; + + if((keys & KEY_R) && !dampen) + { + if (keys & KEY_UP) + { + dampen = 4; + myConfig.offsetY++; + } + if (keys & KEY_DOWN) + { + dampen = 4; + if (myConfig.offsetY > 0) myConfig.offsetY--; + } + if (keys & KEY_LEFT) + { + dampen = 4; + myConfig.offsetX++; + } + if (keys & KEY_RIGHT) + { + dampen = 4; + if (myConfig.offsetX > 0) myConfig.offsetX--; + } + } + + if((keys & KEY_L) && !dampen) + { + if (keys & KEY_UP) + { + dampen = 4; + if (myConfig.scaleY < 200) myConfig.scaleY++; + } + if (keys & KEY_DOWN) + { + dampen = 4; + myConfig.scaleY--; + } + if (keys & KEY_LEFT) + { + dampen = 4; + myConfig.scaleX--; + } + if (keys & KEY_RIGHT) + { + dampen = 4; + if (myConfig.scaleX < 320) myConfig.scaleX++; + } + } + + if( (keys & KEY_SELECT) && !dampen) + { + current_joystick ^= 1; + extern void show_joysticks(); + show_joysticks(); + dampen=30; + } + + if( keys & KEY_START && !dampen) + { + kbd_buf_feed("\rLOAD\"*\",8,1\rRUN\r"); + dampen = 30; + } + + if (dampen) dampen--; + + if (!dampen) + { + if(port!=current_joystick) return j; + + if( keys & KEY_LEFT ) j&=0xfb; + if( keys & KEY_RIGHT ) j&=0xf7; + if( keys & KEY_UP ) j&=0xfe; + if( keys & KEY_DOWN ) j&=0xfd; + if( joy_fire ) j&=0xef; // Fire button + if( joy_up ) j&=0xfe; + if( joy_dn ) j&=0xfd; + } + + return j; +} + + +/* + * The emulation's main loop + */ + +void C64::thread_func(void) +{ + int linecnt = 0; + + while (!quit_thyself) + { + if(have_a_break) + { + scanKeys(); + continue; + } + + // The order of calls is important here + int cycles = TheVIC->EmulateLine(); + TheSID->EmulateLine(); +#if !PRECISE_CIA_CYCLES + TheCIA1->EmulateLine(63); + TheCIA2->EmulateLine(63); +#endif + + if (ThePrefs.TrueDrive) + { + int cycles_1541 = 64; + TheCPU1541->CountVIATimers(cycles_1541); + + if (!TheCPU1541->Idle) + { + // ----------------------------------------------------------------------------------------- + // Warp speed - only draw every 10 frames to give max time to CPUs when the drive is active + // Note, we can't just use the Idle flag here as the drive periodically goes non-idle to + // check status - so we use the LED state which is a better indicator of drive activity... + // ----------------------------------------------------------------------------------------- + if (TheDisplay->led_state[0]) ThePrefs.DrawEveryN = 10; + else ThePrefs.DrawEveryN = isDSiMode() ? 1:2; + + // ----------------------------------------------------------- + // 1541 processor active, alternately execute 6502 and 6510 + // instructions until both have used up their cycles. This + // is now handled inside CPU_emuline.h for the 1541 processor + // to avoid the overhead of lots of function calls... + // ----------------------------------------------------------- + TheCPU1541->EmulateLine(cycles_1541, cycles); + } + else + { + ThePrefs.DrawEveryN = isDSiMode() ? 1:2; + TheCPU->EmulateLine(cycles); + } + } + else + { + // 1541 processor disabled, only emulate 6510 + TheCPU->EmulateLine(cycles); + } + + linecnt++; + } +} + +void C64::Pause() { + have_a_break=true; + TheSID->PauseSound(); +} + +void C64::Resume() { + have_a_break=false; + TheSID->ResumeSound(); +} + diff --git a/arm9/source/C64.h b/arm9/source/C64.h new file mode 100644 index 0000000..83ca77f --- /dev/null +++ b/arm9/source/C64.h @@ -0,0 +1,110 @@ +/* + * C64.h - Put the pieces together + * + * Frodo Copyright (C) Christian Bauer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _C64_H +#define _C64_H + +// Sizes of memory areas +const int C64_RAM_SIZE = 0x10000; +const int COLOR_RAM_SIZE = 0x400; +const int BASIC_ROM_SIZE = 0x2000; +const int KERNAL_ROM_SIZE = 0x2000; +const int CHAR_ROM_SIZE = 0x1000; +const int DRIVE_RAM_SIZE = 0x800; +const int DRIVE_ROM_SIZE = 0x4000; + +class Prefs; +class C64Display; +class MOS6510; +class MOS6569; +class MOS6581; +class MOS6526_1; +class MOS6526_2; +class IEC; +class MOS6502_1541; +class Job1541; +class CmdPipe; + +class C64 { +public: + C64(); + ~C64(); + + void Run(void); + void Quit(void); + void Pause(void); + void Resume(void); + void Reset(void); + void NMI(void); + void VBlank(bool draw_frame); + void NewPrefs(Prefs *prefs); + void PatchKernal(bool fast_reset, bool true_drive); + void SaveRAM(char *filename); + bool SaveSnapshot(char *filename); + bool LoadSnapshot(char *filename); + int SaveCPUState(FILE *f); + int Save1541State(FILE *f); + bool Save1541JobState(FILE *f); + bool SaveVICState(FILE *f); + bool SaveSIDState(FILE *f); + bool SaveCIAState(FILE *f); + bool LoadCPUState(FILE *f); + bool Load1541State(FILE *f); + bool Load1541JobState(FILE *f); + bool LoadVICState(FILE *f); + bool LoadSIDState(FILE *f); + bool LoadCIAState(FILE *f); + + uint8 *RAM, *Basic, *Kernal, + *Char, *Color; // C64 + uint8 *RAM1541, *ROM1541; // 1541 + + C64Display *TheDisplay; + + MOS6510 *TheCPU; // C64 + MOS6569 *TheVIC; + MOS6581 *TheSID; + MOS6526_1 *TheCIA1; + MOS6526_2 *TheCIA2; + IEC *TheIEC; + + MOS6502_1541 *TheCPU1541; // 1541 + Job1541 *TheJob1541; + +private: + void c64_ctor1(void); + void c64_ctor2(void); + void c64_dtor(void); + uint8 poll_joystick(int port); + void thread_func(void); + + bool thread_running; // Emulation thread is running + bool quit_thyself; // Emulation thread shall quit + bool have_a_break; // Emulation thread shall pause + + int joy_minx[2], joy_maxx[2], joy_miny[2], joy_maxy[2]; // For dynamic joystick calibration + uint8 joykey; // Joystick keyboard emulation mask value + + uint8 orig_kernal_1d84, // Original contents of kernal locations $1d84 and $1d85 + orig_kernal_1d85; // (for undoing the Fast Reset patch) +}; + +extern void floppy_soundfx(void); +#endif diff --git a/arm9/source/CIA.cpp b/arm9/source/CIA.cpp new file mode 100644 index 0000000..86c91c1 --- /dev/null +++ b/arm9/source/CIA.cpp @@ -0,0 +1,595 @@ +// ===================================================================================== +// GimliDS Copyright (c) 2025 Dave Bernazzani (wavemotion-dave) +// +// As GimliDS is a port of the Frodo emulator for the DS/DSi/XL/LL handhelds, +// any copying or distribution of this emulator, its source code and associated +// readme files, with or without modification, are permitted per the original +// Frodo emulator license shown below. Hugest thanks to Christian Bauer for his +// efforts to provide a clean open-source emulation base for the C64. +// +// Numerous hacks and 'unsafe' optimizations have been performed on the original +// Frodo emulator codebase to get it running on the small handheld system. You +// are strongly encouraged to seek out the official Frodo sources if you're at +// all interested in this emulator code. +// +// The GimliDS emulator is offered as-is, without any warranty. Please see readme.md +// ===================================================================================== + +/* + * CIA.cpp - 6526 emulation + * + * Frodo Copyright (C) Christian Bauer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Notes: + * ------ + * + * - The EmulateLine() function is called for every emulated raster + * line. It counts down the timers and triggers interrupts if + * necessary. + * - The TOD clocks are counted by CountTOD() during the VBlank, so + * the input frequency is 50Hz + * - The fields KeyMatrix and RevMatrix contain one bit for each + * key on the C64 keyboard (0: key pressed, 1: key released). + * KeyMatrix is used for normal keyboard polling (PRA->PRB), + * RevMatrix for reversed polling (PRB->PRA). + * + * Incompatibilities: + * ------------------ + * + * - The TOD clock should not be stopped on a read access, but + * latched + * - The SDR interrupt is faked + */ + +#include "sysdeps.h" + +#include "CIA.h" +#include "CPUC64.h" +#include "CPU1541.h" +#include "VIC.h" +#include "Prefs.h" + + +/* + * Constructors + */ + +MOS6526::MOS6526(MOS6510 *CPU) : the_cpu(CPU) {} +MOS6526_1::MOS6526_1(MOS6510 *CPU, MOS6569 *VIC) : MOS6526(CPU), the_vic(VIC) {} +MOS6526_2::MOS6526_2(MOS6510 *CPU, MOS6569 *VIC, MOS6502_1541 *CPU1541) : MOS6526(CPU), the_vic(VIC), the_cpu_1541(CPU1541) {} + + +/* + * Reset the CIA + */ + +void MOS6526::Reset(void) +{ + pra = prb = ddra = ddrb = 0; + + ta = tb = 0xffff; + latcha = latchb = 1; + + tod_10ths = tod_sec = tod_min = tod_hr = 0; + alm_10ths = alm_sec = alm_min = alm_hr = 0; + + sdr = icr = cra = crb = int_mask = 0; + + tod_halt = ta_cnt_phi2 = tb_cnt_phi2 = tb_cnt_ta = false; + tod_divider = 0; +} + +void MOS6526_1::Reset(void) +{ + MOS6526::Reset(); + + // Clear keyboard matrix and joystick states + for (int i=0; i<8; i++) + KeyMatrix[i] = RevMatrix[i] = 0xff; + + Joystick1 = Joystick2 = 0xff; + prev_lp = 0x10; +} + +void MOS6526_2::Reset(void) +{ + MOS6526::Reset(); + + // VA14/15 = 0 + the_vic->ChangedVA(0); + + // IEC + IECLines = 0x38; // DATA, CLK, ATN high +} + + +/* + * Get CIA state + */ + +void MOS6526::GetState(MOS6526State *cs) +{ + cs->pra = pra; + cs->prb = prb; + cs->ddra = ddra; + cs->ddrb = ddrb; + + cs->ta_lo = ta & 0xff; + cs->ta_hi = ta >> 8; + cs->tb_lo = tb & 0xff; + cs->tb_hi = tb >> 8; + cs->latcha = latcha; + cs->latchb = latchb; + cs->cra = cra; + cs->crb = crb; + + cs->tod_10ths = tod_10ths; + cs->tod_sec = tod_sec; + cs->tod_min = tod_min; + cs->tod_hr = tod_hr; + cs->alm_10ths = alm_10ths; + cs->alm_sec = alm_sec; + cs->alm_min = alm_min; + cs->alm_hr = alm_hr; + + cs->sdr = sdr; + + cs->int_data = icr; + cs->int_mask = int_mask; +} + + +/* + * Restore CIA state + */ + +void MOS6526::SetState(MOS6526State *cs) +{ + pra = cs->pra; + prb = cs->prb; + ddra = cs->ddra; + ddrb = cs->ddrb; + + ta = (cs->ta_hi << 8) | cs->ta_lo; + tb = (cs->tb_hi << 8) | cs->tb_lo; + latcha = cs->latcha; + latchb = cs->latchb; + cra = cs->cra; + crb = cs->crb; + + tod_10ths = cs->tod_10ths; + tod_sec = cs->tod_sec; + tod_min = cs->tod_min; + tod_hr = cs->tod_hr; + alm_10ths = cs->alm_10ths; + alm_sec = cs->alm_sec; + alm_min = cs->alm_min; + alm_hr = cs->alm_hr; + + sdr = cs->sdr; + + icr = cs->int_data; + int_mask = cs->int_mask; + + tod_halt = false; + ta_cnt_phi2 = ((cra & 0x21) == 0x01); + tb_cnt_phi2 = ((crb & 0x61) == 0x01); + tb_cnt_ta = ((crb & 0x41) == 0x41); +} + + +/* + * Read from register (CIA 1) + */ + +uint8 MOS6526_1::ReadRegister(uint16 adr) +{ + switch (adr) { + case 0x00: { + uint8 ret = pra | ~ddra, tst = (prb | ~ddrb) & Joystick1; + if (!(tst & 0x01)) ret &= RevMatrix[0]; // AND all active columns + if (!(tst & 0x02)) ret &= RevMatrix[1]; + if (!(tst & 0x04)) ret &= RevMatrix[2]; + if (!(tst & 0x08)) ret &= RevMatrix[3]; + if (!(tst & 0x10)) ret &= RevMatrix[4]; + if (!(tst & 0x20)) ret &= RevMatrix[5]; + if (!(tst & 0x40)) ret &= RevMatrix[6]; + if (!(tst & 0x80)) ret &= RevMatrix[7]; + return ret & Joystick2; + } + case 0x01: { + uint8 ret = ~ddrb, tst = (pra | ~ddra) & Joystick2; + if (!(tst & 0x01)) ret &= KeyMatrix[0]; // AND all active rows + if (!(tst & 0x02)) ret &= KeyMatrix[1]; + if (!(tst & 0x04)) ret &= KeyMatrix[2]; + if (!(tst & 0x08)) ret &= KeyMatrix[3]; + if (!(tst & 0x10)) ret &= KeyMatrix[4]; + if (!(tst & 0x20)) ret &= KeyMatrix[5]; + if (!(tst & 0x40)) ret &= KeyMatrix[6]; + if (!(tst & 0x80)) ret &= KeyMatrix[7]; + return (ret | (prb & ddrb)) & Joystick1; + } + case 0x02: return ddra; + case 0x03: return ddrb; + case 0x04: return ta; + case 0x05: return ta >> 8; + case 0x06: return tb; + case 0x07: return tb >> 8; + case 0x08: tod_halt = false; return tod_10ths; + case 0x09: return tod_sec; + case 0x0a: return tod_min; + case 0x0b: tod_halt = true; return tod_hr; + case 0x0c: return sdr; + case 0x0d: { + uint8 ret = icr; // Read and clear ICR + icr = 0; + the_cpu->ClearCIAIRQ(); // Clear IRQ + return ret; + } + case 0x0e: return cra; + case 0x0f: return crb; + } + return 0; // Can't happen +} + + +/* + * Read from register (CIA 2) + */ + +uint8 MOS6526_2::ReadRegister(uint16 adr) +{ + switch (adr) { + case 0x00: + return ((pra | ~ddra) & 0x3f) | (IECLines & the_cpu_1541->IECLines); + case 0x01: return prb | ~ddrb; + case 0x02: return ddra; + case 0x03: return ddrb; + case 0x04: return ta; + case 0x05: return ta >> 8; + case 0x06: return tb; + case 0x07: return tb >> 8; + case 0x08: tod_halt = false; return tod_10ths; + case 0x09: return tod_sec; + case 0x0a: return tod_min; + case 0x0b: tod_halt = true; return tod_hr; + case 0x0c: return sdr; + case 0x0d: { + uint8 ret = icr; // Read and clear ICR + icr = 0; + the_cpu->ClearNMI(); // Clear NMI + return ret; + } + case 0x0e: return cra; + case 0x0f: return crb; + } + return 0; // Can't happen +} + + +/* + * Write to register (CIA 1) + */ + +// Write to port B, check for lightpen interrupt +inline void MOS6526_1::check_lp(void) +{ + if (((prb | ~ddrb) & 0x10) != prev_lp) + the_vic->TriggerLightpen(); + prev_lp = (prb | ~ddrb) & 0x10; +} + +void MOS6526_1::WriteRegister(uint16 adr, uint8 byte) +{ + switch (adr) { + case 0x0: pra = byte; break; + case 0x1: + prb = byte; + check_lp(); + break; + case 0x2: ddra = byte; break; + case 0x3: + ddrb = byte; + check_lp(); + break; + + case 0x4: latcha = (latcha & 0xff00) | byte; break; + case 0x5: + latcha = (latcha & 0xff) | (byte << 8); + if (!(cra & 1)) // Reload timer if stopped + ta = latcha; + break; + + case 0x6: latchb = (latchb & 0xff00) | byte; break; + case 0x7: + latchb = (latchb & 0xff) | (byte << 8); + if (!(crb & 1)) // Reload timer if stopped + tb = latchb; + break; + + case 0x8: + if (crb & 0x80) + alm_10ths = byte & 0x0f; + else + tod_10ths = byte & 0x0f; + break; + case 0x9: + if (crb & 0x80) + alm_sec = byte & 0x7f; + else + tod_sec = byte & 0x7f; + break; + case 0xa: + if (crb & 0x80) + alm_min = byte & 0x7f; + else + tod_min = byte & 0x7f; + break; + case 0xb: + if (crb & 0x80) + alm_hr = byte & 0x9f; + else + tod_hr = byte & 0x9f; + break; + + case 0xc: + sdr = byte; + TriggerInterrupt(8); // Fake SDR interrupt for programs that need it + break; + + case 0xd: + if (ThePrefs.CIAIRQHack) // Hack for addressing modes that read from the address + icr = 0; + if (byte & 0x80) { + int_mask |= byte & 0x7f; + if (icr & int_mask & 0x1f) { // Trigger IRQ if pending + icr |= 0x80; + the_cpu->TriggerCIAIRQ(); + } + } else + int_mask &= ~byte; + break; + + case 0xe: + cra = byte & 0xef; + if (byte & 0x10) // Force load + ta = latcha; + ta_cnt_phi2 = ((byte & 0x21) == 0x01); + break; + + case 0xf: + crb = byte & 0xef; + if (byte & 0x10) // Force load + tb = latchb; + tb_cnt_phi2 = ((byte & 0x61) == 0x01); + tb_cnt_ta = ((byte & 0x41) == 0x41); + break; + } +} + +// Write to port A, check for VIC bank change and IEC lines +inline void MOS6526_2::write_pa(uint8_t byte) +{ + the_vic->ChangedVA(byte & 3); + uint8 old_lines = IECLines; + + IECLines = ((byte << 2) & 0x80) // DATA + | ((byte << 2) & 0x40) // CLK + | ((byte << 1) & 0x10); // ATN + + if ((IECLines ^ old_lines) & 0x10) { // ATN changed + the_cpu_1541->NewATNState(); + if (old_lines & 0x10) // ATN 1->0 + the_cpu_1541->TriggerIECInterrupt(); + } +} + +/* + * Write to register (CIA 2) + */ + +void MOS6526_2::WriteRegister(uint16 adr, uint8 byte) +{ + switch (adr) { + case 0x0: + pra = byte; + write_pa(~pra & ddra); + break; + case 0x1: + prb = byte; + break; + case 0x2: + ddra = byte; + write_pa(~pra & ddra); + break; + case 0x3: + ddrb = byte; + break; + case 0x4: + latcha = (latcha & 0xff00) | byte; + break; + case 0x5: + latcha = (latcha & 0xff) | (byte << 8); + if (!(cra & 1)) // Reload timer if stopped + ta = latcha; + break; + + case 0x6: latchb = (latchb & 0xff00) | byte; break; + case 0x7: + latchb = (latchb & 0xff) | (byte << 8); + if (!(crb & 1)) // Reload timer if stopped + tb = latchb; + break; + + case 0x8: + if (crb & 0x80) + alm_10ths = byte & 0x0f; + else + tod_10ths = byte & 0x0f; + break; + case 0x9: + if (crb & 0x80) + alm_sec = byte & 0x7f; + else + tod_sec = byte & 0x7f; + break; + case 0xa: + if (crb & 0x80) + alm_min = byte & 0x7f; + else + tod_min = byte & 0x7f; + break; + case 0xb: + if (crb & 0x80) + alm_hr = byte & 0x9f; + else + tod_hr = byte & 0x9f; + break; + + case 0xc: + sdr = byte; + TriggerInterrupt(8); // Fake SDR interrupt for programs that need it + break; + + case 0xd: + if (ThePrefs.CIAIRQHack) + icr = 0; + if (byte & 0x80) { + int_mask |= byte & 0x7f; + if (icr & int_mask & 0x1f) { // Trigger NMI if pending + icr |= 0x80; + the_cpu->TriggerNMI(); + } + } else + int_mask &= ~byte; + break; + + case 0xe: + cra = byte & 0xef; + if (byte & 0x10) // Force load + ta = latcha; + ta_cnt_phi2 = ((byte & 0x21) == 0x01); + break; + + case 0xf: + crb = byte & 0xef; + if (byte & 0x10) // Force load + tb = latchb; + tb_cnt_phi2 = ((byte & 0x61) == 0x01); + tb_cnt_ta = ((byte & 0x41) == 0x41); + break; + } +} + + +/* + * Count CIA TOD clock (called during VBlank) + */ + +void MOS6526::CountTOD(void) +{ + uint8 lo, hi; + + // Decrement frequency divider + if (tod_divider) + tod_divider--; + else { + + // Reload divider according to 50/60 Hz flag + if (cra & 0x80) + tod_divider = 4; + else + tod_divider = 5; + + // 1/10 seconds + tod_10ths++; + if (tod_10ths > 9) { + tod_10ths = 0; + + // Seconds + lo = (tod_sec & 0x0f) + 1; + hi = tod_sec >> 4; + if (lo > 9) { + lo = 0; + hi++; + } + if (hi > 5) { + tod_sec = 0; + + // Minutes + lo = (tod_min & 0x0f) + 1; + hi = tod_min >> 4; + if (lo > 9) { + lo = 0; + hi++; + } + if (hi > 5) { + tod_min = 0; + + // Hours + lo = (tod_hr & 0x0f) + 1; + hi = (tod_hr >> 4) & 1; + tod_hr &= 0x80; // Keep AM/PM flag + if (lo > 9) { + lo = 0; + hi++; + } + tod_hr |= (hi << 4) | lo; + if ((tod_hr & 0x1f) > 0x11) + tod_hr = (tod_hr & 0x80) ^ 0x80; + } else + tod_min = (hi << 4) | lo; + } else + tod_sec = (hi << 4) | lo; + } + + // Alarm time reached? Trigger interrupt if enabled + if (tod_10ths == alm_10ths && tod_sec == alm_sec && + tod_min == alm_min && tod_hr == alm_hr) + TriggerInterrupt(4); + } +} + + +/* + * Trigger IRQ (CIA 1) + */ + +void MOS6526_1::TriggerInterrupt(int bit) +{ + icr |= bit; + if (int_mask & bit) { + icr |= 0x80; + the_cpu->TriggerCIAIRQ(); + } +} + + +/* + * Trigger NMI (CIA 2) + */ + +void MOS6526_2::TriggerInterrupt(int bit) +{ + icr |= bit; + if (int_mask & bit) { + icr |= 0x80; + the_cpu->TriggerNMI(); + } +} diff --git a/arm9/source/CIA.h b/arm9/source/CIA.h new file mode 100644 index 0000000..6a4a710 --- /dev/null +++ b/arm9/source/CIA.h @@ -0,0 +1,199 @@ +// ===================================================================================== +// GimliDS Copyright (c) 2025 Dave Bernazzani (wavemotion-dave) +// +// As GimliDS is a port of the Frodo emulator for the DS/DSi/XL/LL handhelds, +// any copying or distribution of this emulator, its source code and associated +// readme files, with or without modification, are permitted per the original +// Frodo emulator license shown below. Hugest thanks to Christian Bauer for his +// efforts to provide a clean open-source emulation base for the C64. +// +// Numerous hacks and 'unsafe' optimizations have been performed on the original +// Frodo emulator codebase to get it running on the small handheld system. You +// are strongly encouraged to seek out the official Frodo sources if you're at +// all interested in this emulator code. +// +// The GimliDS emulator is offered as-is, without any warranty. Please see readme.md +// ===================================================================================== + +/* + * CIA.h - 6526 emulation + * + * Frodo Copyright (C) Christian Bauer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _CIA_H +#define _CIA_H + +#include "Prefs.h" + + +class MOS6510; +class MOS6502_1541; +class MOS6569; +struct MOS6526State; + + +class MOS6526 { +public: + MOS6526(MOS6510 *CPU); + + void Reset(void); + void GetState(MOS6526State *cs); + void SetState(MOS6526State *cs); + void EmulateLine(int cycles); + void CountTOD(void); + virtual void TriggerInterrupt(int bit)=0; + +protected: + MOS6510 *the_cpu; // Pointer to 6510 + + uint8 pra, prb, ddra, ddrb; + + uint16 ta, tb, latcha, latchb; + + uint8 tod_10ths, tod_sec, tod_min, tod_hr; + uint8 alm_10ths, alm_sec, alm_min, alm_hr; + + uint8 sdr, icr, cra, crb; + uint8 int_mask; + + int tod_divider; // TOD frequency divider + + bool tod_halt, // Flag: TOD halted + ta_cnt_phi2, // Flag: Timer A is counting Phi 2 + tb_cnt_phi2, // Flag: Timer B is counting Phi 2 + tb_cnt_ta; // Flag: Timer B is counting underflows of Timer A +}; + + +class MOS6526_1 : public MOS6526 { +public: + MOS6526_1(MOS6510 *CPU, MOS6569 *VIC); + + void Reset(void); + uint8 ReadRegister(uint16 adr); + void WriteRegister(uint16 adr, uint8 byte); + virtual void TriggerInterrupt(int bit); + + uint8 KeyMatrix[8]; // C64 keyboard matrix, 1 bit/key (0: key down, 1: key up) + uint8 RevMatrix[8]; // Reversed keyboard matrix + + uint8 Joystick1; // Joystick 1 AND value + uint8 Joystick2; // Joystick 2 AND value + +private: + void check_lp(void); + + MOS6569 *the_vic; + + uint8 prev_lp; // Previous state of LP line (bit 4) +}; + + +class MOS6526_2 : public MOS6526{ +public: + MOS6526_2(MOS6510 *CPU, MOS6569 *VIC, MOS6502_1541 *CPU1541); + + void Reset(void); + uint8 ReadRegister(uint16 adr); + void WriteRegister(uint16 adr, uint8 byte); + virtual void TriggerInterrupt(int bit); + + uint8 IECLines; // State of IEC lines (bit 7 - DATA, bit 6 - CLK, bit 4 - ATN) + +private: + MOS6569 *the_vic; + MOS6502_1541 *the_cpu_1541; + void write_pa(uint8_t byte); +}; + + +// CIA state +struct MOS6526State { + uint8 pra; + uint8 ddra; + uint8 prb; + uint8 ddrb; + uint8 ta_lo; + uint8 ta_hi; + uint8 tb_lo; + uint8 tb_hi; + uint8 tod_10ths; + uint8 tod_sec; + uint8 tod_min; + uint8 tod_hr; + uint8 sdr; + uint8 int_data; // Pending interrupts + uint8 cra; + uint8 crb; + // Additional registers + uint16 latcha; // Timer latches + uint16 latchb; + uint8 alm_10ths; // Alarm time + uint8 alm_sec; + uint8 alm_min; + uint8 alm_hr; + uint8 int_mask; // Enabled interrupts +}; + + +/* + * Emulate CIA for one cycle/raster line + */ + +inline void MOS6526::EmulateLine(int cycles) +{ + unsigned long tmp; + + // Timer A + if (ta_cnt_phi2) { + ta = tmp = ta - cycles; // Decrement timer + + if (tmp > 0xffff) { // Underflow? + ta = latcha; // Reload timer + + if (cra & 8) { // One-shot? + cra &= 0xfe; + ta_cnt_phi2 = false; + } + TriggerInterrupt(1); + if (tb_cnt_ta) { // Timer B counting underflows of Timer A? + tb = tmp = tb - 1; // tmp = --tb doesn't work + if (tmp > 0xffff) goto tb_underflow; + } + } + } + + // Timer B + if (tb_cnt_phi2) { + tb = tmp = tb - cycles; // Decrement timer + + if (tmp > 0xffff) { // Underflow? +tb_underflow: + tb = latchb; + + if (crb & 8) { // One-shot? + crb &= 0xfe; + tb_cnt_phi2 = false; + tb_cnt_ta = false; + } + TriggerInterrupt(2); + } + } +} + +#endif diff --git a/arm9/source/CPU1541.cpp b/arm9/source/CPU1541.cpp new file mode 100644 index 0000000..d305896 --- /dev/null +++ b/arm9/source/CPU1541.cpp @@ -0,0 +1,756 @@ +// ===================================================================================== +// GimliDS Copyright (c) 2025 Dave Bernazzani (wavemotion-dave) +// +// As GimliDS is a port of the Frodo emulator for the DS/DSi/XL/LL handhelds, +// any copying or distribution of this emulator, its source code and associated +// readme files, with or without modification, are permitted per the original +// Frodo emulator license shown below. Hugest thanks to Christian Bauer for his +// efforts to provide a clean open-source emulation base for the C64. +// +// Numerous hacks and 'unsafe' optimizations have been performed on the original +// Frodo emulator codebase to get it running on the small handheld system. You +// are strongly encouraged to seek out the official Frodo sources if you're at +// all interested in this emulator code. +// +// The GimliDS emulator is offered as-is, without any warranty. Please see readme.md +// ===================================================================================== + +/* + * CPU1541.cpp - 6502 (1541) emulation (line based) + * + * Frodo Copyright (C) Christian Bauer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Notes: + * ------ + * + * - The EmulateLine() function is called for every emulated + * raster line. It has a cycle counter that is decremented + * by every executed opcode and if the counter goes below + * zero, the function returns. + * - Memory map (1541C, the 1541 and 1541-II are a bit different): + * $0000-$07ff RAM (2K) + * $0800-$0fff RAM mirror + * $1000-$17ff free + * $1800-$1bff VIA 1 + * $1c00-$1fff VIA 2 + * $2000-$bfff free + * $c000-$ffff ROM (16K) + * - All memory accesses are done with the read_byte() and + * write_byte() functions which also do the memory address + * decoding. The read_zp() and write_zp() functions allow + * faster access to the zero page, the pop_byte() and + * push_byte() macros for the stack. + * - The PC is either emulated with a 16 bit address or a + * direct memory pointer (for faster access), depending on + * the PC_IS_POINTER #define. In the latter case, a second + * pointer, pc_base, is kept to allow recalculating the + * 16 bit 6502 PC if it has to be pushed on the stack. + * - The possible interrupt sources are: + * INT_VIA1IRQ: I flag is checked, jump to ($fffe) + * INT_VIA2IRQ: I flag is checked, jump to ($fffe) + * INT_RESET: Jump to ($fffc) + * - Interrupts are not checked before every opcode but only + * at certain times: + * On entering EmulateLine() + * On CLI + * On PLP if the I flag was cleared + * On RTI if the I flag was cleared + * - The z_flag variable has the inverse meaning of the + * 6502 Z flag + * - Only the highest bit of the n_flag variable is used + * - The $f2 opcode that would normally crash the 6502 is + * used to implement emulator-specific functions + * - The 1541 6502 emulation also includes a very simple VIA + * emulation (enough to make the IEC bus and GCR loading work). + * It's too small to move it to a source file of its own. + * + * Incompatibilities: + * ------------------ + * + * - If PC_IS_POINTER is set, neither branches accross memory + * areas nor jumps to I/O space are possible + * - Extra cycles for crossing page boundaries are not + * accounted for + */ + +#include "sysdeps.h" + +#include "CPU1541.h" +#include "CPUC64.h" +#include "1541job.h" +#include "C64.h" +#include "CIA.h" +#include "Display.h" +#include "mainmenu.h" + +extern uint8 myRAM1541[DRIVE_RAM_SIZE]; + +/* + * 6502 constructor: Initialize registers + */ + +MOS6502_1541::MOS6502_1541(C64 *c64, Job1541 *job, C64Display *disp, uint8 *Ram, uint8 *Rom) + : ram(Ram), rom(Rom), the_c64(c64), the_display(disp), the_job(job) +{ + a = x = y = 0; + sp = 0xff; + n_flag = z_flag = 0; + v_flag = d_flag = c_flag = false; + i_flag = true; + + borrowed_cycles = 0; + + rom = Rom - 0xC000; // So we don't have to mask the ROM when reading + + via1_t1c = via1_t1l = via1_t2c = via1_t2l = 0; + via1_sr = 0; + via2_t1c = via2_t1l = via2_t2c = via2_t2l = 0; + via2_sr = 0; + + Idle = false; +} + + +/* + * Reset CPU asynchronously + */ + +void MOS6502_1541::AsyncReset(void) +{ + interrupt.intr[INT_RESET] = true; + Idle = false; +} + + +/* + * Read a byte from I/O space + */ + +inline uint8 MOS6502_1541::read_byte_io(uint16 adr) +{ + if ((adr & 0xfc00) == 0x1800) // VIA 1 + switch (adr & 0xf) { + case 0: + return ((via1_prb & 0x1a) + | ((IECLines & TheCIA2->IECLines) >> 7) // DATA + | (((IECLines & TheCIA2->IECLines) >> 4) & 0x04) // CLK + | ((TheCIA2->IECLines << 3) & 0x80)) ^ 0x85; // ATN + case 1: + via1_ifr &= 0xfd; // Clear CA1 interrupt + interrupt.intr[INT_VIA1IRQ] = false; + return 0xff; // Keep 1541C ROMs happy (track 0 sensor) + case 15: + return 0xff; // Keep 1541C ROMs happy (track 0 sensor) + case 2: + return via1_ddrb; + case 3: + return via1_ddra; + case 4: + via1_ifr &= 0xbf; + return via1_t1c; + case 5: + return via1_t1c >> 8; + case 6: + return via1_t1l; + case 7: + return via1_t1l >> 8; + case 8: + via1_ifr &= 0xdf; + return via1_t2c; + case 9: + return via1_t2c >> 8; + case 10: + return via1_sr; + case 11: + return via1_acr; + case 12: + return via1_pcr; + case 13: + return via1_ifr | (via1_ifr & via1_ier ? 0x80 : 0); + case 14: + return via1_ier | 0x80; + default: // Can't happen + return 0; + } + + else if ((adr & 0xfc00) == 0x1c00) // VIA 2 + switch (adr & 0xf) { + case 0: + if (the_job->SyncFound()) + return (via2_prb & 0x7f) | the_job->WPState(); + else + return (via2_prb | 0x80) | the_job->WPState(); + case 1: + case 15: + return the_job->ReadGCRByte(); + case 2: + return via2_ddrb; + case 3: + return via2_ddra; + case 4: + via2_ifr &= 0xbf; + interrupt.intr[INT_VIA2IRQ] = false; // Clear IRQ + return via2_t1c; + case 5: + return via2_t1c >> 8; + case 6: + return via2_t1l; + case 7: + return via2_t1l >> 8; + case 8: + via2_ifr &= 0xdf; + return via2_t2c; + case 9: + return via2_t2c >> 8; + case 10: + return via2_sr; + case 11: + return via2_acr; + case 12: + return via2_pcr; + case 13: + return via2_ifr | (via2_ifr & via2_ier ? 0x80 : 0); + case 14: + return via2_ier | 0x80; + default: // Can't happen + return 0; + } + + else + return adr >> 8; +} + + +/* + * Read a byte from the CPU's address space + */ + +// This can be used when we know we're reading an 'immediate' byte from ROM +inline uint8 MOS6502_1541::read_byte_fast(uint16 adr) +{ + if (adr & 0xC000) + return rom[adr]; + return myRAM1541[adr]; +} + +// The more general read has to handle RAM, ROM and IO space +uint8 MOS6502_1541::read_byte(uint16 adr) +{ + if (adr & 0xC000) + return rom[adr]; + else if ((adr & 0x1800) == 0x0000) + return myRAM1541[adr & 0x07ff]; + else + return read_byte_io(adr); +} + + +/* + * Read a word (little-endian) from the CPU's address space + */ + +inline uint16 MOS6502_1541::read_word(uint16 adr) +{ + return read_byte(adr) | (read_byte(adr+1) << 8); +} + + +/* + * Write a byte to I/O space + */ + +void MOS6502_1541::write_byte_io(uint16 adr, uint8 byte) +{ + if ((adr & 0xfc00) == 0x1800) // VIA 1 + switch (adr & 0xf) { + case 0: + via1_prb = byte; + byte = ~via1_prb & via1_ddrb; + IECLines = ((byte << 6) & (((~byte ^ TheCIA2->IECLines) << 3) & 0x80)) | ((byte << 3) & 0x40); + break; + case 1: + case 15: + via1_pra = byte; + break; + case 2: + via1_ddrb = byte; + byte &= ~via1_prb; + IECLines = ((byte << 6) & (((~byte ^ TheCIA2->IECLines) << 3) & 0x80)) | ((byte << 3) & 0x40); + break; + case 3: + via1_ddra = byte; + break; + case 4: + case 6: + via1_t1l = (via1_t1l & 0xff00) | byte; + break; + case 5: + via1_t1l = (via1_t1l & 0xff) | (byte << 8); + via1_ifr &= 0xbf; + via1_t1c = via1_t1l; + break; + case 7: + via1_t1l = (via1_t1l & 0xff) | (byte << 8); + break; + case 8: + via1_t2l = (via1_t2l & 0xff00) | byte; + break; + case 9: + via1_t2l = (via1_t2l & 0xff) | (byte << 8); + via1_ifr &= 0xdf; + via1_t2c = via1_t2l; + break; + case 10: + via1_sr = byte; + break; + case 11: + via1_acr = byte; + break; + case 12: + via1_pcr = byte; + break; + case 13: + via1_ifr &= ~byte; + break; + case 14: + if (byte & 0x80) + via1_ier |= byte & 0x7f; + else + via1_ier &= ~byte; + break; + } + + else if ((adr & 0xfc00) == 0x1c00) // VIA 2 + switch (adr & 0xf) { + case 0: + if ((via2_prb ^ byte) & 8) // Bit 3: Drive LED + the_display->UpdateLEDs(byte & 8 ? 1 : 0, 0); + + if ((via2_prb ^ byte) & 0x04) // Bit 2: Spindle motor + the_job->SetMotor(byte & 0x04); + + if ((via2_prb ^ byte) & 3) // Bits 0/1: Stepper motor + { + if ((via2_prb & 3) == ((byte+1) & 3)) + the_job->MoveHeadOut(); + else if ((via2_prb & 3) == ((byte-1) & 3)) + the_job->MoveHeadIn(); + } + via2_prb = byte; + break; + case 1: + case 15: + via2_pra = byte; + break; + case 2: + via2_ddrb = byte; + break; + case 3: + via2_ddra = byte; + break; + case 4: + case 6: + via2_t1l = (via2_t1l & 0xff00) | byte; + break; + case 5: + via2_t1l = (via2_t1l & 0xff) | (byte << 8); + via2_ifr &= 0xbf; + via2_t1c = via2_t1l; + break; + case 7: + via2_t1l = (via2_t1l & 0xff) | (byte << 8); + break; + case 8: + via2_t2l = (via2_t2l & 0xff00) | byte; + break; + case 9: + via2_t2l = (via2_t2l & 0xff) | (byte << 8); + via2_ifr &= 0xdf; + via2_t2c = via2_t2l; + break; + case 10: + via2_sr = byte; + break; + case 11: + via2_acr = byte; + break; + case 12: + via2_pcr = byte; + break; + case 13: + via2_ifr &= ~byte; + break; + case 14: + if (byte & 0x80) + via2_ier |= byte & 0x7f; + else + via2_ier &= ~byte; + break; + } +} + + +/* + * Write a byte to the CPU's address space + */ + +inline void MOS6502_1541::write_byte(uint16 adr, uint8 byte) +{ + if (adr & 0xF800) write_byte_io(adr, byte); + else myRAM1541[adr] = byte; +} + + +/* + * Read a byte from the zeropage + */ + +inline uint8 MOS6502_1541::read_zp(uint16 adr) +{ + return myRAM1541[adr]; +} + + +/* + * Read a word (little-endian) from the zeropage + */ + +inline uint16 MOS6502_1541::read_zp_word(uint16 adr) +{ + return myRAM1541[adr & 0xff] | (myRAM1541[(adr+1) & 0xff] << 8); +} + + +/* + * Write a byte to the zeropage + */ + +inline void MOS6502_1541::write_zp(uint16 adr, uint8 byte) +{ + myRAM1541[adr] = byte; +} + + + +/* + * Jump to address + */ + +inline void MOS6502_1541::jump(uint16 adr) +{ + pc = adr; +} + + +/* + * Adc instruction + */ + +void MOS6502_1541::do_adc(uint8 byte) +{ + if (!d_flag) { + uint16 tmp; + + // Binary mode + tmp = a + byte + (c_flag ? 1 : 0); + c_flag = tmp > 0xff; + v_flag = !((a ^ byte) & 0x80) && ((a ^ tmp) & 0x80); + z_flag = n_flag = a = tmp; + + } else { + uint16 al, ah; + + // Decimal mode + al = (a & 0x0f) + (byte & 0x0f) + (c_flag ? 1 : 0); // Calculate lower nybble + if (al > 9) al += 6; // BCD fixup for lower nybble + + ah = (a >> 4) + (byte >> 4); // Calculate upper nybble + if (al > 0x0f) ah++; + + z_flag = a + byte + (c_flag ? 1 : 0); // Set flags + n_flag = ah << 4; // Only highest bit used + v_flag = (((ah << 4) ^ a) & 0x80) && !((a ^ byte) & 0x80); + + if (ah > 9) ah += 6; // BCD fixup for upper nybble + c_flag = ah > 0x0f; // Set carry flag + a = (ah << 4) | (al & 0x0f); // Compose result + } +} + + +/* + * Sbc instruction + */ + +void MOS6502_1541::do_sbc(uint8 byte) +{ + uint16 tmp = a - byte - (c_flag ? 0 : 1); + + if (!d_flag) { + + // Binary mode + c_flag = tmp < 0x100; + v_flag = ((a ^ tmp) & 0x80) && ((a ^ byte) & 0x80); + z_flag = n_flag = a = tmp; + + } else { + uint16 al, ah; + + // Decimal mode + al = (a & 0x0f) - (byte & 0x0f) - (c_flag ? 0 : 1); // Calculate lower nybble + ah = (a >> 4) - (byte >> 4); // Calculate upper nybble + if (al & 0x10) { + al -= 6; // BCD fixup for lower nybble + ah--; + } + if (ah & 0x10) ah -= 6; // BCD fixup for upper nybble + + c_flag = tmp < 0x100; // Set flags + v_flag = ((a ^ tmp) & 0x80) && ((a ^ byte) & 0x80); + z_flag = n_flag = tmp; + + a = (ah << 4) | (al & 0x0f); // Compose result + } +} + + +/* + * Get 6502 register state + */ + +void MOS6502_1541::GetState(MOS6502State *s) +{ + s->a = a; + s->x = x; + s->y = y; + + s->p = 0x20 | (n_flag & 0x80); + if (v_flag) s->p |= 0x40; + if (d_flag) s->p |= 0x08; + if (i_flag) s->p |= 0x04; + if (!z_flag) s->p |= 0x02; + if (c_flag) s->p |= 0x01; + + s->pc = pc; + s->sp = sp | 0x0100; + + s->intr[INT_VIA1IRQ] = interrupt.intr[INT_VIA1IRQ]; + s->intr[INT_VIA2IRQ] = interrupt.intr[INT_VIA2IRQ]; + s->intr[INT_RESET] = interrupt.intr[INT_RESET]; + s->instruction_complete = true; + s->idle = Idle; + + s->via1_pra = via1_pra; s->via1_ddra = via1_ddra; + s->via1_prb = via1_prb; s->via1_ddrb = via1_ddrb; + s->via1_t1c = via1_t1c; s->via1_t1l = via1_t1l; + s->via1_t2c = via1_t2c; s->via1_t2l = via1_t2l; + s->via1_sr = via1_sr; + s->via1_acr = via1_acr; s->via1_pcr = via1_pcr; + s->via1_ifr = via1_ifr; s->via1_ier = via1_ier; + + s->via2_pra = via2_pra; s->via2_ddra = via2_ddra; + s->via2_prb = via2_prb; s->via2_ddrb = via2_ddrb; + s->via2_t1c = via2_t1c; s->via2_t1l = via2_t1l; + s->via2_t2c = via2_t2c; s->via2_t2l = via2_t2l; + s->via2_sr = via2_sr; + s->via2_acr = via2_acr; s->via2_pcr = via2_pcr; + s->via2_ifr = via2_ifr; s->via2_ier = via2_ier; +} + + +/* + * Restore 6502 state + */ + +void MOS6502_1541::SetState(MOS6502State *s) +{ + a = s->a; + x = s->x; + y = s->y; + + n_flag = s->p; + v_flag = s->p & 0x40; + d_flag = s->p & 0x08; + i_flag = s->p & 0x04; + z_flag = !(s->p & 0x02); + c_flag = s->p & 0x01; + + jump(s->pc); + sp = s->sp & 0xff; + + interrupt.intr[INT_VIA1IRQ] = s->intr[INT_VIA1IRQ]; + interrupt.intr[INT_VIA2IRQ] = s->intr[INT_VIA2IRQ]; + interrupt.intr[INT_RESET] = s->intr[INT_RESET]; + Idle = s->idle; + + via1_pra = s->via1_pra; via1_ddra = s->via1_ddra; + via1_prb = s->via1_prb; via1_ddrb = s->via1_ddrb; + via1_t1c = s->via1_t1c; via1_t1l = s->via1_t1l; + via1_t2c = s->via1_t2c; via1_t2l = s->via1_t2l; + via1_sr = s->via1_sr; + via1_acr = s->via1_acr; via1_pcr = s->via1_pcr; + via1_ifr = s->via1_ifr; via1_ier = s->via1_ier; + + via2_pra = s->via2_pra; via2_ddra = s->via2_ddra; + via2_prb = s->via2_prb; via2_ddrb = s->via2_ddrb; + via2_t1c = s->via2_t1c; via2_t1l = s->via2_t1l; + via2_t2c = s->via2_t2c; via2_t2l = s->via2_t2l; + via2_sr = s->via2_sr; + via2_acr = s->via2_acr; via2_pcr = s->via2_pcr; + via2_ifr = s->via2_ifr; via2_ier = s->via2_ier; +} + + +/* + * Reset CPU + */ + +void MOS6502_1541::Reset(void) +{ + the_job->Reset(); + + // IEC lines and VIA registers + IECLines = 0xc0; + + via1_pra = via1_ddra = via1_prb = via1_ddrb = 0; + via1_acr = via1_pcr = 0; + via1_ifr = via1_ier = 0; + via2_pra = via2_ddra = via2_prb = via2_ddrb = 0; + via2_acr = via2_pcr = 0; + via2_ifr = via2_ier = 0; + + // Clear all interrupt lines + interrupt.intr_any = 0; + + // Read reset vector + jump(read_word(0xfffc)); + + // Wake up 1541 + Idle = false; +} + + +/* + * Illegal opcode encountered + */ + +void MOS6502_1541::illegal_op(uint8 op, uint16 at) +{ + char illop_msg[80]; + + sprintf(illop_msg, "1541: Illegal opcode %02x at %04x.", op, at); + if (ShowRequester(illop_msg, "Reset 1541", "Reset C64")) + the_c64->Reset(); + Reset(); +} + + +/* + * Stack macros + */ + +// Pop a byte from the stack +#define pop_byte() myRAM1541[(++sp) | 0x0100] + +// Push a byte onto the stack +#define push_byte(byte) (myRAM1541[((sp--) & 0xff) | 0x0100] = (byte)) + +// Pop processor flags from the stack +#define pop_flags() \ + n_flag = tmp = pop_byte(); \ + v_flag = tmp & 0x40; \ + d_flag = tmp & 0x08; \ + i_flag = tmp & 0x04; \ + z_flag = !(tmp & 0x02); \ + c_flag = tmp & 0x01; + +// Push processor flags onto the stack +#define push_flags(b_flag) \ + tmp = 0x20 | (n_flag & 0x80); \ + if ((via2_pcr & 0x0e) == 0x0e && the_job->ByteReady()) v_flag = true; \ + if (v_flag) tmp |= 0x40; \ + if (b_flag) tmp |= 0x10; \ + if (d_flag) tmp |= 0x08; \ + if (i_flag) tmp |= 0x04; \ + if (!z_flag) tmp |= 0x02; \ + if (c_flag) tmp |= 0x01; \ + push_byte(tmp); + + +void MOS6502_1541::ext_opcode(void) +{ + if (pc < 0xc000) { + illegal_op(0xf2, pc-1); + } + switch (read_byte(pc++)) { + case 0x00: // Go to sleep in DOS idle loop if error flag is clear and no command received + Idle = !(myRAM1541[0x26c] | myRAM1541[0x7c]); + jump(0xebff); + break; + case 0x01: // Write sector + the_job->WriteSector(); + jump(0xf5dc); + break; + case 0x02: // Format track + the_job->FormatTrack(); + jump(0xfd8b); + break; + default: + illegal_op(0xf2, pc-1); + break; + } +} + +/* + * Emulate cycles_left worth of 6502 instructions + * Returns number of cycles of last instruction + */ + +int MOS6502_1541::EmulateLine(int cycles_left, int cpu_cycles) +{ + uint8 tmp, tmp2; + uint16 adr; + int last_cycles = 0; + + // Any pending interrupts? + if (interrupt.intr_any) { +handle_int: + if (interrupt.intr[INT_RESET]) + { + Reset(); + } + else if ((interrupt.intr[INT_VIA1IRQ] || interrupt.intr[INT_VIA2IRQ]) && !i_flag) + { + push_byte(pc >> 8); push_byte(pc); + push_flags(false); + i_flag = true; + jump(read_word(0xfffe)); + last_cycles = 7; + } + } + +#define IS_CPU_1541 +#undef PRECISE_CPU_CYCLES +#define PRECISE_CPU_CYCLES 0 +#include "CPU_emulline.h" +#undef PRECISE_CPU_CYCLES +#define PRECISE_CPU_CYCLES 1 + + return last_cycles; +} diff --git a/arm9/source/CPU1541.h b/arm9/source/CPU1541.h new file mode 100644 index 0000000..dfc7bda --- /dev/null +++ b/arm9/source/CPU1541.h @@ -0,0 +1,288 @@ +// ===================================================================================== +// GimliDS Copyright (c) 2025 Dave Bernazzani (wavemotion-dave) +// +// As GimliDS is a port of the Frodo emulator for the DS/DSi/XL/LL handhelds, +// any copying or distribution of this emulator, its source code and associated +// readme files, with or without modification, are permitted per the original +// Frodo emulator license shown below. Hugest thanks to Christian Bauer for his +// efforts to provide a clean open-source emulation base for the C64. +// +// Numerous hacks and 'unsafe' optimizations have been performed on the original +// Frodo emulator codebase to get it running on the small handheld system. You +// are strongly encouraged to seek out the official Frodo sources if you're at +// all interested in this emulator code. +// +// The GimliDS emulator is offered as-is, without any warranty. Please see readme.md +// ===================================================================================== + +/* + * CPU1541.h - 6502 (1541) emulation (line based) + * + * Frodo Copyright (C) Christian Bauer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _CPU_1541_H +#define _CPU_1541_H + +#include "CIA.h" +#include "C64.h" + + +// Set this to 1 for more precise CPU cycle calculation +#ifndef PRECISE_CPU_CYCLES +#define PRECISE_CPU_CYCLES 0 +#endif + + +// Interrupt types +enum { + INT_VIA1IRQ, + INT_VIA2IRQ, + INT_RESET +}; + + +class C64; +class Job1541; +class C64Display; +struct MOS6502State; + + +// 6502 emulation (1541) +class MOS6502_1541 { +public: + MOS6502_1541(C64 *c64, Job1541 *job, C64Display *disp, uint8 *Ram, uint8 *Rom); + + int EmulateLine(int cycles_left, int cpu_cycles); // Emulate until cycles_left underflows + void ext_opcode(void); + void Reset(void); + void AsyncReset(void); // Reset the CPU asynchronously + void GetState(MOS6502State *s); + void SetState(MOS6502State *s); + void CountVIATimers(int cycles); + void NewATNState(void); + void TriggerIECInterrupt(void); + void trigger_via1_irq(void); + void trigger_via2_irq(void); + bool InterruptEnabled(void); + + MOS6526_2 *TheCIA2; // Pointer to C64 CIA 2 + + uint8 IECLines; // State of IEC lines (bit 7 - DATA, bit 6 - CLK) + bool Idle; // true: 1541 is idle + +private: + uint8 read_byte(uint16 adr); + uint8 read_byte_fast(uint16 adr); + uint8 read_byte_io(uint16 adr); + uint16 read_word(uint16 adr); + void write_byte(uint16 adr, uint8 byte); + void write_byte_io(uint16 adr, uint8 byte); + + uint8 read_zp(uint16 adr); + uint16 read_zp_word(uint16 adr); + void write_zp(uint16 adr, uint8 byte); + + void jump(uint16 adr); + void illegal_op(uint8 op, uint16 at); + void illegal_jump(uint16 at, uint16 to); + + void do_adc(uint8 byte); + void do_sbc(uint8 byte); + + uint8 *ram; // Pointer to main RAM + uint8 *rom; // Pointer to ROM + C64 *the_c64; // Pointer to C64 object + C64Display *the_display; // Pointer to C64 display object + Job1541 *the_job; // Pointer to 1541 job object + + union { // Pending interrupts + uint8 intr[4]; // Index: See definitions above + unsigned long intr_any; + } interrupt; + + uint8 z_flag, n_flag; + uint8 v_flag, d_flag, i_flag, c_flag; + uint8 a, x, y, sp; + uint16_t pc; + + int borrowed_cycles; // Borrowed cycles from next line + + uint8 via1_pra; // PRA of VIA 1 + uint8 via1_ddra; // DDRA of VIA 1 + uint8 via1_prb; // PRB of VIA 1 + uint8 via1_ddrb; // DDRB of VIA 1 + uint16 via1_t1c; // T1 Counter of VIA 1 + uint16 via1_t1l; // T1 Latch of VIA 1 + uint16 via1_t2c; // T2 Counter of VIA 1 + uint16 via1_t2l; // T2 Latch of VIA 1 + uint8 via1_sr; // SR of VIA 1 + uint8 via1_acr; // ACR of VIA 1 + uint8 via1_pcr; // PCR of VIA 1 + uint8 via1_ifr; // IFR of VIA 1 + uint8 via1_ier; // IER of VIA 1 + + uint8 via2_pra; // PRA of VIA 2 + uint8 via2_ddra; // DDRA of VIA 2 + uint8 via2_prb; // PRB of VIA 2 + uint8 via2_ddrb; // DDRB of VIA 2 + uint16 via2_t1c; // T1 Counter of VIA 2 + uint16 via2_t1l; // T1 Latch of VIA 2 + uint16 via2_t2c; // T2 Counter of VIA 2 + uint16 via2_t2l; // T2 Latch of VIA 2 + uint8 via2_sr; // SR of VIA 2 + uint8 via2_acr; // ACR of VIA 2 + uint8 via2_pcr; // PCR of VIA 2 + uint8 via2_ifr; // IFR of VIA 2 + uint8 via2_ier; // IER of VIA 2 +}; + +// 6502 state +struct MOS6502State { + uint8 a, x, y; + uint8 p; // Processor flags + uint16 pc, sp; + + uint8 intr[4]; // Interrupt state + bool instruction_complete; + bool idle; + + uint8 via1_pra; // VIA 1 + uint8 via1_ddra; + uint8 via1_prb; + uint8 via1_ddrb; + uint16 via1_t1c; + uint16 via1_t1l; + uint16 via1_t2c; + uint16 via1_t2l; + uint8 via1_sr; + uint8 via1_acr; + uint8 via1_pcr; + uint8 via1_ifr; + uint8 via1_ier; + + uint8 via2_pra; // VIA 2 + uint8 via2_ddra; + uint8 via2_prb; + uint8 via2_ddrb; + uint16 via2_t1c; + uint16 via2_t1l; + uint16 via2_t2c; + uint16 via2_t2l; + uint8 via2_sr; + uint8 via2_acr; + uint8 via2_pcr; + uint8 via2_ifr; + uint8 via2_ier; +}; + + + +/* + * Trigger VIA1 IRQ + */ +inline void MOS6502_1541::trigger_via1_irq(void) +{ + interrupt.intr[INT_VIA1IRQ] = true; + Idle = false; +} + +/* + * Trigger VIA2 IRQ + */ +inline void MOS6502_1541::trigger_via2_irq(void) +{ + interrupt.intr[INT_VIA2IRQ] = true; + Idle = false; +} + + +/* + * Count VIA timers + */ + +inline void MOS6502_1541::CountVIATimers(int cycles) +{ + unsigned long tmp; + + via1_t1c = tmp = via1_t1c - cycles; + if (tmp > 0xffff) { + via1_t1c = via1_t1l; // Reload from latch + via1_ifr |= 0x40; + } + + if (!(via1_acr & 0x20)) { // Only count in one-shot mode + via1_t2c = tmp = via1_t2c - cycles; + if (tmp > 0xffff) + via1_ifr |= 0x20; + } + + via2_t1c = tmp = via2_t1c - cycles; + if (tmp > 0xffff) { + via2_t1c = via2_t1l; // Reload from latch + via2_ifr |= 0x40; + if (via2_ier & 0x40) + trigger_via2_irq(); + } + + if (!(via2_acr & 0x20)) { // Only count in one-shot mode + via2_t2c = tmp = via2_t2c - cycles; + if (tmp > 0xffff) + via2_ifr |= 0x20; + } +} + + +/* + * ATN line probably changed state, recalc IECLines + */ + +inline void MOS6502_1541::NewATNState(void) +{ + uint8 byte = ~via1_prb & via1_ddrb; + IECLines = ((byte << 6) & ((~byte ^ TheCIA2->IECLines) << 3) & 0x80) // DATA (incl. ATN acknowledge) + | ((byte << 3) & 0x40); // CLK +} + + +/* + * Interrupt by negative edge of ATN on IEC bus + */ + +inline void MOS6502_1541::TriggerIECInterrupt(void) +{ + if (via1_pcr & 0x01) // CA1 positive edge (1541 gets inverted bus signal) + { + via1_ifr |= 0x02; + if (via1_ier & 0x02) // CA1 interrupt enabled? + { + trigger_via1_irq(); + } + } +} + + +/* + * Test if interrupts are enabled (for job loop) + */ + +inline bool MOS6502_1541::InterruptEnabled(void) +{ + return !i_flag; +} + +#endif diff --git a/arm9/source/CPUC64.cpp b/arm9/source/CPUC64.cpp new file mode 100644 index 0000000..d7d7352 --- /dev/null +++ b/arm9/source/CPUC64.cpp @@ -0,0 +1,640 @@ +// ===================================================================================== +// GimliDS Copyright (c) 2025 Dave Bernazzani (wavemotion-dave) +// +// As GimliDS is a port of the Frodo emulator for the DS/DSi/XL/LL handhelds, +// any copying or distribution of this emulator, its source code and associated +// readme files, with or without modification, are permitted per the original +// Frodo emulator license shown below. Hugest thanks to Christian Bauer for his +// efforts to provide a clean open-source emulation base for the C64. +// +// Numerous hacks and 'unsafe' optimizations have been performed on the original +// Frodo emulator codebase to get it running on the small handheld system. You +// are strongly encouraged to seek out the official Frodo sources if you're at +// all interested in this emulator code. +// +// The GimliDS emulator is offered as-is, without any warranty. Please see readme.md +// ===================================================================================== + +/* + * CPUC64.cpp - 6510 (C64) emulation (line based) + * + * Frodo Copyright (C) Christian Bauer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Notes: + * ------ + * + * - The EmulateLine() function is called for every emulated + * raster line. It has a cycle counter that is decremented by every + * executed opcode and if the counter goes below zero, the function + * returns. + * - All memory accesses are done with the read_byte() and + * write_byte() functions which also do the memory address decoding. The + * read_zp() and write_zp() functions allow faster access to the zero + * page, the pop_byte() and push_byte() macros for the stack. + * - If a write occurs to addresses 0 or 1, new_config() is called to check + * whether the memory configuration has changed + * - The possible interrupt sources are: + * INT_VICIRQ: I flag is checked, jump to ($fffe) + * INT_CIAIRQ: I flag is checked, jump to ($fffe) + * INT_NMI: Jump to ($fffa) + * INT_RESET: Jump to ($fffc) + * - Interrupts are not checked before every opcode but only at certain + * times: + * On entering EmulateLine() + * On CLI + * On PLP if the I flag was cleared + * On RTI if the I flag was cleared + * - The z_flag variable has the inverse meaning of the 6510 Z flag. + * - Only the highest bit of the n_flag variable is used. + * - The $f2 opcode that would normally crash the 6510 is used to implement + * emulator-specific functions, mainly those for the IEC routines. + */ + +#include +#include "sysdeps.h" + +#include "CPUC64.h" +#include "C64.h" +#include "VIC.h" +#include "SID.h" +#include "CIA.h" +#include "IEC.h" +#include "Display.h" +#include "mainmenu.h" + +enum { + INT_RESET = 3 +}; + +extern uint8 myRAM[]; + +/* + * 6510 constructor: Initialize registers + */ + +MOS6510::MOS6510(C64 *c64, uint8 *Ram, uint8 *Basic, uint8 *Kernal, uint8 *Char, uint8 *Color) + : the_c64(c64), ram(Ram), basic_rom(Basic), kernal_rom(Kernal), char_rom(Char), color_ram(Color) +{ + a = x = y = 0; + sp = 0xff; + n_flag = z_flag = 0; + v_flag = d_flag = c_flag = false; + i_flag = true; + + kernal_rom_offset = Kernal - 0xe000; // For faster indexing during emulation... + + interrupt.intr[INT_VICIRQ] = false; + interrupt.intr[INT_CIAIRQ] = false; + interrupt.intr[INT_NMI] = false; + interrupt.intr[INT_RESET] = false; + + nmi_state = false; + + borrowed_cycles = 0; + dfff_byte = 0x55; +} + + +/* + * Reset CPU asynchronously + */ + +void MOS6510::AsyncReset(void) +{ + interrupt.intr[INT_RESET] = true; +} + + +/* + * Raise NMI asynchronously (Restore key) + */ + +void MOS6510::AsyncNMI(void) +{ + if (!nmi_state) + interrupt.intr[INT_NMI] = true; +} + + +/* + * Memory configuration has probably changed + */ + +void MOS6510::new_config(void) +{ + if ((ram[0] & 0x10) == 0) { + ram[1] |= 0x10; // Keep cassette sense line high + } + + uint8 port = ~ram[0] | ram[1]; + + basic_in = (port & 3) == 3; + kernal_in = port & 2; + char_in = (port & 3) && !(port & 4); + io_in = (port & 3) && (port & 4); +} + + +/* + * Read a byte from I/O / ROM space + */ + +__attribute__ ((noinline)) uint8 MOS6510::read_byte_io(uint16 adr) +{ + switch (adr >> 12) { + case 0xa: + case 0xb: + if (basic_in) + { + return basic_rom[adr & 0x1fff]; + } + else + return myRAM[adr]; + case 0xc: + return myRAM[adr]; + case 0xd: + if (io_in) + switch ((adr >> 8) & 0x0f) { + case 0x0: // VIC + case 0x1: + case 0x2: + case 0x3: + return TheVIC->ReadRegister(adr & 0x3f); + case 0x4: // SID + case 0x5: + case 0x6: + case 0x7: + return TheSID->ReadRegister(adr & 0x1f); + case 0x8: // Color RAM + case 0x9: + case 0xa: + case 0xb: + return color_ram[adr & 0x03ff] | (rand() & 0xf0); + case 0xc: // CIA 1 + return TheCIA1->ReadRegister(adr & 0x0f); + case 0xd: // CIA 2 + return TheCIA2->ReadRegister(adr & 0x0f); + case 0xe: // REU/Open I/O + case 0xf: + return rand(); + } + else if (char_in) + return char_rom[adr & 0x0fff]; + else + return myRAM[adr]; + case 0xe: + case 0xf: + if (kernal_in) + { + return kernal_rom_offset[adr]; + } + else + return myRAM[adr]; + default: // Can't happen + return 0; + } +} + + +/* + * Read a byte from the CPU's address space + */ + +inline __attribute__((always_inline)) uint8 MOS6510::read_byte(uint16 adr) +{ + if (adr < 0xa000) + return myRAM[adr]; + else + return read_byte_io(adr); +} + +/* + * Read a word (little-endian) from the CPU's address space + */ +inline uint16 MOS6510::read_word(uint16 adr) +{ + return read_byte(adr) | (read_byte(adr+1) << 8); +} + + +/* + * Write byte to I/O space + */ + +__attribute__ ((noinline)) void MOS6510::write_byte_io(uint16 adr, uint8 byte) +{ + if (adr >= 0xe000) + { + myRAM[adr] = byte; + } else if (io_in) + switch ((adr >> 8) & 0x0f) { + case 0x0: // VIC + case 0x1: + case 0x2: + case 0x3: + TheVIC->WriteRegister(adr & 0x3f, byte); + return; + case 0x4: // SID + case 0x5: + case 0x6: + case 0x7: + TheSID->WriteRegister(adr & 0x1f, byte); + return; + case 0x8: // Color RAM + case 0x9: + case 0xa: + case 0xb: + color_ram[adr & 0x03ff] = byte & 0x0f; + return; + case 0xc: // CIA 1 + TheCIA1->WriteRegister(adr & 0x0f, byte); + return; + case 0xd: // CIA 2 + TheCIA2->WriteRegister(adr & 0x0f, byte); + return; + case 0xe: // REU/Open I/O + case 0xf: + return; + } + else + { + myRAM[adr] = byte; + } +} + + +/* + * Write a byte to the CPU's address space + */ + +inline void MOS6510::write_byte(uint16 adr, uint8 byte) +{ + if (adr < 0xd000) + { + myRAM[adr] = byte; + if (!(adr & 0xFFFE)) new_config(); // First two bytes are special... + } else write_byte_io(adr, byte); +} + + +/* + * Read a byte from the zeropage + */ + +inline uint8 MOS6510::read_zp(uint16 adr) +{ + return myRAM[adr]; +} + + +/* + * Read a word (little-endian) from the zeropage + */ + +inline uint16 MOS6510::read_zp_word(uint16 adr) +{ +// !! zeropage word addressing wraps around !! + return myRAM[adr & 0xff] | (myRAM[(adr+1) & 0xff] << 8); +} + + +/* + * Write a byte to the zeropage + */ + +inline void MOS6510::write_zp(uint16 adr, uint8 byte) +{ + myRAM[adr] = byte; + + // Check if memory configuration may have changed. + if (adr < 2) + new_config(); +} + + +/* + * Jump to address + */ +#define jump(adr) pc = (adr) + + +/* + * Adc instruction + */ + +void MOS6510::do_adc(uint8 byte) +{ + if (!d_flag) { + uint16 tmp = a + (byte) + (c_flag ? 1 : 0); + c_flag = tmp > 0xff; + v_flag = !((a ^ (byte)) & 0x80) && ((a ^ tmp) & 0x80); + z_flag = n_flag = a = tmp; + } else { + uint16 al, ah; + al = (a & 0x0f) + ((byte) & 0x0f) + (c_flag ? 1 : 0); + if (al > 9) al += 6; + ah = (a >> 4) + ((byte) >> 4); + if (al > 0x0f) ah++; + z_flag = a + (byte) + (c_flag ? 1 : 0); + n_flag = ah << 4; + v_flag = (((ah << 4) ^ a) & 0x80) && !((a ^ (byte)) & 0x80); + if (ah > 9) ah += 6; + c_flag = ah > 0x0f; + a = (ah << 4) | (al & 0x0f); + } +} + + +/* + * Sbc instruction + */ + +void MOS6510::do_sbc(uint8 byte) +{ + uint16 tmp = a - (byte) - (c_flag ? 0 : 1); + if (!d_flag) { + c_flag = tmp < 0x100; + v_flag = ((a ^ tmp) & 0x80) && ((a ^ (byte)) & 0x80); + z_flag = n_flag = a = tmp; + } else { + uint16 al, ah; + al = (a & 0x0f) - ((byte) & 0x0f) - (c_flag ? 0 : 1); + ah = (a >> 4) - ((byte) >> 4); + if (al & 0x10) { + al -= 6; + ah--; + } + if (ah & 0x10) ah -= 6; + c_flag = tmp < 0x100; + v_flag = ((a ^ tmp) & 0x80) && ((a ^ (byte)) & 0x80); + z_flag = n_flag = tmp; + a = (ah << 4) | (al & 0x0f); + } +} + + +/* + * Get 6510 register state + */ + +void MOS6510::GetState(MOS6510State *s) +{ + s->a = a; + s->x = x; + s->y = y; + + s->p = 0x20 | (n_flag & 0x80); + if (v_flag) s->p |= 0x40; + if (d_flag) s->p |= 0x08; + if (i_flag) s->p |= 0x04; + if (!z_flag) s->p |= 0x02; + if (c_flag) s->p |= 0x01; + + s->ddr = ram[0]; + s->pr = ram[1] & 0x3f; + + s->pc = pc; + s->sp = sp | 0x0100; + + s->intr[INT_VICIRQ] = interrupt.intr[INT_VICIRQ]; + s->intr[INT_CIAIRQ] = interrupt.intr[INT_CIAIRQ]; + s->intr[INT_NMI] = interrupt.intr[INT_NMI]; + s->intr[INT_RESET] = interrupt.intr[INT_RESET]; + s->nmi_state = nmi_state; + s->dfff_byte = dfff_byte; + s->instruction_complete = true; +} + + +/* + * Restore 6510 state + */ + +void MOS6510::SetState(MOS6510State *s) +{ + a = s->a; + x = s->x; + y = s->y; + + n_flag = s->p; + v_flag = s->p & 0x40; + d_flag = s->p & 0x08; + i_flag = s->p & 0x04; + z_flag = !(s->p & 0x02); + c_flag = s->p & 0x01; + + ram[0] = s->ddr; + ram[1] = s->pr; + new_config(); + + jump(s->pc); + sp = s->sp & 0xff; + + interrupt.intr[INT_VICIRQ] = s->intr[INT_VICIRQ]; + interrupt.intr[INT_CIAIRQ] = s->intr[INT_CIAIRQ]; + interrupt.intr[INT_NMI] = s->intr[INT_NMI]; + interrupt.intr[INT_RESET] = s->intr[INT_RESET]; + nmi_state = s->nmi_state; + dfff_byte = s->dfff_byte; +} + + +/* + * Reset CPU + */ + +void MOS6510::Reset(void) +{ + // Delete 'CBM80' if present + if (ram[0x8004] == 0xc3 && ram[0x8005] == 0xc2 && ram[0x8006] == 0xcd + && ram[0x8007] == 0x38 && ram[0x8008] == 0x30) + ram[0x8004] = 0; + + // Initialize extra 6510 registers and memory configuration + ram[0] = ram[1] = 0; + new_config(); + + // Clear all interrupt lines + interrupt.intr_any = 0; + nmi_state = false; + + interrupt.intr[INT_VICIRQ] = false; + interrupt.intr[INT_CIAIRQ] = false; + interrupt.intr[INT_NMI] = false; + interrupt.intr[INT_RESET] = false; + + + // Read reset vector + jump(read_word(0xfffc)); +} + + +/* + * Illegal opcode encountered + */ + +void MOS6510::illegal_op(uint8 op, uint16 at) +{ + char illop_msg[80]; + + sprintf(illop_msg, "Illegal opcode %02x at %04x.", op, at); + ShowRequester(illop_msg, "Reset"); + the_c64->Reset(); + Reset(); +} + + +/* + * Jump to illegal address space (PC_IS_POINTER only) + */ + +void MOS6510::illegal_jump(uint16 at, uint16 to) +{ + char illop_msg[80]; + + sprintf(illop_msg, "Jump to I/O space at %04x to %04x.", at, to); + ShowRequester(illop_msg, "Reset"); + the_c64->Reset(); + Reset(); +} + + +/* + * Stack macros + */ + +// Pop a byte from the stack +#define pop_byte() myRAM[(++sp) | 0x0100] + +// Push a byte onto the stack +#define push_byte(byte) (myRAM[((sp--) & 0xff) | 0x0100] = (byte)) + +// Pop processor flags from the stack +#define pop_flags() \ + n_flag = tmp = pop_byte(); \ + v_flag = tmp & 0x40; \ + d_flag = tmp & 0x08; \ + i_flag = tmp & 0x04; \ + z_flag = !(tmp & 0x02); \ + c_flag = tmp & 0x01; + +// Push processor flags onto the stack +#define push_flags(b_flag) \ + tmp = 0x20 | (n_flag & 0x80); \ + if (v_flag) tmp |= 0x40; \ + if (b_flag) tmp |= 0x10; \ + if (d_flag) tmp |= 0x08; \ + if (i_flag) tmp |= 0x04; \ + if (!z_flag) tmp |= 0x02; \ + if (c_flag) tmp |= 0x01; \ + push_byte(tmp); + +void MOS6510::ext_opcode(void) +{ + if (pc < 0xe000) { + illegal_op(0xf2, pc-1); + } + switch (read_byte(pc++)) { + case 0x00: + ram[0x90] |= TheIEC->Out(ram[0x95], ram[0xa3] & 0x80); + c_flag = false; + jump(0xedac); + break; + case 0x01: + ram[0x90] |= TheIEC->OutATN(ram[0x95]); + c_flag = false; + jump(0xedac); + break; + case 0x02: + ram[0x90] |= TheIEC->OutSec(ram[0x95]); + c_flag = false; + jump(0xedac); + break; + case 0x03: + ram[0x90] |= TheIEC->In(a); + z_flag = n_flag = a; + c_flag = false; + jump(0xedac); + break; + case 0x04: + TheIEC->SetATN(); + jump(0xedfb); + break; + case 0x05: + TheIEC->RelATN(); + jump(0xedac); + break; + case 0x06: + TheIEC->Turnaround(); + jump(0xedac); + break; + case 0x07: + TheIEC->Release(); + jump(0xedac); + break; + default: + illegal_op(0xf2, pc-1); + break; + } +} +/* + * Emulate cycles_left worth of 6510 instructions + * Returns number of cycles of last instruction + */ +ITCM_CODE int MOS6510::EmulateLine(int cycles_left) +{ + uint8 tmp, tmp2; + uint16 adr; // Used by read_adr_abs()! + int last_cycles = 0; + + // Any pending interrupts? + if (interrupt.intr_any) + { +handle_int: + if (interrupt.intr[INT_RESET]) + { + Reset(); + } + else if (interrupt.intr[INT_NMI]) + { + interrupt.intr[INT_NMI] = false; // Simulate an edge-triggered input + push_byte(pc >> 8); push_byte(pc); + push_flags(false); + i_flag = true; + adr = read_word(0xfffa); + jump(adr); + last_cycles = 7; + + } + else if ((interrupt.intr[INT_VICIRQ] || interrupt.intr[INT_CIAIRQ]) && !i_flag) + { + push_byte(pc >> 8); push_byte(pc); + push_flags(false); + i_flag = true; + adr = read_word(0xfffe); + jump(adr); + last_cycles = 7; + } + } + +#include "CPU_emulline.h" + + return last_cycles; +} + diff --git a/arm9/source/CPUC64.h b/arm9/source/CPUC64.h new file mode 100644 index 0000000..41185c8 --- /dev/null +++ b/arm9/source/CPUC64.h @@ -0,0 +1,190 @@ +// ===================================================================================== +// GimliDS Copyright (c) 2025 Dave Bernazzani (wavemotion-dave) +// +// As GimliDS is a port of the Frodo emulator for the DS/DSi/XL/LL handhelds, +// any copying or distribution of this emulator, its source code and associated +// readme files, with or without modification, are permitted per the original +// Frodo emulator license shown below. Hugest thanks to Christian Bauer for his +// efforts to provide a clean open-source emulation base for the C64. +// +// Numerous hacks and 'unsafe' optimizations have been performed on the original +// Frodo emulator codebase to get it running on the small handheld system. You +// are strongly encouraged to seek out the official Frodo sources if you're at +// all interested in this emulator code. +// +// The GimliDS emulator is offered as-is, without any warranty. Please see readme.md +// ===================================================================================== + +/* + * CPUC64.h - 6510 (C64) emulation (line based) + * + * Frodo Copyright (C) Christian Bauer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _CPU_C64_H +#define _CPU_C64_H + +#include "C64.h" + + +// Set this to 1 for more precise CPU cycle calculation +#ifndef PRECISE_CPU_CYCLES +#define PRECISE_CPU_CYCLES 0 +#endif + +// Set this to 1 for instruction-aligned CIA emulation +#ifndef PRECISE_CIA_CYCLES +#define PRECISE_CIA_CYCLES 0 +#endif + + +// Interrupt types +enum { + INT_VICIRQ, + INT_CIAIRQ, + INT_NMI + // INT_RESET (private) +}; + + +class MOS6569; +class MOS6581; +class MOS6526_1; +class MOS6526_2; +class IEC; +struct MOS6510State; + +// 6510 emulation (C64) +class MOS6510 { +public: + MOS6510(C64 *c64, uint8 *Ram, uint8 *Basic, uint8 *Kernal, uint8 *Char, uint8 *Color); + + int EmulateLine(int cycles_left); // Emulate until cycles_left underflows + void Reset(void); + void AsyncReset(void); // Reset the CPU asynchronously + void AsyncNMI(void); // Raise NMI asynchronously (NMI pulse) + void GetState(MOS6510State *s); + void SetState(MOS6510State *s); + + void TriggerVICIRQ(void); + void ClearVICIRQ(void); + void TriggerCIAIRQ(void); + void ClearCIAIRQ(void); + void TriggerNMI(void); + void ClearNMI(void); + + int ExtConfig; // Memory configuration for ExtRead/WriteByte (0..7) + + MOS6569 *TheVIC; // Pointer to VIC + MOS6581 *TheSID; // Pointer to SID + MOS6526_1 *TheCIA1; // Pointer to CIA 1 + MOS6526_2 *TheCIA2; // Pointer to CIA 2 + IEC *TheIEC; // Pointer to drive array + +private: + void ext_opcode(void); + uint8 read_byte(uint16 adr); + uint8 read_byte_io(uint16 adr); + uint16 read_word(uint16 adr); + void write_byte(uint16 adr, uint8 byte); + void write_byte_io(uint16 adr, uint8 byte); + + uint8 read_zp(uint16 adr); + uint16 read_zp_word(uint16 adr); + void write_zp(uint16 adr, uint8 byte); + + void new_config(void); + void illegal_op(uint8 op, uint16 at); + void illegal_jump(uint16 at, uint16 to); + + void do_adc(uint8 byte); + void do_sbc(uint8 byte); + + uint8 read_emulator_id(uint16 adr); + + uint16_t pc; + + C64 *the_c64; // Pointer to C64 object + + uint8 *ram; // Pointer to main RAM + uint8 *basic_rom, *kernal_rom, *char_rom, *color_ram; // Pointers to ROMs and color RAM + uint8 *kernal_rom_offset; + + union { // Pending interrupts + uint8 intr[4]; // Index: See definitions above + unsigned long intr_any; + } interrupt; + bool nmi_state; // State of NMI line + + uint8 z_flag, n_flag; + uint8 v_flag, d_flag, i_flag, c_flag; + uint8 a, x, y, sp; + + int borrowed_cycles; // Borrowed cycles from next line + + uint8 basic_in, kernal_in, char_in, io_in; + uint8 dfff_byte; +}; + +// 6510 state +struct MOS6510State { + uint8 a, x, y; + uint8 p; // Processor flags + uint8 ddr, pr; // Port + uint16 pc, sp; + uint8 intr[4]; // Interrupt state + bool nmi_state; + uint8 dfff_byte; + bool instruction_complete; +}; + + +// Interrupt functions +inline void MOS6510::TriggerVICIRQ(void) +{ + interrupt.intr[INT_VICIRQ] = true; +} + +inline void MOS6510::TriggerCIAIRQ(void) +{ + interrupt.intr[INT_CIAIRQ] = true; +} + +inline void MOS6510::TriggerNMI(void) +{ + if (!nmi_state) { + nmi_state = true; + interrupt.intr[INT_NMI] = true; + } +} + +inline void MOS6510::ClearVICIRQ(void) +{ + interrupt.intr[INT_VICIRQ] = false; +} + +inline void MOS6510::ClearCIAIRQ(void) +{ + interrupt.intr[INT_CIAIRQ] = false; +} + +inline void MOS6510::ClearNMI(void) +{ + nmi_state = false; +} + +#endif diff --git a/arm9/source/CPU_emulline.h b/arm9/source/CPU_emulline.h new file mode 100644 index 0000000..8171192 --- /dev/null +++ b/arm9/source/CPU_emulline.h @@ -0,0 +1,1387 @@ +// ===================================================================================== +// GimliDS Copyright (c) 2025 Dave Bernazzani (wavemotion-dave) +// +// As GimliDS is a port of the Frodo emulator for the DS/DSi/XL/LL handhelds, +// any copying or distribution of this emulator, its source code and associated +// readme files, with or without modification, are permitted per the original +// Frodo emulator license shown below. Hugest thanks to Christian Bauer for his +// efforts to provide a clean open-source emulation base for the C64. +// +// Numerous hacks and 'unsafe' optimizations have been performed on the original +// Frodo emulator codebase to get it running on the small handheld system. You +// are strongly encouraged to seek out the official Frodo sources if you're at +// all interested in this emulator code. +// +// The GimliDS emulator is offered as-is, without any warranty. Please see readme.md +// ===================================================================================== + +/* + * CPU_emulline.h - 6510/6502 emulation core (body of + * EmulateLine() function, the same for + * both 6510 and 6502) + * + * Frodo Copyright (C) Christian Bauer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +/* + * Addressing mode macros + */ + +// Read immediate operand +#ifdef IS_CPU_1541 +#define read_byte_imm() read_byte_fast(pc++) +#else +#define read_byte_imm() read_byte(pc++) +#endif + +// Read zeropage operand address +#define read_adr_zero() ((uint16)read_byte_imm()) + +// Read zeropage x-indexed operand address +#define read_adr_zero_x() ((read_byte_imm() + x) & 0xff) + +// Read zeropage y-indexed operand address +#define read_adr_zero_y() ((read_byte_imm() + y) & 0xff) + +// Read absolute operand address (uses adr!) +#define read_adr_abs() (adr = read_word(pc), pc+=2, adr) + +// Read absolute x-indexed operand address +#define read_adr_abs_x() (read_adr_abs() + x) + +// Read absolute y-indexed operand address +#define read_adr_abs_y() (read_adr_abs() + y) + +// Read indexed indirect operand address +#define read_adr_ind_x() (read_zp_word(read_byte_imm() + x)) + +// Read indirect indexed operand address +#define read_adr_ind_y() (read_zp_word(read_byte_imm()) + y) + +// Read zeropage operand +#define read_byte_zero() read_zp(read_adr_zero()) + +// Read zeropage x-indexed operand +#define read_byte_zero_x() read_zp(read_adr_zero_x()) + +// Read zeropage y-indexed operand +#define read_byte_zero_y() read_zp(read_adr_zero_y()) + +// Read absolute operand +#define read_byte_abs() read_byte(read_adr_abs()) + +#if PRECISE_CPU_CYCLES +// Account for cyles due to crossing page boundaries +#define page_plus(exp, reg) \ + (adr = exp, last_cycles -= (((adr & 0xff) + reg) & 0x100 ? 1:0), adr + reg) + +// Read absolute x-indexed operand +#define read_byte_abs_x() read_byte(page_plus(read_adr_abs(), x)) + +// Read absolute x-indexed operand +#define read_byte_abs_y() read_byte(page_plus(read_adr_abs(), y)) + +// Read indirect y-indexed operand +#define read_byte_ind_y() read_byte(page_plus(read_zp_word(read_byte_imm()), y)) + +#else + +// Read absolute x-indexed operand +#define read_byte_abs_x() read_byte(read_adr_abs_x()) + +// Read absolute x-indexed operand +#define read_byte_abs_y() read_byte(read_adr_abs_y()) + +// Read indirect y-indexed operand +#define read_byte_ind_y() read_byte(read_adr_ind_y()) +#endif + +// Read indexed indirect operand +#define read_byte_ind_x() read_byte(read_adr_ind_x()) + + +/* + * Set N and Z flags according to byte + */ + +#define set_nz(x) (z_flag = n_flag = (x)) + + +/* + * End of opcode, decrement cycles left + */ + +#define ENDOP(cyc) last_cycles = cyc; break; + +#ifndef IS_CPU_1541 + // Main opcode fetch/execute loop +#if PRECISE_CPU_CYCLES + if (cycles_left) cycles_left -= borrowed_cycles; + + while (true) + { +#if PRECISE_CIA_CYCLES && !defined(IS_CPU_1541) + if (last_cycles) { + TheCIA1->EmulateLine(last_cycles); + TheCIA2->EmulateLine(last_cycles); + } +#endif + if ((cycles_left -= last_cycles) < 0) { + borrowed_cycles = -cycles_left; + break; + } +#else + while ((cycles_left -= last_cycles) >= 0) { +#endif + +#else + cpu_cycles += CycleDeltas[myConfig.cpuCycles]; + MOS6510 *localCPU = the_c64->TheCPU; + + while ((cycles_left -= last_cycles) >= 0) + { + // If we are 1541CPU, we want to alternate running instructions with the main CPU ... + while (cpu_cycles > cycles_left) cpu_cycles -= localCPU->EmulateLine(0); +#endif + + switch (read_byte_imm()) + { + // Load group + case 0xa9: // LDA #imm + set_nz(a = read_byte_imm()); + ENDOP(2); + + case 0xa5: // LDA zero + set_nz(a = read_byte_zero()); + ENDOP(3); + + case 0xb5: // LDA zero,X + set_nz(a = read_byte_zero_x()); + ENDOP(4); + + case 0xad: // LDA abs + set_nz(a = read_byte_abs()); + ENDOP(4); + + case 0xbd: // LDA abs,X + set_nz(a = read_byte_abs_x()); + ENDOP(4); + + case 0xb9: // LDA abs,Y + set_nz(a = read_byte_abs_y()); + ENDOP(4); + + case 0xa1: // LDA (ind,X) + set_nz(a = read_byte_ind_x()); + ENDOP(6); + + case 0xb1: // LDA (ind),Y + set_nz(a = read_byte_ind_y()); + ENDOP(5); + + case 0xa2: // LDX #imm + set_nz(x = read_byte_imm()); + ENDOP(2); + + case 0xa6: // LDX zero + set_nz(x = read_byte_zero()); + ENDOP(3); + + case 0xb6: // LDX zero,Y + set_nz(x = read_byte_zero_y()); + ENDOP(4); + + case 0xae: // LDX abs + set_nz(x = read_byte_abs()); + ENDOP(4); + + case 0xbe: // LDX abs,Y + set_nz(x = read_byte_abs_y()); + ENDOP(4); + + case 0xa0: // LDY #imm + set_nz(y = read_byte_imm()); + ENDOP(2); + + case 0xa4: // LDY zero + set_nz(y = read_byte_zero()); + ENDOP(3); + + case 0xb4: // LDY zero,X + set_nz(y = read_byte_zero_x()); + ENDOP(4); + + case 0xac: // LDY abs + set_nz(y = read_byte_abs()); + ENDOP(4); + + case 0xbc: // LDY abs,X + set_nz(y = read_byte_abs_x()); + ENDOP(4); + + + // Store group + case 0x85: // STA zero + write_byte(read_adr_zero(), a); + ENDOP(3); + + case 0x95: // STA zero,X + write_byte(read_adr_zero_x(), a); + ENDOP(4); + + case 0x8d: // STA abs + write_byte(read_adr_abs(), a); + ENDOP(4); + + case 0x9d: // STA abs,X + write_byte(read_adr_abs_x(), a); + ENDOP(5); + + case 0x99: // STA abs,Y + write_byte(read_adr_abs_y(), a); + ENDOP(5); + + case 0x81: // STA (ind,X) + write_byte(read_adr_ind_x(), a); + ENDOP(6); + + case 0x91: // STA (ind),Y + write_byte(read_adr_ind_y(), a); + ENDOP(6); + + case 0x86: // STX zero + write_byte(read_adr_zero(), x); + ENDOP(3); + + case 0x96: // STX zero,Y + write_byte(read_adr_zero_y(), x); + ENDOP(4); + + case 0x8e: // STX abs + write_byte(read_adr_abs(), x); + ENDOP(4); + + case 0x84: // STY zero + write_byte(read_adr_zero(), y); + ENDOP(3); + + case 0x94: // STY zero,X + write_byte(read_adr_zero_x(), y); + ENDOP(4); + + case 0x8c: // STY abs + write_byte(read_adr_abs(), y); + ENDOP(4); + + + // Transfer group + case 0xaa: // TAX + set_nz(x = a); + ENDOP(2); + + case 0x8a: // TXA + set_nz(a = x); + ENDOP(2); + + case 0xa8: // TAY + set_nz(y = a); + ENDOP(2); + + case 0x98: // TYA + set_nz(a = y); + ENDOP(2); + + case 0xba: // TSX + set_nz(x = sp); + ENDOP(2); + + case 0x9a: // TXS + sp = x; + ENDOP(2); + + + // Arithmetic group + case 0x69: // ADC #imm + do_adc(read_byte_imm()); + ENDOP(2); + + case 0x65: // ADC zero + do_adc(read_byte_zero()); + ENDOP(3); + + case 0x75: // ADC zero,X + do_adc(read_byte_zero_x()); + ENDOP(4); + + case 0x6d: // ADC abs + do_adc(read_byte_abs()); + ENDOP(4); + + case 0x7d: // ADC abs,X + do_adc(read_byte_abs_x()); + ENDOP(4); + + case 0x79: // ADC abs,Y + do_adc(read_byte_abs_y()); + ENDOP(4); + + case 0x61: // ADC (ind,X) + do_adc(read_byte_ind_x()); + ENDOP(6); + + case 0x71: // ADC (ind),Y + do_adc(read_byte_ind_y()); + ENDOP(5); + + case 0xe9: // SBC #imm + case 0xeb: // Undocumented opcode + do_sbc(read_byte_imm()); + ENDOP(2); + + case 0xe5: // SBC zero + do_sbc(read_byte_zero()); + ENDOP(3); + + case 0xf5: // SBC zero,X + do_sbc(read_byte_zero_x()); + ENDOP(4); + + case 0xed: // SBC abs + do_sbc(read_byte_abs()); + ENDOP(4); + + case 0xfd: // SBC abs,X + do_sbc(read_byte_abs_x()); + ENDOP(4); + + case 0xf9: // SBC abs,Y + do_sbc(read_byte_abs_y()); + ENDOP(4); + + case 0xe1: // SBC (ind,X) + do_sbc(read_byte_ind_x()); + ENDOP(6); + + case 0xf1: // SBC (ind),Y + do_sbc(read_byte_ind_y()); + ENDOP(5); + + + // Increment/decrement group + case 0xe8: // INX + set_nz(++x); + ENDOP(2); + + case 0xca: // DEX + set_nz(--x); + ENDOP(2); + + case 0xc8: // INY + set_nz(++y); + ENDOP(2); + + case 0x88: // DEY + set_nz(--y); + ENDOP(2); + + case 0xe6: // INC zero + adr = read_adr_zero(); + write_zp(adr, set_nz(read_zp(adr) + 1)); + ENDOP(5); + + case 0xf6: // INC zero,X + adr = read_adr_zero_x(); + write_zp(adr, set_nz(read_zp(adr) + 1)); + ENDOP(6); + + case 0xee: // INC abs + adr = read_adr_abs(); + write_byte(adr, set_nz(read_byte(adr) + 1)); + ENDOP(6); + + case 0xfe: // INC abs,X + adr = read_adr_abs_x(); + write_byte(adr, set_nz(read_byte(adr) + 1)); + ENDOP(7); + + case 0xc6: // DEC zero + adr = read_adr_zero(); + write_zp(adr, set_nz(read_zp(adr) - 1)); + ENDOP(5); + + case 0xd6: // DEC zero,X + adr = read_adr_zero_x(); + write_zp(adr, set_nz(read_zp(adr) - 1)); + ENDOP(6); + + case 0xce: // DEC abs + adr = read_adr_abs(); + write_byte(adr, set_nz(read_byte(adr) - 1)); + ENDOP(6); + + case 0xde: // DEC abs,X + adr = read_adr_abs_x(); + write_byte(adr, set_nz(read_byte(adr) - 1)); + ENDOP(7); + + + // Logic group + case 0x29: // AND #imm + set_nz(a &= read_byte_imm()); + ENDOP(2); + + case 0x25: // AND zero + set_nz(a &= read_byte_zero()); + ENDOP(3); + + case 0x35: // AND zero,X + set_nz(a &= read_byte_zero_x()); + ENDOP(4); + + case 0x2d: // AND abs + set_nz(a &= read_byte_abs()); + ENDOP(4); + + case 0x3d: // AND abs,X + set_nz(a &= read_byte_abs_x()); + ENDOP(4); + + case 0x39: // AND abs,Y + set_nz(a &= read_byte_abs_y()); + ENDOP(4); + + case 0x21: // AND (ind,X) + set_nz(a &= read_byte_ind_x()); + ENDOP(6); + + case 0x31: // AND (ind),Y + set_nz(a &= read_byte_ind_y()); + ENDOP(5); + + case 0x09: // ORA #imm + set_nz(a |= read_byte_imm()); + ENDOP(2); + + case 0x05: // ORA zero + set_nz(a |= read_byte_zero()); + ENDOP(3); + + case 0x15: // ORA zero,X + set_nz(a |= read_byte_zero_x()); + ENDOP(4); + + case 0x0d: // ORA abs + set_nz(a |= read_byte_abs()); + ENDOP(4); + + case 0x1d: // ORA abs,X + set_nz(a |= read_byte_abs_x()); + ENDOP(4); + + case 0x19: // ORA abs,Y + set_nz(a |= read_byte_abs_y()); + ENDOP(4); + + case 0x01: // ORA (ind,X) + set_nz(a |= read_byte_ind_x()); + ENDOP(6); + + case 0x11: // ORA (ind),Y + set_nz(a |= read_byte_ind_y()); + ENDOP(5); + + case 0x49: // EOR #imm + set_nz(a ^= read_byte_imm()); + ENDOP(2); + + case 0x45: // EOR zero + set_nz(a ^= read_byte_zero()); + ENDOP(3); + + case 0x55: // EOR zero,X + set_nz(a ^= read_byte_zero_x()); + ENDOP(4); + + case 0x4d: // EOR abs + set_nz(a ^= read_byte_abs()); + ENDOP(4); + + case 0x5d: // EOR abs,X + set_nz(a ^= read_byte_abs_x()); + ENDOP(4); + + case 0x59: // EOR abs,Y + set_nz(a ^= read_byte_abs_y()); + ENDOP(4); + + case 0x41: // EOR (ind,X) + set_nz(a ^= read_byte_ind_x()); + ENDOP(6); + + case 0x51: // EOR (ind),Y + set_nz(a ^= read_byte_ind_y()); + ENDOP(5); + + + // Compare group + case 0xc9: // CMP #imm + set_nz(adr = a - read_byte_imm()); + c_flag = adr < 0x100; + ENDOP(2); + + case 0xc5: // CMP zero + set_nz(adr = a - read_byte_zero()); + c_flag = adr < 0x100; + ENDOP(3); + + case 0xd5: // CMP zero,X + set_nz(adr = a - read_byte_zero_x()); + c_flag = adr < 0x100; + ENDOP(4); + + case 0xcd: // CMP abs + set_nz(adr = a - read_byte_abs()); + c_flag = adr < 0x100; + ENDOP(4); + + case 0xdd: // CMP abs,X + set_nz(adr = a - read_byte_abs_x()); + c_flag = adr < 0x100; + ENDOP(4); + + case 0xd9: // CMP abs,Y + set_nz(adr = a - read_byte_abs_y()); + c_flag = adr < 0x100; + ENDOP(4); + + case 0xc1: // CMP (ind,X) + set_nz(adr = a - read_byte_ind_x()); + c_flag = adr < 0x100; + ENDOP(6); + + case 0xd1: // CMP (ind),Y + set_nz(adr = a - read_byte_ind_y()); + c_flag = adr < 0x100; + ENDOP(5); + + case 0xe0: // CPX #imm + set_nz(adr = x - read_byte_imm()); + c_flag = adr < 0x100; + ENDOP(2); + + case 0xe4: // CPX zero + set_nz(adr = x - read_byte_zero()); + c_flag = adr < 0x100; + ENDOP(3); + + case 0xec: // CPX abs + set_nz(adr = x - read_byte_abs()); + c_flag = adr < 0x100; + ENDOP(4); + + case 0xc0: // CPY #imm + set_nz(adr = y - read_byte_imm()); + c_flag = adr < 0x100; + ENDOP(2); + + case 0xc4: // CPY zero + set_nz(adr = y - read_byte_zero()); + c_flag = adr < 0x100; + ENDOP(3); + + case 0xcc: // CPY abs + set_nz(adr = y - read_byte_abs()); + c_flag = adr < 0x100; + ENDOP(4); + + + // Bit-test group + case 0x24: // BIT zero + z_flag = a & (tmp = read_byte_zero()); + n_flag = tmp; + v_flag = tmp & 0x40; + ENDOP(3); + + case 0x2c: // BIT abs + z_flag = a & (tmp = read_byte_abs()); + n_flag = tmp; + v_flag = tmp & 0x40; + ENDOP(4); + + + // Shift/rotate group + case 0x0a: // ASL A + c_flag = a & 0x80; + set_nz(a <<= 1); + ENDOP(2); + + case 0x06: // ASL zero + tmp = read_zp(adr = read_adr_zero()); + c_flag = tmp & 0x80; + write_zp(adr, set_nz(tmp << 1)); + ENDOP(5); + + case 0x16: // ASL zero,X + tmp = read_zp(adr = read_adr_zero_x()); + c_flag = tmp & 0x80; + write_zp(adr, set_nz(tmp << 1)); + ENDOP(6); + + case 0x0e: // ASL abs + tmp = read_byte(adr = read_adr_abs()); + c_flag = tmp & 0x80; + write_byte(adr, set_nz(tmp << 1)); + ENDOP(6); + + case 0x1e: // ASL abs,X + tmp = read_byte(adr = read_adr_abs_x()); + c_flag = tmp & 0x80; + write_byte(adr, set_nz(tmp << 1)); + ENDOP(7); + + case 0x4a: // LSR A + c_flag = a & 0x01; + set_nz(a >>= 1); + ENDOP(2); + + case 0x46: // LSR zero + tmp = read_zp(adr = read_adr_zero()); + c_flag = tmp & 0x01; + write_zp(adr, set_nz(tmp >> 1)); + ENDOP(5); + + case 0x56: // LSR zero,X + tmp = read_zp(adr = read_adr_zero_x()); + c_flag = tmp & 0x01; + write_zp(adr, set_nz(tmp >> 1)); + ENDOP(6); + + case 0x4e: // LSR abs + tmp = read_byte(adr = read_adr_abs()); + c_flag = tmp & 0x01; + write_byte(adr, set_nz(tmp >> 1)); + ENDOP(6); + + case 0x5e: // LSR abs,X + tmp = read_byte(adr = read_adr_abs_x()); + c_flag = tmp & 0x01; + write_byte(adr, set_nz(tmp >> 1)); + ENDOP(7); + + case 0x2a: // ROL A + tmp2 = a & 0x80; + set_nz(a = c_flag ? (a << 1) | 0x01 : a << 1); + c_flag = tmp2; + ENDOP(2); + + case 0x26: // ROL zero + tmp = read_zp(adr = read_adr_zero()); + tmp2 = tmp & 0x80; + write_zp(adr, set_nz(c_flag ? (tmp << 1) | 0x01 : tmp << 1)); + c_flag = tmp2; + ENDOP(5); + + case 0x36: // ROL zero,X + tmp = read_zp(adr = read_adr_zero_x()); + tmp2 = tmp & 0x80; + write_zp(adr, set_nz(c_flag ? (tmp << 1) | 0x01 : tmp << 1)); + c_flag = tmp2; + ENDOP(6); + + case 0x2e: // ROL abs + tmp = read_byte(adr = read_adr_abs()); + tmp2 = tmp & 0x80; + write_byte(adr, set_nz(c_flag ? (tmp << 1) | 0x01 : tmp << 1)); + c_flag = tmp2; + ENDOP(6); + + case 0x3e: // ROL abs,X + tmp = read_byte(adr = read_adr_abs_x()); + tmp2 = tmp & 0x80; + write_byte(adr, set_nz(c_flag ? (tmp << 1) | 0x01 : tmp << 1)); + c_flag = tmp2; + ENDOP(7); + + case 0x6a: // ROR A + tmp2 = a & 0x01; + set_nz(a = (c_flag ? (a >> 1) | 0x80 : a >> 1)); + c_flag = tmp2; + ENDOP(2); + + case 0x66: // ROR zero + tmp = read_zp(adr = read_adr_zero()); + tmp2 = tmp & 0x01; + write_zp(adr, set_nz(c_flag ? (tmp >> 1) | 0x80 : tmp >> 1)); + c_flag = tmp2; + ENDOP(5); + + case 0x76: // ROR zero,X + tmp = read_zp(adr = read_adr_zero_x()); + tmp2 = tmp & 0x01; + write_zp(adr, set_nz(c_flag ? (tmp >> 1) | 0x80 : tmp >> 1)); + c_flag = tmp2; + ENDOP(6); + + case 0x6e: // ROR abs + tmp = read_byte(adr = read_adr_abs()); + tmp2 = tmp & 0x01; + write_byte(adr, set_nz(c_flag ? (tmp >> 1) | 0x80 : tmp >> 1)); + c_flag = tmp2; + ENDOP(6); + + case 0x7e: // ROR abs,X + tmp = read_byte(adr = read_adr_abs_x()); + tmp2 = tmp & 0x01; + write_byte(adr, set_nz(c_flag ? (tmp >> 1) | 0x80 : tmp >> 1)); + c_flag = tmp2; + ENDOP(7); + + + // Stack group + case 0x48: // PHA + push_byte(a); + ENDOP(3); + + case 0x68: // PLA + set_nz(a = pop_byte()); + ENDOP(4); + + case 0x08: // PHP + push_flags(true); + ENDOP(3); + + case 0x28: // PLP + pop_flags(); + if (interrupt.intr_any && !i_flag) + goto handle_int; + ENDOP(4); + + + // Jump/branch group + case 0x4c: // JMP abs + adr = read_adr_abs(); + jump(adr); + ENDOP(3); + + case 0x6c: // JMP (ind) + adr = read_adr_abs(); + adr = read_byte(adr) | (read_byte(((adr + 1) & 0xff) | (adr & 0xff00)) << 8); + jump(adr); + ENDOP(5); + + case 0x20: // JSR abs + push_byte((pc+1) >> 8); push_byte(pc+1); + adr = read_adr_abs(); + jump(adr); + ENDOP(6); + + case 0x60: // RTS + adr = pop_byte(); // Split because of pop_byte ++sp side-effect + adr = (adr | pop_byte() << 8) + 1; + jump(adr); + ENDOP(6); + + case 0x40: // RTI + pop_flags(); + adr = pop_byte(); // Split because of pop_byte ++sp side-effect + adr = adr | pop_byte() << 8; + jump(adr); + if (interrupt.intr_any && !i_flag) + goto handle_int; + ENDOP(6); + + case 0x00: // BRK + push_byte((pc+1) >> 8); push_byte(pc+1); + push_flags(true); + i_flag = true; + adr = read_word(0xfffe); + jump(adr); + ENDOP(7); + +#define Branch(flag) \ + if (flag) { \ + uint16 old_pc = pc; \ + pc += (int8)read_byte(pc) + 1; \ + if ((pc ^ old_pc) & 0xff00) { \ + ENDOP(4); \ + } else { \ + ENDOP(3); \ + } \ + } else { \ + pc++; \ + ENDOP(2); \ + } + + case 0xb0: // BCS rel + Branch(c_flag); + + case 0x90: // BCC rel + Branch(!c_flag); + + case 0xf0: // BEQ rel + Branch(!z_flag); + + case 0xd0: // BNE rel + Branch(z_flag); + + case 0x70: // BVS rel +#ifndef IS_CPU_1541 + Branch(v_flag); +#else + Branch((via2_pcr & 0x0e) == 0x0e ? 1 : v_flag); // GCR byte ready flag + if ((via2_pcr & 0x0e) == 0x0e && the_job->ByteReady()) { // CA2 high output and byte ready + v_flag = true; + } + Branch(v_flag); +#endif + + case 0x50: // BVC rel +#ifndef IS_CPU_1541 + Branch(!v_flag); +#else + if ((via2_pcr & 0x0e) == 0x0e && the_job->ByteReady()) { // CA2 high output and byte ready + v_flag = true; + } + Branch(!v_flag); +#endif + + case 0x30: // BMI rel + Branch(n_flag & 0x80); + + case 0x10: // BPL rel + Branch(!(n_flag & 0x80)); + + + // Flags group + case 0x38: // SEC + c_flag = true; + ENDOP(2); + + case 0x18: // CLC + c_flag = false; + ENDOP(2); + + case 0xf8: // SED + d_flag = true; + ENDOP(2); + + case 0xd8: // CLD + d_flag = false; + ENDOP(2); + + case 0x78: // SEI + i_flag = true; + ENDOP(2); + + case 0x58: // CLI + i_flag = false; + if (interrupt.intr_any) + goto handle_int; + ENDOP(2); + + case 0xb8: // CLV + v_flag = false; + ENDOP(2); + + + // NOP group + case 0xea: // NOP + ENDOP(2); + + +/* + * Undocumented opcodes start here + */ + + // NOP group + case 0x1a: // NOP + case 0x3a: + case 0x5a: + case 0x7a: + case 0xda: + case 0xfa: + ENDOP(2); + + case 0x80: // NOP #imm + case 0x82: + case 0x89: + case 0xc2: + case 0xe2: + pc++; + ENDOP(2); + + case 0x04: // NOP zero + case 0x44: + case 0x64: + pc++; + ENDOP(3); + + case 0x14: // NOP zero,X + case 0x34: + case 0x54: + case 0x74: + case 0xd4: + case 0xf4: + pc++; + ENDOP(4); + + case 0x0c: // NOP abs + pc+=2; + ENDOP(4); + + case 0x1c: // NOP abs,X + case 0x3c: + case 0x5c: + case 0x7c: + case 0xdc: + case 0xfc: +#if PRECISE_CPU_CYCLESz + read_byte_abs_x(); +#else + pc+=2; +#endif + ENDOP(4); + + + // Load A/X group + case 0xa7: // LAX zero + set_nz(a = x = read_byte_zero()); + ENDOP(3); + + case 0xb7: // LAX zero,Y + set_nz(a = x = read_byte_zero_y()); + ENDOP(4); + + case 0xaf: // LAX abs + set_nz(a = x = read_byte_abs()); + ENDOP(4); + + case 0xbf: // LAX abs,Y + set_nz(a = x = read_byte_abs_y()); + ENDOP(4); + + case 0xa3: // LAX (ind,X) + set_nz(a = x = read_byte_ind_x()); + ENDOP(6); + + case 0xb3: // LAX (ind),Y + set_nz(a = x = read_byte_ind_y()); + ENDOP(5); + + + // Store A/X group + case 0x87: // SAX zero + write_byte(read_adr_zero(), a & x); + ENDOP(3); + + case 0x97: // SAX zero,Y + write_byte(read_adr_zero_y(), a & x); + ENDOP(4); + + case 0x8f: // SAX abs + write_byte(read_adr_abs(), a & x); + ENDOP(4); + + case 0x83: // SAX (ind,X) + write_byte(read_adr_ind_x(), a & x); + ENDOP(6); + + + // ASL/ORA group +#define ShiftLeftOr \ + c_flag = tmp & 0x80; \ + tmp <<= 1; \ + set_nz(a |= tmp); + + case 0x07: // SLO zero + tmp = read_zp(adr = read_adr_zero()); + ShiftLeftOr; + write_zp(adr, tmp); + ENDOP(5); + + case 0x17: // SLO zero,X + tmp = read_zp(adr = read_adr_zero_x()); + ShiftLeftOr; + write_zp(adr, tmp); + ENDOP(6); + + case 0x0f: // SLO abs + tmp = read_byte(adr = read_adr_abs()); + ShiftLeftOr; + write_byte(adr, tmp); + ENDOP(6); + + case 0x1f: // SLO abs,X + tmp = read_byte(adr = read_adr_abs_x()); + ShiftLeftOr; + write_byte(adr, tmp); + ENDOP(7); + + case 0x1b: // SLO abs,Y + tmp = read_byte(adr = read_adr_abs_y()); + ShiftLeftOr; + write_byte(adr, tmp); + ENDOP(7); + + case 0x03: // SLO (ind,X) + tmp = read_byte(adr = read_adr_ind_x()); + ShiftLeftOr; + write_byte(adr, tmp); + ENDOP(8); + + case 0x13: // SLO (ind),Y + tmp = read_byte(adr = read_adr_ind_y()); + ShiftLeftOr; + write_byte(adr, tmp); + ENDOP(8); + + + // ROL/AND group +#define RoLeftAnd \ + tmp2 = tmp & 0x80; \ + tmp = c_flag ? (tmp << 1) | 0x01 : tmp << 1; \ + set_nz(a &= tmp); \ + c_flag = tmp2; + + case 0x27: // RLA zero + tmp = read_zp(adr = read_adr_zero()); + RoLeftAnd; + write_zp(adr, tmp); + ENDOP(5); + + case 0x37: // RLA zero,X + tmp = read_zp(adr = read_adr_zero_x()); + RoLeftAnd; + write_zp(adr, tmp); + ENDOP(6); + + case 0x2f: // RLA abs + tmp = read_byte(adr = read_adr_abs()); + RoLeftAnd; + write_byte(adr, tmp); + ENDOP(6); + + case 0x3f: // RLA abs,X + tmp = read_byte(adr = read_adr_abs_x()); + RoLeftAnd; + write_byte(adr, tmp); + ENDOP(7); + + case 0x3b: // RLA abs,Y + tmp = read_byte(adr = read_adr_abs_y()); + RoLeftAnd; + write_byte(adr, tmp); + ENDOP(7); + + case 0x23: // RLA (ind,X) + tmp = read_byte(adr = read_adr_ind_x()); + RoLeftAnd; + write_byte(adr, tmp); + ENDOP(8); + + case 0x33: // RLA (ind),Y + tmp = read_byte(adr = read_adr_ind_y()); + RoLeftAnd; + write_byte(adr, tmp); + ENDOP(8); + + + // LSR/EOR group +#define ShiftRightEor \ + c_flag = tmp & 0x01; \ + tmp >>= 1; \ + set_nz(a ^= tmp); + + case 0x47: // SRE zero + tmp = read_zp(adr = read_adr_zero()); + ShiftRightEor; + write_zp(adr, tmp); + ENDOP(5); + + case 0x57: // SRE zero,X + tmp = read_zp(adr = read_adr_zero_x()); + ShiftRightEor; + write_zp(adr, tmp); + ENDOP(6); + + case 0x4f: // SRE abs + tmp = read_byte(adr = read_adr_abs()); + ShiftRightEor; + write_byte(adr, tmp); + ENDOP(6); + + case 0x5f: // SRE abs,X + tmp = read_byte(adr = read_adr_abs_x()); + ShiftRightEor; + write_byte(adr, tmp); + ENDOP(7); + + case 0x5b: // SRE abs,Y + tmp = read_byte(adr = read_adr_abs_y()); + ShiftRightEor; + write_byte(adr, tmp); + ENDOP(7); + + case 0x43: // SRE (ind,X) + tmp = read_byte(adr = read_adr_ind_x()); + ShiftRightEor; + write_byte(adr, tmp); + ENDOP(8); + + case 0x53: // SRE (ind),Y + tmp = read_byte(adr = read_adr_ind_y()); + ShiftRightEor; + write_byte(adr, tmp); + ENDOP(8); + + // ROR/ADC group +#define RoRightAdc \ + tmp2 = tmp & 0x01; \ + tmp = c_flag ? (tmp >> 1) | 0x80 : tmp >> 1; \ + c_flag = tmp2; \ + do_adc(tmp); + + case 0x67: // RRA zero + tmp = read_zp(adr = read_adr_zero()); + RoRightAdc; + write_zp(adr, tmp); + ENDOP(5); + + case 0x77: // RRA zero,X + tmp = read_zp(adr = read_adr_zero_x()); + RoRightAdc; + write_zp(adr, tmp); + ENDOP(6); + + case 0x6f: // RRA abs + tmp = read_byte(adr = read_adr_abs()); + RoRightAdc; + write_byte(adr, tmp); + ENDOP(6); + + case 0x7f: // RRA abs,X + tmp = read_byte(adr = read_adr_abs_x()); + RoRightAdc; + write_byte(adr, tmp); + ENDOP(7); + + case 0x7b: // RRA abs,Y + tmp = read_byte(adr = read_adr_abs_y()); + RoRightAdc; + write_byte(adr, tmp); + ENDOP(7); + + case 0x63: // RRA (ind,X) + tmp = read_byte(adr = read_adr_ind_x()); + RoRightAdc; + write_byte(adr, tmp); + ENDOP(8); + + case 0x73: // RRA (ind),Y + tmp = read_byte(adr = read_adr_ind_y()); + RoRightAdc; + write_byte(adr, tmp); + ENDOP(8); + + + // DEC/CMP group +#define DecCompare \ + set_nz(adr = a - tmp); \ + c_flag = adr < 0x100; + + case 0xc7: // DCP zero + tmp = read_zp(adr = read_adr_zero()) - 1; + write_zp(adr, tmp); + DecCompare; + ENDOP(5); + + case 0xd7: // DCP zero,X + tmp = read_zp(adr = read_adr_zero_x()) - 1; + write_zp(adr, tmp); + DecCompare; + ENDOP(6); + + case 0xcf: // DCP abs + tmp = read_byte(adr = read_adr_abs()) - 1; + write_byte(adr, tmp); + DecCompare; + ENDOP(6); + + case 0xdf: // DCP abs,X + tmp = read_byte(adr = read_adr_abs_x()) - 1; + write_byte(adr, tmp); + DecCompare; + ENDOP(7); + + case 0xdb: // DCP abs,Y + tmp = read_byte(adr = read_adr_abs_y()) - 1; + write_byte(adr, tmp); + DecCompare; + ENDOP(7); + + case 0xc3: // DCP (ind,X) + tmp = read_byte(adr = read_adr_ind_x()) - 1; + write_byte(adr, tmp); + DecCompare; + ENDOP(8); + + case 0xd3: // DCP (ind),Y + tmp = read_byte(adr = read_adr_ind_y()) - 1; + write_byte(adr, tmp); + DecCompare; + ENDOP(8); + + + // INC/SBC group + case 0xe7: // ISB zero + tmp = read_zp(adr = read_adr_zero()) + 1; + do_sbc(tmp); + write_zp(adr, tmp); + ENDOP(5); + + case 0xf7: // ISB zero,X + tmp = read_zp(adr = read_adr_zero_x()) + 1; + do_sbc(tmp); + write_zp(adr, tmp); + ENDOP(6); + + case 0xef: // ISB abs + tmp = read_byte(adr = read_adr_abs()) + 1; + do_sbc(tmp); + write_byte(adr, tmp); + ENDOP(6); + + case 0xff: // ISB abs,X + tmp = read_byte(adr = read_adr_abs_x()) + 1; + do_sbc(tmp); + write_byte(adr, tmp); + ENDOP(7); + + case 0xfb: // ISB abs,Y + tmp = read_byte(adr = read_adr_abs_y()) + 1; + do_sbc(tmp); + write_byte(adr, tmp); + ENDOP(7); + + case 0xe3: // ISB (ind,X) + tmp = read_byte(adr = read_adr_ind_x()) + 1; + do_sbc(tmp); + write_byte(adr, tmp); + ENDOP(8); + + case 0xf3: // ISB (ind),Y + tmp = read_byte(adr = read_adr_ind_y()) + 1; + do_sbc(tmp); + write_byte(adr, tmp); + ENDOP(8); + + + // Complex functions + case 0x0b: // ANC #imm + case 0x2b: + set_nz(a &= read_byte_imm()); + c_flag = n_flag & 0x80; + ENDOP(2); + + case 0x4b: // ASR #imm + a &= read_byte_imm(); + c_flag = a & 0x01; + set_nz(a >>= 1); + ENDOP(2); + + case 0x6b: // ARR #imm + tmp2 = read_byte_imm() & a; + a = (c_flag ? (tmp2 >> 1) | 0x80 : tmp2 >> 1); + if (!d_flag) { + set_nz(a); + c_flag = a & 0x40; + v_flag = (a & 0x40) ^ ((a & 0x20) << 1); + } else { + n_flag = c_flag ? 0x80 : 0; + z_flag = a; + v_flag = (tmp2 ^ a) & 0x40; + if ((tmp2 & 0x0f) + (tmp2 & 0x01) > 5) { + a = (a & 0xf0) | ((a + 6) & 0x0f); + } + if ((c_flag = ((tmp2 + (tmp2 & 0x10)) & 0x1f0) > 0x50) != 0) { + a += 0x60; + } + } + ENDOP(2); + + case 0x8b: // ANE #imm + set_nz(a = read_byte_imm() & x & (a | 0xee)); + ENDOP(2); + + case 0x93: // SHA (ind),Y + tmp2 = read_zp(read_byte(pc) + 1); + write_byte(read_adr_ind_y(), a & x & (tmp2+1)); + ENDOP(6); + + case 0x9b: // SHS abs,Y + tmp2 = read_byte(pc+1); + adr = read_adr_abs_y(); + if ((adr & 0xff) < y) { // Page crossed? + adr &= ((a & x) << 8) | 0xff; + } + write_byte(adr, a & x & (tmp2 + 1)); + sp = a & x; + ENDOP(5); + + case 0x9c: // SHY abs,X + tmp2 = read_byte(pc+1); + write_byte(read_adr_abs_x(), y & (tmp2+1)); + ENDOP(5); + + case 0x9e: // SHX abs,Y + tmp2 = read_byte(pc+1); + write_byte(read_adr_abs_y(), x & (tmp2+1)); + ENDOP(5); + + case 0x9f: // SHA abs,Y + tmp2 = read_byte(pc+1); + write_byte(read_adr_abs_y(), a & x & (tmp2+1)); + ENDOP(5); + + case 0xab: // LXA #imm + set_nz(a = x = (a | 0xee) & read_byte_imm()); + ENDOP(2); + + case 0xbb: // LAS abs,Y + set_nz(a = x = sp = read_byte_abs_y() & sp); + ENDOP(4); + + case 0xcb: // SBX #imm + x &= a; + adr = x - read_byte_imm(); + c_flag = adr < 0x100; + set_nz(x = adr); + ENDOP(2); + + default: + illegal_op(read_byte(pc-1), pc-1); + break; + + // Extension opcode + case 0xf2: ext_opcode(); break; + } + } +#ifdef IS_CPU_1541 + // See if there are any straggler cycles left for the CPU + while (cpu_cycles > 0) cpu_cycles -= the_c64->TheCPU->EmulateLine(1); +#endif diff --git a/arm9/source/Display.cpp b/arm9/source/Display.cpp new file mode 100644 index 0000000..0c93422 --- /dev/null +++ b/arm9/source/Display.cpp @@ -0,0 +1,870 @@ +// ===================================================================================== +// GimliDS Copyright (c) 2025 Dave Bernazzani (wavemotion-dave) +// +// As GimliDS is a port of the Frodo emulator for the DS/DSi/XL/LL handhelds, +// any copying or distribution of this emulator, its source code and associated +// readme files, with or without modification, are permitted per the original +// Frodo emulator license shown below. Hugest thanks to Christian Bauer for his +// efforts to provide a clean open-source emulation base for the C64. +// +// Numerous hacks and 'unsafe' optimizations have been performed on the original +// Frodo emulator codebase to get it running on the small handheld system. You +// are strongly encouraged to seek out the official Frodo sources if you're at +// all interested in this emulator code. +// +// The GimliDS emulator is offered as-is, without any warranty. Please see readme.md +// ===================================================================================== + +/* + * Display.cpp - C64 graphics display, emulator window handling + * + * Frodo Copyright (C) Christian Bauer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "sysdeps.h" + +#include "Display.h" +#include "main.h" +#include "IEC.h" +#include "C64.h" +#include "Prefs.h" +#include "mainmenu.h" +#include +#include "soundbank.h" + + +u8 floppy_sound_counter = 0; + +// "Colodore" palette +uint8_t palette_red[16] = { + 0x00, 0xff, 0x81, 0x75, 0x8e, 0x56, 0x2e, 0xed, 0x8e, 0x55, 0xc4, 0x4a, 0x7b, 0xa9, 0x70, 0xb2 +}; + +uint8_t palette_green[16] = { + 0x00, 0xff, 0x33, 0xce, 0x3c, 0xac, 0x2c, 0xf1, 0x50, 0x38, 0x6c, 0x4a, 0x7b, 0xff, 0x6d, 0xb2 +}; + +uint8_t palette_blue[16] = { + 0x00, 0xff, 0x38, 0xc8, 0x97, 0x4d, 0x9b, 0x71, 0x29, 0x00, 0x71, 0x4a, 0x7b, 0x9f, 0xeb, 0xb2 +}; + + +void floppy_soundfx(void) +{ + if (myConfig.diskSFX) + { + if (floppy_sound_counter == 0) floppy_sound_counter = 250; + } +} + + +/* + * Update drive LED display (deferred until Update()) + */ +u16 LastFloppySound = 0; +u8 last_led_states = 0x00; +void C64Display::UpdateLEDs(int l0, int l1) +{ + led_state[0] = l0; + led_state[1] = l1; + + last_led_states = l0; + + if (led_state[0] == DRVLED_ERROR) + { + DSPrint(24, 21, 2, (char*)"CDE"); // Red Error Label + } + else + { + if (led_state[0] || led_state[1]) + { + DSPrint(24, 21, 2, (char*)"@AB"); // Green Activity Label + } + else + { + DSPrint(24, 21, 2, (char*)" !\""); // White Idle Drive Label + last_led_states = 0; + } + } +} + +/* + * Display_NDS.i by Troy Davis(GPF), adapted from: + * Display_GP32.i by Mike Dawson - C64 graphics display, emulator window handling, + * + * Frodo (C) 1994-1997,2002 Christian Bauer + * X11 stuff by Bernd Schmidt/Lutz Vieweg + */ + +#include "C64.h" +#include "VIC.h" + +#include +#include +#include +#include +#include +#include +#include +#include "diskmenu.h" +#include "keyboard.h" +#include "soundbank.h" +#include + +#define MOVE_MAX 16 + +#define ABS(a) (((a) < 0) ? -(a) : (a)) +#define ROUND(f) ((u32) ((f) < 0.0 ? (f) - 0.5 : (f) + 0.5)) + +#define KB_NORMAL 0 +#define KB_CAPS 1 +#define KB_SHIFT 2 + +#define F_1 0x1 +#define F_2 0x2 +#define F_3 0x3 +#define F_4 0x4 +#define F_5 0x5 +#define F_6 0x6 +#define F_7 0x7 +#define F_8 0x18 + +#define MOUNT_DISK 0xFE +#define MAIN_MENU 0xFF + +#define LFA 0x095 //Left arrow +#define CLR 0x147 +#define PND 0x92 + +#define RST 0x13 // Restore +#define RET '\n' // Enter +#define BSP 0x08 // Backspace +#define CTR 0x21 // Ctrl +#define SPC 0x20// Space +#define ATT 0x22 // At@ +#define UPA 0x23 //uparrow symbol +#define RUN 0x00 // RunStop +#define SLK 0x25 // Shift Lock +#define CMD 0x26 // Commodore key +#define SHF 0x27 // Shift Key + +#define CUP 0x14 // Cursor up +#define CDL 0x15 // Cursor left + +static int m_Mode=KB_SHIFT; + +extern u8 col, row; // console cursor position + +extern uint16 *screen; +uint16 * map; +uint8 *bufmem; +#define BUFMEM_SIZE ((512*(DISPLAY_Y-1))+DISPLAY_X) + +uint8 *emu_screen; +uint8 *emu_buffers[2]; +int emu_buf=0; + +static int keystate[256]; + +extern u8 MainMenu(C64 *the_c64); + + +char str[300]; +int menufirsttime =0; +int choosingfile = 1; +int bg0b, bg1b; + +void ShowKeyboard(void) +{ + videoSetModeSub(MODE_0_2D | DISPLAY_BG0_ACTIVE | DISPLAY_BG1_ACTIVE); + + videoSetModeSub(MODE_0_2D | DISPLAY_BG0_ACTIVE | DISPLAY_BG1_ACTIVE); // BG0 = debug console; BG1 = keyboard + bg0b = bgInitSub(0, BgType_Text8bpp, BgSize_T_256x256, 31,0); + bg1b = bgInitSub(1, BgType_Text8bpp, BgSize_T_256x256, 29,0); + bgSetPriority(bg0b,1); bgSetPriority(bg1b,0); + + decompress(keyboardTiles, bgGetGfxPtr(bg0b), LZ77Vram); + decompress(keyboardMap, (void*) bgGetMapPtr(bg0b), LZ77Vram); + dmaCopy((void*) bgGetMapPtr(bg0b)+32*30*2,(void*) bgGetMapPtr(bg1b),32*24*2); + dmaCopy((void*) keyboardPal,(void*) BG_PALETTE_SUB,256*2); + unsigned short dmaVal = *(bgGetMapPtr(bg1b)+24*32); + dmaFillWords(dmaVal | (dmaVal<<16),(void*) bgGetMapPtr(bg1b),32*24*2); +} + +void WaitForVblank(); + +/* + C64 keyboard matrix: + + Bit 7 6 5 4 3 2 1 0 + 0 CUD F5 F3 F1 F7 CLR RET DEL + 1 SHL E S Z 4 A W 3 + 2 X T F C 6 D R 5 + 3 V U H B 8 G Y 7 + 4 N O K M 0 J I 9 + 5 , @ : . - L P + + 6 / ^ = SHR HOM ; * � + 7 R/S Q C= SPC 2 CTL <- 1 +*/ + +#define MATRIX(a,b) (((a) << 3) | (b)) + + +/* + * Display constructor: Draw Speedometer/LEDs in window + */ + +C64Display::C64Display(C64 *the_c64) : TheC64(the_c64) +{ + +} + + +/* + * Display destructor + */ + +C64Display::~C64Display() +{ +} + + +/* + * Prefs may have changed + */ + +void C64Display::NewPrefs(Prefs *prefs) +{ + floppy_sound_counter = 50; // One seconds of no floppy sound... +} + +uint8* frontBuffer; + +u8 JITTER[] = {0, 64, 128}; +s16 temp_offset = 0; +u16 slide_dampen=0; +void vblankIntr(void) +{ + int cxBG = (myConfig.offsetX << 8); + int cyBG = (myConfig.offsetY+temp_offset) << 8; + int xdxBG = ((320 / myConfig.scaleX) << 8) | (320 % myConfig.scaleX) ; + int ydyBG = ((200 / myConfig.scaleY) << 8) | (200 % myConfig.scaleY); + + REG_BG2X = cxBG; + REG_BG2Y = cyBG; + REG_BG3X = cxBG+JITTER[myConfig.jitter]; + REG_BG3Y = cyBG; + + REG_BG2PA = xdxBG; + REG_BG2PD = ydyBG; + REG_BG3PA = xdxBG; + REG_BG3PD = ydyBG; + + if (temp_offset) + { + if (slide_dampen == 0) + { + if (temp_offset > 0) temp_offset--; + else temp_offset++; + } + else + { + slide_dampen--; + } + } + + if (floppy_sound_counter) + { + if (floppy_sound_counter == 250) + { + if (myConfig.diskSFX) mmEffect(SFX_FLOPPY); + } + floppy_sound_counter--; + } +} + +extern void InterruptHandler(void); +int init_graphics(void) +{ + //set the mode for 2 text layers and two extended background layers + powerOn(POWER_ALL_2D); + + videoSetMode(MODE_5_2D | DISPLAY_BG2_ACTIVE | DISPLAY_BG3_ACTIVE); + + bgInit(3, BgType_Bmp8, BgSize_B8_512x512, 0,0); + bgInit(2, BgType_Bmp8, BgSize_B8_512x512, 0,0); + + REG_BLDCNT = BLEND_ALPHA | BLEND_SRC_BG2 | BLEND_DST_BG3; + REG_BLDALPHA = (8 << 8) | 8; // 50% / 50% + + + //set the first two banks as background memory and the third as sub background memory + //D is not used..if you need a bigger background then you will need to map + //more vram banks consecutivly (VRAM A-D are all 0x20000 bytes in size) + vramSetPrimaryBanks(VRAM_A_MAIN_BG_0x06000000, VRAM_B_MAIN_BG_0x06020000, VRAM_C_SUB_BG , VRAM_D_LCD); + + videoSetModeSub(MODE_0_2D | DISPLAY_BG0_ACTIVE | DISPLAY_BG1_ACTIVE); //sub bg 0 will be used to print text + REG_BG0CNT_SUB = BG_MAP_BASE(31); + BG_PALETTE_SUB[255] = RGB15(31,31,31); + //consoleInit(NULL, 0, BgType_Text4bpp, BgSize_T_256x256, 31, 0, false, true); + + frontBuffer = (uint8*)(0x06000000); + + bufmem = (uint8*)malloc(BUFMEM_SIZE); + + if (!fatInitDefault()) + { + iprintf("Unable to initialize media device!"); + return -1; + } + + chdir("/roms"); + chdir("c64"); + + ShowKeyboard(); + + REG_BG3CNT = BG_BMP8_512x512; +#if 0 + REG_BG3PA = DISPLAY_X-54; //((DISPLAY_X / 256) << 8) | (DISPLAY_X % 256) ;// + REG_BG3PB = 0; + REG_BG3PC = 0; + REG_BG3PD = DISPLAY_X-106;//((DISPLAY_Y / 192) << 8) | ((DISPLAY_Y % 192) + (DISPLAY_Y % 192) / 3) ;// + REG_BG3X = 28<<8;//1<<8;// + REG_BG3Y = 32<<8;//1<<8;// +#else + int cxBG = (myConfig.offsetX << 8); + int cyBG = (myConfig.offsetY) << 8; + int xdxBG = ((320 / myConfig.scaleX) << 8) | (320 % myConfig.scaleX) ; + int ydyBG = ((200 / myConfig.scaleY) << 8) | (200 % myConfig.scaleY); + + REG_BG2X = cxBG; + REG_BG2Y = cyBG; + REG_BG3X = cxBG; + REG_BG3Y = cyBG; + REG_BG3PA = xdxBG; + REG_BG3PD = ydyBG; + + SetYtrigger(190); //trigger 2 lines before vsync + irqSet(IRQ_VBLANK, vblankIntr); + irqEnable(IRQ_VBLANK); + +#endif + return TRUE; + +} +int counta,firsttime; +void WaitForVblank() +{ + swiWaitForVBlank(); +} + +/* + * Redraw bitmap + */ +void C64Display::Update(void) +{ + dmaCopyWordsAsynch(3, bufmem+(512*14), frontBuffer+(512*14), BUFMEM_SIZE-(18*1024)); +} + + +/* + * Draw speedometer + */ + +//***************************************************************************** +// Displays a message on the screen +//***************************************************************************** +void DSPrint(int iX,int iY,int iScr,char *szMessage) +{ + u16 *pusScreen,*pusMap; + u16 usCharac; + char *pTrTxt=szMessage; + + pusScreen=(u16*) bgGetMapPtr(bg1b) + iX + (iY<<5); + pusMap=(u16*) (iScr == 6 ? bgGetMapPtr(bg0b)+24*32 : (iScr == 0 ? bgGetMapPtr(bg0b)+24*32 : bgGetMapPtr(bg0b)+26*32 )); + + while((*pTrTxt)!='\0' ) + { + char ch = *pTrTxt++; + if (ch >= 'a' && ch <= 'z') ch -= 32; // Faster than strcpy/strtoupper + + if (((ch)<' ') || ((ch)>'_')) + usCharac=*(pusMap); // Will render as a vertical bar + else if((ch)<'@') + usCharac=*(pusMap+(ch)-' '); // Number from 0-9 or punctuation + else + usCharac=*(pusMap+32+(ch)-'@'); // Character from A-Z + *pusScreen++=usCharac; + } +} + +void show_joysticks(void) +{ + if (current_joystick) + { + DSPrint(1, 3, 2, (char*)"()"); + DSPrint(1, 4, 2, (char*)"HI"); + DSPrint(3, 3, 2, (char*)"*+"); + DSPrint(3, 4, 2, (char*)"JK"); + } + else + { + DSPrint(3, 3, 2, (char*)"()"); + DSPrint(3, 4, 2, (char*)"HI"); + DSPrint(1, 3, 2, (char*)"*+"); + DSPrint(1, 4, 2, (char*)"JK"); + } +} + +void show_shift_key(void) +{ + if (m_Mode == KB_SHIFT) + { + DSPrint(1, 17, 2, (char*)",-"); + DSPrint(1, 18, 2, (char*)"LM"); + } + else + { + DSPrint(1, 17, 2, (char*)"./"); + DSPrint(1, 18, 2, (char*)"NO"); + } +} + +int i = 0; +int debug[8]={0,0,0,0,0,0,0,0}; +void C64Display::Speedometer(int speed) +{ +#if 1 + char tmp[34]; + + sprintf(tmp, "%-8d", speed); + DSPrint(19, 1, 6, tmp); + + sprintf(tmp, "%-8d %-8d %-6d %-6d", debug[0],debug[1],debug[2],debug[3]); + DSPrint(0, 0, 6, tmp); +#endif + + show_joysticks(); + show_shift_key(); +} + + +/* + * Return pointer to bitmap data + */ + +uint8 *C64Display::BitmapBase(void) +{ + return (uint8 *)bufmem; +} + + + + + +/* + * Return number of bytes per row + */ + +int C64Display::BitmapXMod(void) +{ + return 512; +} + +void C64Display::KeyPress(int key, uint8 *key_matrix, uint8 *rev_matrix) { + int c64_byte, c64_bit, shifted; + if(!keystate[key]) { + keystate[key]=1; + c64_byte=key>>3; + c64_bit=key&7; + shifted=key&128; + c64_byte&=7; + if(shifted) { + key_matrix[6] &= 0xef; + rev_matrix[4] &= 0xbf; + } + key_matrix[c64_byte]&=~(1<>3; + c64_bit=key&7; + shifted=key&128; + c64_byte&=7; + if(shifted) { + key_matrix[6] |= 0x10; + rev_matrix[4] |= 0x40; + } + key_matrix[c64_byte]|=(1<-1) && ((keysCurrent() & KEY_TOUCH) == 0)) + { + KeyRelease(lastc64key, key_matrix, rev_matrix); + } + + if ((keysCurrent() & KEY_TOUCH) == 0) // No touch screen... reset the flag + { + m_tpActive = false; + } + else + if ((m_tpActive == false) && (keysCurrent() & KEY_TOUCH)) + { + touchRead(&m_tp); + m_tpActive = true; + + unsigned short c = 0; + int tilex, tiley; + + tilex = m_tp.px; + tiley = m_tp.py; + + if (tiley > 20) // We're in the keyboard area... + { + if (tiley < 44) // Big Key Row + { + if (tilex < 42) + { + current_joystick ^= 1; + extern void show_joysticks(); + show_joysticks(); + } + else if (tilex < 80) c = CTR; + else if (tilex < 118) c = BSP; + else if (tilex < 156) c = RST; + else if (tilex < 194) c = CMD; + else if (tilex < 255) c = RUN; + } + else if (tiley < 74) // Number Row + { + if (tilex < 23) c = '1'; + else if (tilex < 42) c = '2'; + else if (tilex < 61) c = '3'; + else if (tilex < 80) c = '4'; + else if (tilex < 99) c = '5'; + else if (tilex < 118) c = '6'; + else if (tilex < 137) c = '7'; + else if (tilex < 156) c = '8'; + else if (tilex < 175) c = '9'; + else if (tilex < 194) c = '0'; + else if (tilex < 213) c = '+'; + else if (tilex < 233) c = '-'; + else if (tilex < 256) c = UPA; + } + else if (tiley < 104) // QWERTY Row + { + if (tilex < 23) c = CUP; + else if (tilex < 42) c = 'Q'; + else if (tilex < 61) c = 'W'; + else if (tilex < 80) c = 'E'; + else if (tilex < 99) c = 'R'; + else if (tilex < 118) c = 'T'; + else if (tilex < 137) c = 'Y'; + else if (tilex < 156) c = 'U'; + else if (tilex < 175) c = 'I'; + else if (tilex < 194) c = 'O'; + else if (tilex < 213) c = 'P'; + else if (tilex < 233) c = '@'; + else if (tilex < 256) c = '*'; + } + else if (tiley < 134) // ASDF Row + { + if (tilex < 23) c = CDL; + else if (tilex < 42) c = 'A'; + else if (tilex < 61) c = 'S'; + else if (tilex < 80) c = 'D'; + else if (tilex < 99) c = 'F'; + else if (tilex < 118) c = 'G'; + else if (tilex < 137) c = 'H'; + else if (tilex < 156) c = 'J'; + else if (tilex < 175) c = 'K'; + else if (tilex < 194) c = 'L'; + else if (tilex < 213) c = ':'; + else if (tilex < 233) c = ';'; + else if (tilex < 256) c = '='; + } + else if (tiley < 164) // ZXCV Row + { + if (tilex < 23) c = SHF; + else if (tilex < 42) c = 'Z'; + else if (tilex < 61) c = 'X'; + else if (tilex < 80) c = 'C'; + else if (tilex < 99) c = 'V'; + else if (tilex < 118) c = 'B'; + else if (tilex < 137) c = 'N'; + else if (tilex < 156) c = 'M'; + else if (tilex < 175) c = ','; + else if (tilex < 194) c = '.'; + else if (tilex < 213) c = '/'; + else if (tilex < 256) c = RET; + } + else if (tiley < 192) // Bottom Row + { + if (tilex < 23) c = F_1; + else if (tilex < 42) c = F_3; + else if (tilex < 61) c = F_5; + else if (tilex < 80) c = F_7; + else if (tilex < 190) c = ' '; + else if (tilex < 222) c = MOUNT_DISK; + else if (tilex < 256) c = MAIN_MENU; + } + + if (c==MAIN_MENU) + { + TheC64->Pause(); + MainMenu(TheC64); + ShowKeyboard(); + TheC64->Resume(); + } + else if (c==MOUNT_DISK) + { + TheC64->Pause(); + u8 reload = mount_disk(TheC64); + ShowKeyboard(); + + if (reload & 0x7F) + { + kbd_buf_reset(); + + // Insert the new disk into the drive... + Prefs *prefs = new Prefs(ThePrefs); + strcpy(prefs->DrivePath[0], Drive8File); + strcpy(prefs->DrivePath[1], Drive9File); + prefs->TrueDrive = myConfig.trueDrive; + TheC64->NewPrefs(prefs); + ThePrefs = *prefs; + delete prefs; + + // See if we should issue a system-wide RESET + if (reload == 2) + { + TheC64->PatchKernal(ThePrefs.FastReset, ThePrefs.TrueDrive); + TheC64->Reset(); + } + } + TheC64->Resume(); + + if (reload & 0x80) + { + extern void kbd_buf_feed(const char *s); + kbd_buf_feed("\rLOAD\"*\",8,1\rRUN\r"); + } + } + else if (c != 0) + { + mmEffect(SFX_KEYCLICK); // Play short key click for feedback... + } + + if(c==RET) // Return + { + //consolePrintChar('\n'); + //strcpy(text, ""); + c64_key = MATRIX(0,1); + KeyPress(c64_key, key_matrix, rev_matrix); + lastc64key=c64_key; + } else + if(c==BSP) // Backspace + { + c64_key = MATRIX(0,0); + KeyPress(c64_key, key_matrix, rev_matrix); + lastc64key=c64_key; + + } else + if(c==RUN) + { + mmEffect(SFX_KEYCLICK); // Play short key click for feedback... + c64_key = MATRIX(7,7); + KeyPress(c64_key, key_matrix, rev_matrix); + lastc64key=c64_key; + + } else + if(c==SLK || c==SHF) + { + if(m_Mode==KB_NORMAL) { + m_Mode = KB_SHIFT; + } else { + m_Mode = KB_NORMAL; + } + show_shift_key(); + } + else + { + if(c!=0x0) + { + switch (c) + { + case 'A': c64_key = MATRIX(1,2); break; + case 'B': c64_key = MATRIX(3,4); break; + case 'C': c64_key = MATRIX(2,4); break; + case 'D': c64_key = MATRIX(2,2); break; + case 'E': c64_key = MATRIX(1,6); break; + case 'F': c64_key = MATRIX(2,5); break; + case 'G': c64_key = MATRIX(3,2); break; + case 'H': c64_key = MATRIX(3,5); break; + case 'I': c64_key = MATRIX(4,1); break; + case 'J': c64_key = MATRIX(4,2); break; + case 'K': c64_key = MATRIX(4,5); break; + case 'L': c64_key = MATRIX(5,2); break; + case 'M': c64_key = MATRIX(4,4); break; + case 'N': c64_key = MATRIX(4,7); break; + case 'O': c64_key = MATRIX(4,6); break; + case 'P': c64_key = MATRIX(5,1); break; + case 'Q': c64_key = MATRIX(7,6); break; + case 'R': c64_key = MATRIX(2,1); break; + case 'S': c64_key = MATRIX(1,5); break; + case 'T': c64_key = MATRIX(2,6); break; + case 'U': c64_key = MATRIX(3,6); break; + case 'V': c64_key = MATRIX(3,7); break; + case 'W': c64_key = MATRIX(1,1); break; + case 'X': c64_key = MATRIX(2,7); break; + case 'Y': c64_key = MATRIX(3,1); break; + case 'Z': c64_key = MATRIX(1,4); break; + + case ' ': c64_key = MATRIX(7,4); break; + + case '0': c64_key = MATRIX(4,3); break; + case '1': c64_key = MATRIX(7,0); break; + case '2': c64_key = MATRIX(7,3); break; + case '3': c64_key = MATRIX(1,0); break; + case '4': c64_key = MATRIX(1,3); break; + case '5': c64_key = MATRIX(2,0); break; + case '6': c64_key = MATRIX(2,3); break; + case '7': c64_key = MATRIX(3,0); break; + case '8': c64_key = MATRIX(3,3); break; + case '9': c64_key = MATRIX(4,0); break; + case '*': c64_key = MATRIX(6,1); break; + case ':': c64_key = MATRIX(5,5); break; + case ';': c64_key = MATRIX(6,2); break; + case '=': c64_key = MATRIX(6,5); break; + case '/': c64_key = MATRIX(6,7); break; + + case ATT: c64_key = MATRIX(5,6); break; + + case ',': c64_key = MATRIX(5,7); break; + case '.': c64_key = MATRIX(5,4); break; + case '+': c64_key = MATRIX(5,0); break; + case '-': c64_key = MATRIX(5,3); break; + + case RST: c64_key = MATRIX(7,7); break; + case CLR: c64_key = MATRIX(6,3); break; + case LFA: c64_key = MATRIX(7,1); break; + case UPA: c64_key = MATRIX(6,6); break; + case PND: c64_key = MATRIX(6,0); break; + + case CUP: c64_key = MATRIX(0,7); break; + case CDL: c64_key = MATRIX(0,2); break; + + case F_1: c64_key = MATRIX(0,4); break; + case F_3: c64_key = MATRIX(0,5); break; + case F_5: c64_key = MATRIX(0,6); break; + case F_7: c64_key = MATRIX(0,3); break; + + + default : c64_key = -1; break; + + } + if (c64_key < 0) + return; + if(m_Mode==KB_NORMAL) + { + c64_key= c64_key| 0x80; + } + KeyPress(c64_key, key_matrix, rev_matrix); + lastc64key=c64_key; + } + } + } + } + +} + + +/* + * Check if NumLock is down (for switching the joystick keyboard emulation) + */ + +bool C64Display::NumLock(void) +{ + return false; +} + + +/* + * Allocate C64 colors + */ + + +typedef struct { + int r; + int g; + int b; +} plt; + +static plt palette[256]; + +void C64Display::InitColors(uint8 *colors) +{ + int i; + + for (i = 0; i < 16; i++) + { + palette[i].r = palette_red[i]>>3; + palette[i].g = palette_green[i]>>3; + palette[i].b = palette_blue[i]>>3; + BG_PALETTE[i]=RGB15(palette_red[i]>>3,palette_green[i]>>3,palette_blue[i]>>3); + } + + // frodo internal 8 bit palette + for(i=0; i<256; i++) { + colors[i] = i & 0x0f; + } +} + + +/* + * Show a requester (error message) + */ + +char tmp[256]; +long int ShowRequester(const char *a, const char *b, const char *) +{ + sprintf(tmp, "%s: %s\n", a, b); + DSPrint(0, 0, 6, tmp); + return 1; +} + + + diff --git a/arm9/source/Display.h b/arm9/source/Display.h new file mode 100644 index 0000000..56bb7b8 --- /dev/null +++ b/arm9/source/Display.h @@ -0,0 +1,76 @@ +// ===================================================================================== +// GimliDS Copyright (c) 2025 Dave Bernazzani (wavemotion-dave) +// +// As GimliDS is a port of the Frodo emulator for the DS/DSi/XL/LL handhelds, +// any copying or distribution of this emulator, its source code and associated +// readme files, with or without modification, are permitted per the original +// Frodo emulator license shown below. Hugest thanks to Christian Bauer for his +// efforts to provide a clean open-source emulation base for the C64. +// +// Numerous hacks and 'unsafe' optimizations have been performed on the original +// Frodo emulator codebase to get it running on the small handheld system. You +// are strongly encouraged to seek out the official Frodo sources if you're at +// all interested in this emulator code. +// +// The GimliDS emulator is offered as-is, without any warranty. Please see readme.md +// ===================================================================================== + +/* + * Display.h - C64 graphics display, emulator window handling + * + * Frodo Copyright (C) Christian Bauer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _DISPLAY_H +#define _DISPLAY_H + +const int DISPLAY_X = 0x170; +const int DISPLAY_Y = 0x11f; + +class C64Window; +class C64Screen; +class C64; +class Prefs; + +// Class for C64 graphics display +class C64Display { +public: + C64Display(C64 *the_c64); + ~C64Display(); + void Update(void); + void UpdateLEDs(int l0, int l1); + void Speedometer(int speed); + uint8 *BitmapBase(void); + int BitmapXMod(void); + void KeyPress(int key, uint8 *key_matrix, uint8 *rev_matrix); + void KeyRelease(int key, uint8 *key_matrix, uint8 *rev_matrix); + void PollKeyboard(uint8 *key_matrix, uint8 *rev_matrix, uint8 *joystick); + bool NumLock(void); + void InitColors(uint8 *colors); + void NewPrefs(Prefs *prefs); + C64 *TheC64; + +public: + int led_state[2]; +}; + + +// Exported functions +extern long ShowRequester(const char *str, const char *button1, const char *button2 = NULL); + + +#endif diff --git a/arm9/source/FixPoint.h b/arm9/source/FixPoint.h new file mode 100644 index 0000000..eea8595 --- /dev/null +++ b/arm9/source/FixPoint.h @@ -0,0 +1,433 @@ +/* + * FixPoint.h - Provides fixed point arithmetic (for use in SID.cpp) + * + * (C) 1997 Andreas Dehmel + * + * Frodo Copyright (C) Christian Bauer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * You need to define FIXPOINT_PREC (number of fractional bits) and + * ldSINTAB (ld of the size of the sinus table) as well M_PI + * _before_ including this file. + * Requires at least 32bit ints! + */ + + +#define FIXPOINT_BITS 32 +// Sign-bit +#define FIXPOINT_SIGN (1<<(FIXPOINT_BITS-1)) + + +/* + * Elementary functions for the FixPoint class + */ + +// Multiplies two fixpoint numbers, result is a fixpoint number. +static inline int fixmult(int x, int y) +{ + register unsigned int a,b; + register bool sign; + + sign = (x ^ y) < 0; + if (x < 0) {x = -x;} + if (y < 0) {y = -y;} + // a, b : integer part; x, y : fractional part. All unsigned now (for shift right)!!! + a = (((unsigned int)x) >> FIXPOINT_PREC); x &= ~(a << FIXPOINT_PREC); + b = (((unsigned int)y) >> FIXPOINT_PREC); y &= ~(b << FIXPOINT_PREC); + x = ((a*b) << FIXPOINT_PREC) + (a*y + b*x) + + ((unsigned int)((x*y) + (1 << (FIXPOINT_PREC-1))) >> FIXPOINT_PREC); +#ifdef FIXPOINT_SIGN + if (x < 0) {x ^= FIXPOINT_SIGN;} +#endif + if (sign) {x = -x;} + return(x); +} + + +// Multiplies a fixpoint number with an integer, result is a 32 bit (!) integer in +// contrast to using the standard member-functions which can provide only (32-FIXPOINT_PREC) +// valid bits. +static inline int intmult(int x, int y) // x is fixpoint, y integer +{ + register unsigned int i,j; + register bool sign; + + sign = (x ^ y) < 0; + if (x < 0) {x = -x;} + if (y < 0) {y = -y;} + i = (((unsigned int)x) >> 16); x &= ~(i << 16); // split both into 16.16 parts + j = (((unsigned int)y) >> 16); y &= ~(j << 16); +#if FIXPOINT_PREC <= 16 + // This '32' is independent of the number of bits used, it's due to the 16 bit shift + i = ((i*j) << (32 - FIXPOINT_PREC)) + ((i*y + j*x) << (16 - FIXPOINT_PREC)) + + ((unsigned int)(x*y + (1 << (FIXPOINT_PREC - 1))) >> FIXPOINT_PREC); +#else + { + register unsigned int h; + + h = (i*y + j*x); + i = ((i*j) << (32 - FIXPOINT_PREC)) + (h >> (FIXPOINT_PREC - 16)); + h &= ((1 << (FIXPOINT_PREC - 16)) - 1); x *= y; + i += (x >> FIXPOINT_PREC); x &= ((1 << FIXPOINT_PREC) - 1); + i += (((h + (x >> 16)) + (1 << (FIXPOINT_PREC - 17))) >> (FIXPOINT_PREC - 16)); + } +#endif +#ifdef FIXPOINT_SIGN + if (i < 0) {i ^= FIXPOINT_SIGN;} +#endif + if (sign) {i = -i;} + return(i); +} + + +// Computes the product of a fixpoint number with itself. +static inline int fixsquare(int x) +{ + register unsigned int a; + + if (x < 0) {x = -x;} + a = (((unsigned int)x) >> FIXPOINT_PREC); x &= ~(a << FIXPOINT_PREC); + x = ((a*a) << FIXPOINT_PREC) + ((a*x) << 1) + + ((unsigned int)((x*x) + (1 << (FIXPOINT_PREC-1))) >> FIXPOINT_PREC); +#ifdef FIXPOINT_SIGN + if (x < 0) {x ^= FIXPOINT_SIGN;} +#endif + return(x); +} + + +// Computes the square root of a fixpoint number. +static inline int fixsqrt(int x) +{ + register int test, step; + + if (x < 0) return(-1); + if (x == 0) return(0); + step = (x <= (1<>1)); + test = 0; + while (step != 0) + { + register int h; + + h = fixsquare(test + step); + if (h <= x) {test += step;} + if (h == x) break; + step >>= 1; + } + return(test); +} + + +// Divides a fixpoint number by another fixpoint number, yielding a fixpoint result. +static inline int fixdiv(int x, int y) +{ + register int res, mask; + register bool sign; + + sign = (x ^ y) < 0; + if (x < 0) {x = -x;} + if (y < 0) {y = -y;} + mask = (1< y) {y <<= 1; mask <<= 1;} + while (mask != 0) + { + if (x >= y) {res |= mask; x -= y;} + mask >>= 1; y >>= 1; + } +#ifdef FIXPOINT_SIGN + if (res < 0) {res ^= FIXPOINT_SIGN;} +#endif + if (sign) {res = -res;} + return(res); +} + + + + + +/* + * The C++ Fixpoint class. By no means exhaustive... + * Since it contains only one int data, variables of type FixPoint can be + * passed directly rather than as a reference. + */ + +class FixPoint +{ +private: + int x; + +public: + FixPoint(void); + FixPoint(int y); + ~FixPoint(void); + + // conversions + int Value(void); + int round(void); + operator int(void); + + // unary operators + FixPoint sqrt(void); + FixPoint sqr(void); + FixPoint abs(void); + FixPoint operator+(void); + FixPoint operator-(void); + FixPoint operator++(void); + FixPoint operator--(void); + + // binary operators + int imul(int y); + FixPoint operator=(FixPoint y); + FixPoint operator=(int y); + FixPoint operator+(FixPoint y); + FixPoint operator+(int y); + FixPoint operator-(FixPoint y); + FixPoint operator-(int y); + FixPoint operator/(FixPoint y); + FixPoint operator/(int y); + FixPoint operator*(FixPoint y); + FixPoint operator*(int y); + FixPoint operator+=(FixPoint y); + FixPoint operator+=(int y); + FixPoint operator-=(FixPoint y); + FixPoint operator-=(int y); + FixPoint operator*=(FixPoint y); + FixPoint operator*=(int y); + FixPoint operator/=(FixPoint y); + FixPoint operator/=(int y); + FixPoint operator<<(int y); + FixPoint operator>>(int y); + FixPoint operator<<=(int y); + FixPoint operator>>=(int y); + + // conditional operators + bool operator<(FixPoint y); + bool operator<(int y); + bool operator<=(FixPoint y); + bool operator<=(int y); + bool operator>(FixPoint y); + bool operator>(int y); + bool operator>=(FixPoint y); + bool operator>=(int y); + bool operator==(FixPoint y); + bool operator==(int y); + bool operator!=(FixPoint y); + bool operator!=(int y); +}; + + +/* + * int gets treated differently according to the case: + * + * a) Equations (=) or condition checks (==, <, <= ...): raw int (i.e. no conversion) + * b) As an argument for an arithmetic operation: conversion to fixpoint by shifting + * + * Otherwise loading meaningful values into FixPoint variables would be very awkward. + */ + +FixPoint::FixPoint(void) {x = 0;} + +FixPoint::FixPoint(int y) {x = y;} + +FixPoint::~FixPoint(void) {;} + +inline int FixPoint::Value(void) {return(x);} + +inline int FixPoint::round(void) {return((x + (1 << (FIXPOINT_PREC-1))) >> FIXPOINT_PREC);} + +inline FixPoint::operator int(void) {return(x);} + + +// unary operators +inline FixPoint FixPoint::sqrt(void) {return(fixsqrt(x));} + +inline FixPoint FixPoint::sqr(void) {return(fixsquare(x));} + +inline FixPoint FixPoint::abs(void) {return((x < 0) ? -x : x);} + +inline FixPoint FixPoint::operator+(void) {return(x);} + +inline FixPoint FixPoint::operator-(void) {return(-x);} + +inline FixPoint FixPoint::operator++(void) {x += (1 << FIXPOINT_PREC); return x;} + +inline FixPoint FixPoint::operator--(void) {x -= (1 << FIXPOINT_PREC); return x;} + + +// binary operators +inline int FixPoint::imul(int y) {return(intmult(x,y));} + +inline FixPoint FixPoint::operator=(FixPoint y) {x = y.Value(); return x;} + +inline FixPoint FixPoint::operator=(int y) {x = y; return x;} + +inline FixPoint FixPoint::operator+(FixPoint y) {return(x + y.Value());} + +inline FixPoint FixPoint::operator+(int y) {return(x + (y << FIXPOINT_PREC));} + +inline FixPoint FixPoint::operator-(FixPoint y) {return(x - y.Value());} + +inline FixPoint FixPoint::operator-(int y) {return(x - (y << FIXPOINT_PREC));} + +inline FixPoint FixPoint::operator/(FixPoint y) {return(fixdiv(x,y.Value()));} + +inline FixPoint FixPoint::operator/(int y) {return(x/y);} + +inline FixPoint FixPoint::operator*(FixPoint y) {return(fixmult(x,y.Value()));} + +inline FixPoint FixPoint::operator*(int y) {return(x*y);} + +inline FixPoint FixPoint::operator+=(FixPoint y) {x += y.Value(); return x;} + +inline FixPoint FixPoint::operator+=(int y) {x += (y << FIXPOINT_PREC); return x;} + +inline FixPoint FixPoint::operator-=(FixPoint y) {x -= y.Value(); return x;} + +inline FixPoint FixPoint::operator-=(int y) {x -= (y << FIXPOINT_PREC); return x;} + +inline FixPoint FixPoint::operator*=(FixPoint y) {x = fixmult(x,y.Value()); return x;} + +inline FixPoint FixPoint::operator*=(int y) {x *= y; return x;} + +inline FixPoint FixPoint::operator/=(FixPoint y) {x = fixdiv(x,y.Value()); return x;} + +inline FixPoint FixPoint::operator/=(int y) {x /= y; return x;} + +inline FixPoint FixPoint::operator<<(int y) {return(x << y);} + +inline FixPoint FixPoint::operator>>(int y) {return(x >> y);} + +inline FixPoint FixPoint::operator<<=(int y) {x <<= y; return x;} + +inline FixPoint FixPoint::operator>>=(int y) {x >>= y; return x;} + + +// conditional operators +inline bool FixPoint::operator<(FixPoint y) {return(x < y.Value());} + +inline bool FixPoint::operator<(int y) {return(x < y);} + +inline bool FixPoint::operator<=(FixPoint y) {return(x <= y.Value());} + +inline bool FixPoint::operator<=(int y) {return(x <= y);} + +inline bool FixPoint::operator>(FixPoint y) {return(x > y.Value());} + +inline bool FixPoint::operator>(int y) {return(x > y);} + +inline bool FixPoint::operator>=(FixPoint y) {return(x >= y.Value());} + +inline bool FixPoint::operator>=(int y) {return(x >= y);} + +inline bool FixPoint::operator==(FixPoint y) {return(x == y.Value());} + +inline bool FixPoint::operator==(int y) {return(x == y);} + +inline bool FixPoint::operator!=(FixPoint y) {return(x != y.Value());} + +inline bool FixPoint::operator!=(int y) {return(x != y);} + + + +/* + * In case the first argument is an int (i.e. member-operators not applicable): + * Not supported: things like int/FixPoint. The same difference in conversions + * applies as mentioned above. + */ + + +// binary operators +inline FixPoint operator+(int x, FixPoint y) {return((x << FIXPOINT_PREC) + y.Value());} + +inline FixPoint operator-(int x, FixPoint y) {return((x << FIXPOINT_PREC) - y.Value());} + +inline FixPoint operator*(int x, FixPoint y) {return(x*y.Value());} + + +// conditional operators +inline bool operator==(int x, FixPoint y) {return(x == y.Value());} + +inline bool operator!=(int x, FixPoint y) {return(x != y.Value());} + +inline bool operator<(int x, FixPoint y) {return(x < y.Value());} + +inline bool operator<=(int x, FixPoint y) {return(x <= y.Value());} + +inline bool operator>(int x, FixPoint y) {return(x > y.Value());} + +inline bool operator>=(int x, FixPoint y) {return(x >= y.Value());} + + + +/* + * For more convenient creation of constant fixpoint numbers from constant floats. + */ + +#define FixNo(n) (FixPoint)((int)(n*(1<= 3*(1<= 2*(1<= (1<> (FIXPOINT_PREC - ldSINTAB - 1)) & ((1<<(ldSINTAB+2))-1); + FIXPOINT_SIN_COS_GENERIC +} + + +static inline FixPoint fixcos(FixPoint x) +{ + int angle = x; + + angle = ((angle + (1<<(FIXPOINT_PREC-1))) >> (FIXPOINT_PREC - ldSINTAB - 1)) & ((1<<(ldSINTAB+2))-1); + FIXPOINT_SIN_COS_GENERIC +} + + + +static inline void InitFixSinTab(void) +{ + int i; + float step; + + for (i=0, step=0; i<(1<Ready) + drive[i]->Reset(); + + UpdateLEDs(); +} + + +/* + * Preferences have changed, prefs points to new preferences, + * ThePrefs still holds the previous ones. Check if drive settings + * have changed. + */ + +void IEC::NewPrefs(Prefs *prefs) +{ + // Delete and recreate all changed drives + for (int i=0; i<2; i++) + { + if (strcmp(ThePrefs.DrivePath[i], prefs->DrivePath[i]) || ThePrefs.TrueDrive != prefs->TrueDrive) + { + delete drive[i]; + drive[i] = NULL; // Important because UpdateLEDs is called from drive constructors (via set_error()) + if (!prefs->TrueDrive) + { + drive[i] = create_drive(prefs->DrivePath[i]); + } + } + } + + UpdateLEDs(); +} + + +/* + * Update drive LED display + */ + +void IEC::UpdateLEDs(void) +{ + u8 l0=0; u8 l1=0; + + if (drive[0] != NULL) l0 = drive[0]->LED; + if (drive[1] != NULL) l1 = drive[1]->LED; + + the_display->UpdateLEDs(l0, l1); +} + + +/* + * Output one byte + */ + +uint8 IEC::Out(uint8 byte, bool eoi) +{ + if (listener_active) { + if (received_cmd == CMD_OPEN) + return open_out(byte, eoi); + if (received_cmd == CMD_DATA) + return data_out(byte, eoi); + return ST_TIMEOUT; + } else + return ST_TIMEOUT; +} + + +/* + * Output one byte with ATN (Talk/Listen/Untalk/Unlisten) + */ + +uint8 IEC::OutATN(uint8 byte) +{ + received_cmd = sec_addr = 0; // Command is sent with secondary address + switch (byte & 0xf0) { + case ATN_LISTEN: + listening = true; + return listen(byte & 0x0f); + case ATN_UNLISTEN: + listening = false; + return unlisten(); + case ATN_TALK: + listening = false; + return talk(byte & 0x0f); + case ATN_UNTALK: + listening = false; + return untalk(); + } + return ST_TIMEOUT; +} + + +/* + * Output secondary address + */ + +uint8 IEC::OutSec(uint8 byte) +{ + if (listening) { + if (listener_active) { + sec_addr = byte & 0x0f; + received_cmd = byte & 0xf0; + return sec_listen(); + } + } else { + if (talker_active) { + sec_addr = byte & 0x0f; + received_cmd = byte & 0xf0; + return sec_talk(); + } + } + return ST_TIMEOUT; +} + + +/* + * Read one byte + */ + +uint8 IEC::In(uint8 &byte) +{ + if (talker_active && (received_cmd == CMD_DATA)) + return data_in(byte); + + byte = 0; + return ST_TIMEOUT; +} + + +/* + * Assert ATN (for Untalk) + */ + +void IEC::SetATN(void) +{ + // Only needed for real IEC +} + + +/* + * Release ATN + */ + +void IEC::RelATN(void) +{ + // Only needed for real IEC +} + + +/* + * Talk-attention turn-around + */ + +void IEC::Turnaround(void) +{ + // Only needed for real IEC +} + + +/* + * System line release + */ + +void IEC::Release(void) +{ + // Only needed for real IEC +} + + +/* + * Listen + */ + +uint8 IEC::listen(int device) +{ + //printdbg("IEC::listen"); + if ((device >= 8) && (device <= 11)) { + //printdbg("IEC::listen2"); + if ((listener = drive[device-8]) != NULL && listener->Ready) { + //printdbg("IEC::listen3"); + listener_active = true; + return ST_OK; + } + } + + listener_active = false; + return ST_NOTPRESENT; +} + + +/* + * Talk + */ + +uint8 IEC::talk(int device) +{ + if ((device >= 8) && (device <= 11)) { + if ((talker = drive[device-8]) != NULL && talker->Ready) { + talker_active = true; + return ST_OK; + } + } + + talker_active = false; + return ST_NOTPRESENT; +} + + +/* + * Unlisten + */ + +uint8 IEC::unlisten(void) +{ + listener_active = false; + return ST_OK; +} + + +/* + * Untalk + */ + +uint8 IEC::untalk(void) +{ + talker_active = false; + return ST_OK; +} + + +/* + * Secondary address after Listen + */ + +uint8 IEC::sec_listen(void) +{ + switch (received_cmd) { + + case CMD_OPEN: // Prepare for receiving the file name + name_ptr = name_buf; + name_len = 0; + return ST_OK; + + case CMD_CLOSE: // Close channel + if (listener->LED != DRVLED_ERROR) { + listener->LED = DRVLED_OFF; // Turn off drive LED + UpdateLEDs(); + } + return listener->Close(sec_addr); + } + return ST_OK; +} + + +/* + * Secondary address after Talk + */ + +uint8 IEC::sec_talk(void) +{ + return ST_OK; +} + + +/* + * Byte after Open command: Store character in file name, open file on EOI + */ + +uint8 IEC::open_out(uint8 byte, bool eoi) +{ + if (name_len < NAMEBUF_LENGTH) { + *name_ptr++ = byte; + name_len++; + } + + if (eoi) { + *name_ptr = 0; // End string + listener->LED = DRVLED_ON; // Turn on drive LED + UpdateLEDs(); + return listener->Open(sec_addr, name_buf, name_len); + } + + return ST_OK; +} + + +/* + * Write byte to channel + */ + +uint8 IEC::data_out(uint8 byte, bool eoi) +{ + return listener->Write(sec_addr, byte, eoi); +} + + +/* + * Read byte from channel + */ + +uint8 IEC::data_in(uint8 &byte) +{ + return talker->Read(sec_addr, byte); +} + + +/* + * Drive constructor + */ + +Drive::Drive(IEC *iec) +{ + the_iec = iec; + LED = DRVLED_OFF; + Ready = false; + set_error(ERR_STARTUP); +} + + +/* + * Set error message on drive + */ + +// 1541 error messages +static const char *Errors_1541[] = { + "00, OK,%02d,%02d\x0d", + "01, FILES SCRATCHED,%02d,%02d\x0d", + "03, UNIMPLEMENTED,%02d,%02d\x0d", + "20, READ ERROR,%02d,%02d\x0d", + "21, READ ERROR,%02d,%02d\x0d", + "22, READ ERROR,%02d,%02d\x0d", + "23, READ ERROR,%02d,%02d\x0d", + "24, READ ERROR,%02d,%02d\x0d", + "25, WRITE ERROR,%02d,%02d\x0d", + "26, WRITE PROTECT ON,%02d,%02d\x0d", + "27, READ ERROR,%02d,%02d\x0d", + "28, WRITE ERROR,%02d,%02d\x0d", + "29, DISK ID MISMATCH,%02d,%02d\x0d", + "30, SYNTAX ERROR,%02d,%02d\x0d", + "31, SYNTAX ERROR,%02d,%02d\x0d", + "32, SYNTAX ERROR,%02d,%02d\x0d", + "33, SYNTAX ERROR,%02d,%02d\x0d", + "34, SYNTAX ERROR,%02d,%02d\x0d", + "60, WRITE FILE OPEN,%02d,%02d\x0d", + "61, FILE NOT OPEN,%02d,%02d\x0d", + "62, FILE NOT FOUND,%02d,%02d\x0d", + "63, FILE EXISTS,%02d,%02d\x0d", + "64, FILE TYPE MISMATCH,%02d,%02d\x0d", + "65, NO BLOCK,%02d,%02d\x0d", + "66, ILLEGAL TRACK OR SECTOR,%02d,%02d\x0d", + "70, NO CHANNEL,%02d,%02d\x0d", + "71, DIR ERROR,%02d,%02d\x0d", + "72, DISK FULL,%02d,%02d\x0d", + "73, CBM DOS V2.6 1541,%02d,%02d\x0d", + "74, DRIVE NOT READY,%02d,%02d\x0d" +}; + +void Drive::set_error(int error, int track, int sector) +{ + // Write error message to buffer + sprintf(error_buf, Errors_1541[error], track, sector); + error_ptr = error_buf; + error_len = strlen(error_buf); + current_error = error; + //DSPrint(0,1,6,error_buf); + + // Set drive condition + if (error != ERR_OK && error != ERR_SCRATCHED) + if (error == ERR_STARTUP) + LED = DRVLED_OFF; + else + LED = DRVLED_ERROR; + else if (LED == DRVLED_ERROR) + LED = DRVLED_OFF; + the_iec->UpdateLEDs(); +} + + +/* + * Parse file name, determine access mode and file type + */ + +void Drive::parse_file_name(const uint8 *src, int src_len, uint8 *dest, int &dest_len, int &mode, int &type, int &rec_len, bool convert_charset) +{ + + // If the string contains a ':', the file name starts after that + const uint8 *p = (const uint8 *)memchr(src, ':', src_len); + if (p) { + p++; + src_len -= p - src; + } else + p = src; + + // Transfer file name upto ',' + dest_len = 0; + uint8 *q = dest; + while (*p != ',' && src_len-- > 0) { + if (convert_charset) + *q++ = petscii2ascii(*p++); + else + *q++ = *p++; + dest_len++; + } + *q++ = 0; + + // Strip trailing CRs + while (dest_len > 0 && dest[dest_len - 1] == 0x0d) + dest[--dest_len] = 0; + + // Look for mode and type parameters separated by ',' + p++; src_len--; + while (src_len > 0) { + switch (*p) { + case 'D': + type = FTYPE_DEL; + break; + case 'S': + type = FTYPE_SEQ; + break; + case 'P': + type = FTYPE_PRG; + break; + case 'U': + type = FTYPE_USR; + break; + case 'L': + type = FTYPE_REL; + while (*p != ',' && src_len-- > 0) p++; + p++; src_len--; + rec_len = *p++; src_len--; + if (src_len < 0) + rec_len = 0; + break; + case 'R': + mode = FMODE_READ; + break; + case 'W': + mode = FMODE_WRITE; + break; + case 'A': + mode = FMODE_APPEND; + break; + case 'M': + mode = FMODE_M; + break; + } + + // Skip to ',' + while (*p != ',' && src_len-- > 0) p++; + p++; src_len--; + } +} + + +/* + * Execute DOS command (parse command and call appropriate routine) + */ + +static void parse_block_cmd_args(const uint8 *p, int &arg1, int &arg2, int &arg3, int &arg4) +{ + arg1 = arg2 = arg3 = arg4 = 0; + + while (*p == ' ' || *p == 0x1d || *p == ',') p++; + while (*p >= '0' && *p < '@') + arg1 = arg1 * 10 + (*p++ & 0x0f); + + while (*p == ' ' || *p == 0x1d || *p == ',') p++; + while (*p >= '0' && *p < '@') + arg2 = arg2 * 10 + (*p++ & 0x0f); + + while (*p == ' ' || *p == 0x1d || *p == ',') p++; + while (*p >= '0' && *p < '@') + arg3 = arg3 * 10 + (*p++ & 0x0f); + + while (*p == ' ' || *p == 0x1d || *p == ',') p++; + while (*p >= '0' && *p < '@') + arg4 = arg4 * 10 + (*p++ & 0x0f); +} + +void Drive::execute_cmd(const uint8 *cmd, int cmd_len) +{ + // Strip trailing CRs + while (cmd_len > 0 && cmd[cmd_len - 1] == 0x0d) + cmd_len--; + + // Find token delimiters + const uint8 *colon = (const uint8 *)memchr(cmd, ':', cmd_len); + const uint8 *equal = colon ? (const uint8 *)memchr(colon, '=', cmd_len - (colon - cmd)) : NULL; + const uint8 *comma = (const uint8 *)memchr(cmd, ',', cmd_len); + const uint8 *minus = (const uint8 *)memchr(cmd, '-', cmd_len); + + // Parse command name + set_error(ERR_OK); + switch (cmd[0]) { + case 'B': // Block/buffer + if (!minus) + set_error(ERR_SYNTAX31); + else { + // Parse arguments (up to 4 decimal numbers separated by + // space, cursor right or comma) + const uint8 *p = colon ? colon + 1 : cmd + 3; + int arg1, arg2, arg3, arg4; + parse_block_cmd_args(p, arg1, arg2, arg3, arg4); + + // Switch on command + switch (minus[1]) { + case 'R': + block_read_cmd(arg1, arg3, arg4); + break; + case 'W': + block_write_cmd(arg1, arg3, arg4); + break; + case 'E': + block_execute_cmd(arg1, arg3, arg4); + break; + case 'A': + block_allocate_cmd(arg2, arg3); + break; + case 'F': + block_free_cmd(arg2, arg3); + break; + case 'P': + buffer_pointer_cmd(arg1, arg2); + break; + default: + set_error(ERR_SYNTAX31); + break; + } + } + break; + + case 'M': // Memory + if (cmd[1] != '-') + set_error(ERR_SYNTAX31); + else { + // Read parameters + uint16 adr = uint8(cmd[3]) | (uint8(cmd[4]) << 8); + uint8 len = uint8(cmd[5]); + + // Switch on command + switch (cmd[2]) { + case 'R': + mem_read_cmd(adr, (cmd_len < 6) ? 1 : len); + break; + case 'W': + mem_write_cmd(adr, len, (uint8 *)cmd + 6); + break; + case 'E': + mem_execute_cmd(adr); + break; + default: + set_error(ERR_SYNTAX31); + break; + } + } + break; + + case 'C': // Copy + if (!colon) + set_error(ERR_SYNTAX31); + else if (!equal || memchr(cmd, '*', cmd_len) || memchr(cmd, '?', cmd_len) || (comma && comma < equal)) + set_error(ERR_SYNTAX30); + else + copy_cmd(colon + 1, equal - colon - 1, equal + 1, cmd_len - (equal + 1 - cmd)); + break; + + case 'R': // Rename + if (!colon) + set_error(ERR_SYNTAX34); + else if (!equal || comma || memchr(cmd, '*', cmd_len) || memchr(cmd, '?', cmd_len)) + set_error(ERR_SYNTAX30); + else + rename_cmd(colon + 1, equal - colon - 1, equal + 1, cmd_len - (equal + 1 - cmd)); + break; + + case 'S': // Scratch + if (!colon) + set_error(ERR_SYNTAX34); + else + scratch_cmd(colon + 1, cmd_len - (colon + 1 - cmd)); + break; + + case 'P': // Position + position_cmd(cmd + 1, cmd_len - 1); + break; + + case 'I': // Initialize + initialize_cmd(); + break; + + case 'N': // New (format) + if (!colon) + set_error(ERR_SYNTAX34); + else + new_cmd(colon + 1, comma ? (comma - colon - 1) : cmd_len - (colon + 1 - cmd), comma); + break; + + case 'V': // Validate + validate_cmd(); + break; + + case 'U': // User + if (cmd[1] == '0') + break; + switch (cmd[1] & 0x0f) { + case 1: { // U1/UA: Read block + const uint8 *p = colon ? colon + 1 : cmd + 2; + int arg1, arg2, arg3, arg4; + parse_block_cmd_args(p, arg1, arg2, arg3, arg4); + block_read_cmd(arg1, arg3, arg4, true); + break; + } + case 2: { // U2/UB: Write block + const uint8 *p = colon ? colon + 1 : cmd + 2; + int arg1, arg2, arg3, arg4; + parse_block_cmd_args(p, arg1, arg2, arg3, arg4); + block_write_cmd(arg1, arg3, arg4, true); + break; + } + case 9: // U9/UI: C64/VC20 mode switch + if (cmd[2] != '+' && cmd[2] != '-') + Reset(); + break; + case 10: // U:/UJ: Reset + Reset(); + break; + default: + set_error(ERR_UNIMPLEMENTED); + break; + } + break; + + default: + set_error(ERR_SYNTAX31); + break; + } +} + +// BLOCK-READ:channel,0,track,sector +void Drive::block_read_cmd(int channel, int track, int sector, bool user_cmd) +{ + set_error(ERR_UNIMPLEMENTED); +} + +// BLOCK-WRITE:channel,0,track,sector +void Drive::block_write_cmd(int channel, int track, int sector, bool user_cmd) +{ + set_error(ERR_UNIMPLEMENTED); +} + +// BLOCK-EXECUTE:channel,0,track,sector +void Drive::block_execute_cmd(int channel, int track, int sector) +{ + set_error(ERR_UNIMPLEMENTED); +} + +// BLOCK-ALLOCATE:0,track,sector +void Drive::block_allocate_cmd(int track, int sector) +{ + set_error(ERR_UNIMPLEMENTED); +} + +// BLOCK-FREE:0,track,sector +void Drive::block_free_cmd(int track, int sector) +{ + set_error(ERR_UNIMPLEMENTED); +} + +// BUFFER-POINTER:channel,pos +void Drive::buffer_pointer_cmd(int channel, int pos) +{ + set_error(ERR_UNIMPLEMENTED); +} + +// M-R[] +void Drive::mem_read_cmd(uint16 adr, uint8 len) +{ + unsupp_cmd(); + error_ptr = error_buf; + error_buf[0] = 0; + error_len = 0; + set_error(ERR_OK); +} + +// M-W +void Drive::mem_write_cmd(uint16 adr, uint8 len, uint8 *p) +{ + set_error(ERR_UNIMPLEMENTED); +} + +// M-E +void Drive::mem_execute_cmd(uint16 adr) +{ + set_error(ERR_UNIMPLEMENTED); +} + +// COPY:new=file1,file2,... +// ^ ^ +// new_file old_files +void Drive::copy_cmd(const uint8 *new_file, int new_file_len, const uint8 *old_files, int old_files_len) +{ + set_error(ERR_UNIMPLEMENTED); +} + +// RENAME:new=old +// ^ ^ +// new_file old_file +void Drive::rename_cmd(const uint8 *new_file, int new_file_len, const uint8 *old_file, int old_file_len) +{ + set_error(ERR_UNIMPLEMENTED); +} + +// SCRATCH:file1,file2,... +// ^ +// files +void Drive::scratch_cmd(const uint8 *files, int files_len) +{ + set_error(ERR_UNIMPLEMENTED); +} + +// P +// ^ +// cmd +void Drive::position_cmd(const uint8 *cmd, int cmd_len) +{ + set_error(ERR_UNIMPLEMENTED); +} + +// INITIALIZE +void Drive::initialize_cmd(void) +{ + set_error(ERR_UNIMPLEMENTED); +} + +// NEW:name,id +// ^ ^ +// name comma (or NULL) +void Drive::new_cmd(const uint8 *name, int name_len, const uint8 *comma) +{ + set_error(ERR_UNIMPLEMENTED); +} + +// VALIDATE +void Drive::validate_cmd(void) +{ + set_error(ERR_UNIMPLEMENTED); +} + + +/* + * Notice user of unsupported drive command + */ + +void Drive::unsupp_cmd(void) +{ +} + + +/* + * Convert PETSCII<->ASCII + */ + +uint8 ascii2petscii(char c) +{ + if (((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z'))) + return c ^ 0x20; + return c; +} + +void ascii2petscii(uint8 *dest, const char *src, int n) +{ + while (n-- && (*dest++ = ascii2petscii(*src++))) ; +} + +char petscii2ascii(uint8 c) +{ + if (((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z'))) + return c ^ 0x20; + if ((c >= 0xc1) && (c <= 0xda)) + return c ^ 0x80; + return c; + return c; +} + +void petscii2ascii(char *dest, const uint8 *src, int n) +{ + while (n-- && (*dest++ = petscii2ascii(*src++))) ; +} + + +/* + * Check whether file is a mountable disk image or archive file, return type + */ + +bool IsMountableFile(const char *path, int &type) +{ + // Read header and determine file size + uint8 header[64]; + memset(header, 0, sizeof(header)); + FILE *f = fopen(path, "rb"); + if (f == NULL) + return false; + fseek(f, 0, SEEK_END); + long size = ftell(f); + fseek(f, 0, SEEK_SET); + fread(header, 1, sizeof(header), f); + fclose(f); + + if (IsImageFile(path, header, size)) { + type = FILE_IMAGE; + return true; + } + else return false; +} + + +/* + * Read directory of mountable disk image or archive file into c64_dir_entry vector, + * returns false on error + */ + +//bool ReadDirectory(const char *path, int type, vector &vec) +//{ +// vec.clear(); +// switch (type) { +// case FILE_IMAGE: +// return ReadImageDirectory(path, vec); +// case FILE_ARCH: +// return ReadArchDirectory(path, vec); +// default: +// return false; +// } +//} diff --git a/arm9/source/IEC.h b/arm9/source/IEC.h new file mode 100644 index 0000000..c5288c1 --- /dev/null +++ b/arm9/source/IEC.h @@ -0,0 +1,275 @@ +// ===================================================================================== +// GimliDS Copyright (c) 2025 Dave Bernazzani (wavemotion-dave) +// +// As GimliDS is a port of the Frodo emulator for the DS/DSi/XL/LL handhelds, +// any copying or distribution of this emulator, its source code and associated +// readme files, with or without modification, are permitted per the original +// Frodo emulator license shown below. Hugest thanks to Christian Bauer for his +// efforts to provide a clean open-source emulation base for the C64. +// +// Numerous hacks and 'unsafe' optimizations have been performed on the original +// Frodo emulator codebase to get it running on the small handheld system. You +// are strongly encouraged to seek out the official Frodo sources if you're at +// all interested in this emulator code. +// +// The GimliDS emulator is offered as-is, without any warranty. Please see readme.md +// ===================================================================================== + +/* + * IEC.h - IEC bus routines, 1541 emulation (DOS level) + * + * Frodo Copyright (C) Christian Bauer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _IEC_H +#define _IEC_H + + +/* + * Definitions + */ + +// Maximum length of file names +const int NAMEBUF_LENGTH = 256; + +// C64 status codes +enum { + ST_OK = 0, // No error + ST_READ_TIMEOUT = 0x02, // Timeout on reading + ST_TIMEOUT = 0x03, // Timeout + ST_EOF = 0x40, // End of file + ST_NOTPRESENT = 0x80 // Device not present +}; + +// 1541 error codes +enum { + ERR_OK, // 00 OK + ERR_SCRATCHED, // 01 FILES SCRATCHED + ERR_UNIMPLEMENTED, // 03 UNIMPLEMENTED + ERR_READ20, // 20 READ ERROR (block header not found) + ERR_READ21, // 21 READ ERROR (no sync character) + ERR_READ22, // 22 READ ERROR (data block not present) + ERR_READ23, // 23 READ ERROR (checksum error in data block) + ERR_READ24, // 24 READ ERROR (byte decoding error) + ERR_WRITE25, // 25 WRITE ERROR (write-verify error) + ERR_WRITEPROTECT, // 26 WRITE PROTECT ON + ERR_READ27, // 27 READ ERROR (checksum error in header) + ERR_WRITE28, // 28 WRITE ERROR (long data block) + ERR_DISKID, // 29 DISK ID MISMATCH + ERR_SYNTAX30, // 30 SYNTAX ERROR (general syntax) + ERR_SYNTAX31, // 31 SYNTAX ERROR (invalid command) + ERR_SYNTAX32, // 32 SYNTAX ERROR (command too long) + ERR_SYNTAX33, // 33 SYNTAX ERROR (wildcards on writing) + ERR_SYNTAX34, // 34 SYNTAX ERROR (missing file name) + ERR_WRITEFILEOPEN, // 60 WRITE FILE OPEN + ERR_FILENOTOPEN, // 61 FILE NOT OPEN + ERR_FILENOTFOUND, // 62 FILE NOT FOUND + ERR_FILEEXISTS, // 63 FILE EXISTS + ERR_FILETYPE, // 64 FILE TYPE MISMATCH + ERR_NOBLOCK, // 65 NO BLOCK + ERR_ILLEGALTS, // 66 ILLEGAL TRACK OR SECTOR + ERR_NOCHANNEL, // 70 NO CHANNEL + ERR_DIRERROR, // 71 DIR ERROR + ERR_DISKFULL, // 72 DISK FULL + ERR_STARTUP, // 73 Power-up message + ERR_NOTREADY // 74 DRIVE NOT READY +}; + +// Mountable file types +enum { + FILE_IMAGE, // Disk image, handled by ImageDrive + FILE_ARCH // Archive file, handled by ArchDrive +}; + +// 1541 file types +enum { + FTYPE_DEL, // Deleted + FTYPE_SEQ, // Sequential + FTYPE_PRG, // Program + FTYPE_USR, // User + FTYPE_REL, // Relative + FTYPE_UNKNOWN +}; + +static const char ftype_char[9] = "DSPUL "; + +// 1541 file access modes +enum { + FMODE_READ, // Read + FMODE_WRITE, // Write + FMODE_APPEND, // Append + FMODE_M // Read open file +}; + +// Drive LED states +enum { + DRVLED_OFF, // Inactive, LED off + DRVLED_ON, // Active, LED on + DRVLED_ERROR // Error, blink LED +}; + +// Information about file in disk image/archive file +struct c64_dir_entry { + c64_dir_entry(const uint8 *n, int t, bool o, bool p, size_t s, off_t ofs = 0, uint8 sal = 0, uint8 sah = 0) + : type(t), is_open(o), is_protected(p), size(s), offset(ofs), sa_lo(sal), sa_hi(sah) + { + strncpy((char *)name, (const char *)n, 17); + name[16] = 0; + } + + // Basic information + uint8 name[17]; // File name (C64 charset, null-terminated) + int type; // File type (see defines above) + bool is_open; // Flag: file open + bool is_protected; // Flag: file protected + size_t size; // File size (may be approximated) + + // Special information + off_t offset; // Offset of file in archive file + uint8 sa_lo, sa_hi; // C64 start address +}; + +class Drive; +class C64Display; +class Prefs; + +// Class for complete IEC bus system with drives 8..11 +class IEC { +public: + IEC(C64Display *display); + ~IEC(); + + void Reset(void); + void NewPrefs(Prefs *prefs); + void UpdateLEDs(void); + + uint8 Out(uint8 byte, bool eoi); + uint8 OutATN(uint8 byte); + uint8 OutSec(uint8 byte); + uint8 In(uint8 &byte); + void SetATN(void); + void RelATN(void); + void Turnaround(void); + void Release(void); + +private: + Drive *create_drive(const char *path); + + uint8 listen(int device); + uint8 talk(int device); + uint8 unlisten(void); + uint8 untalk(void); + uint8 sec_listen(void); + uint8 sec_talk(void); + uint8 open_out(uint8 byte, bool eoi); + uint8 data_out(uint8 byte, bool eoi); + uint8 data_in(uint8 &byte); + + C64Display *the_display; // Pointer to display object (for drive LEDs) + + uint8 name_buf[NAMEBUF_LENGTH]; // Buffer for file names and command strings + uint8 *name_ptr; // Pointer for reception of file name + int name_len; // Received length of file name + + Drive *drive[2]; // 2 drives (8 and 9) + + Drive *listener; // Pointer to active listener + Drive *talker; // Pointer to active talker + + bool listener_active; // Listener selected, listener_data is valid + bool talker_active; // Talker selected, talker_data is valid + bool listening; // Last ATN was listen (to decide between sec_listen/sec_talk) + + uint8 received_cmd; // Received command code ($x0) + uint8 sec_addr; // Received secondary address ($0x) +}; + +// Abstract superclass for individual drives +class Drive { +public: + Drive(IEC *iec); + virtual ~Drive() {} + + virtual uint8 Open(int channel, const uint8 *name, int name_len)=0; + virtual uint8 Close(int channel)=0; + virtual uint8 Read(int channel, uint8 &byte)=0; + virtual uint8 Write(int channel, uint8 byte, bool eoi)=0; + virtual void Reset(void)=0; + + int LED; // Drive LED state + bool Ready; // Drive is ready for operation + +protected: + void set_error(int error, int track = 0, int sector = 0); + + void parse_file_name(const uint8 *src, int src_len, uint8 *dest, int &dest_len, int &mode, int &type, int &rec_len, bool convert_charset = false); + + void execute_cmd(const uint8 *cmd, int cmd_len); + virtual void block_read_cmd(int channel, int track, int sector, bool user_cmd = false); + virtual void block_write_cmd(int channel, int track, int sector, bool user_cmd = false); + virtual void block_execute_cmd(int channel, int track, int sector); + virtual void block_allocate_cmd(int track, int sector); + virtual void block_free_cmd(int track, int sector); + virtual void buffer_pointer_cmd(int channel, int pos); + virtual void mem_read_cmd(uint16 adr, uint8 len); + virtual void mem_write_cmd(uint16 adr, uint8 len, uint8 *p); + virtual void mem_execute_cmd(uint16 adr); + virtual void copy_cmd(const uint8 *new_file, int new_file_len, const uint8 *old_files, int old_files_len); + virtual void rename_cmd(const uint8 *new_file, int new_file_len, const uint8 *old_file, int old_file_len); + virtual void scratch_cmd(const uint8 *files, int files_len); + virtual void position_cmd(const uint8 *cmd, int cmd_len); + virtual void initialize_cmd(void); + virtual void new_cmd(const uint8 *name, int name_len, const uint8 *comma); + virtual void validate_cmd(void); + void unsupp_cmd(void); + + char error_buf[256]; // Buffer with current error message + char *error_ptr; // Pointer within error message + int error_len; // Remaining length of error message + int current_error; // Number of current error + + uint8 cmd_buf[64]; // Buffer for incoming command strings + int cmd_len; // Length of received command + +private: + IEC *the_iec; // Pointer to IEC object +}; + + +/* + * Functions + */ + +// Convert ASCII character to PETSCII character +extern uint8 ascii2petscii(char c); + +// Convert ASCII string to PETSCII string +extern void ascii2petscii(uint8 *dest, const char *src, int max); + +// Convert PETSCII character to ASCII character +extern char petscii2ascii(uint8 c); + +// Convert PETSCII string to ASCII string +extern void petscii2ascii(char *dest, const uint8 *src, int max); + +// Check whether file is a mountable disk image or archive file, return type +extern bool IsMountableFile(const char *path, int &type); + +// Read directory of mountable disk image or archive file into c64_dir_entry vector +extern bool ReadDirectory(const char *path, int type, vector &vec); + +#endif diff --git a/arm9/source/Prefs.cpp b/arm9/source/Prefs.cpp new file mode 100644 index 0000000..1bbe51b --- /dev/null +++ b/arm9/source/Prefs.cpp @@ -0,0 +1,53 @@ +/* + * Prefs.cpp - Global preferences + * + * Frodo Copyright (C) Christian Bauer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "sysdeps.h" + +#include "Prefs.h" +#include "Display.h" +#include "C64.h" +#include "main.h" + + +// These are the active preferences +Prefs ThePrefs __attribute__((section(".dtcm"))); + + +/* + * Constructor: Set up preferences with defaults + */ + +Prefs::Prefs() +{ + // These are PAL specific values + DrawEveryN = isDSiMode() ? 1:2; + + strcpy(DrivePath[0], ""); + strcpy(DrivePath[1], ""); + + SIDType = SIDTYPE_DIGITAL; + + LimitSpeed = true; + FastReset = true; + CIAIRQHack = false; + TrueDrive = false; // True Drive Emulation when TRUE (slower emulation) + SIDFilters = true; +} + diff --git a/arm9/source/Prefs.h b/arm9/source/Prefs.h new file mode 100644 index 0000000..06266f8 --- /dev/null +++ b/arm9/source/Prefs.h @@ -0,0 +1,58 @@ +/* + * Prefs.h - Global preferences + * + * Frodo Copyright (C) Christian Bauer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _PREFS_H +#define _PREFS_H +#include "sysdeps.h" + +// SID types +enum { + SIDTYPE_NONE, // SID emulation off + SIDTYPE_DIGITAL, // Digital SID emulation + SIDTYPE_SIDCARD // SID card +}; + + +// Preferences data +class Prefs { +public: + Prefs(); + bool ShowEditor(bool startup, char *prefs_name); + void Check(void); + void Load(char *filename); + bool Save(char *filename); + + bool operator==(const Prefs &rhs) const; + bool operator!=(const Prefs &rhs) const; + + char DrivePath[2][256]; // Path for drive 8 and 9 + int DrawEveryN; // Draw every n-th frame + int SIDType; // SID emulation type + bool LimitSpeed; // Limit speed to 100% + bool FastReset; // Skip RAM test on reset + bool CIAIRQHack; // Write to CIA ICR clears IRQ + bool TrueDrive; // Enable processor-level 1541 emulation + bool SIDFilters; // Emulate SID filters +}; + +// These are the active preferences +extern Prefs ThePrefs; + +#endif diff --git a/arm9/source/SID.cpp b/arm9/source/SID.cpp new file mode 100644 index 0000000..f40fdc1 --- /dev/null +++ b/arm9/source/SID.cpp @@ -0,0 +1,1331 @@ +// ===================================================================================== +// GimliDS Copyright (c) 2025 Dave Bernazzani (wavemotion-dave) +// +// As GimliDS is a port of the Frodo emulator for the DS/DSi/XL/LL handhelds, +// any copying or distribution of this emulator, its source code and associated +// readme files, with or without modification, are permitted per the original +// Frodo emulator license shown below. Hugest thanks to Christian Bauer for his +// efforts to provide a clean open-source emulation base for the C64. +// +// Numerous hacks and 'unsafe' optimizations have been performed on the original +// Frodo emulator codebase to get it running on the small handheld system. You +// are strongly encouraged to seek out the official Frodo sources if you're at +// all interested in this emulator code. +// +// The GimliDS emulator is offered as-is, without any warranty. Please see readme.md +// ===================================================================================== + +/* + * SID.cpp - 6581 emulation + * + * Frodo Copyright (C) Christian Bauer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Incompatibilities: + * ------------------ + * + * - Lots of empirically determined constants in the filter calculations + */ + +#include "sysdeps.h" +#include "VIC.h" +#include +#include +#include "soundbank.h" +#include "soundbank_bin.h" + +#include +#include + +#include "SID.h" +#include "Prefs.h" + +#define USE_FIXPOINT_MATHS +#define FIXPOINT_PREC 16 // number of fractional bits used in fixpoint representation +#define PRECOMPUTE_RESONANCE +#define ldSINTAB 9 // size of sinus table (0 to 90 degrees) + +#ifdef USE_FIXPOINT_MATHS +#include "FixPoint.h" +#endif + + + +/* + * Resonance frequency polynomials + */ + +#define CALC_RESONANCE_LP(f) (227.755\ + - 1.7635 * f\ + - 0.0176385 * f * f\ + + 0.00333484 * f * f * f\ + - 9.05683E-6 * f * f * f * f) + +#define CALC_RESONANCE_HP(f) (366.374\ + - 14.0052 * f\ + + 0.603212 * f * f\ + - 0.000880196 * f * f * f) + + +/* + * Random number generator for noise waveform + */ + +static uint8 sid_random(void); +static uint8 sid_random(void) +{ + static uint32 seed = 1; + seed = seed * 1103515245 + 12345; + return seed >> 16; +} + + +/* + * Constructor + */ + +MOS6581::MOS6581(C64 *c64) : the_c64(c64) +{ + the_renderer = NULL; + for (int i=0; i<32; i++) + regs[i] = 0; + + // Open the renderer + open_close_renderer(SIDTYPE_NONE, ThePrefs.SIDType); +} + + +/* + * Destructor + */ + +MOS6581::~MOS6581() +{ + // Close the renderer + open_close_renderer(ThePrefs.SIDType, SIDTYPE_NONE); +} + + +/* + * Reset the SID + */ + +void MOS6581::Reset(void) +{ + for (int i=0; i<32; i++) + regs[i] = 0; + last_sid_byte = 0; + + // Reset the renderer + if (the_renderer != NULL) + the_renderer->Reset(); +} + + +/* + * Preferences may have changed + */ + +void MOS6581::NewPrefs(Prefs *prefs) +{ + open_close_renderer(ThePrefs.SIDType, prefs->SIDType); + if (the_renderer != NULL) + the_renderer->NewPrefs(prefs); +} + + +/* + * Pause sound output + */ + +void MOS6581::PauseSound(void) +{ + if (the_renderer != NULL) + the_renderer->Pause(); +} + + +/* + * Resume sound output + */ + +void MOS6581::ResumeSound(void) +{ + if (the_renderer != NULL) + the_renderer->Resume(); +} + + +/* + * Get SID state + */ + +void MOS6581::GetState(MOS6581State *ss) +{ + ss->freq_lo_1 = regs[0]; + ss->freq_hi_1 = regs[1]; + ss->pw_lo_1 = regs[2]; + ss->pw_hi_1 = regs[3]; + ss->ctrl_1 = regs[4]; + ss->AD_1 = regs[5]; + ss->SR_1 = regs[6]; + + ss->freq_lo_2 = regs[7]; + ss->freq_hi_2 = regs[8]; + ss->pw_lo_2 = regs[9]; + ss->pw_hi_2 = regs[10]; + ss->ctrl_2 = regs[11]; + ss->AD_2 = regs[12]; + ss->SR_2 = regs[13]; + + ss->freq_lo_3 = regs[14]; + ss->freq_hi_3 = regs[15]; + ss->pw_lo_3 = regs[16]; + ss->pw_hi_3 = regs[17]; + ss->ctrl_3 = regs[18]; + ss->AD_3 = regs[19]; + ss->SR_3 = regs[20]; + + ss->fc_lo = regs[21]; + ss->fc_hi = regs[22]; + ss->res_filt = regs[23]; + ss->mode_vol = regs[24]; + + ss->pot_x = 0xff; + ss->pot_y = 0xff; + ss->osc_3 = 0; + ss->env_3 = 0; +} + + +/* + * Restore SID state + */ + +void MOS6581::SetState(MOS6581State *ss) +{ + regs[0] = ss->freq_lo_1; + regs[1] = ss->freq_hi_1; + regs[2] = ss->pw_lo_1; + regs[3] = ss->pw_hi_1; + regs[4] = ss->ctrl_1; + regs[5] = ss->AD_1; + regs[6] = ss->SR_1; + + regs[7] = ss->freq_lo_2; + regs[8] = ss->freq_hi_2; + regs[9] = ss->pw_lo_2; + regs[10] = ss->pw_hi_2; + regs[11] = ss->ctrl_2; + regs[12] = ss->AD_2; + regs[13] = ss->SR_2; + + regs[14] = ss->freq_lo_3; + regs[15] = ss->freq_hi_3; + regs[16] = ss->pw_lo_3; + regs[17] = ss->pw_hi_3; + regs[18] = ss->ctrl_3; + regs[19] = ss->AD_3; + regs[20] = ss->SR_3; + + regs[21] = ss->fc_lo; + regs[22] = ss->fc_hi; + regs[23] = ss->res_filt; + regs[24] = ss->mode_vol; + + // Stuff the new register values into the renderer + if (the_renderer != NULL) + for (int i=0; i<25; i++) + the_renderer->WriteRegister(i, regs[i]); +} + + +/** + ** Renderer for digital SID emulation (SIDTYPE_DIGITAL) + **/ + +const uint32 SAMPLE_FREQ = 22050; // NDS Sample Rate - reasonable quality and speed +const uint32 SID_FREQ = 985248; // SID frequency in Hz +const uint32 CALC_FREQ = 50; // Frequency at which calc_buffer is called in Hz (should be 50Hz) +const uint32 SID_CYCLES_FIX = ((SID_FREQ << 11)/SAMPLE_FREQ)<<5; // # of SID clocks per sample frame * 65536 +const uint32 SID_CYCLES = SID_CYCLES_FIX << 16; // # of SID clocks per sample frame +const int SAMPLE_BUF_SIZE = 0x138*2;// Size of buffer for sampled voice (double buffered) + +uint8 sample_buf[SAMPLE_BUF_SIZE] __attribute__((section(".dtcm"))); // Buffer for sampled voice +int sample_in_ptr __attribute__((section(".dtcm"))); // Index in sample_buf for writing + +// SID waveforms (some of them :-) +enum { + WAVE_NONE, + WAVE_TRI, + WAVE_SAW, + WAVE_TRISAW, + WAVE_RECT, + WAVE_TRIRECT, + WAVE_SAWRECT, + WAVE_TRISAWRECT, + WAVE_NOISE +}; + +// EG states +enum { + EG_IDLE, + EG_ATTACK, + EG_DECAY, + EG_RELEASE +}; + +// Filter types +enum { + FILT_NONE, + FILT_LP, + FILT_BP, + FILT_LPBP, + FILT_HP, + FILT_NOTCH, + FILT_HPBP, + FILT_ALL +}; + +// Structure for one voice +struct DRVoice { + int wave; // Selected waveform + int eg_state; // Current state of EG + DRVoice *mod_by; // Voice that modulates this one + DRVoice *mod_to; // Voice that is modulated by this one + + uint32 count; // Counter for waveform generator, 8.16 fixed + uint32 add; // Added to counter in every frame + + uint16 freq; // SID frequency value + uint16 pw; // SID pulse-width value + + uint32 a_add; // EG parameters + uint32 d_sub; + uint32 s_level; + uint32 r_sub; + uint32 eg_level; // Current EG level, 8.16 fixed + + uint32 noise; // Last noise generator output value + + bool gate; // EG gate bit + bool ring; // Ring modulation bit + bool test; // Test bit + bool filter; // Flag: Voice filtered + + // The following bit is set for the modulating + // voice, not for the modulated one (as the SID bits) + bool sync; // Sync modulation bit + bool mute; // Voice muted (voice 3 only) +}; + +// Renderer class +class DigitalRenderer : public SIDRenderer { +public: + + DigitalRenderer(); + virtual ~DigitalRenderer(); + + virtual void Reset(void); + virtual void EmulateLine(void); + virtual void WriteRegister(uint16 adr, uint8 byte); + virtual void NewPrefs(Prefs *prefs); + virtual void Pause(void); + virtual void Resume(void); + int16 calc_buffer(int16 *buf, long count); + bool ready; // Flag: Renderer has initialized and is ready +private: + void init_sound(void); + void calc_filter(void); + uint8 volume; // Master volume + + static uint16 TriTable[0x1000*2]; // Tables for certain waveforms + static const uint16 TriSawTable[0x100]; + static const uint16 TriRectTable[0x100]; + static const uint16 SawRectTable[0x100]; + static const uint16 TriSawRectTable[0x100]; + static const uint32 EGTable[16]; // Increment/decrement values for all A/D/R settings + static const uint8 EGDRShift[256]; // For exponential approximation of D/R + static const int16 SampleTab[16]; // Table for sampled voice + + DRVoice voice[3]; // Data for 3 voices + + uint8 f_type; // Filter type + uint8 f_freq; // SID filter frequency (upper 8 bits) + uint8 f_res; // Filter resonance (0..15) +#ifdef USE_FIXPOINT_MATHS + FixPoint f_ampl; + FixPoint d1, d2, g1, g2; + int32 xn1, xn2, yn1, yn2; // can become very large + FixPoint sidquot; +#ifdef PRECOMPUTE_RESONANCE + FixPoint resonanceLP[256]; + FixPoint resonanceHP[256]; +#endif +#else + float f_ampl; // IIR filter input attenuation + float d1, d2, g1, g2; // IIR filter coefficients + float xn1, xn2, yn1, yn2; // IIR filter previous input/output signal +#ifdef PRECOMPUTE_RESONANCE + float resonanceLP[256]; // shortcut for calc_filter + float resonanceHP[256]; +#endif +#endif + int16 *sound_buffer; +}; + +// Static data members +uint16 DigitalRenderer::TriTable[0x1000*2]; + +#ifndef EMUL_MOS8580 +// Sampled from a 6581R4 +const uint16 DigitalRenderer::TriSawTable[0x100] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0808, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1010, 0x3C3C, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0808, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1010, 0x3C3C +}; + +const uint16 DigitalRenderer::TriRectTable[0x100] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8080, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8080, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8080, 0xC0C0, + 0x0000, 0x8080, 0x8080, 0xE0E0, 0x8080, 0xE0E0, 0xF0F0, 0xFCFC, + 0xFFFF, 0xFCFC, 0xFAFA, 0xF0F0, 0xF6F6, 0xE0E0, 0xE0E0, 0x8080, + 0xEEEE, 0xE0E0, 0xE0E0, 0x8080, 0xC0C0, 0x0000, 0x0000, 0x0000, + 0xDEDE, 0xC0C0, 0xC0C0, 0x0000, 0x8080, 0x0000, 0x0000, 0x0000, + 0x8080, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xBEBE, 0x8080, 0x8080, 0x0000, 0x8080, 0x0000, 0x0000, 0x0000, + 0x8080, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x7E7E, 0x4040, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +}; + +const uint16 DigitalRenderer::SawRectTable[0x100] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7878, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7878 +}; + +const uint16 DigitalRenderer::TriSawRectTable[0x100] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +}; +#else +// Sampled from an 8580R5 +const uint16 DigitalRenderer::TriSawTable[0x100] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0808, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1818, 0x3C3C, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1C1C, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x8080, 0x0000, 0x8080, 0x8080, + 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xE0E0, + 0xF0F0, 0xF0F0, 0xF0F0, 0xF0F0, 0xF8F8, 0xF8F8, 0xFCFC, 0xFEFE +}; + +const uint16 DigitalRenderer::TriRectTable[0x100] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xFFFF, 0xFCFC, 0xF8F8, 0xF0F0, 0xF4F4, 0xF0F0, 0xF0F0, 0xE0E0, + 0xECEC, 0xE0E0, 0xE0E0, 0xC0C0, 0xE0E0, 0xC0C0, 0xC0C0, 0xC0C0, + 0xDCDC, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0x8080, 0x8080, + 0xC0C0, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x0000, 0x0000, + 0xBEBE, 0xA0A0, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x0000, + 0x8080, 0x8080, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x8080, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x7E7E, 0x7070, 0x6060, 0x0000, 0x4040, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +}; + +const uint16 DigitalRenderer::SawRectTable[0x100] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8080, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8080, 0x8080, + 0x0000, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0xB0B0, 0xBEBE, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8080, + 0x0000, 0x0000, 0x0000, 0x8080, 0x8080, 0x8080, 0x8080, 0xC0C0, + 0x0000, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0xC0C0, + 0x8080, 0x8080, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xDCDC, + 0x8080, 0x8080, 0x8080, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, + 0xC0C0, 0xC0C0, 0xC0C0, 0xE0E0, 0xE0E0, 0xE0E0, 0xE0E0, 0xECEC, + 0xC0C0, 0xE0E0, 0xE0E0, 0xE0E0, 0xE0E0, 0xF0F0, 0xF0F0, 0xF4F4, + 0xF0F0, 0xF0F0, 0xF8F8, 0xF8F8, 0xF8F8, 0xFCFC, 0xFEFE, 0xFFFF +}; + +const uint16 DigitalRenderer::TriSawRectTable[0x100] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8080, 0x8080, + 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0xC0C0, 0xC0C0, + 0xC0C0, 0xC0C0, 0xE0E0, 0xE0E0, 0xE0E0, 0xF0F0, 0xF8F8, 0xFCFC +}; +#endif + +const uint32 DigitalRenderer::EGTable[16] = { + SID_CYCLES_FIX / 9, SID_CYCLES_FIX / 32, + SID_CYCLES_FIX / 63, SID_CYCLES_FIX / 95, + SID_CYCLES_FIX / 149, SID_CYCLES_FIX / 220, + SID_CYCLES_FIX / 267, SID_CYCLES_FIX / 313, + SID_CYCLES_FIX / 392, SID_CYCLES_FIX / 977, + SID_CYCLES_FIX / 1954, SID_CYCLES_FIX / 3126, + SID_CYCLES_FIX / 3906, SID_CYCLES_FIX / 11720, + SID_CYCLES_FIX / 19531, SID_CYCLES_FIX / 31251 +}; + +const uint8 DigitalRenderer::EGDRShift[256] = { + 5,5,5,5,5,5,5,5,4,4,4,4,4,4,4,4, + 3,3,3,3,3,3,3,3,3,3,3,3,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +}; + +const int16 DigitalRenderer::SampleTab[16] = { + 0x8000, 0x9111, 0xa222, 0xb333, 0xc444, 0xd555, 0xe666, 0xf777, + 0x0888, 0x1999, 0x2aaa, 0x3bbb, 0x4ccc, 0x5ddd, 0x6eee, 0x7fff, +}; + + +/* + * Constructor + */ + +DigitalRenderer::DigitalRenderer() +{ + // Link voices together + voice[0].mod_by = &voice[2]; + voice[1].mod_by = &voice[0]; + voice[2].mod_by = &voice[1]; + voice[0].mod_to = &voice[1]; + voice[1].mod_to = &voice[2]; + voice[2].mod_to = &voice[0]; + + // Calculate triangle table + for (int i=0; i<0x1000; i++) { + TriTable[i] = (i << 4) | (i >> 8); + TriTable[0x1fff-i] = (i << 4) | (i >> 8); + } + +#ifdef PRECOMPUTE_RESONANCE +#ifdef USE_FIXPOINT_MATHS + // slow floating point doesn't matter much on startup! + for (int i=0; i<256; i++) { + resonanceLP[i] = FixNo(CALC_RESONANCE_LP(i)); + resonanceHP[i] = FixNo(CALC_RESONANCE_HP(i)); + } + // Pre-compute the quotient. No problem since int-part is small enough + sidquot = SID_CYCLES_FIX; + // compute lookup table for sin and cos + InitFixSinTab(); +#else + for (int i=0; i<256; i++) { + resonanceLP[i] = CALC_RESONANCE_LP(i); + resonanceHP[i] = CALC_RESONANCE_HP(i); + } +#endif +#endif + + Reset(); + + // System specific initialization + init_sound(); +} + + +/* + * Reset emulation + */ + +void DigitalRenderer::Reset(void) +{ + volume = 0; + + for (int v=0; v<3; v++) { + voice[v].wave = WAVE_NONE; + voice[v].eg_state = EG_IDLE; + voice[v].count = 0x555555; + voice[v].add = 0; + voice[v].freq = voice[v].pw = 0; + voice[v].eg_level = voice[v].s_level = 0; + voice[v].a_add = voice[v].d_sub = voice[v].r_sub = EGTable[0]; + voice[v].gate = voice[v].ring = voice[v].test = false; + voice[v].filter = voice[v].sync = voice[v].mute = false; + } + + f_type = FILT_NONE; + f_freq = f_res = 0; +#ifdef USE_FIXPOINT_MATHS + f_ampl = FixNo(1); + d1 = d2 = g1 = g2 = 0; + xn1 = xn2 = yn1 = yn2 = 0; +#else + f_ampl = 1.0; + d1 = d2 = g1 = g2 = 0.0; + xn1 = xn2 = yn1 = yn2 = 0.0; +#endif + + sample_in_ptr = 0; + memset(sample_buf, 0, SAMPLE_BUF_SIZE); +} + + +/* + * Write to register + */ + +void DigitalRenderer::WriteRegister(uint16 adr, uint8 byte) +{ + if (!ready) + return; + + int v = adr/7; // Voice number + + switch (adr) { + case 0: + case 7: + case 14: + voice[v].freq = (voice[v].freq & 0xff00) | byte; +#ifdef USE_FIXPOINT_MATHS + voice[v].add = sidquot.imul((int)voice[v].freq); +#else + voice[v].add = (uint32)((float)voice[v].freq * SID_FREQ / SAMPLE_FREQ); +#endif + break; + + case 1: + case 8: + case 15: + voice[v].freq = (voice[v].freq & 0xff) | (byte << 8); +#ifdef USE_FIXPOINT_MATHS + voice[v].add = sidquot.imul((int)voice[v].freq); +#else + voice[v].add = (uint32)((float)voice[v].freq * SID_FREQ / SAMPLE_FREQ); +#endif + break; + + case 2: + case 9: + case 16: + voice[v].pw = (voice[v].pw & 0x0f00) | byte; + break; + + case 3: + case 10: + case 17: + voice[v].pw = (voice[v].pw & 0xff) | ((byte & 0xf) << 8); + break; + + case 4: + case 11: + case 18: + voice[v].wave = (byte >> 4) & 0xf; + if ((byte & 1) != voice[v].gate) + { + if (byte & 1) // Gate turned on + voice[v].eg_state = EG_ATTACK; + else // Gate turned off + { + if (voice[v].eg_state != EG_IDLE) + voice[v].eg_state = EG_RELEASE; + } + } + voice[v].gate = byte & 1; + voice[v].mod_by->sync = byte & 2; + voice[v].ring = byte & 4; + if ((voice[v].test = byte & 8) != 0) + voice[v].count = 0; + break; + + case 5: + case 12: + case 19: + voice[v].a_add = EGTable[byte >> 4]; + voice[v].d_sub = EGTable[byte & 0xf]; + break; + + case 6: + case 13: + case 20: + voice[v].s_level = (byte >> 4) * 0x111111; + voice[v].r_sub = EGTable[byte & 0xf]; + break; + + case 22: + if (byte != f_freq) { + f_freq = byte; + if (ThePrefs.SIDFilters) + calc_filter(); + } + break; + + case 23: + voice[0].filter = byte & 1; + voice[1].filter = byte & 2; + voice[2].filter = byte & 4; + if ((byte >> 4) != f_res) { + f_res = byte >> 4; + if (ThePrefs.SIDFilters) + calc_filter(); + } + break; + + case 24: + volume = byte & 0xf; + voice[2].mute = byte & 0x80; + if (((byte >> 4) & 7) != f_type) { + f_type = (byte >> 4) & 7; +#ifdef USE_FIXPOINT_MATHS + xn1 = xn2 = yn1 = yn2 = 0; +#else + xn1 = xn2 = yn1 = yn2 = 0.0; +#endif + if (ThePrefs.SIDFilters) + calc_filter(); + } + break; + } +} + + +/* + * Preferences may have changed + */ + +void DigitalRenderer::NewPrefs(Prefs *prefs) +{ + calc_filter(); +} + + +/* + * Calculate IIR filter coefficients + */ + +void DigitalRenderer::calc_filter(void) +{ +#ifdef USE_FIXPOINT_MATHS + FixPoint fr, arg; + + if (f_type == FILT_ALL) + { + d1 = 0; d2 = 0; g1 = 0; g2 = 0; f_ampl = FixNo(1); return; + } + else if (f_type == FILT_NONE) + { + d1 = 0; d2 = 0; g1 = 0; g2 = 0; f_ampl = 0; return; + } +#else + float fr, arg; + + // Check for some trivial cases + if (f_type == FILT_ALL) { + d1 = 0.0; d2 = 0.0; + g1 = 0.0; g2 = 0.0; + f_ampl = 1.0; + return; + } else if (f_type == FILT_NONE) { + d1 = 0.0; d2 = 0.0; + g1 = 0.0; g2 = 0.0; + f_ampl = 0.0; + return; + } +#endif + + // Calculate resonance frequency + if (f_type == FILT_LP || f_type == FILT_LPBP) +#ifdef PRECOMPUTE_RESONANCE + fr = resonanceLP[f_freq]; +#else + fr = CALC_RESONANCE_LP(f_freq); +#endif + else +#ifdef PRECOMPUTE_RESONANCE + fr = resonanceHP[f_freq]; +#else + fr = CALC_RESONANCE_HP(f_freq); +#endif + +#ifdef USE_FIXPOINT_MATHS + // explanations see below. +#ifdef __NDS__ + arg = fr / (int)(SAMPLE_FREQ >> 1); +#else + arg = fr / (SAMPLE_FREQ >> 1); +#endif + if (arg > FixNo(0.99)) {arg = FixNo(0.99);} + if (arg < FixNo(0.01)) {arg = FixNo(0.01);} + + g2 = FixNo(0.55) + FixNo(1.2) * arg * (arg - 1) + FixNo(0.0133333333) * f_res; + g1 = FixNo(-2) * g2.sqrt() * fixcos(arg); + + if (f_type == FILT_LPBP || f_type == FILT_HPBP) {g2 += FixNo(0.1);} + + if (g1.abs() >= g2 + 1) + { + if (g1 > 0) {g1 = g2 + FixNo(0.99);} + else {g1 = -(g2 + FixNo(0.99));} + } + + switch (f_type) + { + case FILT_LPBP: + case FILT_LP: + d1 = FixNo(2); d2 = FixNo(1); f_ampl = FixNo(0.25) * (1 + g1 + g2); break; + case FILT_HPBP: + case FILT_HP: + d1 = FixNo(-2); d2 = FixNo(1); f_ampl = FixNo(0.25) * (1 - g1 + g2); break; + case FILT_BP: + d1 = 0; d2 = FixNo(-1); + f_ampl = FixNo(0.25) * (1 + g1 + g2) * (1 + fixcos(arg)) / fixsin(arg); + break; + case FILT_NOTCH: + d1 = FixNo(-2) * fixcos(arg); d2 = FixNo(1); + f_ampl = FixNo(0.25) * (1 + g1 + g2) * (1 + fixcos(arg)) / fixsin(arg); + break; + default: break; + } + +#else + + // Limit to <1/2 sample frequency, avoid div by 0 in case FILT_BP below + arg = fr / (float)(SAMPLE_FREQ >> 1); + if (arg > 0.99) + arg = 0.99; + if (arg < 0.01) + arg = 0.01; + + // Calculate poles (resonance frequency and resonance) + g2 = 0.55 + 1.2 * arg * arg - 1.2 * arg + (float)f_res * 0.0133333333; + g1 = -2.0 * sqrt(g2) * cos(M_PI * arg); + + // Increase resonance if LP/HP combined with BP + if (f_type == FILT_LPBP || f_type == FILT_HPBP) + g2 += 0.1; + + // Stabilize filter + if (fabs(g1) >= g2 + 1.0) + if (g1 > 0.0) + g1 = g2 + 0.99; + else + g1 = -(g2 + 0.99); + + // Calculate roots (filter characteristic) and input attenuation + switch (f_type) { + + case FILT_LPBP: + case FILT_LP: + d1 = 2.0; d2 = 1.0; + f_ampl = 0.25 * (1.0 + g1 + g2); + break; + + case FILT_HPBP: + case FILT_HP: + d1 = -2.0; d2 = 1.0; + f_ampl = 0.25 * (1.0 - g1 + g2); + break; + + case FILT_BP: + d1 = 0.0; d2 = -1.0; + f_ampl = 0.25 * (1.0 + g1 + g2) * (1 + cos(M_PI * arg)) / sin(M_PI * arg); + break; + + case FILT_NOTCH: + d1 = -2.0 * cos(M_PI * arg); d2 = 1.0; + f_ampl = 0.25 * (1.0 + g1 + g2) * (1 + cos(M_PI * arg)) / (sin(M_PI * arg)); + break; + + default: + break; + } +#endif +} + + +/* + * Fill one audio buffer with calculated SID sound + */ + +ITCM_CODE int16 DigitalRenderer::calc_buffer(int16 *buf, long count) +{ + // Get filter coefficients, so the emulator won't change + // them in the middle of our calculations +#ifdef USE_FIXPOINT_MATHS + FixPoint cf_ampl = f_ampl; + FixPoint cd1 = d1, cd2 = d2, cg1 = g1, cg2 = g2; +#else + float cf_ampl = f_ampl; + float cd1 = d1, cd2 = d2, cg1 = g1, cg2 = g2; +#endif + + // Index in sample_buf for reading, 16.16 fixed + uint32 sample_count = (sample_in_ptr + SAMPLE_BUF_SIZE/2) << 16; + + count >>= 1; // 16 bit mono output, count is in bytes + + while (count--) + { + + // Get current master volume from sample buffer, + // calculate sampled voice + uint8 master_volume = sample_buf[(sample_count >> 16) % SAMPLE_BUF_SIZE]; + sample_count += ((0x138 * 50) << 16) / SAMPLE_FREQ; + int32 sum_output = SampleTab[master_volume] << 8; + int32 sum_output_filter = 0; + + // Loop for all three voices + for (int j=0; j<3; j++) + { + DRVoice *v = &voice[j]; + + // Envelope generators + uint16 envelope; + + switch (v->eg_state) { + case EG_ATTACK: + v->eg_level += v->a_add; + if (v->eg_level > 0xffffff) { + v->eg_level = 0xffffff; + v->eg_state = EG_DECAY; + } + break; + case EG_DECAY: + if (v->eg_level <= v->s_level || v->eg_level > 0xffffff) + v->eg_level = v->s_level; + else { + v->eg_level -= v->d_sub >> EGDRShift[v->eg_level >> 16]; + if (v->eg_level <= v->s_level || v->eg_level > 0xffffff) + v->eg_level = v->s_level; + } + break; + case EG_RELEASE: + v->eg_level -= v->r_sub >> EGDRShift[v->eg_level >> 16]; + if (v->eg_level > 0xffffff) { + v->eg_level = 0; + v->eg_state = EG_IDLE; + } + break; + case EG_IDLE: + v->eg_level = 0; + break; + } + envelope = (v->eg_level * master_volume) >> 20; + + // Waveform generator + if (v->mute) + continue; + uint16 output; + + if (!v->test) + v->count += v->add; + + if (v->sync && (v->count > 0x1000000)) + v->mod_to->count = 0; + + v->count &= 0xffffff; + + switch (v->wave) { + case WAVE_TRI: + if (v->ring) + output = TriTable[(v->count ^ (v->mod_by->count & 0x800000)) >> 11]; + else + output = TriTable[v->count >> 11]; + break; + case WAVE_SAW: + output = v->count >> 8; + break; + case WAVE_RECT: + if (v->count > (uint32)(v->pw << 12)) + output = 0xffff; + else + output = 0; + break; + case WAVE_TRISAW: + output = TriSawTable[v->count >> 16]; + break; + case WAVE_TRIRECT: + if (v->count > (uint32)(v->pw << 12)) + output = TriRectTable[v->count >> 16]; + else + output = 0; + break; + case WAVE_SAWRECT: + if (v->count > (uint32)(v->pw << 12)) + output = SawRectTable[v->count >> 16]; + else + output = 0; + break; + case WAVE_TRISAWRECT: + if (v->count > (uint32)(v->pw << 12)) + output = TriSawRectTable[v->count >> 16]; + else + output = 0; + break; + case WAVE_NOISE: + if (v->count > 0x100000) { + output = v->noise = sid_random() << 8; + v->count &= 0xfffff; + } else + output = v->noise; + break; + default: + output = 0x8000; + break; + } + if (v->filter) + sum_output_filter += (int16)(output ^ 0x8000) * envelope; + else + sum_output += (int16)(output ^ 0x8000) * envelope; + } + + // Filter + if (ThePrefs.SIDFilters) { +#ifdef USE_FIXPOINT_MATHS + int32 xn = cf_ampl.imul(sum_output_filter); + int32 yn = xn+cd1.imul(xn1)+cd2.imul(xn2)-cg1.imul(yn1)-cg2.imul(yn2); + yn2 = yn1; yn1 = yn; xn2 = xn1; xn1 = xn; + sum_output_filter = yn; +#else + float xn = (float)sum_output_filter * cf_ampl; + float yn = xn + cd1 * xn1 + cd2 * xn2 - cg1 * yn1 - cg2 * yn2; + yn2 = yn1; yn1 = yn; xn2 = xn1; xn1 = xn; + sum_output_filter = (int32)yn; +#endif + } + + // Write to buffer + *buf++ = ((sum_output + sum_output_filter) >> 10 ); + } + buf--; return *buf; +} + +/* + * SID_NDS.i + * + * RISC OS specific parts of the sound emulation + * Frodo (C) 1994-1997,2002 Christian Bauer + * Acorn port by Andreas Dehmel, 1997 + * + */ + +DigitalRenderer* p __attribute__((section(".dtcm"))); +bool paused __attribute__((section(".dtcm"))) = false; +int16 last_sample = 0x8000; + +ITCM_CODE mm_word SoundMixCallback(mm_word len, mm_addr stream, mm_stream_formats format) +{ + if (paused) + { + s16 *p = (s16*)stream; + for (mm_word i=0; icalc_buffer((int16*)stream, len*2); + } + return len; +} + +void init_maxmod(void) +{ + //---------------------------------------------------------------- + // initialize maxmod with our small 3-effect soundbank + //---------------------------------------------------------------- + mmInitDefaultMem((mm_addr)soundbank_bin); + + mmLoadEffect(SFX_FLOPPY); + mmLoadEffect(SFX_KEYCLICK); + mmLoadEffect(SFX_MUS_INTRO); +} + +void DigitalRenderer::init_sound(void) +{ + p = this; + + mm_stream mstream; + memset(&mstream, 0, sizeof(mstream)); + mstream.sampling_rate = SAMPLE_FREQ; + mstream.buffer_length = 0x138 * 2; + mstream.callback = SoundMixCallback; + mstream.format = MM_STREAM_16BIT_MONO; + mstream.timer = MM_TIMER2; + mstream.manual = false; + DC_FlushAll(); + mmStreamOpen(&mstream); + + ready = true; +} + +DigitalRenderer::~DigitalRenderer() +{ + +} + +void DigitalRenderer::EmulateLine(void) +{ + sample_buf[sample_in_ptr] = volume; + sample_in_ptr = (sample_in_ptr + 1) % SAMPLE_BUF_SIZE; +} + +void DigitalRenderer::Pause(void) +{ + paused = true; + //mmPause(); +} + +void DigitalRenderer::Resume(void) +{ + //mmResume(); + paused = false; +} + + + +/* + * Open/close the renderer, according to old and new prefs + */ + +void MOS6581::open_close_renderer(int old_type, int new_type) +{ + if (old_type == new_type) + return; + + // Delete the old renderer + delete the_renderer; + + // Create new renderer + the_renderer = new DigitalRenderer; + + // Stuff the current register values into the new renderer + if (the_renderer != NULL) + for (int i=0; i<25; i++) + the_renderer->WriteRegister(i, regs[i]); +} diff --git a/arm9/source/SID.h b/arm9/source/SID.h new file mode 100644 index 0000000..9ea9859 --- /dev/null +++ b/arm9/source/SID.h @@ -0,0 +1,178 @@ +// ===================================================================================== +// GimliDS Copyright (c) 2025 Dave Bernazzani (wavemotion-dave) +// +// As GimliDS is a port of the Frodo emulator for the DS/DSi/XL/LL handhelds, +// any copying or distribution of this emulator, its source code and associated +// readme files, with or without modification, are permitted per the original +// Frodo emulator license shown below. Hugest thanks to Christian Bauer for his +// efforts to provide a clean open-source emulation base for the C64. +// +// Numerous hacks and 'unsafe' optimizations have been performed on the original +// Frodo emulator codebase to get it running on the small handheld system. You +// are strongly encouraged to seek out the official Frodo sources if you're at +// all interested in this emulator code. +// +// The GimliDS emulator is offered as-is, without any warranty. Please see readme.md +// ===================================================================================== + +/* + * SID.h - 6581 emulation + * + * Frodo Copyright (C) Christian Bauer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _SID_H +#define _SID_H +#include +#include + + +// Define this if you want an emulation of an 8580 +// (affects combined waveforms) +#undef EMUL_MOS8580 + + +class Prefs; +class C64; +class SIDRenderer; +struct MOS6581State; + +// Class for administrative functions +class MOS6581 { +public: + MOS6581(C64 *c64); + ~MOS6581(); + + void Reset(void); + uint8 ReadRegister(uint16 adr); + void WriteRegister(uint16 adr, uint8 byte); + void NewPrefs(Prefs *prefs); + void PauseSound(void); + void ResumeSound(void); + void GetState(MOS6581State *ss); + void SetState(MOS6581State *ss); + void EmulateLine(void); + +private: + void open_close_renderer(int old_type, int new_type); + + C64 *the_c64; // Pointer to C64 object + SIDRenderer *the_renderer; // Pointer to current renderer + uint8 regs[32]; // Copies of the 25 write-only SID registers + uint8 last_sid_byte; // Last value written to SID +}; + + +// Renderers do the actual audio data processing +class SIDRenderer { +public: + virtual ~SIDRenderer() {} + virtual void Reset(void)=0; + virtual void EmulateLine(void)=0; + virtual void WriteRegister(uint16 adr, uint8 byte)=0; + virtual void NewPrefs(Prefs *prefs)=0; + virtual void Pause(void)=0; + virtual void Resume(void)=0; +}; + + +// SID state +struct MOS6581State { + uint8 freq_lo_1; + uint8 freq_hi_1; + uint8 pw_lo_1; + uint8 pw_hi_1; + uint8 ctrl_1; + uint8 AD_1; + uint8 SR_1; + + uint8 freq_lo_2; + uint8 freq_hi_2; + uint8 pw_lo_2; + uint8 pw_hi_2; + uint8 ctrl_2; + uint8 AD_2; + uint8 SR_2; + + uint8 freq_lo_3; + uint8 freq_hi_3; + uint8 pw_lo_3; + uint8 pw_hi_3; + uint8 ctrl_3; + uint8 AD_3; + uint8 SR_3; + + uint8 fc_lo; + uint8 fc_hi; + uint8 res_filt; + uint8 mode_vol; + + uint8 pot_x; + uint8 pot_y; + uint8 osc_3; + uint8 env_3; +}; + + +/* + * Fill buffer (for Unix sound routines), sample volume (for sampled voice) + */ + +inline void MOS6581::EmulateLine(void) +{ + if (the_renderer != NULL) + the_renderer->EmulateLine(); +} + + +/* + * Read from register + */ + +inline uint8 MOS6581::ReadRegister(uint16 adr) +{ + // A/D converters + if (adr == 0x19 || adr == 0x1a) { + last_sid_byte = 0; + return 0xff; + } + + // Voice 3 oscillator/EG readout + if (adr == 0x1b || adr == 0x1c) { + last_sid_byte = 0; + return rand(); + } + + // Write-only register: Return last value written to SID + return last_sid_byte; +} + + +/* + * Write to register + */ + +inline void MOS6581::WriteRegister(uint16 adr, uint8 byte) +{ + // Keep a local copy of the register values + last_sid_byte = regs[adr] = byte; + + if (the_renderer != NULL) + the_renderer->WriteRegister(adr, byte); +} + +#endif diff --git a/arm9/source/VIC.cpp b/arm9/source/VIC.cpp new file mode 100644 index 0000000..4cc5de1 --- /dev/null +++ b/arm9/source/VIC.cpp @@ -0,0 +1,1675 @@ +// ===================================================================================== +// GimliDS Copyright (c) 2025 Dave Bernazzani (wavemotion-dave) +// +// As GimliDS is a port of the Frodo emulator for the DS/DSi/XL/LL handhelds, +// any copying or distribution of this emulator, its source code and associated +// readme files, with or without modification, are permitted per the original +// Frodo emulator license shown below. Hugest thanks to Christian Bauer for his +// efforts to provide a clean open-source emulation base for the C64. +// +// Numerous hacks and 'unsafe' optimizations have been performed on the original +// Frodo emulator codebase to get it running on the small handheld system. You +// are strongly encouraged to seek out the official Frodo sources if you're at +// all interested in this emulator code. +// +// The GimliDS emulator is offered as-is, without any warranty. Please see readme.md +// ===================================================================================== + +/* + * VIC.cpp - 6569R5 emulation (line based) + * + * Frodo Copyright (C) Christian Bauer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Notes: + * ------ + * + * - The EmulateLine() function is called for every emulated + * raster line. It computes one pixel row of the graphics + * according to the current VIC register settings and returns + * the number of cycles available for the CPU in that line. + * - The graphics are output into an 8 bit chunky bitmap + * - The sprite-graphics priority handling and collision + * detection is done in a bit-oriented way with masks. + * The foreground/background pixel mask for the graphics + * is stored in the fore_mask_buf[] array. Multicolor + * sprites are converted from their original chunky format + * to a bitplane representation (two bit masks) for easier + * handling of priorities and collisions. + * - The sprite-sprite priority handling and collision + * detection is done in with the byte array spr_coll_buf[], + * that is used to keep track of which sprites are already + * visible at certain X positions. + * + * Incompatibilities: + * ------------------ + * + * - Raster effects that are achieved by modifying VIC registers + * in the middle of a raster line cannot be emulated + * - Sprite collisions are only detected within the visible + * screen area (excluding borders) + * - Sprites are only drawn if they completely fit within the + * left/right limits of the chunky bitmap + * - The Char ROM is not visible in the bitmap displays at + * addresses $0000 and $8000 + * - The IRQ is cleared on every write access to the flag + * register. This is a hack for the RMW instructions of the + * 6510 that first write back the original value. + */ +#include +#include "sysdeps.h" + +#include "VIC.h" +#include "C64.h" +#include "CPUC64.h" +#include "Display.h" +#include "mainmenu.h" +#include "Prefs.h" + +// First and last displayed line +const unsigned FIRST_DISP_LINE = 0x10; +const unsigned LAST_DISP_LINE = 0x110; + +// First and last possible line for Bad Lines +const unsigned FIRST_DMA_LINE = 0x30; +const unsigned LAST_DMA_LINE = 0xf7; + +// Display window coordinates +const int ROW25_YSTART = 0x33; +const int ROW25_YSTOP = 0xfb; +const int ROW24_YSTART = 0x37; +const int ROW24_YSTOP = 0xf7; + +const int COL40_XSTART = 0x20; +const int COL40_XSTOP = 0x160; +const int COL38_XSTART = 0x27; +const int COL38_XSTOP = 0x157; + + + +// Tables for sprite X expansion +uint16 ExpTable[256] __attribute__((section(".dtcm"))) = { + 0x0000, 0x0003, 0x000C, 0x000F, 0x0030, 0x0033, 0x003C, 0x003F, + 0x00C0, 0x00C3, 0x00CC, 0x00CF, 0x00F0, 0x00F3, 0x00FC, 0x00FF, + 0x0300, 0x0303, 0x030C, 0x030F, 0x0330, 0x0333, 0x033C, 0x033F, + 0x03C0, 0x03C3, 0x03CC, 0x03CF, 0x03F0, 0x03F3, 0x03FC, 0x03FF, + 0x0C00, 0x0C03, 0x0C0C, 0x0C0F, 0x0C30, 0x0C33, 0x0C3C, 0x0C3F, + 0x0CC0, 0x0CC3, 0x0CCC, 0x0CCF, 0x0CF0, 0x0CF3, 0x0CFC, 0x0CFF, + 0x0F00, 0x0F03, 0x0F0C, 0x0F0F, 0x0F30, 0x0F33, 0x0F3C, 0x0F3F, + 0x0FC0, 0x0FC3, 0x0FCC, 0x0FCF, 0x0FF0, 0x0FF3, 0x0FFC, 0x0FFF, + 0x3000, 0x3003, 0x300C, 0x300F, 0x3030, 0x3033, 0x303C, 0x303F, + 0x30C0, 0x30C3, 0x30CC, 0x30CF, 0x30F0, 0x30F3, 0x30FC, 0x30FF, + 0x3300, 0x3303, 0x330C, 0x330F, 0x3330, 0x3333, 0x333C, 0x333F, + 0x33C0, 0x33C3, 0x33CC, 0x33CF, 0x33F0, 0x33F3, 0x33FC, 0x33FF, + 0x3C00, 0x3C03, 0x3C0C, 0x3C0F, 0x3C30, 0x3C33, 0x3C3C, 0x3C3F, + 0x3CC0, 0x3CC3, 0x3CCC, 0x3CCF, 0x3CF0, 0x3CF3, 0x3CFC, 0x3CFF, + 0x3F00, 0x3F03, 0x3F0C, 0x3F0F, 0x3F30, 0x3F33, 0x3F3C, 0x3F3F, + 0x3FC0, 0x3FC3, 0x3FCC, 0x3FCF, 0x3FF0, 0x3FF3, 0x3FFC, 0x3FFF, + 0xC000, 0xC003, 0xC00C, 0xC00F, 0xC030, 0xC033, 0xC03C, 0xC03F, + 0xC0C0, 0xC0C3, 0xC0CC, 0xC0CF, 0xC0F0, 0xC0F3, 0xC0FC, 0xC0FF, + 0xC300, 0xC303, 0xC30C, 0xC30F, 0xC330, 0xC333, 0xC33C, 0xC33F, + 0xC3C0, 0xC3C3, 0xC3CC, 0xC3CF, 0xC3F0, 0xC3F3, 0xC3FC, 0xC3FF, + 0xCC00, 0xCC03, 0xCC0C, 0xCC0F, 0xCC30, 0xCC33, 0xCC3C, 0xCC3F, + 0xCCC0, 0xCCC3, 0xCCCC, 0xCCCF, 0xCCF0, 0xCCF3, 0xCCFC, 0xCCFF, + 0xCF00, 0xCF03, 0xCF0C, 0xCF0F, 0xCF30, 0xCF33, 0xCF3C, 0xCF3F, + 0xCFC0, 0xCFC3, 0xCFCC, 0xCFCF, 0xCFF0, 0xCFF3, 0xCFFC, 0xCFFF, + 0xF000, 0xF003, 0xF00C, 0xF00F, 0xF030, 0xF033, 0xF03C, 0xF03F, + 0xF0C0, 0xF0C3, 0xF0CC, 0xF0CF, 0xF0F0, 0xF0F3, 0xF0FC, 0xF0FF, + 0xF300, 0xF303, 0xF30C, 0xF30F, 0xF330, 0xF333, 0xF33C, 0xF33F, + 0xF3C0, 0xF3C3, 0xF3CC, 0xF3CF, 0xF3F0, 0xF3F3, 0xF3FC, 0xF3FF, + 0xFC00, 0xFC03, 0xFC0C, 0xFC0F, 0xFC30, 0xFC33, 0xFC3C, 0xFC3F, + 0xFCC0, 0xFCC3, 0xFCCC, 0xFCCF, 0xFCF0, 0xFCF3, 0xFCFC, 0xFCFF, + 0xFF00, 0xFF03, 0xFF0C, 0xFF0F, 0xFF30, 0xFF33, 0xFF3C, 0xFF3F, + 0xFFC0, 0xFFC3, 0xFFCC, 0xFFCF, 0xFFF0, 0xFFF3, 0xFFFC, 0xFFFF +}; + +uint16 MultiExpTable[256] __attribute__((section(".dtcm"))) = { + 0x0000, 0x0005, 0x000A, 0x000F, 0x0050, 0x0055, 0x005A, 0x005F, + 0x00A0, 0x00A5, 0x00AA, 0x00AF, 0x00F0, 0x00F5, 0x00FA, 0x00FF, + 0x0500, 0x0505, 0x050A, 0x050F, 0x0550, 0x0555, 0x055A, 0x055F, + 0x05A0, 0x05A5, 0x05AA, 0x05AF, 0x05F0, 0x05F5, 0x05FA, 0x05FF, + 0x0A00, 0x0A05, 0x0A0A, 0x0A0F, 0x0A50, 0x0A55, 0x0A5A, 0x0A5F, + 0x0AA0, 0x0AA5, 0x0AAA, 0x0AAF, 0x0AF0, 0x0AF5, 0x0AFA, 0x0AFF, + 0x0F00, 0x0F05, 0x0F0A, 0x0F0F, 0x0F50, 0x0F55, 0x0F5A, 0x0F5F, + 0x0FA0, 0x0FA5, 0x0FAA, 0x0FAF, 0x0FF0, 0x0FF5, 0x0FFA, 0x0FFF, + 0x5000, 0x5005, 0x500A, 0x500F, 0x5050, 0x5055, 0x505A, 0x505F, + 0x50A0, 0x50A5, 0x50AA, 0x50AF, 0x50F0, 0x50F5, 0x50FA, 0x50FF, + 0x5500, 0x5505, 0x550A, 0x550F, 0x5550, 0x5555, 0x555A, 0x555F, + 0x55A0, 0x55A5, 0x55AA, 0x55AF, 0x55F0, 0x55F5, 0x55FA, 0x55FF, + 0x5A00, 0x5A05, 0x5A0A, 0x5A0F, 0x5A50, 0x5A55, 0x5A5A, 0x5A5F, + 0x5AA0, 0x5AA5, 0x5AAA, 0x5AAF, 0x5AF0, 0x5AF5, 0x5AFA, 0x5AFF, + 0x5F00, 0x5F05, 0x5F0A, 0x5F0F, 0x5F50, 0x5F55, 0x5F5A, 0x5F5F, + 0x5FA0, 0x5FA5, 0x5FAA, 0x5FAF, 0x5FF0, 0x5FF5, 0x5FFA, 0x5FFF, + 0xA000, 0xA005, 0xA00A, 0xA00F, 0xA050, 0xA055, 0xA05A, 0xA05F, + 0xA0A0, 0xA0A5, 0xA0AA, 0xA0AF, 0xA0F0, 0xA0F5, 0xA0FA, 0xA0FF, + 0xA500, 0xA505, 0xA50A, 0xA50F, 0xA550, 0xA555, 0xA55A, 0xA55F, + 0xA5A0, 0xA5A5, 0xA5AA, 0xA5AF, 0xA5F0, 0xA5F5, 0xA5FA, 0xA5FF, + 0xAA00, 0xAA05, 0xAA0A, 0xAA0F, 0xAA50, 0xAA55, 0xAA5A, 0xAA5F, + 0xAAA0, 0xAAA5, 0xAAAA, 0xAAAF, 0xAAF0, 0xAAF5, 0xAAFA, 0xAAFF, + 0xAF00, 0xAF05, 0xAF0A, 0xAF0F, 0xAF50, 0xAF55, 0xAF5A, 0xAF5F, + 0xAFA0, 0xAFA5, 0xAFAA, 0xAFAF, 0xAFF0, 0xAFF5, 0xAFFA, 0xAFFF, + 0xF000, 0xF005, 0xF00A, 0xF00F, 0xF050, 0xF055, 0xF05A, 0xF05F, + 0xF0A0, 0xF0A5, 0xF0AA, 0xF0AF, 0xF0F0, 0xF0F5, 0xF0FA, 0xF0FF, + 0xF500, 0xF505, 0xF50A, 0xF50F, 0xF550, 0xF555, 0xF55A, 0xF55F, + 0xF5A0, 0xF5A5, 0xF5AA, 0xF5AF, 0xF5F0, 0xF5F5, 0xF5FA, 0xF5FF, + 0xFA00, 0xFA05, 0xFA0A, 0xFA0F, 0xFA50, 0xFA55, 0xFA5A, 0xFA5F, + 0xFAA0, 0xFAA5, 0xFAAA, 0xFAAF, 0xFAF0, 0xFAF5, 0xFAFA, 0xFAFF, + 0xFF00, 0xFF05, 0xFF0A, 0xFF0F, 0xFF50, 0xFF55, 0xFF5A, 0xFF5F, + 0xFFA0, 0xFFA5, 0xFFAA, 0xFFAF, 0xFFF0, 0xFFF5, 0xFFFA, 0xFFFF +}; + +static union { + struct { + uint8 a,b,c,d; + } a; + uint32 b; +} TextColorTable[16][16][16]; + +#ifdef GLOBAL_VARS +static uint16 mc_color_lookup[4] __attribute__((section(".dtcm"))); +static uint8 text_chunky_buf[40*8] __attribute__((section(".dtcm"))); +static uint16 mx[8] __attribute__((section(".dtcm"))); +static uint8 mx8 __attribute__((section(".dtcm"))); +static uint8 my[8] __attribute__((section(".dtcm"))); +static uint8 ctrl1 __attribute__((section(".dtcm"))); +static uint8 ctrl2 __attribute__((section(".dtcm"))); +static uint8 lpx __attribute__((section(".dtcm"))); +static uint8 lpy __attribute__((section(".dtcm"))); +static uint8 me __attribute__((section(".dtcm"))); +static uint8 mxe __attribute__((section(".dtcm"))); +static uint8 mye __attribute__((section(".dtcm"))); +static uint8 mdp __attribute__((section(".dtcm"))); +static uint8 mmc __attribute__((section(".dtcm"))); +static uint8 vbase __attribute__((section(".dtcm"))); +static uint8 irq_flag __attribute__((section(".dtcm"))); +static uint8 irq_mask __attribute__((section(".dtcm"))); +static uint8 clx_spr __attribute__((section(".dtcm"))); +static uint8 clx_bgr __attribute__((section(".dtcm"))); +static uint8 ec __attribute__((section(".dtcm"))); +static uint8 b0c __attribute__((section(".dtcm"))); +static uint8 b1c __attribute__((section(".dtcm"))); +static uint8 b2c __attribute__((section(".dtcm"))); +static uint8 b3c __attribute__((section(".dtcm"))); +static uint8 mm0 __attribute__((section(".dtcm"))); +static uint8 mm1 __attribute__((section(".dtcm"))); + +static uint8 sc[8] __attribute__((section(".dtcm"))); + +static uint8 *ram __attribute__((section(".dtcm"))); +static uint8 *char_rom __attribute__((section(".dtcm"))); +static uint8 *color_ram __attribute__((section(".dtcm"))); // Pointers to RAM and ROM + +static C64 *the_c64 __attribute__((section(".dtcm"))); // Pointer to C64 +static C64Display *the_display __attribute__((section(".dtcm"))); // Pointer to C64Display +static MOS6510 *the_cpu __attribute__((section(".dtcm"))); // Pointer to 6510 + +static uint8 colors[256] __attribute__((section(".dtcm"))); // Indices of the 16 C64 colors (16 times mirrored to avoid "& 0x0f") + +static uint8 ec_color __attribute__((section(".dtcm"))); +static uint8 b0c_color __attribute__((section(".dtcm"))); +static uint8 b1c_color __attribute__((section(".dtcm"))); +static uint8 b2c_color __attribute__((section(".dtcm"))); +static uint8 b3c_color __attribute__((section(".dtcm"))); + +static uint8 mm0_color __attribute__((section(".dtcm"))); +static uint8 mm1_color __attribute__((section(".dtcm"))); // Indices for MOB multicolors +static uint8 spr_color[8] __attribute__((section(".dtcm"))); // Indices for MOB colors +static uint32 ec_color_long __attribute__((section(".dtcm"))); // ec_color expanded to 32 bits + +static uint8 matrix_line[40] __attribute__((section(".dtcm"))); // Buffer for video line, read in Bad Lines +static uint8 color_line[40] __attribute__((section(".dtcm"))); // Buffer for color line, read in Bad Lines + +static uint8 *chunky_line_start __attribute__((section(".dtcm"))); // Pointer to start of current line in bitmap buffer +static int xmod __attribute__((section(".dtcm"))); // Number of bytes per row + +static uint8 *matrix_base __attribute__((section(".dtcm"))); // Video matrix base +static uint8 *char_base __attribute__((section(".dtcm"))); // Character generator base +static uint8 *bitmap_base __attribute__((section(".dtcm"))); // Bitmap base + +static uint16 raster_y __attribute__((section(".dtcm"))); // Current raster line +static uint16 irq_raster __attribute__((section(".dtcm"))); // Interrupt raster line +static uint16 dy_start __attribute__((section(".dtcm"))); // Comparison values for border logic +static uint16 dy_stop __attribute__((section(".dtcm"))); +static uint16 rc __attribute__((section(".dtcm"))); // Row counter +static uint16 vc __attribute__((section(".dtcm"))); // Video counter +static uint16 vc_base __attribute__((section(".dtcm"))); // Video counter base +static uint16 x_scroll __attribute__((section(".dtcm"))); // X scroll value +static uint16 y_scroll __attribute__((section(".dtcm"))); +static uint16 cia_vabase __attribute__((section(".dtcm"))); // CIA VA14/15 video base + +static int display_idx __attribute__((section(".dtcm"))); // Index of current display mode +static int skip_counter __attribute__((section(".dtcm"))); // Counter for frame-skipping +static uint32 mc[8] __attribute__((section(".dtcm"))); // Sprite data counters +static uint8 sprite_on __attribute__((section(".dtcm"))); // 8 Flags: Sprite display/DMA active + +static uint8 spr_coll_buf[DISPLAY_X+48] __attribute__((section(".dtcm"))); // Buffer for sprite-sprite collisions and priorities +static uint8 fore_mask_buf[DISPLAY_X/8] __attribute__((section(".dtcm"))); // Foreground mask for sprite-graphics collisions and priorities + +static bool display_state __attribute__((section(".dtcm"))); // true: Display state, false: Idle state +static bool border_on __attribute__((section(".dtcm"))); // Flag: Upper/lower border on +static bool border_40_col __attribute__((section(".dtcm"))); // Flag: 40 column border +static bool frame_skipped __attribute__((section(".dtcm"))); // Flag: Frame is being skipped +static uint8 bad_lines_enabled __attribute__((section(".dtcm"))); // Flag: Bad Lines enabled for this frame +static bool lp_triggered __attribute__((section(".dtcm"))); // Flag: Lightpen was triggered in this frame +#endif + + +/* + * Constructor: Initialize variables + */ + +static void init_text_color_table(uint8 *colors) +{ + for (int i = 0; i < 16; i++) + for (int j = 0; j < 16; j++) + for (int k = 0; k < 16; k++) { + TextColorTable[i][j][k].a.a = colors[k & 8 ? i : j]; + TextColorTable[i][j][k].a.b = colors[k & 4 ? i : j]; + TextColorTable[i][j][k].a.c = colors[k & 2 ? i : j]; + TextColorTable[i][j][k].a.d = colors[k & 1 ? i : j]; + } +} + +MOS6569::MOS6569(C64 *c64, C64Display *disp, MOS6510 *CPU, uint8 *RAM, uint8 *Char, uint8 *Color) +#ifndef GLOBAL_VARS + : char_rom(Char), color_ram(Color), the_c64(c64), the_display(disp), the_cpu(CPU) +#endif +{ + int i; + + // Set pointers +#ifdef GLOBAL_VARS + the_c64 = c64; + the_display = disp; + the_cpu = CPU; + ram = RAM; + char_rom = Char; + color_ram = Color; +#endif + matrix_base = RAM; + char_base = RAM; + bitmap_base = RAM; + + // Get bitmap info + chunky_line_start = disp->BitmapBase(); + xmod = disp->BitmapXMod(); + + // Initialize VIC registers + mx8 = 0; + ctrl1 = ctrl2 = 0; + lpx = lpy = 0; + me = mxe = mye = mdp = mmc = 0; + vbase = irq_flag = irq_mask = 0; + clx_spr = clx_bgr = 0; + cia_vabase = 0; + ec = b0c = b1c = b2c = b3c = mm0 = mm1 = 0; + for (i=0; i<8; i++) mx[i] = my[i] = sc[i] = 0; + + // Initialize other variables + raster_y = 0xffff; + rc = 7; + irq_raster = vc = vc_base = x_scroll = y_scroll = 0; + dy_start = ROW24_YSTART; + dy_stop = ROW24_YSTOP; + + display_idx = 0; + display_state = false; + border_on = false; + lp_triggered = false; + + sprite_on = 0; + for (i=0; i<8; i++) + mc[i] = 21; + + frame_skipped = false; + skip_counter = 1; + + // Clear foreground mask + memset(fore_mask_buf, 0, DISPLAY_X/8); + + // Preset colors to black + disp->InitColors(colors); + init_text_color_table(colors); + ec_color = b0c_color = b1c_color = b2c_color = b3c_color = mm0_color = mm1_color = colors[0]; + ec_color_long = (ec_color << 24) | (ec_color << 16) | (ec_color << 8) | ec_color; + for (i=0; i<8; i++) spr_color[i] = colors[0]; +} + + + + +#ifdef GLOBAL_VARS +static void make_mc_table(void) +#else +void MOS6569::make_mc_table(void) +#endif +{ + mc_color_lookup[0] = b0c_color | (b0c_color << 8); + mc_color_lookup[1] = b1c_color | (b1c_color << 8); + mc_color_lookup[2] = b2c_color | (b2c_color << 8); +} + + +/* + * Convert video address to pointer + */ + +#ifdef GLOBAL_VARS +inline uint8 *get_physical(uint16 adr) +#else +inline uint8 *MOS6569::get_physical(uint16 adr) +#endif +{ + int va = adr | cia_vabase; + if ((va & 0x7000) == 0x1000) + return char_rom + (va & 0x0fff); + else + return ram + va; +} + + +/* + * Get VIC state + */ + +void MOS6569::GetState(MOS6569State *vd) +{ + int i; + + vd->m0x = mx[0] & 0xff; vd->m0y = my[0]; + vd->m1x = mx[1] & 0xff; vd->m1y = my[1]; + vd->m2x = mx[2] & 0xff; vd->m2y = my[2]; + vd->m3x = mx[3] & 0xff; vd->m3y = my[3]; + vd->m4x = mx[4] & 0xff; vd->m4y = my[4]; + vd->m5x = mx[5] & 0xff; vd->m5y = my[5]; + vd->m6x = mx[6] & 0xff; vd->m6y = my[6]; + vd->m7x = mx[7] & 0xff; vd->m7y = my[7]; + vd->mx8 = mx8; + + vd->ctrl1 = (ctrl1 & 0x7f) | ((raster_y & 0x100) >> 1); + vd->raster = raster_y & 0xff; + vd->lpx = lpx; vd->lpy = lpy; + vd->ctrl2 = ctrl2; + vd->vbase = vbase; + vd->irq_flag = irq_flag; + vd->irq_mask = irq_mask; + + vd->me = me; vd->mxe = mxe; vd->mye = mye; vd->mdp = mdp; vd->mmc = mmc; + vd->mm = clx_spr; vd->md = clx_bgr; + + vd->ec = ec; + vd->b0c = b0c; vd->b1c = b1c; vd->b2c = b2c; vd->b3c = b3c; + vd->mm0 = mm0; vd->mm1 = mm1; + vd->m0c = sc[0]; vd->m1c = sc[1]; + vd->m2c = sc[2]; vd->m3c = sc[3]; + vd->m4c = sc[4]; vd->m5c = sc[5]; + vd->m6c = sc[6]; vd->m7c = sc[7]; + + vd->pad0 = 0; + vd->irq_raster = irq_raster; + vd->vc = vc; + vd->vc_base = vc_base; + vd->rc = rc; + vd->spr_dma = vd->spr_disp = sprite_on; + for (i=0; i<8; i++) + vd->mc[i] = vd->mc_base[i] = mc[i]; + vd->display_state = display_state; + vd->bad_line = raster_y >= FIRST_DMA_LINE && raster_y <= LAST_DMA_LINE && ((raster_y & 7) == y_scroll) && bad_lines_enabled; + vd->bad_line_enable = bad_lines_enabled; + vd->lp_triggered = lp_triggered; + vd->border_on = border_on; + + vd->bank_base = cia_vabase; + vd->matrix_base = ((vbase & 0xf0) << 6) | cia_vabase; + vd->char_base = ((vbase & 0x0e) << 10) | cia_vabase; + vd->bitmap_base = ((vbase & 0x08) << 10) | cia_vabase; + for (i=0; i<8; i++) + vd->sprite_base[i] = (matrix_base[0x3f8 + i] << 6) | cia_vabase; + + vd->cycle = 1; + vd->raster_x = 0; + vd->ml_index = 0; + vd->ref_cnt = 0xff; + vd->last_vic_byte = 0; + vd->ud_border_on = border_on; +} + + +/* + * Set VIC state (only works if in VBlank) + */ + +void MOS6569::SetState(MOS6569State *vd) +{ + int i, j; + + mx[0] = vd->m0x; my[0] = vd->m0y; + mx[1] = vd->m1x; my[1] = vd->m1y; + mx[2] = vd->m2x; my[2] = vd->m2y; + mx[3] = vd->m3x; my[3] = vd->m3y; + mx[4] = vd->m4x; my[4] = vd->m4y; + mx[5] = vd->m5x; my[5] = vd->m5y; + mx[6] = vd->m6x; my[6] = vd->m6y; + mx[7] = vd->m7x; my[7] = vd->m7y; + mx8 = vd->mx8; + for (i=0, j=1; i<8; i++, j<<=1) { + if (mx8 & j) + mx[i] |= 0x100; + else + mx[i] &= 0xff; + } + + ctrl1 = vd->ctrl1; + ctrl2 = vd->ctrl2; + x_scroll = ctrl2 & 7; + y_scroll = ctrl1 & 7; + if (ctrl1 & 8) { + dy_start = ROW25_YSTART; + dy_stop = ROW25_YSTOP; + } else { + dy_start = ROW24_YSTART; + dy_stop = ROW24_YSTOP; + } + border_40_col = ctrl2 & 8; + display_idx = ((ctrl1 & 0x60) | (ctrl2 & 0x10)) >> 4; + + raster_y = vd->raster | ((vd->ctrl1 & 0x80) << 1); + lpx = vd->lpx; lpy = vd->lpy; + + vbase = vd->vbase; + cia_vabase = vd->bank_base; + matrix_base = get_physical((vbase & 0xf0) << 6); + char_base = get_physical((vbase & 0x0e) << 10); + bitmap_base = get_physical((vbase & 0x08) << 10); + + irq_flag = vd->irq_flag; + irq_mask = vd->irq_mask; + + me = vd->me; mxe = vd->mxe; mye = vd->mye; mdp = vd->mdp; mmc = vd->mmc; + clx_spr = vd->mm; clx_bgr = vd->md; + + ec = vd->ec; + ec_color = colors[ec]; + ec_color_long = (ec_color << 24) | (ec_color << 16) | (ec_color << 8) | ec_color; + + b0c = vd->b0c; b1c = vd->b1c; b2c = vd->b2c; b3c = vd->b3c; + b0c_color = colors[b0c]; + b1c_color = colors[b1c]; + b2c_color = colors[b2c]; + b3c_color = colors[b3c]; + make_mc_table(); + + mm0 = vd->mm0; mm1 = vd->mm1; + mm0_color = colors[mm0]; + mm1_color = colors[mm1]; + + sc[0] = vd->m0c; sc[1] = vd->m1c; + sc[2] = vd->m2c; sc[3] = vd->m3c; + sc[4] = vd->m4c; sc[5] = vd->m5c; + sc[6] = vd->m6c; sc[7] = vd->m7c; + for (i=0; i<8; i++) + spr_color[i] = colors[sc[i]]; + + irq_raster = vd->irq_raster; + vc = vd->vc; + vc_base = vd->vc_base; + rc = vd->rc; + sprite_on = vd->spr_dma; + for (i=0; i<8; i++) + mc[i] = vd->mc[i]; + display_state = vd->display_state; + bad_lines_enabled = vd->bad_line_enable; + lp_triggered = vd->lp_triggered; + border_on = vd->border_on; +} + + +/* + * Trigger raster IRQ + */ + +#ifdef GLOBAL_VARS +static inline void raster_irq(void) +#else +inline void MOS6569::raster_irq(void) +#endif +{ + irq_flag |= 0x01; + if (irq_mask & 0x01) { + irq_flag |= 0x80; + the_cpu->TriggerVICIRQ(); + } +} + + +/* + * Read from VIC register + */ + +ITCM_CODE uint8 MOS6569::ReadRegister(uint16 adr) +{ + switch (adr) { + case 0x00: case 0x02: case 0x04: case 0x06: + case 0x08: case 0x0a: case 0x0c: case 0x0e: + return mx[adr >> 1]; + + case 0x01: case 0x03: case 0x05: case 0x07: + case 0x09: case 0x0b: case 0x0d: case 0x0f: + return my[adr >> 1]; + + case 0x10: // Sprite X position MSB + return mx8; + + case 0x11: // Control register 1 + return (ctrl1 & 0x7f) | ((raster_y & 0x100) >> 1); + + case 0x12: // Raster counter + return raster_y; + + case 0x13: // Light pen X + return lpx; + + case 0x14: // Light pen Y + return lpy; + + case 0x15: // Sprite enable + return me; + + case 0x16: // Control register 2 + return ctrl2 | 0xc0; + + case 0x17: // Sprite Y expansion + return mye; + + case 0x18: // Memory pointers + return vbase | 0x01; + + case 0x19: // IRQ flags + return irq_flag | 0x70; + + case 0x1a: // IRQ mask + return irq_mask | 0xf0; + + case 0x1b: // Sprite data priority + return mdp; + + case 0x1c: // Sprite multicolor + return mmc; + + case 0x1d: // Sprite X expansion + return mxe; + + case 0x1e:{ // Sprite-sprite collision + uint8 ret = clx_spr; + clx_spr = 0; // Read and clear + return ret; + } + + case 0x1f:{ // Sprite-background collision + uint8 ret = clx_bgr; + clx_bgr = 0; // Read and clear + return ret; + } + + case 0x20: return ec | 0xf0; + case 0x21: return b0c | 0xf0; + case 0x22: return b1c | 0xf0; + case 0x23: return b2c | 0xf0; + case 0x24: return b3c | 0xf0; + case 0x25: return mm0 | 0xf0; + case 0x26: return mm1 | 0xf0; + + case 0x27: case 0x28: case 0x29: case 0x2a: + case 0x2b: case 0x2c: case 0x2d: case 0x2e: + return sc[adr - 0x27] | 0xf0; + + default: + return 0xff; + } +} + + +/* + * Write to VIC register + */ +ITCM_CODE void MOS6569::WriteRegister(uint16 adr, uint8 byte) +{ + switch (adr) { + case 0x00: case 0x02: case 0x04: case 0x06: + case 0x08: case 0x0a: case 0x0c: case 0x0e: + mx[adr >> 1] = (mx[adr >> 1] & 0xff00) | byte; + break; + + case 0x10:{ + int i, j; + mx8 = byte; + for (i=0, j=1; i<8; i++, j<<=1) { + if (mx8 & j) + mx[i] |= 0x100; + else + mx[i] &= 0xff; + } + break; + } + + case 0x01: case 0x03: case 0x05: case 0x07: + case 0x09: case 0x0b: case 0x0d: case 0x0f: + my[adr >> 1] = byte; + break; + + case 0x11:{ // Control register 1 + ctrl1 = byte; + y_scroll = byte & 7; + + uint16 new_irq_raster = (irq_raster & 0xff) | ((byte & 0x80) << 1); + if (irq_raster != new_irq_raster && raster_y == new_irq_raster) + raster_irq(); + irq_raster = new_irq_raster; + + if (byte & 8) { + dy_start = ROW25_YSTART; + dy_stop = ROW25_YSTOP; + } else { + dy_start = ROW24_YSTART; + dy_stop = ROW24_YSTOP; + } + + display_idx = ((ctrl1 & 0x60) | (ctrl2 & 0x10)) >> 4; + break; + } + + case 0x12:{ // Raster counter + uint16 new_irq_raster = (irq_raster & 0xff00) | byte; + if (irq_raster != new_irq_raster && raster_y == new_irq_raster) + raster_irq(); + irq_raster = new_irq_raster; + break; + } + + case 0x15: // Sprite enable + me = byte; + break; + + case 0x16: // Control register 2 + ctrl2 = byte; + x_scroll = byte & 7; + border_40_col = byte & 8; + display_idx = ((ctrl1 & 0x60) | (ctrl2 & 0x10)) >> 4; + break; + + case 0x17: // Sprite Y expansion + mye = byte; + break; + + case 0x18: // Memory pointers + vbase = byte; + matrix_base = get_physical((byte & 0xf0) << 6); + char_base = get_physical((byte & 0x0e) << 10); + bitmap_base = get_physical((byte & 0x08) << 10); + break; + + case 0x19: // IRQ flags + irq_flag = irq_flag & (~byte & 0x0f); + the_cpu->ClearVICIRQ(); // Clear interrupt (hack!) + if (irq_flag & irq_mask) // Set master bit if allowed interrupt still pending + irq_flag |= 0x80; + break; + + case 0x1a: // IRQ mask + irq_mask = byte & 0x0f; + if (irq_flag & irq_mask) { // Trigger interrupt if pending and now allowed + irq_flag |= 0x80; + the_cpu->TriggerVICIRQ(); + } else { + irq_flag &= 0x7f; + the_cpu->ClearVICIRQ(); + } + break; + + case 0x1b: // Sprite data priority + mdp = byte; + break; + + case 0x1c: // Sprite multicolor + mmc = byte; + break; + + case 0x1d: // Sprite X expansion + mxe = byte; + break; + + case 0x20: + extern uint8_t palette_red[16]; + extern uint8_t palette_green[16]; + extern uint8_t palette_blue[16]; + ec_color = colors[ec = byte]; + ec_color_long = (ec_color << 24) | (ec_color << 16) | (ec_color << 8) | ec_color; + BG_PALETTE_SUB[1]=RGB15(palette_red[ec_color]>>3,palette_green[ec_color]>>3,palette_blue[ec_color]>>3); + break; + + case 0x21: + if (b0c != byte) { + b0c_color = colors[b0c = byte & 0xF]; + make_mc_table(); + } + break; + + case 0x22: + if (b1c != byte) { + b1c_color = colors[b1c = byte & 0xF]; + make_mc_table(); + } + break; + + case 0x23: + if (b2c != byte) { + b2c_color = colors[b2c = byte & 0xF]; + make_mc_table(); + } + break; + + case 0x24: b3c_color = colors[b3c = byte & 0xF]; break; + case 0x25: mm0_color = colors[mm0 = byte]; break; + case 0x26: mm1_color = colors[mm1 = byte]; break; + + case 0x27: case 0x28: case 0x29: case 0x2a: + case 0x2b: case 0x2c: case 0x2d: case 0x2e: + spr_color[adr - 0x27] = colors[sc[adr - 0x27] = byte]; + break; + } +} + + +/* + * CIA VA14/15 has changed + */ + +void MOS6569::ChangedVA(uint16 new_va) +{ + cia_vabase = new_va << 14; + WriteRegister(0x18, vbase); // Force update of memory pointers +} + + +/* + * Trigger lightpen interrupt, latch lightpen coordinates + */ + +void MOS6569::TriggerLightpen(void) +{ + if (!lp_triggered) { // Lightpen triggers only once per frame + lp_triggered = true; + + lpx = 0; // Latch current coordinates + lpy = raster_y; + + irq_flag |= 0x08; // Trigger IRQ + if (irq_mask & 0x08) { + irq_flag |= 0x80; + the_cpu->TriggerVICIRQ(); + } + } +} + + +/* + * VIC vertical blank: Reset counters and redraw screen + */ + +#ifdef GLOBAL_VARS +static inline void vblank(void) +#else +inline void MOS6569::vblank(void) +#endif +{ + raster_y = vc_base = 0; + lp_triggered = false; + + if (!(frame_skipped = --skip_counter)) + { + skip_counter = ThePrefs.DrawEveryN; + } + + the_c64->VBlank(!frame_skipped); + + // Get bitmap pointer for next frame. This must be done + // after calling the_c64->VBlank() because the preferences + // and screen configuration may have been changed there + chunky_line_start = the_display->BitmapBase(); + xmod = the_display->BitmapXMod(); +} + + +#ifdef GLOBAL_VARS +ITCM_CODE void el_std_text(uint8 *p, uint8 *q, uint8 *r) +#else +inline void MOS6569::el_std_text(uint8 *p, uint8 *q, uint8 *r) +#endif +{ + unsigned int b0cc = b0c; + uint32 *lp = (uint32 *)p; + uint8 *cp = color_line; + uint8 *mp = matrix_line; + u32 bgcolor = (b0cc << 24) | (b0cc << 16) | (b0cc << 8) | (b0cc << 0); + + // Loop for 40 characters + for (int i=0; i<40; i++) + { + uint8 data = r[i] = q[mp[i] << 3]; + + if (!data) + { + *lp++ = bgcolor; + *lp++ = bgcolor; + } + else + { + uint8 color = cp[i]; + *lp++ = TextColorTable[color][b0cc][data>>4].b; + *lp++ = TextColorTable[color][b0cc][data&0xf].b; + } + } +} + + +#ifdef GLOBAL_VARS +ITCM_CODE void el_mc_text(uint8 *p, uint8 *q, uint8 *r) +#else +inline void MOS6569::el_mc_text(uint8 *p, uint8 *q, uint8 *r) +#endif +{ + uint16 *wp = (uint16 *)p; + uint8 *cp = color_line; + uint8 *mp = matrix_line; + uint16 *mclp = mc_color_lookup; + u32 bgcolor = (mclp[0] << 24) | (mclp[0] << 16) | (mclp[0] << 8) | (mclp[0] << 0); + u32 bgcolor2 = (b0c << 24) | (b0c << 16) | (b0c << 8) | (b0c << 0); + + // Loop for 40 characters + for (int i=0; i<40; i++) + { + uint8 data = q[mp[i] << 3]; + + if (cp[i] & 8) { + r[i] = (data & 0xaa) | (data & 0xaa) >> 1; + if (!data) + { + *(uint32 *)wp = bgcolor; + wp += 2; + *(uint32 *)wp = bgcolor; + wp += 2; + } + else + { + uint8 color = colors[cp[i] & 7]; + mclp[3] = color | (color << 8); + *wp++ = mclp[(data >> 6) & 3]; + *wp++ = mclp[(data >> 4) & 3]; + *wp++ = mclp[(data >> 2) & 3]; + *wp++ = mclp[(data >> 0) & 3]; + } + + } else { // Standard mode in multicolor mode + r[i] = data; + if (!data) + { + *(uint32 *)wp = bgcolor2; + wp += 2; + *(uint32 *)wp = bgcolor2; + wp += 2; + } + else + { + uint8 color = cp[i]; + *(uint32 *)wp = TextColorTable[color][b0c][data>>4].b; + wp += 2; + *(uint32 *)wp = TextColorTable[color][b0c][data&0xf].b; + wp += 2; + } + } + } +} + + +#ifdef GLOBAL_VARS +void el_std_bitmap(uint8 *p, uint8 *q, uint8 *r) +#else +inline void MOS6569::el_std_bitmap(uint8 *p, uint8 *q, uint8 *r) +#endif +{ + uint32 *lp = (uint32 *)p; + uint8 *mp = matrix_line; + + // Loop for 40 characters + for (int i=0; i<40; i++, q+=8) + { + uint8 data = r[i] = *q; + uint8 color = mp[i] >> 4; + uint8 bcolor = mp[i] & 15; + + *lp++ = TextColorTable[color][bcolor][data>>4].b; + *lp++ = TextColorTable[color][bcolor][data&0xf].b; + } +} + + +#ifdef GLOBAL_VARS +void el_mc_bitmap(uint8 *p, uint8 *q, uint8 *r) +#else +inline void MOS6569::el_mc_bitmap(uint8 *p, uint8 *q, uint8 *r) +#endif +{ + uint16 lookup[4]; + uint16 *wp = (uint16 *)p - 1; + uint8 *cp = color_line; + uint8 *mp = matrix_line; + + lookup[0] = (b0c_color << 8) | b0c_color; + + // Loop for 40 characters + for (int i=0; i<40; i++, q+=8) + { + uint8 color, acolor, bcolor; + + color = colors[mp[i] >> 4]; + lookup[1] = (color << 8) | color; + bcolor = colors[mp[i]]; + lookup[2] = (bcolor << 8) | bcolor; + acolor = colors[cp[i]]; + lookup[3] = (acolor << 8) | acolor; + + uint8 data = *q; + r[i] = (data & 0xaa) | (data & 0xaa) >> 1; + + *++wp = lookup[(data >> 6) & 3]; + *++wp = lookup[(data >> 4) & 3]; + *++wp = lookup[(data >> 2) & 3]; + *++wp = lookup[(data >> 0) & 3]; + } +} + + +#ifdef GLOBAL_VARS +static inline void el_ecm_text(uint8 *p, uint8 *q, uint8 *r) +#else +inline void MOS6569::el_ecm_text(uint8 *p, uint8 *q, uint8 *r) +#endif +{ + uint32 *lp = (uint32 *)p; + uint8 *cp = color_line; + uint8 *mp = matrix_line; + uint8 *bcp = &b0c; + + // Loop for 40 characters + for (int i=0; i<40; i++) + { + uint8 data = r[i] = mp[i]; + uint8 color = cp[i]; + uint8 bcolor = bcp[(data >> 6) & 3]; + + data = q[(data & 0x3f) << 3]; + *lp++ = TextColorTable[color][bcolor][data>>4].b; + *lp++ = TextColorTable[color][bcolor][data&0xf].b; + } +} + + +#ifdef GLOBAL_VARS +void el_std_idle(uint8 *p, uint8 *r) +#else +inline void MOS6569::el_std_idle(uint8 *p, uint8 *r) +#endif +{ + uint8 data = *get_physical(ctrl1 & 0x40 ? 0x39ff : 0x3fff); + uint32 *lp = (uint32 *)p; + uint32 conv0 = TextColorTable[0][b0c][data>>4].b; + uint32 conv1 = TextColorTable[0][b0c][data&0xf].b; + + for (int i=0; i<40; i++) { + *lp++ = conv0; + *lp++ = conv1; + *r++ = data; + } +} + + +#ifdef GLOBAL_VARS +ITCM_CODE void el_mc_idle(uint8 *p, uint8 *r) +#else +inline void MOS6569::el_mc_idle(uint8 *p, uint8 *r) +#endif +{ + uint8 data = *get_physical(0x3fff); + uint32 *lp = (uint32 *)p - 1; + r--; + + uint16 lookup[4]; + lookup[0] = (b0c_color << 8) | b0c_color; + lookup[1] = lookup[2] = lookup[3] = colors[0]; + + uint16 conv0 = (lookup[(data >> 6) & 3] << 16) | lookup[(data >> 4) & 3]; + uint16 conv1 = (lookup[(data >> 2) & 3] << 16) | lookup[(data >> 0) & 3]; + + for (int i=0; i<40; i++) { + *++lp = conv0; + *++lp = conv1; + *++r = data; + } +} + + +#ifdef GLOBAL_VARS +ITCM_CODE void el_sprites(uint8 *chunky_ptr) +#else +inline void MOS6569::el_sprites(uint8 *chunky_ptr) +#endif +{ + int i; + int snum, sbit; // Sprite number/bit mask + int spr_coll=0, gfx_coll=0; + + // Draw each active sprite + for (snum=0, sbit=1; snum<8; snum++, sbit<<=1) + if ((sprite_on & sbit) && mx[snum] < DISPLAY_X-32) + { + int spr_mask_pos; // Sprite bit position in fore_mask_buf + uint32 sdata, fore_mask; + + uint8 *p = chunky_ptr + mx[snum] + 8; + uint8 *q = spr_coll_buf + mx[snum] + 8; + + uint8 *sdatap = get_physical(matrix_base[0x3f8 + snum] << 6 | (mc[snum] * 3)); + sdata = (*sdatap << 24) | (*(sdatap+1) << 16) | (*(sdatap+2) << 8); + + uint8 color = spr_color[snum]; + + spr_mask_pos = mx[snum] + 8 - x_scroll; + + uint8 *fmbp = fore_mask_buf + (spr_mask_pos / 8); + int sshift = spr_mask_pos & 7; + fore_mask = (((*(fmbp+0) << 24) | (*(fmbp+1) << 16) | (*(fmbp+2) << 8) + | (*(fmbp+3))) << sshift) | (*(fmbp+4) >> (8-sshift)); + + if (mxe & sbit) { // X-expanded + if (mx[snum] >= DISPLAY_X-56) + continue; + + uint32 sdata_l = 0, sdata_r = 0, fore_mask_r; + fore_mask_r = (((*(fmbp+4) << 24) | (*(fmbp+5) << 16) | (*(fmbp+6) << 8) + | (*(fmbp+7))) << sshift) | (*(fmbp+8) >> (8-sshift)); + + if (mmc & sbit) { // Multicolor mode + uint32 plane0_l, plane0_r, plane1_l, plane1_r; + + // Expand sprite data + sdata_l = MultiExpTable[sdata >> 24 & 0xff] << 16 | MultiExpTable[sdata >> 16 & 0xff]; + sdata_r = MultiExpTable[sdata >> 8 & 0xff] << 16; + + // Convert sprite chunky pixels to bitplanes + plane0_l = (sdata_l & 0x55555555) | (sdata_l & 0x55555555) << 1; + plane1_l = (sdata_l & 0xaaaaaaaa) | (sdata_l & 0xaaaaaaaa) >> 1; + plane0_r = (sdata_r & 0x55555555) | (sdata_r & 0x55555555) << 1; + plane1_r = (sdata_r & 0xaaaaaaaa) | (sdata_r & 0xaaaaaaaa) >> 1; + + // Collision with graphics? + if ((fore_mask & (plane0_l | plane1_l)) || (fore_mask_r & (plane0_r | plane1_r))) { + gfx_coll |= sbit; + if (mdp & sbit) { + plane0_l &= ~fore_mask; // Mask sprite if in background + plane1_l &= ~fore_mask; + plane0_r &= ~fore_mask_r; + plane1_r &= ~fore_mask_r; + } + } + + // Paint sprite + for (i=0; i<32; i++, plane0_l<<=1, plane1_l<<=1) { + uint8 col; + if (plane1_l & 0x80000000) { + if (plane0_l & 0x80000000) + col = mm1_color; + else + col = color; + } else { + if (plane0_l & 0x80000000) + col = mm0_color; + else + continue; + } + // Check for collisions + if (q[i]) + spr_coll |= q[i] | sbit; + else { + p[i] = col; + q[i] = sbit; + } + } + for (; i<48; i++, plane0_r<<=1, plane1_r<<=1) { + uint8 col; + if (plane1_r & 0x80000000) { + if (plane0_r & 0x80000000) + col = mm1_color; + else + col = color; + } else { + if (plane0_r & 0x80000000) + col = mm0_color; + else + continue; + } + // Check for collisions + if (q[i]) + spr_coll |= q[i] | sbit; + else { + p[i] = col; + q[i] = sbit; + } + } + + } else { // Standard mode + + // Expand sprite data + sdata_l = ExpTable[sdata >> 24 & 0xff] << 16 | ExpTable[sdata >> 16 & 0xff]; + sdata_r = ExpTable[sdata >> 8 & 0xff] << 16; + + // Collision with graphics? + if ((fore_mask & sdata_l) || (fore_mask_r & sdata_r)) { + gfx_coll |= sbit; + if (mdp & sbit) { + sdata_l &= ~fore_mask; // Mask sprite if in background + sdata_r &= ~fore_mask_r; + } + } + + // Paint sprite + for (i=0; i<32; i++, sdata_l<<=1) + if (sdata_l & 0x80000000) { + if (q[i]) // Collision with sprite? + spr_coll |= q[i] | sbit; + else { // Draw pixel if no collision + p[i] = color; + q[i] = sbit; + } + } + for (; i<48; i++, sdata_r<<=1) + if (sdata_r & 0x80000000) { + if (q[i]) // Collision with sprite? + spr_coll |= q[i] | sbit; + else { // Draw pixel if no collision + p[i] = color; + q[i] = sbit; + } + } + } + + } else // Unexpanded + + if (mmc & sbit) { // Multicolor mode + uint32 plane0, plane1; + + // Convert sprite chunky pixels to bitplanes + plane0 = (sdata & 0x55555555) | (sdata & 0x55555555) << 1; + plane1 = (sdata & 0xaaaaaaaa) | (sdata & 0xaaaaaaaa) >> 1; + + // Collision with graphics? + if (fore_mask & (plane0 | plane1)) { + gfx_coll |= sbit; + if (mdp & sbit) { + plane0 &= ~fore_mask; // Mask sprite if in background + plane1 &= ~fore_mask; + } + } + + // Paint sprite + for (i=0; i<24; i++, plane0<<=1, plane1<<=1) { + uint8 col; + if (plane1 & 0x80000000) { + if (plane0 & 0x80000000) + col = mm1_color; + else + col = color; + } else { + if (plane0 & 0x80000000) + col = mm0_color; + else + continue; + } + if (q[i]) + spr_coll |= q[i] | sbit; + else { + p[i] = col; + q[i] = sbit; + } + } + + } else { // Standard mode + + // Collision with graphics? + if (fore_mask & sdata) { + gfx_coll |= sbit; + if (mdp & sbit) + sdata &= ~fore_mask; // Mask sprite if in background + } + + // Paint sprite + for (i=0; i<24; i++, sdata<<=1) + if (sdata & 0x80000000) { + if (q[i]) { // Collision with sprite? + spr_coll |= q[i] | sbit; + } else { // Draw pixel if no collision + p[i] = color; + q[i] = sbit; + } + } + + } + } + + // Check sprite-sprite collisions + if (clx_spr) + clx_spr |= spr_coll; + else { + clx_spr |= spr_coll; + irq_flag |= 0x04; + if (irq_mask & 0x04) { + irq_flag |= 0x80; + the_cpu->TriggerVICIRQ(); + } + } + + // Check sprite-background collisions + if (clx_bgr) + clx_bgr |= gfx_coll; + else { + clx_bgr |= gfx_coll; + irq_flag |= 0x02; + if (irq_mask & 0x02) { + irq_flag |= 0x80; + the_cpu->TriggerVICIRQ(); + } + } +} + + +#ifdef GLOBAL_VARS +ITCM_CODE int el_update_mc(int raster) +#else +inline int MOS6569::el_update_mc(int raster) +#endif +{ + int i, j; + int cycles_used = 0; + uint8 spron = sprite_on; + uint8 spren = me; + uint8 sprye = mye; + uint16 raster8bit = raster & 0xff; + //uint16 *mcp = mc; + uint8 *myp = my; + + // Increment sprite data counters + for (i=0, j=1; i<8; i++, j<<=1, myp++) + { + // Sprite enabled? + if (spren & j) + { + // Yes, activate if Y position matches raster counter + if (*myp == raster8bit) + { + mc[i] = 0; + spron |= j; + } else goto spr_off; + } + else + { +spr_off: + // No, turn sprite off when data counter exceeds 60 and increment counter + if (mc[i] != 21) // Instead of increment by 3 and looking for 63, we inc++ and look for 21... compensate for added speed + { + if (sprye & j) // Y expansion + { + if (!((*myp ^ raster8bit) & 1)) + { + cycles_used++; + if (++mc[i] == 21) spron &= ~j; + } + } + else + { + cycles_used++; + if (++mc[i] == 21) spron &= ~j; + } + } + } + } + + sprite_on = spron; + return (cycles_used<<1); // Each cycles_used above is 2 actual cycles +} + +/* + * Emulate one raster line + */ + +int dampen_memcpy=0; +int MOS6569::EmulateLine(void) +{ + int cycles_left = 63 + CycleDeltas[myConfig.cpuCycles]; // Cycles left for CPU + bool is_bad_line = false; + + // Get raster counter into local variable for faster access and increment + unsigned int raster = raster_y+1; + + // End of screen reached? + if (raster != TOTAL_RASTERS) + raster_y = raster; + else { + dampen_memcpy++; + vblank(); + raster = 0; + } + + // Trigger raster IRQ if IRQ line reached + if (raster == irq_raster) + raster_irq(); + + // In line $30, the DEN bit controls if Bad Lines can occur + if (raster == 0x30) + bad_lines_enabled = ctrl1 & 0x10; + + // Skip frame? Only calculate Bad Lines then + if (frame_skipped) { + if (raster >= FIRST_DMA_LINE && raster <= LAST_DMA_LINE && ((raster & 7) == y_scroll) && bad_lines_enabled) { + is_bad_line = true; + cycles_left = 23 + CycleDeltas[myConfig.badCycles]; + } + goto VIC_nop; + } + + // Within the visible range? + if (raster >= FIRST_DISP_LINE && raster <= LAST_DISP_LINE) { + + // Our output goes here + uint8 *chunky_ptr = chunky_line_start; + + // Set video counter + vc = vc_base; + + // Bad Line condition? + if (raster >= FIRST_DMA_LINE && raster <= LAST_DMA_LINE && ((raster & 7) == y_scroll) && bad_lines_enabled) { + + // Turn on display + display_state = is_bad_line = true; + cycles_left = 23 + CycleDeltas[myConfig.badCycles]; + rc = 0; + + // Read and latch 40 bytes from video matrix and color RAM + uint8 *mp = matrix_line - 1; + uint8 *cp = color_line - 1; + int vc1 = vc - 1; + uint8 *mbp = matrix_base + vc1; + uint8 *crp = color_ram + vc1; + for (int i=0; i<40; i++) + { + *++mp = *++mbp; + *++cp = *++crp; + } + } + + // Handler upper/lower border + if (raster == dy_stop) + border_on = true; + if (raster == dy_start && (ctrl1 & 0x10)) // Don't turn off border if DEN bit cleared + border_on = false; + + if (!border_on) { + + // Display window contents + uint8 *p = chunky_ptr + COL40_XSTART; // Pointer in chunky display buffer + uint8 *r = fore_mask_buf + COL40_XSTART/8; // Pointer in foreground mask buffer +#ifdef ALIGNMENT_CHECK + uint8 *use_p = ((((int)p) & 3) == 0) ? p : text_chunky_buf; +#endif + + { + p--; + uint8 b0cc = b0c_color; + int limit = x_scroll; + for (int i=0; i0 + *++p = b0cc; + p++; + } + + if (display_state) { + switch (display_idx) { + + case 0: // Standard text +#ifndef CAN_ACCESS_UNALIGNED +#ifdef ALIGNMENT_CHECK + el_std_text(use_p, char_base + rc, r); + if (use_p != p) + memcpy(p, use_p, 8*40); +#else + if (x_scroll & 3) { + if (dampen_memcpy&1) + { + el_std_text(text_chunky_buf, char_base + rc, r); + memcpy(p, text_chunky_buf, 8*40); + } + } else + el_std_text(p, char_base + rc, r); +#endif +#else + el_std_text(p, char_base + rc, r); +#endif + break; + + case 1: // Multicolor text +#ifndef CAN_ACCESS_UNALIGNED +#ifdef ALIGNMENT_CHECK + el_mc_text(use_p, char_base + rc, r); + if (use_p != p) + memcpy(p, use_p, 8*40); +#else + if (x_scroll & 3) { + if (dampen_memcpy&1) + { + el_mc_text(text_chunky_buf, char_base + rc, r); + memcpy(p, text_chunky_buf, 8*40); + } + } else + el_mc_text(p, char_base + rc, r); +#endif +#else + el_mc_text(p, char_base + rc, r); +#endif + break; + + case 2: // Standard bitmap +#ifndef CAN_ACCESS_UNALIGNED +#ifdef ALIGNMENT_CHECK + el_std_bitmap(use_p, bitmap_base + (vc << 3) + rc, r); + if (use_p != p) + memcpy(p, use_p, 8*40); +#else + if (x_scroll & 3) { + if (dampen_memcpy&1) + { + el_std_bitmap(text_chunky_buf, bitmap_base + (vc << 3) + rc, r); + memcpy(p, text_chunky_buf, 8*40); + } + } else + el_std_bitmap(p, bitmap_base + (vc << 3) + rc, r); +#endif +#else + el_std_bitmap(p, bitmap_base + (vc << 3) + rc, r); +#endif + break; + + case 3: // Multicolor bitmap +#ifndef CAN_ACCESS_UNALIGNED +#ifdef ALIGNMENT_CHECK + el_mc_bitmap(use_p, bitmap_base + (vc << 3) + rc, r); + if (use_p != p) + memcpy(p, use_p, 8*40); +#else + if (x_scroll & 3) { + if (dampen_memcpy&1) + { + el_mc_bitmap(text_chunky_buf, bitmap_base + (vc << 3) + rc, r); + memcpy(p, text_chunky_buf, 8*40); + } + } else + el_mc_bitmap(p, bitmap_base + (vc << 3) + rc, r); +#endif +#else + el_mc_bitmap(p, bitmap_base + (vc << 3) + rc, r); +#endif + break; + + case 4: // ECM text +#ifndef CAN_ACCESS_UNALIGNED +#ifdef ALIGNMENT_CHECK + el_ecm_text(use_p, char_base + rc, r); + if (use_p != p) + memcpy(p, use_p, 8*40); +#else + if (x_scroll & 3) { + if (dampen_memcpy&1) + { + el_ecm_text(text_chunky_buf, char_base + rc, r); + memcpy(p, text_chunky_buf, 8*40); + } + } else + el_ecm_text(p, char_base + rc, r); +#endif +#else + el_ecm_text(p, char_base + rc, r); +#endif + break; + + default: // Invalid mode (all black) + memset(p, colors[0], 320); + memset(r, 0, 40); + break; + } + vc += 40; + + } else { // Idle state graphics + switch (display_idx) { + + case 0: // Standard text + case 1: // Multicolor text + case 4: // ECM text +#ifndef CAN_ACCESS_UNALIGNED +#ifdef ALIGNMENT_CHECK + el_std_idle(use_p, r); + if (use_p != p) {memcpy(p, use_p, 8*40);} +#else + if (x_scroll & 3) { + if (dampen_memcpy&1) + { + el_std_idle(text_chunky_buf, r); + memcpy(p, text_chunky_buf, 8*40); + } + } else + el_std_idle(p, r); +#endif +#else + el_std_idle(p, r); +#endif + break; + + case 3: // Multicolor bitmap +#ifndef CAN_ACCESS_UNALIGNED +#ifdef ALIGNMENT_CHECK + el_mc_idle(use_p, r); + if (use_p != p) {memcpy(p, use_p, 8*40);} +#else + if (x_scroll & 3) { + if (dampen_memcpy&1) + { + el_mc_idle(text_chunky_buf, r); + memcpy(p, text_chunky_buf, 8*40); + } + } else + el_mc_idle(p, r); +#endif +#else + el_mc_idle(p, r); +#endif + break; + + default: // Invalid mode (all black) + memset(p, colors[0], 320); + memset(r, 0, 40); + break; + } + } + + // Draw sprites + // Clear sprite collision buffer - but only if we have spites to draw on this line + if (sprite_on) memset((uint32 *)spr_coll_buf, 0x00, sizeof(spr_coll_buf)); + el_sprites(chunky_ptr); + + // Handle left/right border + uint32 *lp = (uint32 *)chunky_ptr + 4; + uint32 c = ec_color_long; + for (int i=5; i= FIRST_DMA_LINE-1 && raster <= LAST_DMA_LINE-1 && (((raster+1) & 7) == y_scroll) && bad_lines_enabled) + rc = 0; + } + +VIC_nop: + // Skip this if all sprites are off + if (me | sprite_on) + cycles_left -= el_update_mc(raster); + + return cycles_left; +} diff --git a/arm9/source/VIC.h b/arm9/source/VIC.h new file mode 100644 index 0000000..6b1507d --- /dev/null +++ b/arm9/source/VIC.h @@ -0,0 +1,250 @@ +// ===================================================================================== +// GimliDS Copyright (c) 2025 Dave Bernazzani (wavemotion-dave) +// +// As GimliDS is a port of the Frodo emulator for the DS/DSi/XL/LL handhelds, +// any copying or distribution of this emulator, its source code and associated +// readme files, with or without modification, are permitted per the original +// Frodo emulator license shown below. Hugest thanks to Christian Bauer for his +// efforts to provide a clean open-source emulation base for the C64. +// +// Numerous hacks and 'unsafe' optimizations have been performed on the original +// Frodo emulator codebase to get it running on the small handheld system. You +// are strongly encouraged to seek out the official Frodo sources if you're at +// all interested in this emulator code. +// +// The GimliDS emulator is offered as-is, without any warranty. Please see readme.md +// ===================================================================================== + +/* + * VIC.h - 6569R5 emulation (line based) + * + * Frodo Copyright (C) Christian Bauer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _VIC_H +#define _VIC_H +#include + +// Define this if you want global variables instead of member variables +#if defined(__i386) || defined(mc68000) || defined(__MC68K__) +#define GLOBAL_VARS +#endif + +// Define this if you have a processor that can do unaligned accesses quickly +#if defined(__i386) || defined(mc68000) || defined(__MC68K__) +#define CAN_ACCESS_UNALIGNED +#endif + + +// Total number of raster lines (PAL) +const unsigned TOTAL_RASTERS = 0x138; + +// Screen refresh frequency (PAL) +const unsigned SCREEN_FREQ = 50; + + +class MOS6510; +class C64Display; +class C64; +struct MOS6569State; + + +class MOS6569 { +public: + MOS6569(C64 *c64, C64Display *disp, MOS6510 *CPU, uint8 *RAM, uint8 *Char, uint8 *Color); + + uint8 ReadRegister(uint16 adr); + void WriteRegister(uint16 adr, uint8 byte); + int EmulateLine(void); + void ChangedVA(uint16 new_va); // CIA VA14/15 has changed + void TriggerLightpen(void); // Trigger lightpen interrupt + void GetState(MOS6569State *vd); + void SetState(MOS6569State *vd); + +private: +#ifndef GLOBAL_VARS + void vblank(void); + void raster_irq(void); + + uint16 mx[8]; // VIC registers + uint8 my[8]; + uint8 mx8; + uint8 ctrl1, ctrl2; + uint8 lpx, lpy; + uint8 me, mxe, mye, mdp, mmc; + uint8 vbase; + uint8 irq_flag, irq_mask; + uint8 clx_spr, clx_bgr; + uint8 ec, b0c, b1c, b2c, b3c, mm0, mm1; + uint8 sc[8]; + + uint8 *ram, *char_rom, *color_ram; // Pointers to RAM and ROM + C64 *the_c64; // Pointer to C64 + C64Display *the_display; // Pointer to C64Display + MOS6510 *the_cpu; // Pointer to 6510 + + uint8 colors[256]; // Indices of the 16 C64 colors (16 times mirrored to avoid "& 0x0f") + + uint8 ec_color, b0c_color, b1c_color, + b2c_color, b3c_color; // Indices for exterior/background colors + uint8 mm0_color, mm1_color; // Indices for MOB multicolors + uint8 spr_color[8]; // Indices for MOB colors + + uint32 ec_color_long; // ec_color expanded to 32 bits + + uint8 matrix_line[40]; // Buffer for video line, read in Bad Lines + uint8 color_line[40]; // Buffer for color line, read in Bad Lines + + uint8 *chunky_line_start; // Pointer to start of current line in bitmap buffer + int xmod; // Number of bytes per row + + uint16 raster_y; // Current raster line + uint16 irq_raster; // Interrupt raster line + uint16 dy_start; // Comparison values for border logic + uint16 dy_stop; + uint16 rc; // Row counter + uint16 vc; // Video counter + uint16 vc_base; // Video counter base + uint16 x_scroll; // X scroll value + uint16 y_scroll; // Y scroll value + uint16 cia_vabase; // CIA VA14/15 video base + + uint16 mc[8]; // Sprite data counters + + int display_idx; // Index of current display mode + int skip_counter; // Counter for frame-skipping + + long pad0; // Keep buffers long-aligned + uint8 spr_coll_buf[DISPLAY_X]; // Buffer for sprite-sprite collisions and priorities + uint8 fore_mask_buf[DISPLAY_X/8]; // Foreground mask for sprite-graphics collisions and priorities +#ifndef CAN_ACCESS_UNALIGNED + uint8 text_chunky_buf[40*8]; // Line graphics buffer +#endif + + bool display_state; // true: Display state, false: Idle state + bool border_on; // Flag: Upper/lower border on (Frodo SC: Main border flipflop) + bool frame_skipped; // Flag: Frame is being skipped + uint8 bad_lines_enabled; // Flag: Bad Lines enabled for this frame + bool lp_triggered; // Flag: Lightpen was triggered in this frame + + uint8 *get_physical(uint16 adr); + void make_mc_table(void); + void el_std_text(uint8 *p, uint8 *q, uint8 *r); + void el_mc_text(uint8 *p, uint8 *q, uint8 *r); + void el_std_bitmap(uint8 *p, uint8 *q, uint8 *r); + void el_mc_bitmap(uint8 *p, uint8 *q, uint8 *r); + void el_ecm_text(uint8 *p, uint8 *q, uint8 *r); + void el_std_idle(uint8 *p, uint8 *r); + void el_mc_idle(uint8 *p, uint8 *r); + void el_sprites(uint8 *chunky_ptr); + int el_update_mc(int raster); + + uint16 mc_color_lookup[4]; + + bool border_40_col; // Flag: 40 column border + uint8 sprite_on; // 8 flags: Sprite display/DMA active + + uint8 *matrix_base; // Video matrix base + uint8 *char_base; // Character generator base + uint8 *bitmap_base; // Bitmap base +#endif +}; + + +// VIC state +struct MOS6569State { + uint8 m0x; // Sprite coordinates + uint8 m0y; + uint8 m1x; + uint8 m1y; + uint8 m2x; + uint8 m2y; + uint8 m3x; + uint8 m3y; + uint8 m4x; + uint8 m4y; + uint8 m5x; + uint8 m5y; + uint8 m6x; + uint8 m6y; + uint8 m7x; + uint8 m7y; + uint8 mx8; + + uint8 ctrl1; // Control registers + uint8 raster; + uint8 lpx; + uint8 lpy; + uint8 me; + uint8 ctrl2; + uint8 mye; + uint8 vbase; + uint8 irq_flag; + uint8 irq_mask; + uint8 mdp; + uint8 mmc; + uint8 mxe; + uint8 mm; + uint8 md; + + uint8 ec; // Color registers + uint8 b0c; + uint8 b1c; + uint8 b2c; + uint8 b3c; + uint8 mm0; + uint8 mm1; + uint8 m0c; + uint8 m1c; + uint8 m2c; + uint8 m3c; + uint8 m4c; + uint8 m5c; + uint8 m6c; + uint8 m7c; + // Additional registers + uint8 pad0; + uint16 irq_raster; // IRQ raster line + uint16 vc; // Video counter + uint16 vc_base; // Video counter base + uint8 rc; // Row counter + uint8 spr_dma; // 8 Flags: Sprite DMA active + uint8 spr_disp; // 8 Flags: Sprite display active + uint8 mc[8]; // Sprite data counters + uint8 mc_base[8]; // Sprite data counter bases + bool display_state; // true: Display state, false: Idle state + bool bad_line; // Flag: Bad Line state + bool bad_line_enable; // Flag: Bad Lines enabled for this frame + bool lp_triggered; // Flag: Lightpen was triggered in this frame + bool border_on; // Flag: Upper/lower border on (Frodo SC: Main border flipflop) + + uint16 bank_base; // VIC bank base address + uint16 matrix_base; // Video matrix base + uint16 char_base; // Character generator base + uint16 bitmap_base; // Bitmap base + uint16 sprite_base[8]; // Sprite bases + + // Frodo SC: + int cycle; // Current cycle in line (1..63) + uint16 raster_x; // Current raster x position + int ml_index; // Index in matrix/color_line[] + uint8 ref_cnt; // Refresh counter + uint8 last_vic_byte; // Last byte read by VIC + bool ud_border_on; // Flag: Upper/lower border on +}; + +#endif diff --git a/arm9/source/diskmenu.cpp b/arm9/source/diskmenu.cpp new file mode 100644 index 0000000..91668be --- /dev/null +++ b/arm9/source/diskmenu.cpp @@ -0,0 +1,686 @@ +// ===================================================================================== +// GimliDS Copyright (c) 2025 Dave Bernazzani (wavemotion-dave) +// +// As GimliDS is a port of the Frodo emulator for the DS/DSi/XL/LL handhelds, +// any copying or distribution of this emulator, its source code and associated +// readme files, with or without modification, are permitted per the original +// Frodo emulator license shown below. Hugest thanks to Christian Bauer for his +// efforts to provide a clean open-source emulation base for the C64. +// +// Numerous hacks and 'unsafe' optimizations have been performed on the original +// Frodo emulator codebase to get it running on the small handheld system. You +// are strongly encouraged to seek out the official Frodo sources if you're at +// all interested in this emulator code. +// +// The GimliDS emulator is offered as-is, without any warranty. Please see readme.md +// ===================================================================================== + +// Diskette Menu Loading Code + +#include +#include +#include +#include +#include +#include + +#include +#include +#include "diskmenu.h" +#include "mainmenu.h" +#include "keyboard.h" +#include "mainmenu_bg.h" +#include "diskmenu_bg.h" +#include "Prefs.h" +#include "C64.h" + +char Drive8File[MAX_FILENAME_LEN]; +char Drive9File[MAX_FILENAME_LEN]; + +extern int bg0b, bg1b; +int countZX=0; +int ucGameAct=0; +int ucGameChoice = -1; +FIC64 gpFic[MAX_FILES]; +char szName[256]; +char szFile[256]; +u32 file_size = 0; +char strBuf[40]; + +#define WAITVBL swiWaitForVBlank();swiWaitForVBlank();swiWaitForVBlank(); + +/********************************************************************************* + * Show The 14 games on the list to allow the user to choose a new game. + ********************************************************************************/ +static char szName2[40]; +void dsDisplayFiles(u16 NoDebGame, u8 ucSel) +{ + u16 ucBcl,ucGame; + u8 maxLen; + + DSPrint(31,5,0,(NoDebGame>0 ? (char*)"<" : (char*)" ")); + DSPrint(31,22,0,(NoDebGame+14" : (char*)" ")); + + for (ucBcl=0;ucBcl<18; ucBcl++) + { + ucGame= ucBcl+NoDebGame; + if (ucGame < countZX) + { + maxLen=(int)strlen(gpFic[ucGame].szName); + strcpy(szName,gpFic[ucGame].szName); + if (maxLen>30) szName[30]='\0'; + if (gpFic[ucGame].uType == DIRECTORY) + { + szName[28] = 0; // Needs to be 2 chars shorter with brackets + sprintf(szName2, "[%s]",szName); + sprintf(szName,"%-30s",szName2); + DSPrint(1,5+ucBcl,(ucSel == ucBcl ? 2 : 0),szName); + } + else + { + sprintf(szName,"%-30s",strupr(szName)); + DSPrint(1,5+ucBcl,(ucSel == ucBcl ? 2 : 0 ),szName); + } + } + else + { + DSPrint(1,5+ucBcl,(ucSel == ucBcl ? 2 : 0 ),(char *)" "); + } + } +} + + +// ------------------------------------------------------------------------- +// Standard qsort routine for the games - we sort all directory +// listings first and then a case-insenstive sort of all games. +// ------------------------------------------------------------------------- +int Filescmp (const void *c1, const void *c2) +{ + FIC64 *p1 = (FIC64 *) c1; + FIC64 *p2 = (FIC64 *) c2; + + if (p1->szName[0] == '.' && p2->szName[0] != '.') + return -1; + if (p2->szName[0] == '.' && p1->szName[0] != '.') + return 1; + if ((p1->uType == DIRECTORY) && !(p2->uType == DIRECTORY)) + return -1; + if ((p2->uType == DIRECTORY) && !(p1->uType == DIRECTORY)) + return 1; + return strcasecmp (p1->szName, p2->szName); +} + +/********************************************************************************* + * Find files (TAP/TZX/Z80/SNA) available - sort them for display. + ********************************************************************************/ +void speccySEFindFiles(u8 bTapeOnly) +{ + u32 uNbFile; + DIR *dir; + struct dirent *pent; + + uNbFile=0; + countZX=0; + + dir = opendir("."); + while (((pent=readdir(dir))!=NULL) && (uNbFiled_name); + + if(pent->d_type == DT_DIR) + { + if (!((szFile[0] == '.') && ((int)strlen(szFile) == 1))) + { + // Do not include the [sav] and [pok] directories + if ((strcasecmp(szFile, "sav") != 0)) + { + strcpy(gpFic[uNbFile].szName,szFile); + gpFic[uNbFile].uType = DIRECTORY; + uNbFile++; + countZX++; + } + } + } + else { + if ((strlen(szFile)>4) && (strlen(szFile)<(MAX_FILENAME_LEN-4)) && (szFile[0] != '.') && (szFile[0] != '_')) // For MAC don't allow files starting with an underscore + { + if ( (strcasecmp(strrchr(szFile, '.'), ".D64") == 0) ) { + strcpy(gpFic[uNbFile].szName,szFile); + gpFic[uNbFile].uType = SPECCY_FILE; + uNbFile++; + countZX++; + } + } + } + } + closedir(dir); + + // ---------------------------------------------- + // If we found any files, go sort the list... + // ---------------------------------------------- + if (countZX) + { + qsort (gpFic, countZX, sizeof(FIC64), Filescmp); + } +} + +// ---------------------------------------------------------------- +// Let the user select a new game (rom) file and load it up! +// ---------------------------------------------------------------- +u8 speccySELoadFile(u8 bTapeOnly) +{ + bool bDone=false; + u16 ucHaut=0x00, ucBas=0x00,ucSHaut=0x00, ucSBas=0x00, romSelected= 0, firstRomDisplay=0,nbRomPerPage, uNbRSPage; + s16 uLenFic=0, ucFlip=0, ucFlop=0; + u8 retVal = 0; + + // Show the menu... + while ((keysCurrent() & (KEY_TOUCH | KEY_START | KEY_SELECT | KEY_A | KEY_B))!=0); + + speccySEFindFiles(bTapeOnly); + + ucGameChoice = -1; + + nbRomPerPage = (countZX>=18 ? 18 : countZX); + uNbRSPage = (countZX>=5 ? 5 : countZX); + + if (ucGameAct>countZX-nbRomPerPage) + { + firstRomDisplay=countZX-nbRomPerPage; + romSelected=ucGameAct-countZX+nbRomPerPage; + } + else + { + firstRomDisplay=ucGameAct; + romSelected=0; + } + + if (romSelected >= countZX) romSelected = 0; // Just start at the top + + dsDisplayFiles(firstRomDisplay,romSelected); + + // ----------------------------------------------------- + // Until the user selects a file or exits the menu... + // ----------------------------------------------------- + while (!bDone) + { + if (keysCurrent() & KEY_UP) + { + if (!ucHaut) + { + ucGameAct = (ucGameAct>0 ? ucGameAct-1 : countZX-1); + if (romSelected>uNbRSPage) { romSelected -= 1; } + else { + if (firstRomDisplay>0) { firstRomDisplay -= 1; } + else { + if (romSelected>0) { romSelected -= 1; } + else { + firstRomDisplay=countZX-nbRomPerPage; + romSelected=nbRomPerPage-1; + } + } + } + ucHaut=0x01; + dsDisplayFiles(firstRomDisplay,romSelected); + } + else { + + ucHaut++; + if (ucHaut>10) ucHaut=0; + } + uLenFic=0; ucFlip=-50; ucFlop=0; + } + else + { + ucHaut = 0; + } + if (keysCurrent() & KEY_DOWN) + { + if (!ucBas) { + ucGameAct = (ucGameAct< countZX-1 ? ucGameAct+1 : 0); + if (romSelected10) ucBas=0; + } + uLenFic=0; ucFlip=-50; ucFlop=0; + } + else { + ucBas = 0; + } + + // ------------------------------------------------------------- + // Left and Right on the D-Pad will scroll 1 page at a time... + // ------------------------------------------------------------- + if (keysCurrent() & KEY_RIGHT) + { + if (!ucSBas) + { + ucGameAct = (ucGameAct< countZX-nbRomPerPage ? ucGameAct+nbRomPerPage : countZX-nbRomPerPage); + if (firstRomDisplay10) ucSBas=0; + } + uLenFic=0; ucFlip=-50; ucFlop=0; + } + else { + ucSBas = 0; + } + + // ------------------------------------------------------------- + // Left and Right on the D-Pad will scroll 1 page at a time... + // ------------------------------------------------------------- + if (keysCurrent() & KEY_LEFT) + { + if (!ucSHaut) + { + ucGameAct = (ucGameAct> nbRomPerPage ? ucGameAct-nbRomPerPage : 0); + if (firstRomDisplay>nbRomPerPage) { firstRomDisplay -= nbRomPerPage; } + else { firstRomDisplay = 0; } + if (ucGameAct == 0) romSelected = 0; + if (romSelected > ucGameAct) romSelected = ucGameAct; + ucSHaut=0x01; + dsDisplayFiles(firstRomDisplay,romSelected); + } + else + { + ucSHaut++; + if (ucSHaut>10) ucSHaut=0; + } + uLenFic=0; ucFlip=-50; ucFlop=0; + } + else { + ucSHaut = 0; + } + + // ------------------------------------------------------------------------- + // They B key will exit out of the ROM selection without picking a new game + // ------------------------------------------------------------------------- + if ( keysCurrent() & KEY_B ) + { + bDone=true; + retVal = 0; + while (keysCurrent() & KEY_B); + } + + // ------------------------------------------------------------------- + // Any of these keys will pick the current ROM and try to load it... + // ------------------------------------------------------------------- + if (keysCurrent() & KEY_A || keysCurrent() & KEY_Y || keysCurrent() & KEY_X) + { + if (gpFic[ucGameAct].uType != DIRECTORY) + { + bDone=true; + if (keysCurrent() & KEY_X) retVal = 2; else retVal = 1; + ucGameChoice = ucGameAct; + WAITVBL; + } + else + { + chdir(gpFic[ucGameAct].szName); + speccySEFindFiles(bTapeOnly); + ucGameAct = 0; + nbRomPerPage = (countZX>=14 ? 14 : countZX); + uNbRSPage = (countZX>=5 ? 5 : countZX); + if (ucGameAct>countZX-nbRomPerPage) { + firstRomDisplay=countZX-nbRomPerPage; + romSelected=ucGameAct-countZX+nbRomPerPage; + } + else { + firstRomDisplay=ucGameAct; + romSelected=0; + } + dsDisplayFiles(firstRomDisplay,romSelected); + while (keysCurrent() & KEY_A); + } + } + + // -------------------------------------------- + // If the filename is too long... scroll it. + // -------------------------------------------- + if ((int)strlen(gpFic[ucGameAct].szName) > 30) + { + ucFlip++; + if (ucFlip >= 25) + { + ucFlip = 0; + uLenFic++; + if ((uLenFic+30)>(int)strlen(gpFic[ucGameAct].szName)) + { + ucFlop++; + if (ucFlop >= 15) + { + uLenFic=0; + ucFlop = 0; + } + else + uLenFic--; + } + strncpy(szName,gpFic[ucGameAct].szName+uLenFic,30); + szName[30] = '\0'; + DSPrint(1,5+romSelected,2,szName); + } + } + swiWaitForVBlank(); + } + + // Wait for some key to be pressed before returning + while ((keysCurrent() & (KEY_TOUCH | KEY_START | KEY_SELECT | KEY_A | KEY_B | KEY_R | KEY_L | KEY_UP | KEY_DOWN))!=0); + + return retVal; +} + +u16 nds_key; + +void LoadGameConfig(void) +{ + if (strlen(Drive8File) > 1) + { + file_crc = getCRC32((u8*)Drive8File, strlen(Drive8File)); + FindConfig(); + } +} + +void BottomScreenDiskette(void) +{ + decompress(diskmenu_bgTiles, bgGetGfxPtr(bg0b), LZ77Vram); + decompress(diskmenu_bgMap, (void*) bgGetMapPtr(bg0b), LZ77Vram); + dmaCopy((void*) bgGetMapPtr(bg0b)+32*30*2,(void*) bgGetMapPtr(bg1b),32*24*2); + dmaCopy((void*) diskmenu_bgPal,(void*) BG_PALETTE_SUB,256*2); + unsigned short dmaVal = *(bgGetMapPtr(bg1b)+24*32); + dmaFillWords(dmaVal | (dmaVal<<16),(void*) bgGetMapPtr(bg1b),32*24*2); +} + +void BottomScreenMainMenu(void) +{ + decompress(mainmenu_bgTiles, bgGetGfxPtr(bg0b), LZ77Vram); + decompress(mainmenu_bgMap, (void*) bgGetMapPtr(bg0b), LZ77Vram); + dmaCopy((void*) bgGetMapPtr(bg0b)+32*30*2,(void*) bgGetMapPtr(bg1b),32*24*2); + dmaCopy((void*) mainmenu_bgPal,(void*) BG_PALETTE_SUB,256*2); + unsigned short dmaVal = *(bgGetMapPtr(bg1b)+24*32); + dmaFillWords(dmaVal | (dmaVal<<16),(void*) bgGetMapPtr(bg1b),32*24*2); +} + +void DisplayFileNameDiskette(void) +{ + char tmp[34]; + + DSPrint(5,6,6, (char*)" "); + DSPrint(5,10,6, (char*)" "); + if (strlen(Drive8File) > 1) + { + DSPrint(5,5,6, (char *)"DRIVE 8 IS MOUNTED WITH:"); + strncpy(tmp, Drive8File, 27); tmp[26]=0; + DSPrint(5,6,6, tmp); + } + else + { + DSPrint(5,5,6, (char *)"DRIVE 8 IS NOT MOUNTED "); + } + + if (strlen(Drive9File) > 1) + { + DSPrint(5,9,6, (char *)"DRIVE 9 IS MOUNTED WITH:"); + strncpy(tmp, Drive9File, 27); tmp[26]=0; + DSPrint(5,10,6, tmp); + } + else + { + DSPrint(5,9,6, (char *)"DRIVE 9 IS NOT MOUNTED "); + } + + if (myConfig.trueDrive) + { + DSPrint(0,22,6, (char *)" TRUE DRIVE IS ENABLED (SLOW) "); + } + else + { + DSPrint(0,22,6, (char *)" TRUE DRIVE IS DISABLED (FAST) "); + } +} + +// ---------------------------------------------------------------------- +// The Disk Menu can be called up directly from the keyboard graphic +// and allows the user to rewind the tape, swap in a new tape, etc. +// ---------------------------------------------------------------------- +#define MENU_ACTION_END 255 // Always the last sentinal value +#define MENU_ACTION_EXIT 0 // Exit the menu +#define MENU_ACTION_DRIVE8 1 // Mount Drive 8 File +#define MENU_ACTION_DRIVE9 2 // Mount Drive 9 File +#define MENU_ACTION_EJECT 3 // Eject all drives +#define MENU_ACTION_REBOOT_C64 4 // Force C64 Reboot +#define MENU_ACTION_TRUE_DRIVE 5 // Toggle True Drive +#define MENU_ACTION_CONFIG 6 // Configure Game +#define MENU_ACTION_SKIP 99 // Skip this MENU choice + +typedef struct +{ + char *menu_string; + u8 menu_action; +} MenuItem_t; + +typedef struct +{ + char *title; + u8 start_row; + MenuItem_t menulist[15]; +} DiskMenu_t; + +DiskMenu_t disk_menu = +{ + (char *)" ", 10, + { + {(char *)" MOUNT DISK 8 ", MENU_ACTION_DRIVE8}, + {(char *)" MOUNT DISK 9 ", MENU_ACTION_DRIVE9}, + {(char *)" EJECT DISKS ", MENU_ACTION_EJECT}, + {(char *)" TOGGLE TRUEDRIVE ", MENU_ACTION_TRUE_DRIVE}, + {(char *)" CONFIG GAME ", MENU_ACTION_CONFIG}, + {(char *)" REBOOT C64U ", MENU_ACTION_REBOOT_C64}, + {(char *)" EXIT MENU ", MENU_ACTION_EXIT}, + {(char *)" NULL ", MENU_ACTION_END}, + }, +}; + + +static DiskMenu_t *menu = &disk_menu; + +// ------------------------------------------------------- +// Show the Disk Menu text - highlight the selected row. +// ------------------------------------------------------- +u8 diskette_menu_items = 0; +void DiskMenuShow(bool bClearScreen, u8 sel) +{ + diskette_menu_items = 0; + + if (bClearScreen) + { + // ------------------------------------- + // Put up the Diskette menu background + // ------------------------------------- + BottomScreenDiskette(); + } + + // --------------------------------------------------- + // Pick the right context menu based on the machine + // --------------------------------------------------- + menu = &disk_menu; + + // Display the menu title + DSPrint(15-(strlen(menu->title)/2), menu->start_row, 6, menu->title); + + // And display all of the menu items + while (menu->menulist[diskette_menu_items].menu_action != MENU_ACTION_END) + { + DSPrint(16-(strlen(menu->menulist[diskette_menu_items].menu_string)/2), menu->start_row+2+diskette_menu_items, (diskette_menu_items == sel) ? 7:6, menu->menulist[diskette_menu_items].menu_string); + diskette_menu_items++; + } + + // ---------------------------------------------------------------------------------------------- + // And near the bottom, display the file/rom/disk that is currently loaded into memory. + // ---------------------------------------------------------------------------------------------- + DisplayFileNameDiskette(); +} + +// ------------------------------------------------------------------------ +// Handle Disk mini-menu interface... Allows rewind, swap tape, etc. +// ------------------------------------------------------------------------ +u8 DisketteMenu(C64 *the_c64) +{ + u8 menuSelection = 0; + u8 retVal = 0; + + while ((keysCurrent() & (KEY_TOUCH | KEY_LEFT | KEY_RIGHT | KEY_A ))!=0); + + // ------------------------------------------------------------------ + //Show the cassette menu background - we'll draw text on top of this + // ------------------------------------------------------------------ + DiskMenuShow(true, menuSelection); + + u8 bExitMenu = false; + while (true) + { + nds_key = keysCurrent(); + if (nds_key) + { + if (nds_key & KEY_UP) + { + menuSelection = (menuSelection > 0) ? (menuSelection-1):(diskette_menu_items-1); + while (menu->menulist[menuSelection].menu_action == MENU_ACTION_SKIP) + { + menuSelection = (menuSelection > 0) ? (menuSelection-1):(diskette_menu_items-1); + } + DiskMenuShow(false, menuSelection); + } + if (nds_key & KEY_DOWN) + { + menuSelection = (menuSelection+1) % diskette_menu_items; + while (menu->menulist[menuSelection].menu_action == MENU_ACTION_SKIP) + { + menuSelection = (menuSelection+1) % diskette_menu_items; + } + DiskMenuShow(false, menuSelection); + } + + if (nds_key & KEY_B) // Treat this as selecting 'exit' + { + bExitMenu = true; + } + else + if (nds_key & KEY_A) // User has picked a menu item... let's see what it is! + { + switch(menu->menulist[menuSelection].menu_action) + { + case MENU_ACTION_EXIT: + bExitMenu = true; + break; + + case MENU_ACTION_DRIVE8: + BottomScreenMainMenu(); + retVal = speccySELoadFile(0); + if (ucGameChoice >= 0) + { + retVal = 1; + strcpy(Drive8File, gpFic[ucGameChoice].szName); + LoadGameConfig(); + } + DiskMenuShow(true, menuSelection); + break; + + case MENU_ACTION_DRIVE9: + BottomScreenMainMenu(); + retVal = speccySELoadFile(0); + if (ucGameChoice >= 0) + { + retVal = 1; + strcpy(Drive9File, gpFic[ucGameChoice].szName); + } + DiskMenuShow(true, menuSelection); + break; + + case MENU_ACTION_EJECT: + strcpy(Drive8File, ""); + strcpy(Drive9File, ""); + retVal = 1; + DiskMenuShow(true, menuSelection); + break; + + case MENU_ACTION_TRUE_DRIVE: + myConfig.trueDrive ^= 1; + DiskMenuShow(true, menuSelection); + break; + + case MENU_ACTION_CONFIG: + if (file_crc != 0x00000000) + { + u8 last_trueDrive = myConfig.trueDrive; + BottomScreenMainMenu(); + GimliDSGameOptions(); + if (last_trueDrive != myConfig.trueDrive) // Need to reload... + { + Prefs *prefs = new Prefs(ThePrefs); + prefs->TrueDrive = myConfig.trueDrive; + the_c64->NewPrefs(prefs); + ThePrefs = *prefs; + delete prefs; + } + DiskMenuShow(true, menuSelection); + } + else + { + DSPrint(0, 20, 6, (char*)" NO GAME IS LOADED "); + WAITVBL;WAITVBL;WAITVBL;WAITVBL;WAITVBL;WAITVBL; + WAITVBL;WAITVBL;WAITVBL;WAITVBL;WAITVBL;WAITVBL; + WAITVBL;WAITVBL;WAITVBL;WAITVBL;WAITVBL;WAITVBL; + DSPrint(0, 20, 6, (char*)" "); + } + break; + + case MENU_ACTION_REBOOT_C64: + retVal = 2; + bExitMenu = true; + break; + } + } + + if (bExitMenu) break; + while ((keysCurrent() & (KEY_UP | KEY_DOWN | KEY_A ))!=0); + WAITVBL;WAITVBL;WAITVBL; + } + } + + while ((keysCurrent() & (KEY_UP | KEY_DOWN | KEY_A ))!=0); + WAITVBL;WAITVBL;WAITVBL; + + return retVal; +} + +u8 mount_disk(C64 *the_c64) +{ + strcpy(Drive8File, ThePrefs.DrivePath[0]); + strcpy(Drive9File, ThePrefs.DrivePath[1]); + + u8 retVal = DisketteMenu(the_c64); + + return retVal; +} diff --git a/arm9/source/diskmenu.h b/arm9/source/diskmenu.h new file mode 100644 index 0000000..6121001 --- /dev/null +++ b/arm9/source/diskmenu.h @@ -0,0 +1,21 @@ +#define MAX_FILES 2048 +#define MAX_FILENAME_LEN 256 + +#define SPECCY_FILE 0x01 +#define DIRECTORY 0x02 +class C64; +extern void DSPrint(int iX,int iY,int iScr,char *szMessage); + +typedef struct { + char szName[MAX_FILENAME_LEN+1]; + u8 uType; + u32 uCrc; +} FIC64; + +extern char Drive8File[MAX_FILENAME_LEN]; +extern char Drive9File[MAX_FILENAME_LEN]; + +extern FIC64 gpFic[MAX_FILES]; +extern int ucGameChoice; + +extern u8 mount_disk(C64 *the_c64); diff --git a/arm9/source/lzav.h b/arm9/source/lzav.h new file mode 100644 index 0000000..2de2dfe --- /dev/null +++ b/arm9/source/lzav.h @@ -0,0 +1,2324 @@ +/** + * @file lzav.h + * + * @version 4.17 + * + * @brief Self-contained inclusion file for the "LZAV" in-memory data + * compression and decompression algorithms. + * + * The source code is written in ISO C99, with full C++ compliance enabled + * conditionally and automatically, if compiled with a C++ compiler. + * + * Description is available at https://github.com/avaneev/lzav + * + * E-mail: aleksey.vaneev@gmail.com or info@voxengo.com + * + * LICENSE: + * + * Copyright (c) 2023-2025 Aleksey Vaneev + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef LZAV_INCLUDED +#define LZAV_INCLUDED + +#define LZAV_API_VER 0x107 ///< API version, unrelated to source code version. +#define LZAV_VER_STR "4.17" ///< LZAV source code version string. + +/** + * @def LZAV_FMT_MIN + * @brief Minimal stream format id supported by the decompressor. A value of 2 + * can be defined externally, to reduce decompressor's code size. + */ + +#if !defined( LZAV_FMT_MIN ) + #define LZAV_FMT_MIN 1 +#endif // !defined( LZAV_FMT_MIN ) + +/** + * @def LZAV_NS_CUSTOM + * @brief If this macro is defined externally, all symbols will be placed + * into the namespace specified by the macro, and won't be exported to the + * global namespace. WARNING: if the defined value of the macro is empty, the + * symbols will be placed into the global namespace anyway. + */ + +/** + * @def LZAV_NOEX + * @brief Macro that defines the "noexcept" function specifier for C++ + * environment. + */ + +/** + * @def LZAV_NULL + * @brief Macro that defines "nullptr" value, for C++ guidelines conformance. + */ + +/** + * @def LZAV_NS + * @brief Macro that defines an actual implementation namespace in C++ + * environment, with export of relevant symbols to the global namespace + * (if @ref LZAV_NS_CUSTOM is undefined). + */ + +#if defined( __cplusplus ) + + #include + #include + + #if __cplusplus >= 201103L + + #include + + #define LZAV_NOEX noexcept + #define LZAV_NULL nullptr + + #else // __cplusplus >= 201103L + + #include + + #define LZAV_NOEX throw() + #define LZAV_NULL NULL + + #endif // __cplusplus >= 201103L + + #if defined( LZAV_NS_CUSTOM ) + #define LZAV_NS LZAV_NS_CUSTOM + #else // defined( LZAV_NS_CUSTOM ) + #define LZAV_NS lzav + #endif // defined( LZAV_NS_CUSTOM ) + +#else // defined( __cplusplus ) + + #include + #include + #include + + #define LZAV_NOEX + #define LZAV_NULL 0 + +#endif // defined( __cplusplus ) + +#if SIZE_MAX < 0xFFFFFFFFU + + #error LZAV: the platform or the compiler has incompatible size_t type. + +#endif // size_t check + +/** + * @def LZAV_X86 + * @brief Macro is defined if `x86` or `x86_64` platform was detected. + */ + +#if defined( i386 ) || defined( __i386 ) || defined( __i386__ ) || \ + defined( _X86_ ) || defined( __x86_64 ) || defined( __x86_64__ ) || \ + defined( __amd64 ) || defined( __amd64__ ) || defined( _M_IX86 ) || \ + ( defined( _M_AMD64 ) && !defined( _M_ARM64EC )) + + #define LZAV_X86 + +#endif // x86 platform check + +/** + * @def LZAV_LITTLE_ENDIAN + * @brief Endianness definition macro, can be used as a logical constant. + */ + +#if defined( __LITTLE_ENDIAN__ ) || defined( __LITTLE_ENDIAN ) || \ + defined( _LITTLE_ENDIAN ) || ( defined( __BYTE_ORDER__ ) && \ + __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ ) || \ + defined( LZAV_X86 ) || defined( _WIN32 ) || defined( _M_ARM ) || \ + defined( _M_ARM64EC ) + + #define LZAV_LITTLE_ENDIAN 1 + +#elif defined( __BIG_ENDIAN__ ) || defined( __BIG_ENDIAN ) || \ + defined( _BIG_ENDIAN ) || ( defined( __BYTE_ORDER__ ) && \ + __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ ) || \ + defined( __SYSC_ZARCH__ ) || defined( __zarch__ ) || \ + defined( __s390x__ ) || defined( __sparc ) || defined( __sparc__ ) + + #define LZAV_LITTLE_ENDIAN 0 + +#else // defined( __BIG_ENDIAN__ ) + + #warning LZAV: cannot determine endianness, assuming little-endian. + + #define LZAV_LITTLE_ENDIAN 1 + +#endif // defined( __BIG_ENDIAN__ ) + +/** + * @def LZAV_PTR32 + * @brief Macro denotes that pointers are likely 32-bit (pointer overflow + * checks are required). + */ + +#if SIZE_MAX <= 0xFFFFFFFFU && \ + ( !defined( UINTPTR_MAX ) || UINTPTR_MAX <= 0xFFFFFFFFU ) + + #define LZAV_PTR32 + +#endif // 32-bit pointers check + +/** + * @def LZAV_ARCH64 + * @brief Macro that denotes availability of 64-bit instructions. + */ + +#if defined( __LP64__ ) || defined( _LP64 ) || !defined( LZAV_PTR32 ) || \ + defined( __x86_64__ ) || defined( __aarch64__ ) || \ + defined( _M_X64 ) || defined( _M_ARM64 ) + + #define LZAV_ARCH64 + +#endif // 64-bit availability check + +/** + * @def LZAV_GCC_BUILTINS + * @brief Macro that denotes availability of GCC-style built-in functions. + */ + +#if defined( __GNUC__ ) || defined( __clang__ ) || \ + defined( __IBMC__ ) || defined( __IBMCPP__ ) || \ + defined( __COMPCERT__ ) || ( defined( __INTEL_COMPILER ) && \ + __INTEL_COMPILER >= 1300 && !defined( _MSC_VER )) + + #define LZAV_GCC_BUILTINS + +#endif // GCC built-ins check + +/** + * @def LZAV_IEC32( x ) + * @brief In-place endianness-correction macro, for singular 32-bit variables. + * @param x Value to correct in-place. + */ + +#if LZAV_LITTLE_ENDIAN + + #define LZAV_IEC32( x ) (void) 0 + +#else // LZAV_LITTLE_ENDIAN + + #if defined( LZAV_GCC_BUILTINS ) + + #define LZAV_IEC32( x ) x = __builtin_bswap32( x ) + + #elif defined( _MSC_VER ) + + #define LZAV_IEC32( x ) x = _byteswap_ulong( x ) + + #else // defined( _MSC_VER ) + + #define LZAV_IEC32( x ) x = (uint32_t) ( \ + x >> 24 | \ + ( x & 0x00FF0000 ) >> 8 | \ + ( x & 0x0000FF00 ) << 8 | \ + x << 24 ) + + #endif // defined( _MSC_VER ) + +#endif // LZAV_LITTLE_ENDIAN + +/** + * @def LZAV_LIKELY( x ) + * @brief Likelihood macro that is used for manually-guided + * micro-optimization. + * @param x Expression that is likely to be evaluated to 1. + */ + +/** + * @def LZAV_UNLIKELY( x ) + * @brief Unlikelihood macro that is used for manually-guided + * micro-optimization. + * @param x Expression that is unlikely to be evaluated to 1. + */ + +#if defined( LZAV_GCC_BUILTINS ) && \ + !( defined( __aarch64__ ) && defined( __APPLE__ )) + + #define LZAV_LIKELY( x ) __builtin_expect( x, 1 ) + #define LZAV_UNLIKELY( x ) __builtin_expect( x, 0 ) + +#else // Likelihood macros + + #define LZAV_LIKELY( x ) ( x ) + #define LZAV_UNLIKELY( x ) ( x ) + +#endif // Likelihood macros + +#if defined( _MSC_VER ) && !defined( LZAV_GCC_BUILTINS ) + #include // For _BitScanForward. +#endif // defined( _MSC_VER ) && !defined( LZAV_GCC_BUILTINS ) + +#if defined( LZAV_NS ) + +namespace LZAV_NS { + +using std :: memcpy; +using std :: memset; +using std :: malloc; +using std :: free; +using std :: size_t; + +#if __cplusplus >= 201103L + + using std :: intptr_t; + using std :: uint16_t; + using std :: uint32_t; + using uint8_t = unsigned char; ///< For C++ type aliasing compliance. + + #if defined( LZAV_ARCH64 ) + using std :: uint64_t; + #endif // defined( LZAV_ARCH64 ) + +#endif // __cplusplus >= 201103L + +namespace enum_wrapper { + +#endif // defined( LZAV_NS ) + +/** + * @brief Decompression error codes. + */ + +enum LZAV_ERROR +{ + LZAV_E_PARAMS = -1, ///< Incorrect function parameters. + LZAV_E_SRCOOB = -2, ///< Source buffer OOB. + LZAV_E_DSTOOB = -3, ///< Destination buffer OOB. + LZAV_E_REFOOB = -4, ///< Back-reference OOB. + LZAV_E_DSTLEN = -5, ///< Decompressed length mismatch. + LZAV_E_UNKFMT = -6, ///< Unknown stream format. + LZAV_E_PTROVR = -7 ///< Pointer overflow. +}; + +#if defined( LZAV_NS ) + +} // namespace enum_wrapper + +using namespace enum_wrapper; + +#endif // defined( LZAV_NS ) + +#define LZAV_HASH_C1 0x243F6A88 ///< Hash function constant 1. +#define LZAV_HASH_C2 0x85A308D3 ///< Hash function constant 2. + +/** + * Enumeration used to define compression algorithm's parameters. + */ + +enum LZAV_PARAM +{ + LZAV_WIN_LEN = ( 1 << 23 ), ///< LZ77 window length, in bytes. + LZAV_REF_LEN = ( 15 + 255 + 254 ), ///< Max ref length, minus `mref`. + LZAV_LIT_FIN = 6, ///< The number of literals required at finish. + LZAV_OFS_MIN = 8, ///< The minimal reference offset to use. + LZAV_OFS_TH1 = (( 1 << 10 ) - 1 ), ///< Reference offset threshold 1. + LZAV_OFS_TH2 = (( 1 << 18 ) - 1 ), ///< Reference offset threshold 2. + LZAV_FMT_CUR = 2 ///< Stream format identifier used by the compressor. +}; + +/** + * @brief Data match length finding function. + * + * Function finds the number of continuously-matching leading bytes between + * two buffers. This function is well-optimized for a wide variety of + * compilers and platforms. + * + * @param p1 Pointer to buffer 1. + * @param p2 Pointer to buffer 2. + * @param ml Maximal number of bytes to match. + * @return The number of matching leading bytes. + */ + +static inline size_t lzav_match_len( const uint8_t* p1, const uint8_t* p2, + const size_t ml ) LZAV_NOEX +{ + const uint8_t* const p1s = p1; + const uint8_t* const p1e = p1 + ml; + +#if defined( LZAV_ARCH64 ) + + while( LZAV_LIKELY( p1 + 7 < p1e )) + { + uint64_t v1, v2, vd; + memcpy( &v1, p1, 8 ); + memcpy( &v2, p2, 8 ); + vd = v1 ^ v2; + + if( vd != 0 ) + { + #if defined( LZAV_GCC_BUILTINS ) + + #if LZAV_LITTLE_ENDIAN + return( (size_t) ( p1 - p1s + ( __builtin_ctzll( vd ) >> 3 ))); + #else // LZAV_LITTLE_ENDIAN + return( (size_t) ( p1 - p1s + ( __builtin_clzll( vd ) >> 3 ))); + #endif // LZAV_LITTLE_ENDIAN + + #else // defined( LZAV_GCC_BUILTINS ) + + #if defined( _MSC_VER ) + unsigned long i; + _BitScanForward64( &i, (unsigned __int64) vd ); + return( (size_t) ( p1 - p1s + ( i >> 3 ))); + #else // defined( _MSC_VER ) + #if !LZAV_LITTLE_ENDIAN + const uint64_t sw = vd >> 32 | vd << 32; + const uint64_t sw2 = + ( sw & (uint64_t) 0xFFFF0000FFFF0000 ) >> 16 | + ( sw & (uint64_t) 0x0000FFFF0000FFFF ) << 16; + vd = ( sw2 & (uint64_t) 0xFF00FF00FF00FF00 ) >> 8 | + ( sw2 & (uint64_t) 0x00FF00FF00FF00FF ) << 8; + #endif // !LZAV_LITTLE_ENDIAN + + const uint64_t m = (uint64_t) 0x0101010101010101; + + return( (size_t) ( p1 - p1s + + (((( vd ^ ( vd - 1 )) & ( m - 1 )) * m ) >> 56 ))); + #endif // defined( _MSC_VER ) + + #endif // defined( LZAV_GCC_BUILTINS ) + } + + p1 += 8; + p2 += 8; + } + + // At most 7 bytes left. + + if( LZAV_LIKELY( p1 + 3 < p1e )) + { + +#else // defined( LZAV_ARCH64 ) + + while( LZAV_LIKELY( p1 + 3 < p1e )) + { + +#endif // defined( LZAV_ARCH64 ) + + uint32_t v1, v2, vd; + memcpy( &v1, p1, 4 ); + memcpy( &v2, p2, 4 ); + vd = v1 ^ v2; + + if( vd != 0 ) + { + #if defined( LZAV_GCC_BUILTINS ) + + #if LZAV_LITTLE_ENDIAN + return( (size_t) ( p1 - p1s + ( __builtin_ctz( vd ) >> 3 ))); + #else // LZAV_LITTLE_ENDIAN + return( (size_t) ( p1 - p1s + ( __builtin_clz( vd ) >> 3 ))); + #endif // LZAV_LITTLE_ENDIAN + + #else // defined( LZAV_GCC_BUILTINS ) + + #if defined( _MSC_VER ) + unsigned long i; + _BitScanForward( &i, (unsigned long) vd ); + return( (size_t) ( p1 - p1s + ( i >> 3 ))); + #else // defined( _MSC_VER ) + LZAV_IEC32( vd ); + const uint32_t m = 0x01010101; + + return( (size_t) ( p1 - p1s + + (((( vd ^ ( vd - 1 )) & ( m - 1 )) * m ) >> 24 ))); + #endif // defined( _MSC_VER ) + + #endif // defined( LZAV_GCC_BUILTINS ) + } + + p1 += 4; + p2 += 4; + } + + // At most 3 bytes left. + + if( p1 < p1e ) + { + if( *p1 != p2[ 0 ]) + { + return( (size_t) ( p1 - p1s )); + } + + if( ++p1 < p1e ) + { + if( *p1 != p2[ 1 ]) + { + return( (size_t) ( p1 - p1s )); + } + + if( ++p1 < p1e ) + { + if( *p1 != p2[ 2 ]) + { + return( (size_t) ( p1 - p1s )); + } + } + } + } + + return( ml ); +} + +/** + * @brief Data match length finding function, reverse direction. + * + * @param p1 Origin pointer to buffer 1. + * @param p2 Origin pointer to buffer 2. + * @param ml Maximal number of bytes to back-match. + * @return The number of matching prior bytes, not including origin position. + */ + +static inline size_t lzav_match_len_r( const uint8_t* p1, const uint8_t* p2, + const size_t ml ) LZAV_NOEX +{ + if( LZAV_UNLIKELY( ml == 0 )) + { + return( 0 ); + } + + if( p1[ -1 ] != p2[ -1 ]) + { + return( 0 ); + } + + if( LZAV_UNLIKELY( ml != 1 )) + { + const uint8_t* const p1s = p1; + const uint8_t* p1e = p1 - ml + 1; + p1--; + p2--; + + while( LZAV_UNLIKELY( p1 > p1e )) + { + uint16_t v1, v2; + memcpy( &v1, p1 - 2, 2 ); + memcpy( &v2, p2 - 2, 2 ); + + const uint32_t vd = (uint32_t) ( v1 ^ v2 ); + + if( vd != 0 ) + { + #if LZAV_LITTLE_ENDIAN + return( (size_t) ( p1s - p1 + (( vd & 0xFF00 ) == 0 ))); + #else // LZAV_LITTLE_ENDIAN + return( (size_t) ( p1s - p1 + (( vd & 0x00FF ) == 0 ))); + #endif // LZAV_LITTLE_ENDIAN + } + + p1 -= 2; + p2 -= 2; + } + + p1e--; + + if( p1 > p1e && p1[ -1 ] != p2[ -1 ]) + { + return( (size_t) ( p1s - p1 )); + } + } + + return( ml ); +} + +/** + * @brief Internal LZAV block header writing function (stream format 2). + * + * Internal function writes a block to the output buffer. This function can be + * used in custom compression algorithms. + * + * Stream format 2. + * + * "Raw" compressed stream consists of any quantity of unnumerated "blocks". + * A block starts with a header byte, followed by several optional bytes. + * Bits 4-5 of the header specify block's type. + * + * CC00LLLL: literal block (1-6 bytes). `LLLL` is literal length. + * + * OO01RRRR: 10-bit offset block (2-4 bytes). `RRRR` is reference length. + * + * OO10RRRR: 18-bit offset block (3-5 bytes). + * + * OO11RRRR: 23-bit offset block (4-6 bytes). + * + * If `LLLL` or `RRRR` equals 0, a value of 16 is assumed, and an additional + * length byte follows. If in a literal block this additional byte's highest + * bit is 1, one more length byte follows that defines higher bits of length + * (up to 4 bytes). In a reference block, additional 1-2 length bytes follow + * the offset bytes. `CC` is a reference offset carry value (additional 2 + * lowest bits of offset of the next reference block). Block type 3 includes 3 + * carry bits (highest bits of 4th byte). + * + * The overall compressed data is prefixed with a byte whose lower 4 bits + * contain minimal reference length (mref), and the highest 4 bits contain + * stream format identifier. Compressed data always finishes with + * @ref LZAV_LIT_FIN literals. The lzav_write_fin_2() function should be used + * to finalize compression. + * + * Except the last block, a literal block is always followed by a reference + * block. + * + * @param op Output buffer pointer. + * @param lc Literal length, in bytes. + * @param rc Reference length, in bytes, not lesser than mref. + * @param d Reference offset, in bytes. Should be lesser than + * @ref LZAV_WIN_LEN, and not lesser than `rc` since fast copy on + * decompression cannot provide consistency of copying of data that is not in + * the output yet. + * @param ipa Literals anchor pointer. + * @param cbpp Pointer to the pointer to the latest offset carry block header. + * Cannot be 0, but the contained pointer can be 0 (initial value). + * @param cshp Pointer to offset carry shift. + * @param mref Minimal reference length, in bytes, used by the compression + * algorithm. + * @return Incremented output buffer pointer. + */ + +static inline uint8_t* lzav_write_blk_2( uint8_t* op, size_t lc, size_t rc, + size_t d, const uint8_t* ipa, uint8_t** const cbpp, int* const cshp, + const size_t mref ) LZAV_NOEX +{ + // Perform offset carry to a previous block (`csh` may be zero). + + const int csh = *cshp; + rc = rc + 1 - mref; + **cbpp |= (uint8_t) (( d << 8 ) >> csh ); + d >>= csh; + + if( LZAV_UNLIKELY( lc != 0 )) + { + // Write a literal block. + + size_t cv; // Offset carry value in literal block. + cv = ( d & 3 ) << 6; + d >>= 2; + + if( LZAV_LIKELY( lc < 9 )) + { + *op = (uint8_t) ( cv | lc ); + op++; + + memcpy( op, ipa, 8 ); + op += lc; + } + else + if( LZAV_LIKELY( lc < 16 )) + { + *op = (uint8_t) ( cv | lc ); + op++; + + memcpy( op, ipa, 16 ); + op += lc; + } + else + if( LZAV_LIKELY( lc < 16 + 128 )) + { + #if LZAV_LITTLE_ENDIAN + uint16_t ov = (uint16_t) (( lc - 16 ) << 8 | cv ); + #else // LZAV_LITTLE_ENDIAN + uint16_t ov = (uint16_t) ( cv << 8 | ( lc - 16 )); + #endif // LZAV_LITTLE_ENDIAN + + memcpy( op, &ov, 2 ); + op += 2; + + memcpy( op, ipa, 16 ); + memcpy( op + 16, ipa + 16, 16 ); + + if( lc < 33 ) + { + op += lc; + } + else + { + ipa += 32; + op += 32; + lc -= 32; + + do + { + *op = *ipa; + ipa++; + op++; + } while( --lc != 0 ); + } + } + else + { + *op = (uint8_t) cv; + op++; + + size_t lcw = lc - 16; + + while( lcw > 127 ) + { + *op = (uint8_t) ( 0x80 | lcw ); + lcw >>= 7; + op++; + } + + *op = (uint8_t) lcw; + op++; + + memcpy( op, ipa, lc ); + op += lc; + } + } + + // Write a reference block. + + static const int ocsh[ 4 ] = { 0, 0, 0, 3 }; + const size_t bt = (size_t) 1 + ( d > LZAV_OFS_TH1 ) + ( d > LZAV_OFS_TH2 ); + + if( LZAV_LIKELY( rc < 16 )) + { + uint32_t ov = (uint32_t) ( d << 6 | bt << 4 | rc ); + LZAV_IEC32( ov ); + memcpy( op, &ov, 4 ); + + op += bt; + *cshp = ocsh[ bt ]; + *cbpp = op; + + return( op + 1 ); + } + + uint32_t ov = (uint32_t) ( d << 6 | bt << 4 ); + LZAV_IEC32( ov ); + memcpy( op, &ov, 4 ); + + op += bt; + *cshp = ocsh[ bt ]; + *cbpp = op; + + if( LZAV_LIKELY( rc < 16 + 255 )) + { + op[ 1 ] = (uint8_t) ( rc - 16 ); + return( op + 2 ); + } + + op[ 1 ] = (uint8_t) 255; + op[ 2 ] = (uint8_t) ( rc - 16 - 255 ); + return( op + 3 ); +} + +/** + * @brief Internal LZAV finishing function (stream format 2). + * + * Internal function writes finishing literal block(s) to the output buffer. + * This function can be used in custom compression algorithms. + * + * Stream format 2. + * + * @param op Output buffer pointer. + * @param lc Literal length, in bytes. Not less than @ref LZAV_LIT_FIN. + * @param ipa Literals anchor pointer. + * @return Incremented output buffer pointer. + */ + +static inline uint8_t* lzav_write_fin_2( uint8_t* op, size_t lc, + const uint8_t* ipa ) LZAV_NOEX +{ + if( lc < 16 ) + { + *op = (uint8_t) lc; + op++; + } + else + { + *op = 0; + op++; + + size_t lcw = lc - 16; + + while( lcw > 127 ) + { + *op = (uint8_t) ( 0x80 | lcw ); + lcw >>= 7; + op++; + } + + *op = (uint8_t) lcw; + op++; + } + + memcpy( op, ipa, lc ); + return( op + lc ); +} + +/** + * @brief Function returns buffer size required for LZAV compression. + * + * @param srcl The length of the source data to be compressed. + * @return The required allocation size for destination compression buffer. + * Always a positive value. + */ + +static inline int lzav_compress_bound( const int srcl ) LZAV_NOEX +{ + if( srcl <= 0 ) + { + return( 16 ); + } + + const int k = 16 + 127 + 1; + const int l2 = srcl / ( k + 6 ); + + return(( srcl - l2 * 6 + k - 1 ) / k * 2 - l2 + srcl + 16 ); +} + +/** + * @brief Function returns buffer size required for the higher-ratio LZAV + * compression. + * + * @param srcl The length of the source data to be compressed. + * @return The required allocation size for destination compression buffer. + * Always a positive value. + */ + +static inline int lzav_compress_bound_hi( const int srcl ) LZAV_NOEX +{ + if( srcl <= 0 ) + { + return( 16 ); + } + + const int l2 = srcl / ( 16 + 5 ); + + return(( srcl - l2 * 5 + 15 ) / 16 * 2 - l2 + srcl + 16 ); +} + +/** + * @brief Hash-table initialization function. + * + * Function initializes the hash-table by replicating the contents of the + * specified tuple value. + * + * @param[out] ht Hash-table pointer. + * @param htsize Hash-table size. The size should be a power of 2 value, not + * lesser than 64 bytes. + * @param[in] initv Pointer to initialized 8-byte tuple. + */ + +static inline void lzav_ht_init( uint8_t* const ht, const size_t htsize, + const uint32_t* const initv ) LZAV_NOEX +{ + memcpy( ht, initv, 8 ); + memcpy( ht + 8, initv, 8 ); + memcpy( ht + 16, ht, 16 ); + memcpy( ht + 32, ht, 16 ); + memcpy( ht + 48, ht, 16 ); + + uint8_t* const hte = ht + htsize; + uint8_t* htc = ht + 64; + + while( LZAV_LIKELY( htc != hte )) + { + memcpy( htc, ht, 16 ); + memcpy( htc + 16, ht, 16 ); + memcpy( htc + 32, ht, 16 ); + memcpy( htc + 48, ht, 16 ); + htc += 64; + } +} + +/** + * @brief LZAV compression function, with external buffer option. + * + * Function performs in-memory data compression using the LZAV compression + * algorithm and stream format. The function produces a "raw" compressed data, + * without a header containing data length nor identifier nor checksum. + * + * Note that compression algorithm and its output on the same source data may + * differ between LZAV versions, and may differ between big- and little-endian + * systems. However, the decompression of a compressed data produced by any + * prior compressor version will remain possible. + * + * @param[in] src Source (uncompressed) data pointer, can be 0 if `srcl` + * equals 0. Address alignment is unimportant. + * @param[out] dst Destination (compressed data) buffer pointer. The allocated + * size should be at least lzav_compress_bound() bytes large. Address + * alignment is unimportant. Should be different to `src`. + * @param srcl Source data length, in bytes, can be 0: in this case the + * compressed length is assumed to be 0 as well. + * @param dstl Destination buffer's capacity, in bytes. + * @param ext_buf External buffer to use for hash-table, set to null for the + * function to manage memory itself (via standard `malloc`). Supplying a + * pre-allocated buffer is useful if compression is performed during + * application's operation often: this reduces memory allocation overhead and + * fragmentation. Note that the access to the supplied buffer is not + * implicitly thread-safe. Buffer's address must be aligned to 32 bits. + * @param ext_bufl The capacity of the `ext_buf`, in bytes, should be a + * power-of-2 value. Set to 0 if `ext_buf` is null. The capacity should not be + * lesser than `4*srcl`, and for default compression ratio should not be + * greater than 1 MiB. Same `ext_bufl` value can be used for any smaller + * source data. Using smaller `ext_bufl` values reduces the compression ratio + * and, at the same time, increases compression speed. This aspect can be + * utilized on memory-constrained and low-performance processors. + * @return The length of compressed data, in bytes. Returns 0 if `srcl` is + * lesser or equal to 0, or if `dstl` is too small, or if buffer pointers are + * invalid, or if not enough memory. + */ + +static inline int lzav_compress( const void* const src, void* const dst, + const int srcl, const int dstl, void* const ext_buf, + const int ext_bufl ) LZAV_NOEX +{ + if(( srcl <= 0 ) | ( src == LZAV_NULL ) | ( dst == LZAV_NULL ) | + ( src == dst ) | ( dstl < lzav_compress_bound( srcl ))) + { + return( 0 ); + } + + const size_t mref = 6; // Minimal reference length, in bytes. + const size_t mlen = LZAV_REF_LEN + mref; + + uint8_t* op = (uint8_t*) dst; // Destination (compressed data) pointer. + *op = (uint8_t) ( LZAV_FMT_CUR << 4 | mref ); // Write prefix byte. + op++; + + if( srcl < 16 ) + { + // Handle a very short source data. + + *op = (uint8_t) srcl; + op++; + + memcpy( op, src, (size_t) srcl ); + + if( srcl > LZAV_LIT_FIN - 1 ) + { + return( 2 + srcl ); + } + + memset( op + srcl, 0, (size_t) ( LZAV_LIT_FIN - srcl )); + return( 2 + LZAV_LIT_FIN ); + } + + uint32_t stack_buf[ 2048 ]; // On-stack hash-table. + void* alloc_buf = LZAV_NULL; // Hash-table allocated on heap. + uint8_t* ht = (uint8_t*) stack_buf; // The actual hash-table pointer. + + size_t htsize; // Hash-table's size in bytes (power-of-2). + htsize = ( 1 << 7 ) * sizeof( uint32_t ) * 4; + + if( ext_buf == LZAV_NULL ) + { + while( htsize != ( 1 << 20 ) && ( htsize >> 2 ) < (size_t) srcl ) + { + htsize <<= 1; + } + + if( htsize > sizeof( stack_buf )) + { + alloc_buf = malloc( htsize ); + + if( alloc_buf == LZAV_NULL ) + { + return( 0 ); + } + + ht = (uint8_t*) alloc_buf; + } + } + else + { + size_t htsizem; + + if( ext_bufl > (int) sizeof( stack_buf )) + { + htsizem = (size_t) ext_bufl; + ht = (uint8_t*) ext_buf; + } + else + { + htsizem = sizeof( stack_buf ); + } + + while(( htsize >> 2 ) < (size_t) srcl ) + { + const size_t htsize2 = htsize << 1; + + if( htsize2 > htsizem ) + { + break; + } + + htsize = htsize2; + } + } + + // Initialize the hash-table. Each hash-table item consists of 2 tuples + // (4 initial match bytes; 32-bit source data offset). Set source data + // offset to avoid OOB in back-match. + + uint32_t initv[ 2 ] = { 0, 16 }; + + if( LZAV_LIKELY( srcl > 19 )) + { + memcpy( initv, (const uint8_t*) src + 16, 4 ); + } + + lzav_ht_init( ht, htsize, initv ); + + const uint32_t hmask = (uint32_t) (( htsize - 1 ) ^ 15 ); // Hash mask. + const uint8_t* ip = (const uint8_t*) src; // Source data pointer. + const uint8_t* const ipe = ip + srcl - LZAV_LIT_FIN; // End pointer. + const uint8_t* const ipet = ipe - 15 + LZAV_LIT_FIN; // Hashing threshold, + // avoids I/O OOB. + const uint8_t* ipa = ip; // Literals anchor pointer. + + uint8_t* cbp = op; // Pointer to the latest offset carry block header. + int csh = 0; // Offset carry shift. + + intptr_t mavg = 100 << 21; // Running average of hash match rate (*2^15). + // Two-factor average: success (0-64) by average reference length. + uint32_t rndb = 0; // PRNG bit derived from the non-matching offset. + + ip += 16; // Skip source bytes, to avoid OOB in back-match. + + while( LZAV_LIKELY( ip < ipet )) + { + // Hash source data (endianness is minimally important for compression + // efficiency). + + uint32_t iw1; + uint16_t iw2, ww2; + memcpy( &iw1, ip, 4 ); + + uint32_t Seed1 = LZAV_HASH_C1; + uint32_t hval = LZAV_HASH_C2; + memcpy( &iw2, ip + 4, 2 ); + + Seed1 ^= iw1; + hval ^= iw2; + hval *= Seed1; + hval >>= 12; + + // Hash-table access. + + uint32_t* const hp = (uint32_t*) ( ht + ( hval & hmask )); + const uint32_t ipo = (uint32_t) ( ip - (const uint8_t*) src ); + const uint32_t hw1 = hp[ 0 ]; // Tuple 1's match word. + const uint8_t* wp; // At window pointer. + size_t d, ml, rc, lc; + + // Find source data in hash-table tuples. + + if( LZAV_LIKELY( iw1 != hw1 )) + { + if( LZAV_LIKELY( iw1 != hp[ 2 ])) + { + goto _no_match; + } + + wp = (const uint8_t*) src + hp[ 3 ]; + memcpy( &ww2, wp + 4, 2 ); + + if( LZAV_UNLIKELY( iw2 != ww2 )) + { + goto _no_match; + } + } + else + { + wp = (const uint8_t*) src + hp[ 1 ]; + memcpy( &ww2, wp + 4, 2 ); + + if( LZAV_UNLIKELY( iw2 != ww2 )) + { + if( LZAV_LIKELY( iw1 != hp[ 2 ])) + { + goto _no_match; + } + + wp = (const uint8_t*) src + hp[ 3 ]; + memcpy( &ww2, wp + 4, 2 ); + + if( LZAV_UNLIKELY( iw2 != ww2 )) + { + goto _no_match; + } + } + } + + // Source data and hash-table entry matched. + + d = (size_t) ( ip - wp ); // Reference offset (distance). + ml = (size_t) ( ipe - ip ); // Max reference match length. Make sure + // `LZAV_LIT_FIN` literals remain on finish. + + if( LZAV_UNLIKELY( d - LZAV_OFS_MIN > + LZAV_WIN_LEN - LZAV_OFS_MIN - 1 )) + { + // Small offsets may be inefficient (wrap over 0 for efficiency). + + goto _d_oob; + } + + // Disallow reference copy overlap by using `d` as max match length. + + ml = ( ml > d ? d : ml ); + ml = ( ml > mlen ? mlen : ml ); + + if( LZAV_LIKELY( d > 273 )) + { + // Update a matching entry only if it is not an adjacent + // replication. Otherwise, source data consisting of same-byte + // runs won't compress well. + + if( LZAV_LIKELY( iw1 == hw1 )) // Replace tuple, or insert. + { + hp[ 1 ] = ipo; + } + else + { + hp[ 2 ] = hw1; + hp[ 3 ] = hp[ 1 ]; + hp[ 0 ] = iw1; + hp[ 1 ] = ipo; + } + } + + rc = mref + lzav_match_len( ip + mref, wp + mref, ml - mref ); + + lc = (size_t) ( ip - ipa ); + + if( LZAV_UNLIKELY( lc != 0 )) + { + // Try to consume literals by finding a match at a back-position. + + ml -= rc; + size_t bmc = ( lc > 16 ? 16 : lc ); + + if( LZAV_LIKELY( ml > bmc )) + { + ml = bmc; + } + + bmc = lzav_match_len_r( ip, wp, ml ); + + if( LZAV_UNLIKELY( bmc != 0 )) + { + rc += bmc; + ip -= bmc; + lc -= bmc; + } + } + + op = lzav_write_blk_2( op, lc, rc, d, ipa, &cbp, &csh, mref ); + ip += rc; + ipa = ip; + mavg += ( (intptr_t) ( rc << 21 ) - mavg ) >> 10; + continue; + + _d_oob: + ip++; + + if( LZAV_LIKELY( d < LZAV_WIN_LEN )) + { + continue; + } + + hp[ 1 + ( iw1 != hw1 ) * 2 ] = ipo; + continue; + + _no_match: + hp[ 2 ] = iw1; + + mavg -= mavg >> 11; + + hp[ 3 ] = ipo; + + if( mavg < ( 200 << 14 ) && ip != ipa ) // Speed-up threshold. + { + // Compression speed-up technique that keeps the number of hash + // evaluations around 45% of compressed data length. In some cases + // reduces the number of blocks by several percent. + + ip += 1 + rndb; // Use PRNG bit to dither match positions. + rndb = ipo & 1; // Delay to decorrelate from current match. + + if( LZAV_UNLIKELY( mavg < ( 130 << 14 ))) + { + ip++; + + if( LZAV_UNLIKELY( mavg < ( 100 << 14 ))) + { + ip += (intptr_t) 100 - ( mavg >> 14 ); // Gradually faster. + } + } + } + + ip++; + } + + if( alloc_buf != LZAV_NULL ) + { + free( alloc_buf ); + } + + return( (int) ( lzav_write_fin_2( op, (size_t) ( ipe - ipa + + LZAV_LIT_FIN ), ipa ) - (uint8_t*) dst )); +} + +/** + * @brief Default LZAV compression function. + * + * Function performs in-memory data compression using the LZAV compression + * algorithm, with the default settings. + * + * See the lzav_compress() function for a more detailed description. + * + * @param[in] src Source (uncompressed) data pointer. + * @param[out] dst Destination (compressed data) buffer pointer. The allocated + * size should be at least lzav_compress_bound() bytes large. + * @param srcl Source data length, in bytes. + * @param dstl Destination buffer's capacity, in bytes. + * @return The length of compressed data, in bytes. Returns 0 if `srcl` is + * lesser or equal to 0, or if `dstl` is too small, or if not enough memory. + */ + +static inline int lzav_compress_default( const void* const src, + void* const dst, const int srcl, const int dstl ) LZAV_NOEX +{ + return( lzav_compress( src, dst, srcl, dstl, LZAV_NULL, 0 )); +} + +/** + * @brief Higher-ratio LZAV compression function (much slower). + * + * Function performs in-memory data compression using the higher-ratio LZAV + * compression algorithm. + * + * @param[in] src Source (uncompressed) data pointer. + * @param[out] dst Destination (compressed data) buffer pointer. The allocated + * size should be at least lzav_compress_bound_hi() bytes large. + * @param srcl Source data length, in bytes. + * @param dstl Destination buffer's capacity, in bytes. + * @return The length of compressed data, in bytes. Returns 0 if `srcl` is + * lesser or equal to 0, or if `dstl` is too small, or if buffer pointers are + * invalid, or if not enough memory. + */ + +static inline int lzav_compress_hi( const void* const src, void* const dst, + const int srcl, const int dstl ) LZAV_NOEX +{ + if(( srcl <= 0 ) | ( src == LZAV_NULL ) | ( dst == LZAV_NULL ) | + ( src == dst ) | ( dstl < lzav_compress_bound_hi( srcl ))) + { + return( 0 ); + } + + const size_t mref = 5; // Minimal reference length, in bytes. + const size_t mlen = LZAV_REF_LEN + mref; + + uint8_t* op = (uint8_t*) dst; // Destination (compressed data) pointer. + *op = (uint8_t) ( LZAV_FMT_CUR << 4 | mref ); // Write prefix byte. + op++; + + if( srcl < 16 ) + { + // Handle a very short source data. + + *op = (uint8_t) srcl; + op++; + + memcpy( op, src, (size_t) srcl ); + + if( srcl > LZAV_LIT_FIN - 1 ) + { + return( 2 + srcl ); + } + + memset( op + srcl, 0, (size_t) ( LZAV_LIT_FIN - srcl )); + return( 2 + LZAV_LIT_FIN ); + } + + size_t htsize; // Hash-table's size in bytes (power-of-2). + htsize = ( 1 << 7 ) * sizeof( uint32_t ) * 2 * 8; + + while( htsize != ( 1 << 23 ) && ( htsize >> 2 ) < (size_t) srcl ) + { + htsize <<= 1; + } + + uint8_t* const ht = (uint8_t*) malloc( htsize ); // The hash-table pointer. + + if( ht == LZAV_NULL ) + { + return( 0 ); + } + + // Initialize the hash-table. Each hash-table item consists of 8 tuples + // (4 initial match bytes; 32-bit source data offset). The last value of + // the last tuple is used as head tuple offset (an even value). + + uint32_t initv[ 2 ] = { 0, 0 }; + memcpy( initv, src, 4 ); + + lzav_ht_init( ht, htsize, initv ); + + const uint32_t hmask = (uint32_t) (( htsize - 1 ) ^ 63 ); // Hash mask. + const uint8_t* ip = (const uint8_t*) src; // Source data pointer. + const uint8_t* const ipe = ip + srcl - LZAV_LIT_FIN; // End pointer. + const uint8_t* const ipet = ipe - 15 + LZAV_LIT_FIN; // Hashing threshold, + // avoids I/O OOB. + const uint8_t* ipa = ip; // Literals anchor pointer. + + uint8_t* cbp = op; // Pointer to the latest offset carry block header. + int csh = 0; // Offset carry shift. + + size_t prc = 0; // Length of a previously found match. + size_t pd = 0; // Distance of a previously found match. + const uint8_t* pip = ip; // Source pointer of a previously found match. + + while( LZAV_LIKELY( ip < ipet )) + { + // Hash source data (endianness is minimally important for compression + // efficiency). + + uint32_t iw1; + memcpy( &iw1, ip, 4 ); + + uint32_t Seed1 = LZAV_HASH_C1; + uint32_t hval = LZAV_HASH_C2; + + Seed1 ^= iw1; + hval ^= ip[ 4 ]; + hval *= Seed1; + hval >>= 8; + + // Hash-table access. + + uint32_t* const hp = (uint32_t*) ( ht + ( hval & hmask )); + const uint32_t ipo = (uint32_t) ( ip - (const uint8_t*) src ); + size_t ti0 = hp[ 15 ]; // Head tuple offset. + + // Find source data in hash-table tuples, in up to 7 previous + // positions. + + const uint8_t* wp = ip; // Best found window pointer. + const size_t mle = (size_t) ( ipe - ip ); // Match length bound. + size_t rc = 0; // Best found match length-4, 0 - not found. + size_t d; // Reference offset (distance). + size_t ti = ti0; + int i; + + if( LZAV_LIKELY( mlen < mle )) + { + // Optimized match-finding. + + for( i = 0; i < 7; i++ ) + { + const uint32_t ww1 = hp[ ti ]; + const uint8_t* const wp0 = (const uint8_t*) src + hp[ ti + 1 ]; + d = (size_t) ( ip - wp0 ); + ti = ( ti == 12 ? 0 : ti + 2 ); + + if( iw1 == ww1 ) + { + d = ( d < 4 ? 4 : d ); + + const size_t rc0 = lzav_match_len( ip + 4, wp0 + 4, + ( d > mlen ? mlen : d ) - 4 ); + + if( rc0 > rc ) + { + wp = wp0; + rc = rc0; + } + } + } + } + else + { + for( i = 0; i < 7; i++ ) + { + const uint32_t ww1 = hp[ ti ]; + const uint8_t* const wp0 = (const uint8_t*) src + hp[ ti + 1 ]; + d = (size_t) ( ip - wp0 ); + ti = ( ti == 12 ? 0 : ti + 2 ); + + if( iw1 == ww1 ) + { + // Disallow reference copy overlap by using `d` as max + // match length. Fix `d` if it is lesser than 4 (this is + // safe as max `ip` is lesser than `ipe` by `mref` bytes). + + d = ( d < 4 ? 4 : d ); + + // Make sure `LZAV_LIT_FIN` literals remain on finish. + + size_t ml = ( mle > d ? d : mle ); + ml = ( ml > mlen ? mlen : ml ); + + const size_t rc0 = lzav_match_len( ip + 4, wp0 + 4, + ml - 4 ); + + if( rc0 > rc ) + { + wp = wp0; + rc = rc0; + } + } + } + } + + rc += 4; + d = (size_t) ( ip - wp ); + + if( LZAV_LIKELY( d != rc )) + { + // Update hash-table entry, if there was no match, or if the match + // is not an adjacent replication. + + ti0 = ( ti0 == 0 ? 12 : ti0 - 2 ); + hp[ ti0 ] = iw1; + hp[ ti0 + 1 ] = ipo; + hp[ 15 ] = (uint32_t) ti0; + } + + if(( rc < mref + ( d > LZAV_OFS_TH2 )) | + ( d - LZAV_OFS_MIN > LZAV_WIN_LEN - LZAV_OFS_MIN - 1 )) + { + ip++; + continue; + } + + // Source data and hash-table entry match of suitable length. + + const uint8_t* const ip0 = ip; + size_t lc = (size_t) ( ip - ipa ); + + if( LZAV_UNLIKELY( lc != 0 )) + { + // Try to consume literals by finding a match at back-position. + + size_t ml = ( mle > d ? d : mle ); + ml = ( ml > mlen ? mlen : ml ); + ml -= rc; + + const size_t wpo = (size_t) ( wp - (const uint8_t*) src ); + + if( LZAV_LIKELY( ml > lc )) + { + ml = lc; + } + + if( LZAV_UNLIKELY( ml > wpo )) + { + ml = wpo; + } + + const size_t bmc = lzav_match_len_r( ip, wp, ml ); + + if( LZAV_UNLIKELY( bmc != 0 )) + { + rc += bmc; + ip -= bmc; + lc -= bmc; + } + } + + if( prc == 0 ) + { + // Save match for a later comparison. + + prc = rc; + pd = d; + pip = ip; + ip = ip0 + 1; + continue; + } + + // Block size overhead estimation, and comparison with a previously + // found match. + + const size_t plc = (size_t) ( pip - ipa ); + const int lb = ( lc != 0 ); + const int sh0 = 10 + csh; + const int sh = sh0 + lb * 2; + const size_t ov = lc + (size_t) lb + ( lc > 15 ) + 2 + + ( d >= ( (size_t) 1 << sh )) + + ( d >= ( (size_t) 1 << ( sh + 8 ))); + + const int plb = ( plc != 0 ); + const int psh = sh0 + plb * 2; + const size_t pov = plc + (size_t) plb + ( plc > 15 ) + 2 + + ( pd >= ( (size_t) 1 << psh )) + + ( pd >= ( (size_t) 1 << ( psh + 8 ))); + + if( LZAV_LIKELY( prc * ov > rc * pov )) + { + const uint8_t* const nipa = pip + prc; + + if( LZAV_UNLIKELY( nipa <= ip )) + { + // A winning previous match does not overlap a current match. + + op = lzav_write_blk_2( op, plc, prc, pd, ipa, &cbp, &csh, + mref ); + + ipa = nipa; + prc = rc; + pd = d; + pip = ip; + ip = ip0 + 1; + continue; + } + + rc = prc; + d = pd; + ip = pip; + lc = plc; + } + + op = lzav_write_blk_2( op, lc, rc, d, ipa, &cbp, &csh, mref ); + ip += rc; + ipa = ip; + prc = 0; + } + + if( prc != 0 ) + { + op = lzav_write_blk_2( op, (size_t) ( pip - ipa ), prc, pd, ipa, &cbp, + &csh, mref ); + + ipa = pip + prc; + } + + free( ht ); + + return( (int) ( lzav_write_fin_2( op, (size_t) ( ipe - ipa + + LZAV_LIT_FIN ), ipa ) - (uint8_t*) dst )); +} + +/** + * @def LZAV_LOAD32( a ) + * @brief Defines `bv` and loads 32-bit unsigned value from memory, with + * endianness-correction. + * + * @param a Memory address. + */ + +/** + * @def LZAV_SET_IPD_CV( x, v, sh ) + * @brief Defines `ipd` as pointer to back-reference, checks bounds, + * updates carry bit variables. + * + * @param x Reference offset. + * @param v Next `cv` value. + * @param sh Next `csh` value. + */ + +/** + * @def LZAV_SET_IPD( x ) + * @brief Defines `ipd` as pointer to back-reference, checks bounds, + * resets carry bit variables. + * + * @param x Reference offset. + */ + +/** + * @brief Internal LZAV decompression function (stream format 2). + * + * Function decompresses "raw" data previously compressed into the LZAV stream + * format 2. + * + * This function should not be called directly since it does not check the + * format identifier. + * + * @param[in] src Source (compressed) data pointer. + * @param[out] dst Destination (decompressed data) buffer pointer. + * @param srcl Source data length, in bytes. + * @param dstl Expected destination data length, in bytes. + * @param[out] pwl Pointer to variable that receives the number of bytes + * written to the destination buffer (until error or end of buffer). + * @return The length of decompressed data, in bytes, or any negative value if + * some error happened. + */ + +static inline int lzav_decompress_2( const void* const src, void* const dst, + const int srcl, const int dstl, int* const pwl ) LZAV_NOEX +{ + const uint8_t* ip = (const uint8_t*) src; // Compressed data pointer. + const uint8_t* const ipe = ip + srcl; // Compressed data boundary pointer. + const uint8_t* const ipet = ipe - 6; // Block header read threshold. + uint8_t* op = (uint8_t*) dst; // Destination (decompressed data) pointer. + uint8_t* const ope = op + dstl; // Destination boundary pointer. + uint8_t* const opet = ope - 63; // Threshold for fast copy to destination. + *pwl = dstl; + const size_t mref1 = (size_t) ( *ip & 15 ) - 1; // Minimal ref length - 1. + size_t bh; // Current block header, updated in each branch. + size_t cv = 0; // Reference offset carry value. + int csh = 0; // Reference offset carry shift. + + #define LZAV_LOAD32( a ) \ + uint32_t bv; \ + memcpy( &bv, a, 4 ); \ + LZAV_IEC32( bv ) + + #define LZAV_SET_IPD_CV( x, v, sh ) \ + const size_t d = ( x ) << csh | cv; \ + csh = ( sh ); \ + const size_t md = (size_t) ( op - (uint8_t*) dst ); \ + cv = ( v ); \ + ipd = op - d; \ + if( LZAV_UNLIKELY( d > md )) \ + goto _err_refoob + + #define LZAV_SET_IPD( x ) \ + LZAV_SET_IPD_CV( x, 0, 0 ) + + ip++; // Advance beyond prefix byte. + + if( LZAV_UNLIKELY( ip >= ipet )) + { + goto _err_srcoob; + } + + bh = *ip; + + while( LZAV_LIKELY( ip < ipet )) + { + const uint8_t* ipd; // Source data pointer. + size_t cc; // Byte copy count. + size_t bt; // Block type. + + if( LZAV_UNLIKELY(( bh & 0x30 ) == 0 )) // Block type 0. + { + size_t ncv = bh >> 6; // Additional offset carry bits. + ip++; + cc = bh & 15; + + if( LZAV_LIKELY( cc != 0 )) // True, if no additional length byte. + { + ipd = ip; + ncv <<= csh; + ip += cc; + + if( LZAV_LIKELY(( op < opet ) & ( ipd < ipe - 22 ))) // 15+6+1 + { + cv |= ncv; + bh = *ip; + csh += 2; + memcpy( op, ipd, 16 ); + op += cc; + + goto _refblk; // Reference block follows, if not EOS. + } + } + else + { + bh = *ip; + ncv <<= csh; + cc = bh & 0x7F; + ip++; + + if( LZAV_UNLIKELY(( bh & 0x80 ) != 0 )) + { + int sh = 7; + + do + { + bh = *ip; + ip++; + cc |= ( bh & 0x7F ) << sh; + + if( sh == 28 ) // No more than 4 additional bytes. + { + break; + } + + sh += 7; + + } while(( bh & 0x80 ) != 0 ); + + cc &= 0x7FFFFFFF; // For malformed data. + } + + cc += 16; + ipd = ip; + ip += cc; + + uint8_t* const opcc = op + cc; + + #if defined( LZAV_PTR32 ) + if( LZAV_UNLIKELY(( ip < ipd ) | ( opcc < op ))) + { + goto _err_ptrovr; + } + #endif // defined( LZAV_PTR32 ) + + if( LZAV_LIKELY(( opcc < opet ) & ( ip < ipe - 70 ))) // 63+6+1 + { + do + { + memcpy( op, ipd, 16 ); + memcpy( op + 16, ipd + 16, 16 ); + memcpy( op + 32, ipd + 32, 16 ); + memcpy( op + 48, ipd + 48, 16 ); + op += 64; + ipd += 64; + } while( op < opcc ); + + cv |= ncv; + bh = *ip; + csh += 2; + op = opcc; + + goto _refblk; // Reference block follows, if not EOS. + } + } + + uint8_t* const opcc = op + cc; + + if( LZAV_UNLIKELY( opcc > ope )) + { + if( LZAV_UNLIKELY( ip > ipe )) + { + goto _err_srcoob_lit; + } + + goto _err_dstoob_lit; + } + + if( LZAV_LIKELY( ip < ipe )) + { + cv |= ncv; + bh = *ip; + csh += 2; + memcpy( op, ipd, cc ); + op = opcc; + continue; + } + + if( LZAV_UNLIKELY( ip != ipe )) + { + goto _err_srcoob_lit; + } + + memcpy( op, ipd, cc ); + op = opcc; + break; + + _err_srcoob_lit: + cc = (size_t) ( ipe - ipd ); + + if( cc < (size_t) ( ope - op )) + { + memcpy( op, ipd, cc ); + *pwl = (int) ( op + cc - (uint8_t*) dst ); + } + else + { + memcpy( op, ipd, (size_t) ( ope - op )); + } + + return( LZAV_E_SRCOOB ); + + _err_dstoob_lit: + memcpy( op, ipd, (size_t) ( ope - op )); + return( LZAV_E_DSTOOB ); + } + + _refblk: + bt = ( bh >> 4 ) & 3; + ip++; + const int bt8 = (int) ( bt << 3 ); + + #if defined( LZAV_X86 ) + + static const uint32_t om[ 4 ] = { 0, 0xFF, 0xFFFF, 0xFFFFFF }; + static const int ocsh[ 4 ] = { 0, 0, 0, 3 }; + + LZAV_LOAD32( ip ); + ip += bt; + const uint32_t o = bv & om[ bt ]; + bv >>= bt8; + + const int wcsh = ocsh[ bt ]; + + LZAV_SET_IPD_CV( bh >> 6 | ( o & 0x1FFFFF ) << 2, o >> 21, wcsh ); + + #else // defined( LZAV_X86 ) + + // Memory accesses on RISC are less efficient here. + + LZAV_LOAD32( ip ); + const uint32_t om = ( (uint32_t) 1 << bt8 ) - 1; + ip += bt; + const size_t o = bv & om; + bv >>= bt8; + + LZAV_SET_IPD_CV( bh >> 6 | ( o & 0x1FFFFF ) << 2, o >> 21, + ( bt == 3 ? 3 : 0 )); + + #endif // defined( LZAV_X86 ) + + cc = bh & 15; + + if( LZAV_LIKELY( cc != 0 )) // True, if no additional length byte. + { + cc += mref1; + bh = bv & 0xFF; + + if( LZAV_LIKELY( op < opet )) + { + if( LZAV_LIKELY( d > 15 )) + { + memcpy( op, ipd, 16 ); + memcpy( op + 16, ipd + 16, 4 ); + op += cc; + continue; + } + + if( LZAV_LIKELY( d > 7 )) + { + memcpy( op, ipd, 8 ); + memcpy( op + 8, ipd + 8, 8 ); + op += cc; + continue; + } + + if( d > 3 ) + { + memcpy( op, ipd, 4 ); + memcpy( op + 4, ipd + 4, 4 ); + op += cc; + continue; + } + + goto _err_refoob; + } + + if( LZAV_UNLIKELY( cc > d )) + { + goto _err_refoob; + } + + uint8_t* const opcc = op + cc; + + if( LZAV_UNLIKELY( opcc > ope )) + { + goto _err_dstoob_ref; + } + + memcpy( op, ipd, cc ); + op = opcc; + continue; + } + else + { + bh = bv & 0xFF; + ip++; + cc = 16 + mref1 + bh; + + if( LZAV_UNLIKELY( bh == 255 )) + { + cc += *ip; + ip++; + } + + uint8_t* const opcc = op + cc; + bh = *ip; + + if( LZAV_LIKELY(( opcc < opet ) & ( d > 15 ))) + { + do + { + memcpy( op, ipd, 16 ); + memcpy( op + 16, ipd + 16, 16 ); + memcpy( op + 32, ipd + 32, 16 ); + memcpy( op + 48, ipd + 48, 16 ); + op += 64; + ipd += 64; + } while( op < opcc ); + + op = opcc; + continue; + } + + if( LZAV_UNLIKELY( cc > d )) + { + goto _err_refoob; + } + + if( LZAV_UNLIKELY( opcc > ope )) + { + goto _err_dstoob_ref; + } + + memcpy( op, ipd, cc ); + op = opcc; + continue; + } + + _err_dstoob_ref: + memcpy( op, ipd, (size_t) ( ope - op )); + return( LZAV_E_DSTOOB ); + } + + if( LZAV_UNLIKELY( op != ope )) + { + goto _err_dstlen; + } + + return( (int) ( op - (uint8_t*) dst )); + +_err_srcoob: + *pwl = (int) ( op - (uint8_t*) dst ); + return( LZAV_E_SRCOOB ); + +_err_refoob: + *pwl = (int) ( op - (uint8_t*) dst ); + return( LZAV_E_REFOOB ); + +_err_dstlen: + *pwl = (int) ( op - (uint8_t*) dst ); + return( LZAV_E_DSTLEN ); + +#if defined( LZAV_PTR32 ) +_err_ptrovr: + *pwl = (int) ( op - (uint8_t*) dst ); + return( LZAV_E_PTROVR ); +#endif // defined( LZAV_PTR32 ) +} + +#if LZAV_FMT_MIN < 2 + +/** + * @def LZAV_LOAD16( a ) + * @brief Defines `bv` and loads 16-bit unsigned value from memory, with + * endianness-correction. + * + * @param a Memory address. + */ + +/** + * @def LZAV_MEMMOVE( d, s, c ) + * @brief Stack-based `memmove` function which gets optimized into SIMD + * instructions. + * + * @param d Destination address. + * @param s Source address. + * @param c Byte copy count (must be a constant). + */ + +/** + * @brief Internal LZAV decompression function (stream format 1). + * + * Function decompresses "raw" data previously compressed into the LZAV stream + * format 1. + * + * This function should not be called directly since it does not check the + * format identifier. + * + * @param[in] src Source (compressed) data pointer. + * @param[out] dst Destination (decompressed data) buffer pointer. + * @param srcl Source data length, in bytes. + * @param dstl Expected destination data length, in bytes. + * @return The length of decompressed data, in bytes, or any negative value if + * some error happened. + */ + +static inline int lzav_decompress_1( const void* const src, void* const dst, + const int srcl, const int dstl ) LZAV_NOEX +{ + const uint8_t* ip = (const uint8_t*) src; // Compressed data pointer. + const uint8_t* const ipe = ip + srcl; // Compressed data boundary pointer. + const uint8_t* const ipet = ipe - 5; // Block header read threshold. + uint8_t* op = (uint8_t*) dst; // Destination (decompressed data) pointer. + uint8_t* const ope = op + dstl; // Destination boundary pointer. + uint8_t* const opet = ope - 63; // Threshold for fast copy to destination. + const size_t mref1 = (size_t) ( *ip & 15 ) - 1; // Minimal ref length - 1. + size_t bh = 0; // Current block header, updated in each branch. + size_t cv = 0; // Reference offset carry value. + int csh = 0; // Reference offset carry shift. + + #if LZAV_LITTLE_ENDIAN + #define LZAV_LOAD16( a ) \ + uint16_t bv; \ + memcpy( &bv, a, 2 ) + #else // LZAV_LITTLE_ENDIAN + #define LZAV_LOAD16( a ) \ + uint16_t bv = (uint16_t) ( *( a ) | *( a + 1 ) << 8 ) + #endif // LZAV_LITTLE_ENDIAN + + #define LZAV_MEMMOVE( d, s, c ) \ + { uint8_t tmp[ c ]; memcpy( tmp, s, c ); memcpy( d, tmp, c ); } (void) 0 + + ip++; // Advance beyond prefix byte. + + if( LZAV_UNLIKELY( ip >= ipet )) + { + goto _err_srcoob; + } + + bh = *ip; + + while( LZAV_LIKELY( ip < ipet )) + { + const uint8_t* ipd; // Source data pointer. + size_t cc; // Byte copy count. + + if( LZAV_UNLIKELY(( bh & 0x30 ) == 0 )) // Block type 0. + { + cv = bh >> 6; + csh = 2; + ip++; + cc = bh & 15; + + if( LZAV_LIKELY( cc != 0 )) // True, if no additional length byte. + { + ipd = ip; + ip += cc; + + if( LZAV_LIKELY(( op < opet ) & ( ipd < ipe - 15 - 6 ))) + { + bh = *ip; + memcpy( op, ipd, 16 ); + op += cc; + goto _refblk; // Reference block follows, if not EOS. + } + } + else + { + LZAV_LOAD16( ip ); + + const size_t l2 = (size_t) ( bv & 0xFF ); + cc = 16; + ip++; + const int lb = ( l2 == 255 ); + cc += l2 + (( bv >> 8 ) & ( 0x100 - lb )); + ip += lb; + + ipd = ip; + ip += cc; + + if( LZAV_LIKELY(( op < opet ) & ( ipd < ipe - 63 - 1 ))) + { + memcpy( op, ipd, 16 ); + memcpy( op + 16, ipd + 16, 16 ); + memcpy( op + 32, ipd + 32, 16 ); + memcpy( op + 48, ipd + 48, 16 ); + + if( LZAV_LIKELY( cc < 65 )) + { + bh = *ip; + op += cc; + continue; + } + + ipd += 64; + op += 64; + cc -= 64; + } + } + + if( LZAV_LIKELY( ip < ipe )) + { + bh = *ip; + } + else + if( LZAV_UNLIKELY( ip != ipe )) + { + goto _err_srcoob; + } + + if( LZAV_UNLIKELY( op + cc > ope )) + { + goto _err_dstoob; + } + + // This and other alike copy-blocks are transformed into fast SIMD + // instructions, by a modern compiler. Direct use of `memcpy` is + // slower due to shortness of data remaining to copy, on average. + + while( cc != 0 ) + { + *op = *ipd; + ipd++; + op++; + cc--; + } + + continue; + } + + _refblk: + cc = bh & 15; + + if( LZAV_UNLIKELY(( bh & 32 ) == 0 )) // True, if block type 1. + { + LZAV_SET_IPD( bh >> 6 | (size_t) ip[ 1 ] << 2 ); + ip += 2; + bh = *ip; + } + else // Block type 2 or 3. + { + if( LZAV_LIKELY(( bh & 16 ) == 0 )) // True, if block type 2. + { + LZAV_LOAD16( ip + 1 ); + LZAV_SET_IPD( bh >> 6 | (size_t) bv << 2 ); + ip += 3; + bh = *ip; + } + else // Block type 3. + { + LZAV_LOAD32( ip + 1 ); + LZAV_SET_IPD_CV( bv & 0xFFFFFF, bh >> 6, 2 ); + ip += 4; + bh = bv >> 24; + } + } + + if( LZAV_LIKELY( cc != 0 )) // True, if no additional length byte. + { + cc += mref1; + + if( LZAV_LIKELY( op < opet )) + { + LZAV_MEMMOVE( op, ipd, 16 ); + LZAV_MEMMOVE( op + 16, ipd + 16, 4 ); + + op += cc; + continue; + } + } + else + { + cc = 16 + mref1 + bh; + ip++; + bh = *ip; + + if( LZAV_LIKELY( op < opet )) + { + LZAV_MEMMOVE( op, ipd, 16 ); + LZAV_MEMMOVE( op + 16, ipd + 16, 16 ); + LZAV_MEMMOVE( op + 32, ipd + 32, 16 ); + LZAV_MEMMOVE( op + 48, ipd + 48, 16 ); + + if( LZAV_LIKELY( cc < 65 )) + { + op += cc; + continue; + } + + ipd += 64; + op += 64; + cc -= 64; + } + } + + if( LZAV_UNLIKELY( op + cc > ope )) + { + goto _err_dstoob; + } + + while( cc != 0 ) + { + *op = *ipd; + ipd++; + op++; + cc--; + } + } + + if( LZAV_UNLIKELY( op != ope )) + { + goto _err_dstlen; + } + + return( (int) ( op - (uint8_t*) dst )); + +_err_srcoob: + return( LZAV_E_SRCOOB ); + +_err_dstoob: + return( LZAV_E_DSTOOB ); + +_err_refoob: + return( LZAV_E_REFOOB ); + +_err_dstlen: + return( LZAV_E_DSTLEN ); +} + +#undef LZAV_LOAD16 +#undef LZAV_MEMMOVE + +#endif // LZAV_FMT_MIN < 2 + +#undef LZAV_LOAD32 +#undef LZAV_SET_IPD_CV +#undef LZAV_SET_IPD + +/** + * @brief LZAV decompression function (partial). + * + * Function decompresses "raw" data previously compressed into the LZAV stream + * format, for partial or recovery decompression. For example, this function + * can be used to decompress only an initial segment of a larger data block. + * + * @param[in] src Source (compressed) data pointer, can be 0 if `srcl` is 0. + * Address alignment is unimportant. + * @param[out] dst Destination (decompressed data) buffer pointer. Address + * alignment is unimportant. Should be different to `src`. + * @param srcl Source data length, in bytes, can be 0. + * @param dstl Destination buffer length, in bytes, can be 0. + * @return The length of decompressed data, in bytes. Always a non-negative + * value (error codes are not returned). + */ + +static inline int lzav_decompress_partial( const void* const src, + void* const dst, const int srcl, const int dstl ) LZAV_NOEX +{ + if( srcl <= 0 || src == LZAV_NULL || dst == LZAV_NULL || src == dst || + dstl <= 0 ) + { + return( 0 ); + } + + const int fmt = *(const uint8_t*) src >> 4; + int dl = 0; + + if( fmt == 2 ) + { + lzav_decompress_2( src, dst, srcl, dstl, &dl ); + } + + return( dl ); +} + +/** + * @brief LZAV decompression function. + * + * Function decompresses "raw" data previously compressed into the LZAV stream + * format. + * + * Note that while the function does perform checks to avoid OOB memory + * accesses, and checks for decompressed data length equality, this is not a + * strict guarantee of a valid decompression. In cases when the compressed + * data is stored in a long-term storage without embedded data integrity + * mechanisms (e.g., a database without RAID 1 guarantee, a binary container + * without a digital signature nor CRC), then a checksum (hash) of the + * original uncompressed data should be stored, and then evaluated against + * that of the decompressed data. Also, a separate checksum (hash) of + * application-defined header, which contains uncompressed and compressed data + * lengths, should be checked before decompression. A high-performance + * "komihash" hash function can be used to obtain a hash value of the data. + * + * @param[in] src Source (compressed) data pointer, can be 0 if `srcl` is 0. + * Address alignment is unimportant. + * @param[out] dst Destination (decompressed data) buffer pointer. Address + * alignment is unimportant. Should be different to `src`. + * @param srcl Source data length, in bytes, can be 0. + * @param dstl Expected destination data length, in bytes, can be 0. Should + * not be confused with the actual size of the destination buffer (which may + * be larger). + * @return The length of decompressed data, in bytes, or any negative value if + * some error happened. Always returns a negative value if the resulting + * decompressed data length differs from `dstl`. This means that error result + * handling requires just a check for a negative return value (see the + * LZAV_ERROR enum for possible values). + */ + +static inline int lzav_decompress( const void* const src, void* const dst, + const int srcl, const int dstl ) LZAV_NOEX +{ + if( srcl < 0 ) + { + return( LZAV_E_PARAMS ); + } + + if( srcl == 0 ) + { + return( dstl == 0 ? 0 : LZAV_E_PARAMS ); + } + + if( src == LZAV_NULL || dst == LZAV_NULL || src == dst || dstl <= 0 ) + { + return( LZAV_E_PARAMS ); + } + + const int fmt = *(const uint8_t*) src >> 4; + + if( fmt == 2 ) + { + int tmp; + return( lzav_decompress_2( src, dst, srcl, dstl, &tmp )); + } + +#if LZAV_FMT_MIN < 2 + if( fmt == 1 ) + { + return( lzav_decompress_1( src, dst, srcl, dstl )); + } +#endif // LZAV_FMT_MIN < 2 + + return( LZAV_E_UNKFMT ); +} + +#if defined( LZAV_NS ) + +} // namespace LZAV_NS + +#if !defined( LZAV_NS_CUSTOM ) + +namespace { + +using namespace LZAV_NS :: enum_wrapper; +using LZAV_NS :: lzav_compress_bound; +using LZAV_NS :: lzav_compress_bound_hi; +using LZAV_NS :: lzav_compress; +using LZAV_NS :: lzav_compress_default; +using LZAV_NS :: lzav_compress_hi; +using LZAV_NS :: lzav_decompress_partial; +using LZAV_NS :: lzav_decompress; + +} // namespace + +#endif // !defined( LZAV_NS_CUSTOM ) + +#endif // defined( LZAV_NS ) + +// Defines for Doxygen. + +#if !defined( LZAV_NS_CUSTOM ) + #define LZAV_NS_CUSTOM +#endif // !defined( LZAV_NS_CUSTOM ) + +#undef LZAV_NS_CUSTOM +#undef LZAV_NOEX +#undef LZAV_NULL +#undef LZAV_X86 +#undef LZAV_GCC_BUILTINS +#undef LZAV_IEC32 +#undef LZAV_LIKELY +#undef LZAV_UNLIKELY +#undef LZAV_HASH_C1 +#undef LZAV_HASH_C2 + +#endif // LZAV_INCLUDED diff --git a/arm9/source/main.cpp b/arm9/source/main.cpp new file mode 100644 index 0000000..a96990d --- /dev/null +++ b/arm9/source/main.cpp @@ -0,0 +1,283 @@ +// ===================================================================================== +// GimliDS Copyright (c) 2025 Dave Bernazzani (wavemotion-dave) +// +// As GimliDS is a port of the Frodo emulator for the DS/DSi/XL/LL handhelds, +// any copying or distribution of this emulator, its source code and associated +// readme files, with or without modification, are permitted per the original +// Frodo emulator license shown below. Hugest thanks to Christian Bauer for his +// efforts to provide a clean open-source emulation base for the C64. +// +// Numerous hacks and 'unsafe' optimizations have been performed on the original +// Frodo emulator codebase to get it running on the small handheld system. You +// are strongly encouraged to seek out the official Frodo sources if you're at +// all interested in this emulator code. +// +// The GimliDS emulator is offered as-is, without any warranty. Please see readme.md +// ===================================================================================== + +/* + * main.cpp - Main program + * + * Frodo Copyright (C) Christian Bauer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "sysdeps.h" + +#include "main.h" +#include "C64.h" +#include "Display.h" +#include "Prefs.h" + +#include "mainmenu.h" +#include "intro.h" +#include +#include +#include +#include +extern int init_graphics(void); + +extern void InterruptHandler(void); + +// Global variables +C64 *TheC64 = NULL; // Global C64 object +void intro_logo(void); +extern void init_maxmod(void); +extern void ShowKeyboard(void); +extern void BottomScreenMainMenu(void); + +#define KERNAL_ROM_FILE "kernal.rom" +#define BASIC_ROM_FILE "basic.rom" +#define CHAR_ROM_FILE "char.rom" +#define DRIVE_ROM_FILE "1541.rom" + +/* + * Load C64 ROM files + */ + +char big_path[300]; +u8 Frodo::load_rom(const char *which, const char *path, uint8 *where, size_t size) +{ + sprintf(big_path, "/roms/bios/%s", path); // Try /roms/bios + FILE *f = fopen(big_path, "rb"); + if (f) + { + size_t actual = fread(where, 1, size, f); + fclose(f); + if (actual == size) return 1; + } + else // Try /roms/c64 + { + sprintf(big_path, "/roms/c64/%s", path); + FILE *f = fopen(big_path, "rb"); + if (f) + { + size_t actual = fread(where, 1, size, f); + fclose(f); + if (actual == size) return 1; + } + else // Try current directory + { + FILE *f = fopen(path, "rb"); + if (f) + { + size_t actual = fread(where, 1, size, f); + fclose(f); + if (actual == size) return 1; + } + } + } + return 0; +} + +void Frodo::load_rom_files() +{ + u8 roms_loaded = 0; + roms_loaded += load_rom("Basic", BASIC_ROM_FILE, TheC64->Basic, BASIC_ROM_SIZE); + roms_loaded += load_rom("Kernal", KERNAL_ROM_FILE, TheC64->Kernal, KERNAL_ROM_SIZE); + roms_loaded += load_rom("Char", CHAR_ROM_FILE, TheC64->Char, CHAR_ROM_SIZE); + roms_loaded += load_rom("1541", DRIVE_ROM_FILE, TheC64->ROM1541, DRIVE_ROM_SIZE); + + if (roms_loaded != 4) + { + BottomScreenMainMenu(); + + DSPrint(0,5, 6, (char*) "ONE OR MORE BIOS ROMS NOT FOUND "); + DSPrint(0,7, 6, (char*) "THIS EMULATOR REQUIRES ORIGINAL "); + DSPrint(0,8, 6, (char*) "C64 BIOS ROMS AS FOLLOWS: "); + DSPrint(0,10,6, (char*) "KERNAL.ROM 8K CRC32:dbe3e7c7 "); + DSPrint(0,11,6, (char*) "BASIC.ROM 8K CRC32:f833d117 "); + DSPrint(0,12,6, (char*) "CHAR.ROM 4K CRC32:ec4272ee "); + DSPrint(0,13,6, (char*) "1541.ROM 16K CRC32:899fa3c5 "); + DSPrint(0,15,6, (char*) "PLACE THESE EXACTLY NAMED ROMS "); + DSPrint(0,16,6, (char*) "IN /ROMS/BIOS or /ROMS/C64 or "); + DSPrint(0,17,6, (char*) "IN THE SAME DIRECTORY AS THE EMU"); + while(1) asm("nop"); + } +} + +/* + * Create application object and start it + */ +extern "C" { +int main(int argc, char **argv) +{ + Frodo *the_app; + char *args[]={ (char*)"Gimli", NULL }; + + defaultExceptionHandler(); + + intro_logo(); + + if (!init_graphics()) + return 0; + + LoadConfig(); + + the_app = new Frodo(); + + the_app->ArgvReceived(1, args); + + keysSetRepeat(15, 6); + + the_app->ReadyToRun(); + delete the_app; + + return (1); +} + + +/* + * Constructor: Initialize member variables + */ + +Frodo::Frodo() +{ + TheC64 = NULL; +} + + +/* + * Process command line arguments + */ + +void Frodo::ArgvReceived(int argc, char **argv) +{ +} + + +/* + * Arguments processed, run emulation + */ + +void Frodo::ReadyToRun(void) +{ + // Create and start C64 + TheC64 = new C64; + + load_rom_files(); + + TheC64->Run(); + delete TheC64; +} + + +} + +bool IsDirectory(const char *path){ + struct stat st; + return stat(path, &st) == 0 && S_ISDIR(st.st_mode); +} + +#include +#include "soundbank.h" + +u16 vusCptVBL=0; +void vblankIntro() +{ + vusCptVBL++; +} + +/****************************************************************************** +* Routine FadeToColor : Fade from background to black or white +******************************************************************************/ +void FadeToColor(unsigned char ucSens, unsigned short ucBG, unsigned char ucScr, unsigned char valEnd, unsigned char uWait) { + unsigned short ucFade; + unsigned char ucBcl; + + // Fade-out to black + if (ucScr & 0x01) REG_BLDCNT=ucBG; + if (ucScr & 0x02) REG_BLDCNT_SUB=ucBG; + if (ucSens == 1) { + for(ucFade=0;ucFadevalEnd;ucFade--) { + if (ucScr & 0x01) REG_BLDY=ucFade; + if (ucScr & 0x02) REG_BLDY_SUB=ucFade; + for (ucBcl=0;ucBcl +#include +#include +#include +#include +#include + +#include +#include +#include "C64.h" +#include "diskmenu.h" +#include "mainmenu.h" +#include "mainmenu_bg.h" +#include "Prefs.h" + +extern C64 *TheC64; +extern int bg0b, bg1b; + +#define WAITVBL swiWaitForVBlank();swiWaitForVBlank();swiWaitForVBlank(); +static u16 nds_key; +extern void BottomScreenMainMenu(void); + +// ---------------------------------------------------------------------- +// The Disk Menu can be called up directly from the keyboard graphic +// and allows the user to rewind the tape, swap in a new tape, etc. +// ---------------------------------------------------------------------- +#define MENU_ACTION_END 255 // Always the last sentinal value +#define MENU_ACTION_EXIT 0 // Exit the menu +#define MENU_ACTION_RESET_EMU 1 // Reset Emulator +#define MENU_ACTION_SAVE_STATE 2 // +#define MENU_ACTION_LOAD_STATE 3 // +#define MENU_ACTION_CONFIG 4 // +#define MENU_ACTION_SKIP 99 // Skip this MENU choice + +typedef struct +{ + char *menu_string; + u8 menu_action; +} MenuItem_t; + +typedef struct +{ + char *title; + u8 start_row; + MenuItem_t menulist[15]; +} MainMenu_t; + +MainMenu_t main_menu = +{ + (char *)"MAIN MENU", 7, + { + {(char *)" CONFIG GAME ", MENU_ACTION_CONFIG}, + {(char *)" SAVE STATE ", MENU_ACTION_SAVE_STATE}, + {(char *)" LOAD STATE ", MENU_ACTION_LOAD_STATE}, + {(char *)" RESET C64 ", MENU_ACTION_RESET_EMU}, + {(char *)" EXIT MENU ", MENU_ACTION_EXIT}, + {(char *)" NULL ", MENU_ACTION_END}, + }, +}; + +static MainMenu_t *menu = &main_menu; + +// ------------------------------------------------------- +// Show the Main Menu text - highlight the selected row. +// ------------------------------------------------------- +u8 main_menu_items = 0; +void MainMenuShow(bool bClearScreen, u8 sel) +{ + main_menu_items = 0; + + if (bClearScreen) + { + BottomScreenMainMenu(); + } + + // --------------------------------------------------- + // Pick the right context menu based on the machine + // --------------------------------------------------- + menu = &main_menu; + + // Display the menu title + DSPrint(15-(strlen(menu->title)/2), menu->start_row, 6, menu->title); + + // And display all of the menu items + while (menu->menulist[main_menu_items].menu_action != MENU_ACTION_END) + { + DSPrint(16-(strlen(menu->menulist[main_menu_items].menu_string)/2), menu->start_row+2+main_menu_items, (main_menu_items == sel) ? 7:6, menu->menulist[main_menu_items].menu_string); + main_menu_items++; + } +} + +static char theDrivePath[256]; + +void check_and_make_sav_directory(void) +{ + // Init filename = romname and SAV in place of ROM + DIR* dir = opendir("sav"); + if (dir) closedir(dir); // Directory exists... close it out and move on. + else mkdir("sav", 0777); // Otherwise create the directory... +} + + +// ------------------------------------------------------------------------ +// Handle Main Menu interface... +// ------------------------------------------------------------------------ +u8 MainMenu(C64 *the_c64) +{ + u8 menuSelection = 0; + u8 retVal = 0; + + while ((keysCurrent() & (KEY_TOUCH | KEY_LEFT | KEY_RIGHT | KEY_A ))!=0); + + // ------------------------------------------------------------------ + //Show the cassette menu background - we'll draw text on top of this + // ------------------------------------------------------------------ + MainMenuShow(true, menuSelection); + + u8 bExitMenu = false; + while (true) + { + nds_key = keysCurrent(); + if (nds_key) + { + if (nds_key & KEY_UP) + { + menuSelection = (menuSelection > 0) ? (menuSelection-1):(main_menu_items-1); + while (menu->menulist[menuSelection].menu_action == MENU_ACTION_SKIP) + { + menuSelection = (menuSelection > 0) ? (menuSelection-1):(main_menu_items-1); + } + MainMenuShow(false, menuSelection); + } + if (nds_key & KEY_DOWN) + { + menuSelection = (menuSelection+1) % main_menu_items; + while (menu->menulist[menuSelection].menu_action == MENU_ACTION_SKIP) + { + menuSelection = (menuSelection+1) % main_menu_items; + } + MainMenuShow(false, menuSelection); + } + if (nds_key & KEY_B) // Treat this as selecting 'exit' + { + bExitMenu = true; + } + else if (nds_key & KEY_A) // User has picked a menu item... let's see what it is! + { + switch(menu->menulist[menuSelection].menu_action) + { + case MENU_ACTION_RESET_EMU: + the_c64->PatchKernal(ThePrefs.FastReset, ThePrefs.TrueDrive); + the_c64->Reset(); + bExitMenu = true; + break; + + case MENU_ACTION_CONFIG: + if (file_crc != 0x00000000) + { + u8 last_trueDrive = myConfig.trueDrive; + GimliDSGameOptions(); + if (last_trueDrive != myConfig.trueDrive) // Need to reload... + { + Prefs *prefs = new Prefs(ThePrefs); + prefs->TrueDrive = myConfig.trueDrive; + the_c64->NewPrefs(prefs); + ThePrefs = *prefs; + delete prefs; + } + bExitMenu = true; + } + else + { + DSPrint(0, 18, 6, (char*)" NO GAME IS LOADED "); + WAITVBL;WAITVBL;WAITVBL;WAITVBL;WAITVBL;WAITVBL; + WAITVBL;WAITVBL;WAITVBL;WAITVBL;WAITVBL;WAITVBL; + WAITVBL;WAITVBL;WAITVBL;WAITVBL;WAITVBL;WAITVBL; + DSPrint(0, 18, 6, (char*)" "); + } + break; + + case MENU_ACTION_SAVE_STATE: + { + check_and_make_sav_directory(); + sprintf(theDrivePath,"sav/%s", ThePrefs.DrivePath[0]); + int len = strlen(theDrivePath); + if (len > 4) + { + char *p=&theDrivePath[len-4]; + strcpy(p,".GSS"); + } + if (the_c64->SaveSnapshot(theDrivePath) == false) + { + DSPrint(0, 18, 6, (char*)" UNABLE TO SAVE STATE "); + } + else + { + DSPrint(0, 18, 6, (char*)" .GSS SNAPSHOT SAVED "); + } + WAITVBL;WAITVBL;WAITVBL;WAITVBL;WAITVBL;WAITVBL; + WAITVBL;WAITVBL;WAITVBL;WAITVBL;WAITVBL;WAITVBL; + WAITVBL;WAITVBL;WAITVBL;WAITVBL;WAITVBL;WAITVBL; + DSPrint(0, 18, 6, (char*)" "); + bExitMenu = true; + } + break; + + case MENU_ACTION_LOAD_STATE: + { + check_and_make_sav_directory(); + sprintf(theDrivePath,"sav/%s", ThePrefs.DrivePath[0]); + int len = strlen(theDrivePath); + if (len > 4) + { + char *p=&theDrivePath[len-4]; + strcpy(p,".GSS"); + } + if (the_c64->LoadSnapshot(theDrivePath) == false) + { + DSPrint(0, 18, 6, (char*)" NO VALID SNAPSHOT FOUND "); + WAITVBL;WAITVBL;WAITVBL;WAITVBL;WAITVBL;WAITVBL; + WAITVBL;WAITVBL;WAITVBL;WAITVBL;WAITVBL;WAITVBL; + WAITVBL;WAITVBL;WAITVBL;WAITVBL;WAITVBL;WAITVBL; + DSPrint(0, 18, 6, (char*)" "); + } + bExitMenu = true; + } + break; + + case MENU_ACTION_EXIT: + bExitMenu = true; + break; + } + } + + if (bExitMenu) break; + while ((keysCurrent() & (KEY_UP | KEY_DOWN | KEY_A ))!=0); + WAITVBL;WAITVBL;WAITVBL; + } + } + + while ((keysCurrent() & (KEY_UP | KEY_DOWN | KEY_A ))!=0); + WAITVBL;WAITVBL;WAITVBL; + + return retVal; +} + + +// zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz + +#define CRC32_POLY 0x04C11DB7 + +const u32 crc32_table[256] = { + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, // 0 [0x00 .. 0x07] + 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, // 8 [0x08 .. 0x0F] + 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, // 16 [0x10 .. 0x17] + 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, // 24 [0x18 .. 0x1F] + 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, // 32 [0x20 .. 0x27] + 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, // 40 [0x28 .. 0x2F] + 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, // 48 [0x30 .. 0x37] + 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, // 56 [0x38 .. 0x3F] + 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, // 64 [0x40 .. 0x47] + 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, // 72 [0x48 .. 0x4F] + 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, // 80 [0x50 .. 0x57] + 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, // 88 [0x58 .. 0x5F] + 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, // 96 [0x60 .. 0x67] + 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, // 104 [0x68 .. 0x6F] + 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, // 112 [0x70 .. 0x77] + 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, // 120 [0x78 .. 0x7F] + 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, // 128 [0x80 .. 0x87] + 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, // 136 [0x88 .. 0x8F] + 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, // 144 [0x90 .. 0x97] + 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, // 152 [0x98 .. 0x9F] + 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, // 160 [0xA0 .. 0xA7] + 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, // 168 [0xA8 .. 0xAF] + 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, // 176 [0xB0 .. 0xB7] + 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, // 184 [0xB8 .. 0xBF] + 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, // 192 [0xC0 .. 0xC7] + 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, // 200 [0xC8 .. 0xCF] + 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, // 208 [0xD0 .. 0xD7] + 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, // 216 [0xD8 .. 0xDF] + 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, // 224 [0xE0 .. 0xE7] + 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, // 232 [0xE8 .. 0xEF] + 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, // 240 [0xF0 .. 0xF7] + 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D, // 248 [0xF8 .. 0xFF] +}; + +// -------------------------------------------------- +// Compute the CRC of a memory buffer of any size... +// -------------------------------------------------- +u32 getCRC32(u8 *buf, int size) +{ + u32 crc = 0xFFFFFFFF; + + for (int i=0; i < size; i++) + { + crc = (crc >> 8) ^ crc32_table[(crc & 0xFF) ^ (u8)buf[i]]; + } + + return ~crc; +} + +extern char strBuf[]; +u32 file_crc = 0x00000000; +u8 option_table=0; + +struct Config_t AllConfigs[MAX_CONFIGS]; +struct Config_t myConfig __attribute((aligned(4))) __attribute__((section(".dtcm"))); + + +void SetDefaultGameConfig(void) +{ + myConfig.game_crc = 0; // No game in this slot yet + + myConfig.key_A = 0; + myConfig.key_B = 1; + myConfig.key_Y = 2; + myConfig.key_X = 3; + myConfig.autoFire = 0; + myConfig.trueDrive = 0; + myConfig.jitter = 1; // Medium + myConfig.diskSFX = 1; // Disk sound effects on + myConfig.reserved1 = 0; + myConfig.reserved2 = 0; + myConfig.reserved3 = 0; + myConfig.reserved4 = 0; + myConfig.reserved5 = 0; + myConfig.reserved6 = 0xA5; // So it's easy to spot on an "upgrade" and we can re-default it + + myConfig.cpuCycles = 0; // Normal 63 - this is the adjustment to that + myConfig.badCycles = 0; // Normal 23 - this is the adjustment to that + + myConfig.offsetX = 32; + myConfig.offsetY = 35; + myConfig.scaleX = 256; + myConfig.scaleY = 200; +} + +s16 CycleDeltas[] = {0,1,2,3,4,5,6,7,8,9,-9,-8,-7,-6,-5,-4,-3,-2,-1}; + +// ---------------------------------------------------------------------- +// Read file twice and ensure we get the same CRC... if not, do it again +// until we get a clean read. Return the filesize to the caller... +// ---------------------------------------------------------------------- +u32 ReadFileCarefully(char *filename, u8 *buf, u32 buf_size, u32 buf_offset) +{ + u32 crc1 = 0; + u32 crc2 = 1; + u32 fileSize = 0; + + // -------------------------------------------------------------------------------------------- + // I've seen some rare issues with reading files from the SD card on a DSi so we're doing + // this slow and careful - we will read twice and ensure that we get the same CRC both times. + // -------------------------------------------------------------------------------------------- + do + { + // Read #1 + crc1 = 0xFFFFFFFF; + FILE* file = fopen(filename, "rb"); + if (file) + { + if (buf_offset) fseek(file, buf_offset, SEEK_SET); + fileSize = fread(buf, 1, buf_size, file); + crc1 = getCRC32(buf, buf_size); + fclose(file); + } + + // Read #2 + crc2 = 0xFFFFFFFF; + FILE* file2 = fopen(filename, "rb"); + if (file2) + { + if (buf_offset) fseek(file2, buf_offset, SEEK_SET); + fread(buf, 1, buf_size, file2); + crc2 = getCRC32(buf, buf_size); + fclose(file2); + } + } while (crc1 != crc2); // If the file couldn't be read, file_size will be 0 and the CRCs will both be 0xFFFFFFFF + + return fileSize; +} + + +// --------------------------------------------------------------------------- +// Write out the GimliDS.DAT configuration file to capture the settings for +// each game. This one file contains global settings ~1000 game settings. +// --------------------------------------------------------------------------- +void SaveConfig(bool bShow) +{ + FILE *fp; + int slot = 0; + + if (bShow) DSPrint(6,23,0, (char*)"SAVING CONFIGURATION"); + + // If there is a game loaded, save that into a slot... re-use the same slot if it exists + myConfig.game_crc = file_crc; + + // Find the slot we should save into... + for (slot=0; slot 0) optionHighlighted--; else optionHighlighted=(idx-1); + sprintf(strBuf, " %-12s : %-14s", Option_Table[option_table][optionHighlighted].label, Option_Table[option_table][optionHighlighted].option[*(Option_Table[option_table][optionHighlighted].option_val)]); + DSPrint(1,5+optionHighlighted,2, strBuf); + } + if (keysCurrent() & KEY_DOWN) // Next option + { + sprintf(strBuf, " %-12s : %-14s", Option_Table[option_table][optionHighlighted].label, Option_Table[option_table][optionHighlighted].option[*(Option_Table[option_table][optionHighlighted].option_val)]); + DSPrint(1,5+optionHighlighted,0, strBuf); + if (optionHighlighted < (idx-1)) optionHighlighted++; else optionHighlighted=0; + sprintf(strBuf, " %-12s : %-14s", Option_Table[option_table][optionHighlighted].label, Option_Table[option_table][optionHighlighted].option[*(Option_Table[option_table][optionHighlighted].option_val)]); + DSPrint(1,5+optionHighlighted,2, strBuf); + } + + if (keysCurrent() & KEY_RIGHT) // Toggle option clockwise + { + *(Option_Table[option_table][optionHighlighted].option_val) = (*(Option_Table[option_table][optionHighlighted].option_val) + 1) % Option_Table[option_table][optionHighlighted].option_max; + sprintf(strBuf, " %-12s : %-14s", Option_Table[option_table][optionHighlighted].label, Option_Table[option_table][optionHighlighted].option[*(Option_Table[option_table][optionHighlighted].option_val)]); + DSPrint(1,5+optionHighlighted,2, strBuf); + } + if (keysCurrent() & KEY_LEFT) // Toggle option counterclockwise + { + if ((*(Option_Table[option_table][optionHighlighted].option_val)) == 0) + *(Option_Table[option_table][optionHighlighted].option_val) = Option_Table[option_table][optionHighlighted].option_max -1; + else + *(Option_Table[option_table][optionHighlighted].option_val) = (*(Option_Table[option_table][optionHighlighted].option_val) - 1) % Option_Table[option_table][optionHighlighted].option_max; + sprintf(strBuf, " %-12s : %-14s", Option_Table[option_table][optionHighlighted].label, Option_Table[option_table][optionHighlighted].option[*(Option_Table[option_table][optionHighlighted].option_val)]); + DSPrint(1,5+optionHighlighted,2, strBuf); + } + if (keysCurrent() & KEY_START) // Save Options + { + SaveConfig(TRUE); + } + if ((keysCurrent() & KEY_B) || (keysCurrent() & KEY_A)) // Exit options + { + option_table = 0; // Reset for next time + break; + } + } + swiWaitForVBlank(); + } + + // Give a third of a second time delay... + for (int i=0; i<20; i++) + { + swiWaitForVBlank(); + } + + return; +} diff --git a/arm9/source/mainmenu.h b/arm9/source/mainmenu.h new file mode 100644 index 0000000..cfd12a2 --- /dev/null +++ b/arm9/source/mainmenu.h @@ -0,0 +1,48 @@ + +#define MAX_CONFIGS 1150 +#define CONFIG_VERSION 0x0004 + +extern s16 CycleDeltas[]; + +struct __attribute__((__packed__)) Config_t +{ + u32 game_crc; + u8 key_A; + u8 key_B; + u8 key_X; + u8 key_Y; + u8 trueDrive; + u8 autoFire; + u8 jitter; + u8 diskSFX; + u8 reserved1; + u8 reserved2; + u8 reserved3; + u8 reserved4; + u8 reserved5; + u8 reserved6; + u8 cpuCycles; + u8 badCycles; + s16 offsetX; + s16 offsetY; + s16 scaleX; + s16 scaleY; +}; + +extern struct Config_t myConfig; + + +#define KEY_MAP_JOY_FIRE 0 +#define KEY_MAP_SPACE 1 +#define KEY_MAP_RETURN 2 +#define KEY_MAP_JOY_UP 3 +#define KEY_MAP_JOY_DN 4 +#define KEY_MAP_PAN_UP 5 +#define KEY_MAP_PAN_DN 6 + +extern u32 getCRC32(u8 *buf, int size); +extern u32 file_crc; +void LoadConfig(void); +void SaveConfig(void); +void FindConfig(void); +void GimliDSGameOptions(void); diff --git a/arm9/source/soundbank.h b/arm9/source/soundbank.h new file mode 100644 index 0000000..5f70863 --- /dev/null +++ b/arm9/source/soundbank.h @@ -0,0 +1,6 @@ +#define SFX_FLOPPY 0 +#define SFX_KEYCLICK 1 +#define SFX_MUS_INTRO 2 +#define MSL_NSONGS 0 +#define MSL_NSAMPS 3 +#define MSL_BANKSIZE 3 diff --git a/arm9/source/sysconfig.h b/arm9/source/sysconfig.h new file mode 100644 index 0000000..305025d --- /dev/null +++ b/arm9/source/sysconfig.h @@ -0,0 +1,129 @@ +/* sysconfig.h.in. Generated from configure.in by autoheader. */ + +/* Define if you have the header file, and it defines `DIR'. */ +#define HAVE_DIRENT_H 1 + +/* Define if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define if you have the `gettimeofday' function. */ +#define HAVE_GETTIMEOFDAY 1 + +/* Define if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define if you have the `mkdir' function. */ +#define HAVE_MKDIR 1 + +/* Define if you have the header file, and it defines `DIR'. */ +#undef HAVE_NDIR_H + +/* Define if you have the `rmdir' function. */ +#define HAVE_RMDIR 1 + +/* Define if you have the `select' function. */ +#undef HAVE_SELECT + +/* Define if you have the `statfs' function. */ +#undef HAVE_STATFS + +/* Define if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define if you have the `strstr' function. */ +#define HAVE_STRSTR 1 + +/* Define if `st_blocks' is member of `struct stat'. */ +#define HAVE_STRUCT_STAT_ST_BLOCKS 1 + +/* Define if you have the header file, and it defines `DIR'. */ +#define HAVE_SYS_DIR_H 1 + +/* Define if you have the header file. */ +#undef HAVE_SYS_MOUNT_H + +/* Define if you have the header file, and it defines `DIR'. */ +#undef HAVE_SYS_NDIR_H + +/* Define if you have the header file. */ +#define HAVE_SYS_PARAM_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_SELECT_H 1 + +/* Define if you have the header file. */ +#undef HAVE_SYS_STATFS_H + +/* Define if you have the header file. */ +#define HAVE_SYS_STATVFS_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define if you have the header file. */ +#undef HAVE_SYS_VFS_H + +/* Define if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define if you have the `usleep' function. */ +#undef HAVE_USLEEP + +/* Define if you have the header file. */ +#undef HAVE_UTIME_H + +/* Define if `utime(file, NULL)' sets file's timestamp to the present. */ +#undef HAVE_UTIME_NULL + +/* Define if you have the header file. */ +#undef HAVE_VALUES_H + +/* The size of a `char', as computed by sizeof. */ +#define SIZEOF_CHAR 1 + +/* The size of a `int', as computed by sizeof. */ +#define SIZEOF_INT 4 + +/* The size of a `long', as computed by sizeof. */ +#define SIZEOF_LONG 4 + +/* The size of a `long long', as computed by sizeof. */ +#define SIZEOF_LONG_LONG 8 + +/* The size of a `short', as computed by sizeof. */ +#define SIZEOF_SHORT 2 + +/* Define if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define if you can safely include both and . */ +#undef TIME_WITH_SYS_TIME + +/* Define if your declares `struct tm'. */ +#undef TM_IN_SYS_TIME + +// Use iprintf/iscanf on NDS to save ~50 KB +#define sscanf siscanf +#define printf iprintf +#define fprintf fiprintf +#define sprintf siprintf +#define snprintf sniprintf +#define vsnprintf vsniprintf diff --git a/arm9/source/sysdeps.h b/arm9/source/sysdeps.h new file mode 100644 index 0000000..aea4319 --- /dev/null +++ b/arm9/source/sysdeps.h @@ -0,0 +1,200 @@ +/* + * sysdeps.h - Try to include the right system headers and get other + * system-specific stuff right + * + * Frodo Copyright (C) Christian Bauer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "sysconfig.h" +#include + +extern int debug[]; +// +//#ifdef EMU +//#include +//#else +//#include "gba_nds_fat/gba_nds_fat.h" +//#endif +//#include +//#include +// +//#undef FILE +//#undef DIR +//#undef size_t +//#undef fopen +//#undef fread +//#undef fwrite +//#undef fclose +//#undef ftell +//#undef rewind +//#undef fseek +//#undef chdir +//#undef ftell +//#undef getc +//#undef tmpfile +//#undef rewind +//#undef putc +//#undef fputc +//#undef fscanf +//#undef feof +//#undef stdin +//#undef stdout +//#undef fflush +// +//#ifdef EMU +//#define FILE KOS_FILE +//#define fopen KOS_fopen +//#define fwrite KOS_fwrite +//#define fread KOS_fread +//#define fclose KOS_fclose +//#define fseek KOS_fseek +//#define fputs KOS_fputs +//#define fgets KOS_fgets +//#define fputc KOS_fputc +//#define getc KOS_getc +//#define putc KOS_putc +//#define fgetc KOS_fgetc +//#define fprintf KOS_fprintf +//#define vfprintf KOS_fprintf +//#define ftell KOS_ftell +//#define tmpfile KOS_tmpfile +//#define rewind KOS_rewind +//#define feof KOS_feof +//#define stdin KOS_stdin +//#define stdout KOS_stdout +//#define fscanf KOS_fscanf +//#define fflush KOS_fflush +//#else +//#define FILE FAT_FILE +//#define fopen FAT_fopen +//#define fwrite FAT_fwrite +//#define fread FAT_fread +//#define fclose FAT_fclose +//#define fseek FAT_fseek +//#define fputs FAT_fputs +//#define fgets FAT_fgets +//#define fputc FAT_fputc +//#define getc FAT_getc +//#define putc FAT_putc +//#define fgetc FAT_fgetc +//#define fprintf FAT_fprintf +//#define vfprintf FAT_fprintf +//#define ftell FAT_ftell +//#define tmpfile FAT_tmpfile +//#define rewind FAT_rewind +//#define feof FAT_feof +//#define stdin FAT_stdin +//#define stdout FAT_stdout +//#define fscanf FAT_fscanf +//#define fflush FAT_fflush +//#endif +#include +#include +#include +#include +#include + +#include +using std::vector; + +#ifdef HAVE_SYS_TYPES_H +#include +#endif + +#ifdef HAVE_VALUES_H +#include +#endif + +#ifdef HAVE_STRINGS_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif + +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_FCNTL_H +#include +#endif + +#ifdef HAVE_UTIME_H +#include +#endif + +#ifdef HAVE_SYS_PARAM_H +#include +#endif + +#ifdef HAVE_SYS_SELECT_H +#include +#endif + +#ifdef HAVE_SYS_VFS_H +#include +#endif + +#ifdef HAVE_SYS_STAT_H +#include +#endif + +#ifdef HAVE_SYS_MOUNT_H +#include +#endif + +#ifdef HAVE_SYS_STATFS_H +#include +#endif + +#ifdef HAVE_SYS_STATVFS_H +#include +#endif + +#if TIME_WITH_SYS_TIME +# include +# include +#else +# if HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif + +#if HAVE_DIRENT_H +# include +#else +# define dirent direct +# if HAVE_SYS_NDIR_H +# include +# endif +# if HAVE_SYS_DIR_H +# include +# endif +# if HAVE_NDIR_H +# include +# endif +#endif + +#include +#include + +#if EEXIST == ENOTEMPTY +#define BROKEN_OS_PROBABLY_AIX +#endif +