Разработка и ромхакинг > Ромхакинг
Как реализовать рандом на проце M68K?
sergi:
Собственно в процессе кодинга игр возникла необходимость в мгновенном или не слишком медленном рандоме.
Вроде говорят что это дело цепляют за тактовую частоту процессора, ну может кто знает по этой теме что.
Я пока использовал инкремент который осуществляется каждое обновлени экрана т.е. 60 раз в секунду, но это медленно
получается только 60 цифр за секунду, мне бы побыстрее чего :?
HoRRoR:
Инкременируй и при каждом вызове функции, а потом бери какой-нибудь хеш.
sergi:
Цикл игры обычно зацеплен за обновление экрана
т.е. ждем прерывания по кадровому обновлению, при этом зачастую обычно вырубают преривания по строкам(наверно в пистолетах их только используют) и обновляем графику, палитры и опрашиваем джой, ну и инкрементирую я при этом
но проблема как раз в том что медленно, а отдельно процедура это всеравно по какомуто признаку должна быть не закономерная а реально рандомная :-\
HoRRoR:
Дык и инкрементируй при вызове функции - чем не изменение состояния? Ведь каждый раз при вызове функции будут разные значения, а разность рэндома решает уже не счётчик, а алгоритм взятия хеша и преобразования его в выходное значение в зависимости от требуемого типа и диапазона.
А лучше вместо счётчика менять при каждом удобном случае зерно - некий хеш, который меняется алгоритмом, дающим каждый непохожие результаты. А затем из этого зерна извлекать твой рэндом. На обновление экрана (да и вообще, куда не лень) тоже повесишь смену зерна - будет меньше закономерностей.
sergi:
Ну тогда следует уточнить что такое алгоритм взятия хэша - пример нужен, а то я не догоняю :-\
HoRRoR:
Алгоритм из ANSI-C:
--- Код: ---#define RAND_MAX 32767
unsigned long next=1;
int rand(void) {
next=next*1103515245+12345;
return((unsigned int)(next/65536)%32768);
}
void srand(unsigned int seed) {
next=seed;
}
--- Конец кода ---
При вызове srand() в качестве зерна можно выставлять какой-нибудь счётчик. Желательно при этом его увеличивать хотя бы на 1, чтобы быть увереным, что при каждом вызове его значение будет меняться.
sergi:
Ну возможно я не уточнил - мне нужно в ассемблере это дело а не в С, я на асме пишу
HoRRoR:
А есть разница? Алгоритм - он и в Африке алгоритм.
sergi:
unsigned int меня беспокоит :(
да и вообще хотелось бы за какую то величину физическую зацеплено чтобы было, там какой такт проца или комманды - вроде есть такое же, только я не знаю как достать :-\
HoRRoR:
--- Цитата: sergi от 19 Ноября 2009, 18:31:25 ---unsigned int меня беспокоит :(
--- Конец цитаты ---
о_О
--- Цитата: sergi от 19 Ноября 2009, 18:31:25 ---да и вообще хотелось бы за какую то величину физическую зацеплено чтобы было, там какой такт проца или комманды - вроде есть такое же, только я не знаю как достать :-\
--- Конец цитаты ---
Смысл?.. Как ни крути - закономерность будет всегда. Т.е. при одинаковых условиях будут выдаваться одинаковые значения.
Коль уж так хочется - реализуй вышеописанные функции, а в srand() в качестве параметра передавай какую-нибудь "физическую величину", если сможешь её раздобыть.
sergi:
Ну мне понятно что ты там делишь, умножаешь получается какоето число
но всеже если кто знает другой способ, то буду благодарен
то что можно умножать и делить я учту, может комбинированный вариант сделаю
HoRRoR:
А как иначе ты собрался делать рэндом? Какие-то неверные у тебя о нём представления.
Умножать/делить надо, чтобы получилось неожиданное значение. В этом и есть вся суть "случайности". Ты можешь подобрать любые другие аналоги, необязательно использовать именно эти операции. Можешь сделать xor с чем-нибудь, затем сдвиг влево на несколько разрядов, затем сложить с чем-нибудь.
evgeny:
Проще говоря, нужно брать любые переменные, которые часто меняются и проделать с ними математические операции, складывать, делить, прибавить значения опроса джойстика и другие прерывания и сохранить результат в новой переменной, которая и станет отвечать за рандом.
romanich:
--- Цитата: sergi от 19 Ноября 2009, 15:39:11 ---получается только 60 цифр за секунду, мне бы побыстрее чего :?
--- Конец цитаты ---
Заэнабли HBlank INT и будет ещё в 262 раза (NTSC) быстрее :)
sergi:
Заэнэбливание HBLank у меня ведет к тормозам, может чего не так конечно делаю, но лучше его не трогать пока
я думал все о номере исполняемой комманде - кто знает как его выцедить :?
ну там есть же статус регистр, а номер команды где хранится PC - программ каунтер т.е.
HoRRoR:
Представь себе картину: хочет человек просверлить в стене дырку. Он берёт железную руду, переплавляет, делает стальной сплав, вытачивает сверло, создаёт крутящий механизм, расчитывает всё до деталей, и в итоге просверливает дыру.
Раздаётся звонок в дверь - пришёл сосед, просит одолжить перфоратор. Человек идёт в кладовую, достаёт перфоратор, даёт соседу, попутно думая "вот у меня правильная дырка, а у него будет неправильная".
Вот у тебя примерно то же самое. Результат в любом случае будет один, а пути его достижения делятся на стандартно-логичный и феерически-спонтанный в вакууме.
sergi:
Так это же мечта человечества - стать богом и самому творить что хотеть, хочешь перфоратор, хочешь стенку с дыркой для разных нужд - все там будем :lol:
romanich:
--- Цитата: sergi от 20 Ноября 2009, 16:58:06 ---Заэнэбливание HBLank у меня ведет к тормозам, может чего не так конечно делаю, но лучше его не трогать пока
--- Конец цитаты ---
в своё время мне понравился такой генератор:
--- Код: ---u32 System_Seed=0; //Обязательно = 0 !!!!!
//Random Number Generator
u32 System_Random(u32 Modular)
{
__asm
{
mov eax,System_Seed
mov cx,0x21
@1:
add eax,eax
jnc @2
xor al,0xC5
@2:
loop @1
mov System_Seed,eax
}
if(Modular) return(System_Seed%Modular);
return System_Seed;
}
--- Конец кода ---
беспроблемно переложится на м68к
sergi:
В общем я решил так сделать и сделал
Сначала добавляю какое то число находящееся в середине нужного диапазона к тому числу которое инкрементируется каждое обновление экрана
потом беру счетчик Program Counter - вроде он содержит адрес исполняемой комманды, ну не знаю его ли он точно содержит или чего другое, потом делю его на то число которое получилось после добавления к инкрементируемому каждый экран, а результат потом еще разделяю на 2 части по 4 бита, ну мне так нужнее и смотрю не вылетело ли каждое за указанные рамки, если вылетело то еще раз добавляю среднее число к тому результату который получился, а нижнее число (нижние 4 бита) если выбиваются из диапазона то тупо делю сдвигом вправо
в принципе такими махинациями получается ну какойто псевдо-рандом, который сложно предугадать, т.к. там еще параметры бывают меняются и рандом берется несколько раз
в общем результатом доволен
но делю не сдвигом а именно делением в M68K это комманда divu.w
в принципе шустро делает, скоростью я доволен, да и рандомностью тоже
А вообще мне нужно было число от 0 до 100 :)
Ti_:
--- Цитата: sergi от 26 Ноября 2009, 11:24:56 ---но делю не сдвигом а именно делением в M68K это комманда divu.w
--- Конец цитаты ---
деление самое медленное у сеги.
вот рандом готовый мошт кому пригодится (думаю тема актуальна ещё, раз готового так никто и не выложил!)
--- Код: ---Rock n' Roll Racing :
ROM:00001328 movem.l d1-d2,-(sp)
ROM:0000132C move.w $51E6(a4),d0
ROM:00001330 move.w $51E8(a4),d1
ROM:00001334 move.w d1,d2
ROM:00001336 mulu.w #$43E5,d0
ROM:0000133A mulu.w #$15A,d1
ROM:0000133E add.l d1,d0
ROM:00001340 swap d0
ROM:00001342 clr.w d0
ROM:00001344 mulu.w #$43E5,d2
ROM:00001348 add.l d2,d0
ROM:0000134A addq.l #1,d0
ROM:0000134C move.l d0,$51E6(a4)
ROM:00001350 swap d0
ROM:00001352 andi.w #$7FFF,d0
ROM:00001356 movem.l (sp)+,d1-d2
ROM:0000135A rts
Dune - The Battle for Arrakis :
ROM:00000E10 move.l #$349F285A,(random_value1).w
......
ROM:00000E42 sub_E42: ; CODE XREF: sub_C0C+8p
ROM:00000E42 ; sub_439Aj ...
ROM:00000E42 lea (random_value1).w,a0
ROM:00000E46 moveq #0,d0
ROM:00000E48 move.b 3(a0),d0
ROM:00000E4C lsr.b #2,d0
ROM:00000E4E move.b 1(a0),d1
ROM:00000E52 roxl.b #1,d1
ROM:00000E54 move.b d1,1(a0)
ROM:00000E58 move.b 2(a0),d1
ROM:00000E5C roxl.b #1,d1
ROM:00000E5E move.b d1,2(a0)
ROM:00000E62 eori #$11,ccr
ROM:00000E66 move.b 3(a0),d1
ROM:00000E6A subx.b d1,d0
ROM:00000E6C lsr.b #1,d0
ROM:00000E6E move.b 3(a0),d1
ROM:00000E72 roxr.b #1,d1
ROM:00000E74 move.b d1,3(a0)
ROM:00000E78 move.b 3(a0),d0
ROM:00000E7C move.b 2(a0),d1
ROM:00000E80 eor.b d1,d0
ROM:00000E82 rts
не использовано (? )
OM:00000E84 sub_E84:
ROM:00000E84 movem.l d2-d3,-(sp)
ROM:00000E88 move.b (random_value4).w,d0
ROM:00000E8C move.b (random_value3).w,d1
ROM:00000E90 move.b (random_value2).w,d2
ROM:00000E94 move.b d0,d3
ROM:00000E96 lsr.b #2,d0
ROM:00000E98 roxl.b #1,d2
ROM:00000E9A move.b d2,(random_value2).w
ROM:00000E9E roxl.b #1,d1
ROM:00000EA0
ROM:00000EA0 loc_EA0:
ROM:00000EA0 move.b d1,(random_value3).w
ROM:00000EA4 eori #$11,ccr
ROM:00000EA8 subx.b d3,d0
ROM:00000EAA lsr.b #1,d0
ROM:00000EAC roxr.b #1,d3
ROM:00000EAE move.b d3,(random_value4).w
ROM:00000EB2 move.b d3,d0
ROM:00000EB4 eor.b d1,d0
ROM:00000EB6 andi.w #$FF,d0
ROM:00000EBA movem.l (sp)+,d2-d3
ROM:00000EBE rts
--- Конец кода ---
Навигация
Перейти к полной версии