Post your WIPs
-
- Posts: 1445
- Joined: Mon Feb 11, 2013 8:08 am
- Location: Brisbane, Australia
Re: Post your WIPs
Yes - it needs to be cycle accurate because I am bastardizing it as a timer to end the scanline. TIMR0_OVF is already being used for something else crazy.
It however does not need to be "uart accurate". I don't care if it can emulate the sending of data or if it listens to the configuration bits regarding bits lenghts and parity etc.
All I need is that it triggers an interrupt 1305 clocks cycles after I do a
STS UBRR0L, r16
STS UDR0, r16
That is how many clocks the real hardware will trigger USART0_TXCI with UBRR0L being set to 8 and data length set to 7.
I was planing on cheating and modifying cuzebox so it just triggered an interrupt on that clock count rather than trying to emulate the intricacies of the uart prescaler etc.
I don't think I am smart enough to modify cuzebox to fully emulate the USART hardware.
It however does not need to be "uart accurate". I don't care if it can emulate the sending of data or if it listens to the configuration bits regarding bits lenghts and parity etc.
All I need is that it triggers an interrupt 1305 clocks cycles after I do a
STS UBRR0L, r16
STS UDR0, r16
That is how many clocks the real hardware will trigger USART0_TXCI with UBRR0L being set to 8 and data length set to 7.
I was planing on cheating and modifying cuzebox so it just triggered an interrupt on that clock count rather than trying to emulate the intricacies of the uart prescaler etc.
I don't think I am smart enough to modify cuzebox to fully emulate the USART hardware.
Re: Post your WIPs
Here is my "This looks like where the changes need to happen" analysis, but it's probably not complete, and there are probably some side-effects that I haven't anticipated, so I'm not going to actually attempt an implementation. I think that Jubatian is the only one that has a complete understanding of how CUzeBox works, but I at least wanted to try to understand what modifications would need to be made to support this, just as a fun exercise.CunningFellow wrote: ↑Wed Oct 11, 2017 11:14 am Yes - it needs to be cycle accurate because I am bastardizing it as a timer to end the scanline. TIMR0_OVF is already being used for something else crazy.
It however does not need to be "uart accurate". I don't care if it can emulate the sending of data or if it listens to the configuration bits regarding bits lenghts and parity etc.
All I need is that it triggers an interrupt 1305 clocks cycles after I do a
STS UBRR0L, r16
STS UDR0, r16
That is how many clocks the real hardware will trigger USART0_TXCI with UBRR0L being set to 8 and data length set to 7.
I was planing on cheating and modifying cuzebox so it just triggered an interrupt on that clock count rather than trying to emulate the intricacies of the uart prescaler etc.
I don't think I am smart enough to modify cuzebox to fully emulate the USART hardware.
There are two different implementations of the opcode decoder in cu_avr_n.h and cu_avr_e.h, but I don't think those need to be touched, because we're not adding or changing any opcodes, only keying off the values set by existing opcodes (STS).
In cu_avr.c, there is a function called cu_avr_write_io. Depending on how much we want to cheat at this, I assume that we'll need to add cases for CU_IO_UBRR0L and CU_IO_UDR0, and CU_IO_USCRA, CU_IO_USCRB, CU_IO_USCRC along with some state variables so we can calculate how many clocks the interrupt needs to fire after.
You said that in your code, those two instructions were right after each other, but the timing would still be correct as long as those two instructions were within 80 clocks of each other?
I would take a look at the cu_avr_interrupt function in that file to see how it works, but I don't think we'll need to modify that, only understand it. It looks another case needs to be added to the cu_avr_itcheck function to get it to enter the new interrupt that has to be defined.
These variables look like they might be good ones to search for in the code to understand how the interrupt scheduling code works:
Code: Select all
/* Interrupt might be waiting to be serviced flag. This is set nonzero by
** any event which should trigger an IT including setting the I flag in the
** status register. It can be safely set nonzero to ask for a certain IT
** check. */
boole event_it;
/* Interrupt entry necessary if set. */
boole event_it_enter;
/* Vector to call when entering interrupt */
auint event_it_vect;
Like I said before, I'm not going to attempt these modifications myself, but I figured this could be a good opportunity to at least familiarize myself with a bit more of the CUzeBox codebase.
Re: Post your WIPs
These are about right. What you need to pay more attention is cu_avr_hwexec and the event system implemented, that is, how CUzeBox determines the next cycle when it should service a hardware event (this is a critical part of having blazing fast emulation). Just check what other peripherals do to time stuff.
Emulation is cycle-exact on terms of when an input port is sampled or when an output can have effect, so normally you don't need hacks, things will just work (unlike in Uzem where Timer1 carried ugly hacks to realize cycle-accurate timing). If you are unsure, Mode 13 or something similar may be a good base to fix your timing even if you don't have any instrumentation. I actually did this: I compared the last pixel between the real hardware and CUzeBox, how it is affected by shifting around timing in either.
The process is roughly that using the real hardware, you have to get to the point where your code does what you think it should be doing. In the case of Mode 13, it is that the interrupt fires exactly after the last "out" (resulting in a 7 clocks wide last pixel due to 3 cy IT latency + 3 cy "jmp" instruction in the vector table). You reduce the timer one by one until you see the last pixel disappearing. The value just before that is the correct timer value for the mode. Then you do the same for the emulator. If in the end the two values are the same, the emulator is cycle exact.
Simple, and really no tools are required beyond the Uzebox.
If you however have a fixed time, just start adding nops to shift around the end of the display to get the same effect (or the point where you fire the timer).
Emulation is cycle-exact on terms of when an input port is sampled or when an output can have effect, so normally you don't need hacks, things will just work (unlike in Uzem where Timer1 carried ugly hacks to realize cycle-accurate timing). If you are unsure, Mode 13 or something similar may be a good base to fix your timing even if you don't have any instrumentation. I actually did this: I compared the last pixel between the real hardware and CUzeBox, how it is affected by shifting around timing in either.
The process is roughly that using the real hardware, you have to get to the point where your code does what you think it should be doing. In the case of Mode 13, it is that the interrupt fires exactly after the last "out" (resulting in a 7 clocks wide last pixel due to 3 cy IT latency + 3 cy "jmp" instruction in the vector table). You reduce the timer one by one until you see the last pixel disappearing. The value just before that is the correct timer value for the mode. Then you do the same for the emulator. If in the end the two values are the same, the emulator is cycle exact.
Simple, and really no tools are required beyond the Uzebox.
If you however have a fixed time, just start adding nops to shift around the end of the display to get the same effect (or the point where you fire the timer).
Re: Post your WIPs
I'm working on a Doodle Jump type of game. It's called UzeJump. I've got the basics done, I just need to work on the levels and scrolling.
Picture:
https://i.imgur.com/BQLPrls.png
Here's the source code if you want to take a look:
https://github.com/ry755/UzeJump
Picture:
https://i.imgur.com/BQLPrls.png
Here's the source code if you want to take a look:
https://github.com/ry755/UzeJump
Re: Post your WIPs
Very cool, looking forward to seeing this one progress
Re: Post your WIPs
I have to second what Uze said about Mega Bomber. Its arguably the most graphically impressive game for the Uzebox and it could almost pass as being a SNES game so I was diappointed to test it with a friend last night and discover that two player mode doesn't work. Surely adding a working second player would be pretty easy to do? I've not looked at or tried building its code yet.
With Mega Bomber's two player mode not working, it makes me doubt that four player mode (via a multi-tap) has ever worked. Does the standard UB kernel support the multi-tap ie 4 or 5 joystick inputs?
With Mega Bomber's two player mode not working, it makes me doubt that four player mode (via a multi-tap) has ever worked. Does the standard UB kernel support the multi-tap ie 4 or 5 joystick inputs?
Re: Post your WIPs
I've not been able to build Mega Bomber ( in the MegaBomber subdir of https://github.com/weber21w/uzebox-weber/ )
Code: Select all
avr-gcc -I"../../../../uzebox/kernel/" -mmcu=atmega644 -mmcu=atmega644 -Wall -gdwarf-2 -std=gnu99 -DF_CPU=28636360UL -Os -fsigned-char -ffunction-sections -MD -MP -MT uzeboxSoundEngineCore.o -MF dep/uzeboxSoundEngineCore.o.d -DVIDEO_MODE=3 -DINTRO_LOGO=0 -DSOUND_CHANNEL_4_ENABLE=1 -DSOUND_CHANNEL_2_ENABLE=1 -DSOUND_CHANNEL_3_ENABLE=1 -DCENTER_ADJUSTMENT=4 -DMAX_SPRITES=31 -DRAM_TILES_COUNT=31 -DSCREEN_SECTIONS_COUNT=0 -DSCREEN_TILES_V=23 -DFIRST_RENDER_LINE=60 -DFORMAT_EEPROM=0 -mcall-prologues -x assembler-with-cpp -Wa,-gdwarf2 -c ../../../../uzebox/kernel//uzeboxSoundEngineCore.s
avr-gcc -I"../../../../uzebox/kernel/" -mmcu=atmega644 -Wall -gdwarf-2 -std=gnu99 -DF_CPU=28636360UL -Os -fsigned-char -ffunction-sections -MD -MP -MT uzeboxVideoEngine.o -MF dep/uzeboxVideoEngine.o.d -DVIDEO_MODE=3 -DINTRO_LOGO=0 -DSOUND_CHANNEL_4_ENABLE=1 -DSOUND_CHANNEL_2_ENABLE=1 -DSOUND_CHANNEL_3_ENABLE=1 -DCENTER_ADJUSTMENT=4 -DMAX_SPRITES=31 -DRAM_TILES_COUNT=31 -DSCREEN_SECTIONS_COUNT=0 -DSCREEN_TILES_V=23 -DFIRST_RENDER_LINE=60 -DFORMAT_EEPROM=0 -mcall-prologues -c ../../../../uzebox/kernel//uzeboxVideoEngine.c
avr-gcc -I"../../../../uzebox/kernel/" -mmcu=atmega644 -Wall -gdwarf-2 -std=gnu99 -DF_CPU=28636360UL -Os -fsigned-char -ffunction-sections -MD -MP -MT main.o -MF dep/main.o.d -DVIDEO_MODE=3 -DINTRO_LOGO=0 -DSOUND_CHANNEL_4_ENABLE=1 -DSOUND_CHANNEL_2_ENABLE=1 -DSOUND_CHANNEL_3_ENABLE=1 -DCENTER_ADJUSTMENT=4 -DMAX_SPRITES=31 -DRAM_TILES_COUNT=31 -DSCREEN_SECTIONS_COUNT=0 -DSCREEN_TILES_V=23 -DFIRST_RENDER_LINE=60 -DFORMAT_EEPROM=0 -mcall-prologues -c ../main.c
In file included from ../gamedefines.h:235:0,
from ../engine.h:1,
from ../main.c:23:
../functiondefs.h:120:4: error: variable ‘colormap’ must be const in order to be put into read-only section by means of ‘__attribute__((progmem))’
u8 colormap[] PROGMEM = {0x0F,0x30,0xF0,0xC0,0x37};
^
In file included from ../engine.h:5:0,
from ../main.c:23:
../logic.h: In function ‘FindKiller’:
../logic.h:512:7: warning: variable ‘closest’ set but not used [-Wunused-but-set-variable]
u8 closest = 255;
^
make: *** [Makefile:83: main.o] Error 1
Re: Post your WIPs
I see Lee hasn't updated his repo since 2017. It'd be great if we can get Mega Bomber to build again and get two player mode working as I think Mega Bomber could become a good demo for the Uzebox with only a little extra effort.
Re: Post your WIPs
I have got Mega Bomber to build simply by adding a const to the start of line 120 of functiondefs.h but the player sprites don't get drawn correctly and there are no enemies so it doesn't look like this is the same (latest) code that was used to build the binary on the wiki.
Hopefully Lee still has a copy or he can tell us where the latest source is?
Hopefully Lee still has a copy or he can tell us where the latest source is?
Re: Post your WIPs
Oh eh...
Hopefully I will find it in spring cleaning. I think I had the source on a laptop for both the igloo(cool walking under igloo roof foreground) and several other levels at one point, sorry for not releasing it but the code got rotten and split up. The AI was getting there, but was no entertainment to play against at it's best, and ran out of flash. I'm surprised 2 players doesnt work.
The game could be done with reflashing per level, but it turned to chaos trying to find a way to make a complete game in 60K. As is, a pretty demo that kept a large chunk of it's 60K assets on the screen at once. The state of the code got bad because I had different builds, each with 1 single level, and each build had it's own custom code for various level gimmicks.
If trying to make a complete game, probably easier to build from scratch IMO. The clever thing was just reducing an almost grid based game, into strictly grid based. Probably not much to learn from the code but I will release whatever I can find.
Hopefully I will find it in spring cleaning. I think I had the source on a laptop for both the igloo(cool walking under igloo roof foreground) and several other levels at one point, sorry for not releasing it but the code got rotten and split up. The AI was getting there, but was no entertainment to play against at it's best, and ran out of flash. I'm surprised 2 players doesnt work.
The game could be done with reflashing per level, but it turned to chaos trying to find a way to make a complete game in 60K. As is, a pretty demo that kept a large chunk of it's 60K assets on the screen at once. The state of the code got bad because I had different builds, each with 1 single level, and each build had it's own custom code for various level gimmicks.
If trying to make a complete game, probably easier to build from scratch IMO. The clever thing was just reducing an almost grid based game, into strictly grid based. Probably not much to learn from the code but I will release whatever I can find.